21 struct file_info files[MAX_FILES];
26 int parse_config_input(ezxml_t cfg_input);
27 int write_output(char * filename, ezxml_t cfg_output);
28 int copy_file(int file_index, FILE * data_file);
31 printf("Usage: build_vm <infile> [-o outfile]\n");
34 int main(int argc, char ** argv) {
36 char * outfile = NULL;
40 memset((char *)files, 0, sizeof(files));
44 while ((c = getopt(argc, argv, "ho:")) != -1) {
62 infile = argv[optind];
65 if (outfile == NULL) {
66 char * endptr = rindex(infile, '.');
68 outfile = malloc(strlen(infile) + strlen(".dat") + 1);
70 strncpy(outfile, infile, endptr - infile);
72 sprintf(outfile, "%s.dat", outfile);
77 printf("Input: [%s] ==>> Output: [%s]\n", infile, outfile);
79 ezxml_t cfg_input = ezxml_parse_file(infile);
81 if (cfg_input == NULL) {
82 printf("Could not open configuration input file: %s\n", infile);
90 if (parse_config_input(cfg_input) == -1) {
91 printf("Error parsing configuration input\n");
95 // printf("xml : %s\n", ezxml_toxml(cfg_input));
103 write_output(outfile, cfg_input);
109 char * get_val(ezxml_t cfg, char * tag) {
110 char * attrib = (char *)ezxml_attr(cfg, tag);
111 ezxml_t txt = ezxml_child(cfg, tag);
113 if ((txt != NULL) && (attrib != NULL)) {
114 printf("Invalid Cfg file: Duplicate value for %s (attr=%s, txt=%s)\n",
115 tag, attrib, ezxml_txt(txt));
119 return (attrib == NULL) ? ezxml_txt(txt) : attrib;
124 int parse_config_input(ezxml_t cfg_input) {
125 ezxml_t file_tags = NULL;
126 ezxml_t tmp_file_tag = NULL;
128 // files are transformed into blobs that are slapped to the end of the file
130 file_tags = ezxml_child(cfg_input, "files");
132 tmp_file_tag = ezxml_child(file_tags, "file");
134 while (tmp_file_tag) {
135 char * filename = get_val(tmp_file_tag, "filename");
136 struct stat file_stats;
137 char * id = get_val(tmp_file_tag, "id");
141 if (stat(filename, &file_stats) != 0) {
146 files[num_files].size = (unsigned int)file_stats.st_size;
147 strncpy(files[num_files].id, id, 256);
148 strncpy(files[num_files].filename, filename, 2048);
150 snprintf(index_buf, 256, "%d", num_files);
151 ezxml_set_attr_d(tmp_file_tag, "index", index_buf);
154 tmp_file_tag = ezxml_next(tmp_file_tag);
162 int write_output(char * filename, ezxml_t cfg_output) {
163 FILE * data_file = fopen(filename, "w+");
164 char * new_cfg_str = ezxml_toxml(cfg_output);
165 unsigned int cfg_len = strlen(new_cfg_str);
166 unsigned long long zero = 0;
168 unsigned long long offset = 0;
169 unsigned long long file_cnt = num_files;
171 fwrite("v3vee\0\0\0", 8, 1, data_file);
174 // printf("New config: \n%s\n", new_cfg_str);
176 fwrite(&cfg_len, sizeof(unsigned int), 1, data_file);
177 offset += sizeof(unsigned int);
179 fwrite(new_cfg_str, cfg_len, 1, data_file);
182 fwrite(&zero, 1, 8, data_file);
185 printf("Total number of files: %llu\n", file_cnt);
187 fwrite(&file_cnt, 8, 1, data_file);
190 // each index entry is 16 bytes long plus end padding
191 offset += (16 * num_files) + 8;
193 for (i = 0; i < num_files; i++) {
194 fwrite(&i, 4, 1, data_file);
195 fwrite(&(files[i].size), 4, 1, data_file);
196 fwrite(&offset, 8, 1, data_file);
198 offset += files[i].size;
201 fwrite(&zero, 1, 8, data_file);
203 for (i = 0; i < num_files; i++) {
205 copy_file(i, data_file);
217 #define XFER_BLK_SIZE 4096
219 int copy_file(int file_index, FILE * data_file) {
220 char xfer_buf[XFER_BLK_SIZE];
221 int bytes_to_read = files[file_index].size;
223 int xfer_len = XFER_BLK_SIZE;
224 FILE * in_file = NULL;
225 char * filename = files[file_index].filename;
232 printf("Copying [%d] -- %s \n",
237 if (ioctl(STDIO_FD, TIOCGWINSZ, &wsz) == -1) {
238 printf("ioctl error on STDIO\n");
243 memset(cons_line, 0, 256);
244 snprintf(cons_line, 256, "\r(%s) [", files[file_index].id);
245 prog_len = wsz.ws_col - (strlen(cons_line) + 11);
249 in_file = fopen(filename, "r");
251 while (bytes_to_read > 0) {
252 struct winsize tmp_wsz;
255 if (ioctl(STDIO_FD, TIOCGWINSZ, &tmp_wsz) == -1) {
256 printf("ioctl error on STDIO\n");
260 ratio = (double)bytes_read / (double)(files[file_index].size);
261 tmp_dots = (int)(ratio * (double)prog_len);
263 if ((tmp_dots != num_dots) || (tmp_wsz.ws_col != wsz.ws_col)) {
270 num_blanks = prog_len - num_dots;
272 memset(cons_line, 0, 256);
273 snprintf(cons_line, 256, "\r(%s) [", files[file_index].id);
275 for (i = 0; i <= num_dots; i++) {
276 strcat(cons_line, "=");
279 for (i = 0; i < num_blanks - 1; i++) {
280 strcat(cons_line, " ");
283 strcat(cons_line, "] ");
285 // printf("console width = %d\n", wsz.ws_col);
286 write(STDIO_FD, cons_line, wsz.ws_col);
291 if (xfer_len > bytes_to_read) {
292 xfer_len = bytes_to_read;
295 if (fread(xfer_buf, xfer_len, 1, in_file) == 0) {
296 printf("Error reading data file %s\n", filename);
300 if (fwrite(xfer_buf, xfer_len, 1, data_file) == 0) {
301 printf("Error writing data file contents");
306 bytes_read += xfer_len;
307 bytes_to_read -= xfer_len;
310 strcat(cons_line, "Done\n");
311 write(STDIO_FD, cons_line, wsz.ws_col);