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);
80 if (strcmp("", ezxml_error(cfg_input)) != 0) {
81 printf("%s\n", ezxml_error(cfg_input));
85 if (cfg_input == NULL) {
86 printf("Could not open configuration input file: %s\n", infile);
94 if (parse_config_input(cfg_input) == -1) {
95 printf("Error parsing configuration input\n");
99 // printf("xml : %s\n", ezxml_toxml(cfg_input));
107 write_output(outfile, cfg_input);
113 char * get_val(ezxml_t cfg, char * tag) {
114 char * attrib = (char *)ezxml_attr(cfg, tag);
115 ezxml_t txt = ezxml_child(cfg, tag);
117 if ((txt != NULL) && (attrib != NULL)) {
118 printf("Invalid Cfg file: Duplicate value for %s (attr=%s, txt=%s)\n",
119 tag, attrib, ezxml_txt(txt));
123 return (attrib == NULL) ? ezxml_txt(txt) : attrib;
128 int parse_config_input(ezxml_t cfg_input) {
129 ezxml_t file_tags = NULL;
130 ezxml_t tmp_file_tag = NULL;
132 // files are transformed into blobs that are slapped to the end of the file
134 file_tags = ezxml_child(cfg_input, "files");
136 tmp_file_tag = ezxml_child(file_tags, "file");
138 while (tmp_file_tag) {
139 char * filename = get_val(tmp_file_tag, "filename");
140 struct stat file_stats;
141 char * id = get_val(tmp_file_tag, "id");
145 if (stat(filename, &file_stats) != 0) {
150 files[num_files].size = (unsigned int)file_stats.st_size;
151 strncpy(files[num_files].id, id, 256);
152 strncpy(files[num_files].filename, filename, 2048);
154 snprintf(index_buf, 256, "%d", num_files);
155 ezxml_set_attr_d(tmp_file_tag, "index", index_buf);
158 tmp_file_tag = ezxml_next(tmp_file_tag);
166 int write_output(char * filename, ezxml_t cfg_output) {
167 FILE * data_file = fopen(filename, "w+");
168 char * new_cfg_str = ezxml_toxml(cfg_output);
169 unsigned int cfg_len = strlen(new_cfg_str);
170 unsigned long long zero = 0;
172 unsigned long long offset = 0;
173 unsigned long long file_cnt = num_files;
175 fwrite("v3vee\0\0\0", 8, 1, data_file);
178 // printf("New config: \n%s\n", new_cfg_str);
180 fwrite(&cfg_len, sizeof(unsigned int), 1, data_file);
181 offset += sizeof(unsigned int);
183 fwrite(new_cfg_str, cfg_len, 1, data_file);
186 fwrite(&zero, 1, 8, data_file);
189 printf("Total number of files: %llu\n", file_cnt);
191 fwrite(&file_cnt, 8, 1, data_file);
194 // each index entry is 16 bytes long plus end padding
195 offset += (16 * num_files) + 8;
197 for (i = 0; i < num_files; i++) {
198 fwrite(&i, 4, 1, data_file);
199 fwrite(&(files[i].size), 4, 1, data_file);
200 fwrite(&offset, 8, 1, data_file);
202 offset += files[i].size;
205 fwrite(&zero, 1, 8, data_file);
207 for (i = 0; i < num_files; i++) {
209 copy_file(i, data_file);
221 #define XFER_BLK_SIZE 4096
223 int copy_file(int file_index, FILE * data_file) {
224 char xfer_buf[XFER_BLK_SIZE];
225 int bytes_to_read = files[file_index].size;
227 int xfer_len = XFER_BLK_SIZE;
228 FILE * in_file = NULL;
229 char * filename = files[file_index].filename;
236 printf("Copying [%d] -- %s \n",
241 if (ioctl(STDIO_FD, TIOCGWINSZ, &wsz) == -1) {
242 printf("ioctl error on STDIO\n");
247 memset(cons_line, 0, 256);
248 snprintf(cons_line, 256, "\r(%s) [", files[file_index].id);
249 prog_len = wsz.ws_col - (strlen(cons_line) + 11);
253 in_file = fopen(filename, "r");
255 while (bytes_to_read > 0) {
256 struct winsize tmp_wsz;
259 if (ioctl(STDIO_FD, TIOCGWINSZ, &tmp_wsz) == -1) {
260 printf("ioctl error on STDIO\n");
264 ratio = (double)bytes_read / (double)(files[file_index].size);
265 tmp_dots = (int)(ratio * (double)prog_len);
267 if ((tmp_dots != num_dots) || (tmp_wsz.ws_col != wsz.ws_col)) {
274 num_blanks = prog_len - num_dots;
276 memset(cons_line, 0, 256);
277 snprintf(cons_line, 256, "\r(%s) [", files[file_index].id);
279 for (i = 0; i <= num_dots; i++) {
280 strcat(cons_line, "=");
283 for (i = 0; i < num_blanks - 1; i++) {
284 strcat(cons_line, " ");
287 strcat(cons_line, "] ");
289 // printf("console width = %d\n", wsz.ws_col);
290 write(STDIO_FD, cons_line, wsz.ws_col);
295 if (xfer_len > bytes_to_read) {
296 xfer_len = bytes_to_read;
299 if (fread(xfer_buf, xfer_len, 1, in_file) == 0) {
300 printf("Error reading data file %s\n", filename);
304 if (fwrite(xfer_buf, xfer_len, 1, data_file) == 0) {
305 printf("Error writing data file contents");
310 bytes_read += xfer_len;
311 bytes_to_read -= xfer_len;
314 strcat(cons_line, "Done\n");
315 write(STDIO_FD, cons_line, wsz.ws_col);