-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathfs-builder.cc
138 lines (111 loc) · 4.07 KB
/
fs-builder.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iostream>
#include <memory>
#include <stdint.h>
#include <string>
#include <vector>
#if defined(_WIN32)
/* This at least works on MinGW */
#include <getopt.h>
#endif
struct InputFile {
InputFile (const std::string & name)
{
this->mFullName = name;
this->mBaseName = name;
std::ifstream file;
file.open(name.c_str(), std::ios::binary | std::ios::in);
if (file.good()) {
mExists = true;
file.seekg(0, std::ios::end);
mSize = file.tellg();
file.close();
} else {
mExists = false;
}
}
std::string mBaseName;
std::string mFullName;
size_t mSize;
bool mExists;
};
int main (int argc, char *argv[]) {
std::auto_ptr<std::string> ptrOutputFileName;
std::vector<InputFile *> inputFiles;
/* First handle explicit argument switches */
for (int whichOption; (whichOption = getopt(argc, argv, "+o:")) != -1;) {
switch (whichOption) {
case 'o':
if (ptrOutputFileName.get()) {
std::cout << "Output filename already set (" << *ptrOutputFileName << ")" << std::endl;
::exit(1);
}
else {
ptrOutputFileName.reset(new std::string(optarg));
}
break;
default:
/* getopt() has already printed an error message */
::exit(1);
break;
}
}
/* Collect all unprocessed arguments as a list of files to be packed */
for (unsigned int index = optind; index < argc; index++) {
InputFile * input = new InputFile(argv[index]);
if (input->mExists) {
inputFiles.push_back(input);
} else {
std::cerr << input->mFullName << " does not exist\n";
::exit(1);
}
}
if (!ptrOutputFileName.get()) {
std::cout << "Output file (-o <filename>) required" << std::endl;
::exit(1);
}
std::ofstream outputFile;
outputFile.open(ptrOutputFileName->c_str(),
std::ios::out | std::ios::trunc | std::ios::binary);
/* Write out each file in sequence */
for (unsigned int i = 0; i < inputFiles.size(); i++) {
std::ifstream infile;
infile.open(inputFiles[i]->mFullName.c_str(), std::ios::in | std::ios::binary);
/* Length of file name. Save as big-endian uint32_t */
uint32_t name_len = inputFiles[i]->mBaseName.length();
uint8_t name_len_be[4] = {((name_len & 0xff000000) >> 24),
((name_len & 0x00ff0000) >> 16),
((name_len & 0x0000ff00) >> 8),
((name_len & 0x000000ff) >> 0)};
outputFile.write((char const *)name_len_be, sizeof(name_len_be));
/* File name content */
outputFile.write(inputFiles[i]->mBaseName.c_str(),
inputFiles[i]->mBaseName.length());
/* Payload length. Also is big-endian uint32_t */
uint32_t payload_len = inputFiles[i]->mSize;
uint8_t payload_len_be[4] = {((payload_len & 0xff000000) >> 24),
((payload_len & 0x00ff0000) >> 16),
((payload_len & 0x0000ff00) >> 8),
((payload_len & 0x000000ff) >> 0)};
outputFile.write((char const *)payload_len_be, sizeof(payload_len_be));
/* Payload */
for (size_t remaining = inputFiles[i]->mSize;
remaining > 0;)
{
char buf[4096];
size_t transfer_size = std::min(sizeof(buf), remaining);
infile.read(&buf[0], transfer_size);
outputFile.write(&buf[0], transfer_size);
remaining -= transfer_size;
}
}
outputFile.close();
for (std::vector<InputFile *>::iterator i = inputFiles.begin();
i != inputFiles.end(); ++i)
{
InputFile * f = *i;
delete f;
}
}