11 #include <sys/types.h>
28 struct xml_option * next;
39 unsigned long long num_files = 0;
40 struct file_info files[MAX_FILES];
43 int read_file(int fd, int size, unsigned char * buf);
47 int create_vm(char * vm_name, void * img_data, unsigned int img_size) {
48 struct v3_guest_img guest_img;
52 memset(&guest_img, 0, sizeof(struct v3_guest_img));
54 guest_img.size = img_size;
55 guest_img.guest_data = img_data;
56 strncpy(guest_img.name, vm_name, 127);
59 v3_fd = open(v3_dev, O_RDONLY);
62 printf("Error opening V3Vee control device\n");
66 dev_idx = ioctl(v3_fd, V3_CREATE_GUEST, &guest_img);
70 printf("Error (%d) creating VM\n", dev_idx);
74 printf("VM (%s) created at /dev/v3-vm%d\n", vm_name, dev_idx);
76 /* Close the file descriptor. */
83 int load_image(char * vm_name, char * filename) {
85 struct stat guest_stats;
87 void * img_data = NULL;
89 guest_fd = open(filename, O_RDONLY);
92 printf("Error Opening guest image: %s\n", filename);
96 if (fstat(guest_fd, &guest_stats) == -1) {
97 printf("ERROR: Could not stat guest image file -- %s\n", filename);
101 img_size = guest_stats.st_size;
103 // load guest image into user memory
104 img_data = malloc(img_size);
106 read_file(guest_fd, img_size, img_data);
110 printf("Guest image Loaded (size=%u)\n", img_size);
111 return create_vm(vm_name, img_data, img_size);
116 ezxml_t open_xml_file(char * filename) {
118 ezxml_t xml_input = ezxml_parse_file(filename);
120 if (xml_input == NULL) {
121 printf("Error: Could not open XML input file (%s)\n", filename);
123 } else if (strcmp("", ezxml_error(xml_input)) != 0) {
124 printf("%s\n", ezxml_error(xml_input));
132 int find_xml_options(ezxml_t xml, struct xml_option ** opts) {
134 ezxml_t child = xml->child;
135 struct xml_option * next_opt = NULL;
137 char * opt = (char *)ezxml_attr(xml, "opt_tag");
140 next_opt = malloc(sizeof(struct xml_option));
142 memset(next_opt, 0, sizeof(struct xml_option));
145 next_opt->location = xml;
146 next_opt->next = NULL;
148 // printf("Option found: %s\n", opt);
159 if (next_opt != 0x0) {
160 num_opts += find_xml_options(child, &(next_opt->next));
162 num_opts += find_xml_options(child, opts);
170 while (next_opt->next) {
171 next_opt = next_opt->next;
175 child = child->ordered;
183 char * get_val(ezxml_t cfg, char * tag) {
184 char * attrib = (char *)ezxml_attr(cfg, tag);
185 ezxml_t txt = ezxml_child(cfg, tag);
187 if ((txt != NULL) && (attrib != NULL)) {
188 printf("Invalid Cfg file: Duplicate value for %s (attr=%s, txt=%s)\n",
189 tag, attrib, ezxml_txt(txt));
193 return (attrib == NULL) ? ezxml_txt(txt) : attrib;
197 int parse_aux_files(ezxml_t cfg_input) {
198 ezxml_t file_tags = NULL;
199 ezxml_t tmp_file_tag = NULL;
201 // files are transformed into blobs that are slapped to the end of the file
203 file_tags = ezxml_child(cfg_input, "files");
205 tmp_file_tag = ezxml_child(file_tags, "file");
207 while (tmp_file_tag) {
208 char * filename = get_val(tmp_file_tag, "filename");
209 struct stat file_stats;
210 char * id = get_val(tmp_file_tag, "id");
214 if (stat(filename, &file_stats) != 0) {
219 files[num_files].size = (unsigned int)file_stats.st_size;
220 strncpy(files[num_files].id, id, 256);
221 strncpy(files[num_files].filename, filename, 2048);
223 snprintf(index_buf, 256, "%llu", num_files);
224 ezxml_set_attr_d(tmp_file_tag, "index", index_buf);
227 tmp_file_tag = ezxml_next(tmp_file_tag);
234 int build_image(char * vm_name, char * filename, struct cfg_value * cfg_vals, int num_options) {
237 struct xml_option * xml_opts = NULL;
238 int num_xml_opts = 0;
239 void * guest_img_data = NULL;
240 int guest_img_size = 0;
243 xml = open_xml_file(filename);
246 num_xml_opts = find_xml_options(xml, &xml_opts);
248 // printf("%d options\n", num_xml_opts);
251 for (i = 0; i < num_options; i++) {
252 struct cfg_value * cfg_val = &cfg_vals[i];
253 struct xml_option * xml_opt = xml_opts;
256 if (strcasecmp(cfg_val->tag, xml_opt->tag) == 0) {
260 xml_opt = xml_opt->next;
265 printf("Could not find Config option (%s) in XML file\n", cfg_val->tag);
269 ezxml_set_txt(xml_opt->location, cfg_val->value);
275 parse_aux_files(xml);
277 // create image data blob
279 char * new_xml_str = ezxml_toxml(xml);
280 int file_data_size = 0;
283 unsigned long long file_offset = 0;
290 8 bytes (number of files) +
291 num_files * 16 byte file header +
295 for (i = 0; i < num_files; i++) {
296 file_data_size += files[i].size;
299 guest_img_size = 8 + 4 + strlen(new_xml_str) + 8 + 8 +
300 (num_files * 16) + 8 + file_data_size;
303 guest_img_data = malloc(guest_img_size);
304 memset(guest_img_data, 0, guest_img_size);
306 memcpy(guest_img_data, "v3vee\0\0\0", 8);
309 *(unsigned int *)(guest_img_data + offset) = strlen(new_xml_str);
312 memcpy(guest_img_data + offset, new_xml_str, strlen(new_xml_str));
313 offset += strlen(new_xml_str);
315 memset(guest_img_data + offset, 0, 8);
318 *(unsigned long long *)(guest_img_data + offset) = num_files;
322 // The file offset starts at the end of the file list
323 file_offset = offset + (16 * num_files) + 8;
325 for (i = 0; i < num_files; i++) {
326 *(unsigned int *)(guest_img_data + offset) = i;
328 *(unsigned int *)(guest_img_data + offset) = files[i].size;
330 *(unsigned long long *)(guest_img_data + offset) = file_offset;
333 file_offset += files[i].size;
337 memset(guest_img_data + offset, 0, 8);
341 for (i = 0; i < num_files; i++) {
342 int fd = open(files[i].filename, O_RDONLY);
345 printf("Error: Could not open aux file (%s)\n", files[i].filename);
349 read_file(fd, files[i].size, (unsigned char *)(guest_img_data + offset));
353 offset += files[i].size;
361 printf("Guest Image Created (size=%u)\n", guest_img_size);
362 return create_vm(vm_name, guest_img_data, guest_img_size);
370 int main(int argc, char** argv) {
371 char * filename = NULL;
378 while (( c = getopt(argc, argv, "b")) != -1) {
386 if (argc - optind + 1 < 3) {
387 printf("usage: v3_create [-b] <guest_img> <vm name> [cfg options]\n");
391 filename = argv[optind];
392 name = argv[optind + 1];
395 if (build_flag == 1) {
396 int cfg_idx = optind + 2;
398 struct cfg_value * cfg_vals = NULL;
400 printf("Building VM Image (cfg=%s) (name=%s) (%d config options)\n", filename, name, argc - cfg_idx);
402 cfg_vals = malloc(sizeof(struct cfg_value) * argc - cfg_idx);
406 while (i < argc - cfg_idx) {
410 value = argv[cfg_idx + i];
412 tag = strsep(&value, "=");
416 printf("Invalid Option format: %s\n", argv[cfg_idx + i]);
420 cfg_vals[i].tag = tag;
421 cfg_vals[i].value = value;
423 printf("Config option: %s: %s\n", tag, value);
429 return build_image(name, filename, cfg_vals, argc - cfg_idx);
433 printf("Loading VM Image (img=%s) (name=%s)\n", filename, name);
434 return load_image(name, filename);
442 int read_file(int fd, int size, unsigned char * buf) {
443 int left_to_read = size;
446 while (left_to_read != 0) {
447 int bytes_read = read(fd, buf + have_read, left_to_read);
449 if (bytes_read <= 0) {
453 have_read += bytes_read;
454 left_to_read -= bytes_read;
457 if (left_to_read != 0) {
458 printf("Error could not finish reading file\n");