11 #include <sys/types.h>
22 unsigned long long num_files = 0;
23 struct file_info files[MAX_FILES];
26 int create_vm(char * vm_name, void * img_data, unsigned int img_size) {
27 struct v3_guest_img guest_img;
31 memset(&guest_img, 0, sizeof(struct v3_guest_img));
33 guest_img.size = img_size;
34 guest_img.guest_data = img_data;
35 strncpy(guest_img.name, vm_name, 127);
37 dev_idx = v3_dev_ioctl(V3_CREATE_GUEST, &guest_img);
40 printf("Error (%d) creating VM\n", dev_idx);
44 printf("VM (%s) created at /dev/v3-vm%d\n", vm_name, dev_idx);
49 int load_image(char * vm_name, char * filename) {
51 struct stat guest_stats;
53 void * img_data = NULL;
55 guest_fd = open(filename, O_RDONLY);
58 printf("Error Opening guest image: %s\n", filename);
62 if (fstat(guest_fd, &guest_stats) == -1) {
63 printf("ERROR: Could not stat guest image file -- %s\n", filename);
67 img_size = guest_stats.st_size;
69 // load guest image into user memory
70 img_data = malloc(img_size);
72 v3_read_file(guest_fd, img_size, img_data);
76 printf("Guest image Loaded (size=%u)\n", img_size);
77 return create_vm(vm_name, img_data, img_size);
82 ezxml_t open_xml_file(char * filename) {
84 ezxml_t xml_input = ezxml_parse_file(filename);
86 if (xml_input == NULL) {
87 printf("Error: Could not open XML input file (%s)\n", filename);
89 } else if (strcmp("", ezxml_error(xml_input)) != 0) {
90 printf("%s\n", ezxml_error(xml_input));
98 int find_xml_options(ezxml_t xml, struct xml_option ** opts) {
100 ezxml_t child = xml->child;
101 struct xml_option * next_opt = NULL;
103 char * opt = (char *)ezxml_attr(xml, "opt_tag");
106 next_opt = malloc(sizeof(struct xml_option));
108 memset(next_opt, 0, sizeof(struct xml_option));
111 next_opt->location = xml;
112 next_opt->next = NULL;
114 // printf("Option found: %s\n", opt);
125 if (next_opt != 0x0) {
126 num_opts += find_xml_options(child, &(next_opt->next));
128 num_opts += find_xml_options(child, opts);
136 while (next_opt->next) {
137 next_opt = next_opt->next;
141 child = child->ordered;
149 char * get_val(ezxml_t cfg, char * tag) {
150 char * attrib = (char *)ezxml_attr(cfg, tag);
151 ezxml_t txt = ezxml_child(cfg, tag);
153 if ((txt != NULL) && (attrib != NULL)) {
154 printf("Invalid Cfg file: Duplicate value for %s (attr=%s, txt=%s)\n",
155 tag, attrib, ezxml_txt(txt));
159 return (attrib == NULL) ? ezxml_txt(txt) : attrib;
163 int parse_aux_files(ezxml_t cfg_input) {
164 ezxml_t file_tags = NULL;
165 ezxml_t tmp_file_tag = NULL;
167 // files are transformed into blobs that are slapped to the end of the file
169 file_tags = ezxml_child(cfg_input, "files");
171 tmp_file_tag = ezxml_child(file_tags, "file");
173 while (tmp_file_tag) {
174 char * filename = get_val(tmp_file_tag, "filename");
175 struct stat file_stats;
176 char * id = get_val(tmp_file_tag, "id");
180 if (stat(filename, &file_stats) != 0) {
185 files[num_files].size = (unsigned int)file_stats.st_size;
186 strncpy(files[num_files].id, id, 256);
187 strncpy(files[num_files].filename, filename, 2048);
189 snprintf(index_buf, 256, "%llu", num_files);
190 ezxml_set_attr_d(tmp_file_tag, "index", index_buf);
193 tmp_file_tag = ezxml_next(tmp_file_tag);
200 int build_image(char * vm_name, char * filename, struct cfg_value * cfg_vals, int num_options) {
203 struct xml_option * xml_opts = NULL;
204 int num_xml_opts = 0;
205 void * guest_img_data = NULL;
206 int guest_img_size = 0;
209 xml = open_xml_file(filename);
212 num_xml_opts = find_xml_options(xml, &xml_opts);
214 // printf("%d options\n", num_xml_opts);
217 for (i = 0; i < num_options; i++) {
218 struct cfg_value * cfg_val = &cfg_vals[i];
219 struct xml_option * xml_opt = xml_opts;
222 if (strcasecmp(cfg_val->tag, xml_opt->tag) == 0) {
226 xml_opt = xml_opt->next;
231 printf("Could not find Config option (%s) in XML file\n", cfg_val->tag);
235 ezxml_set_txt(xml_opt->location, cfg_val->value);
241 parse_aux_files(xml);
243 // create image data blob
245 char * new_xml_str = ezxml_toxml(xml);
246 int file_data_size = 0;
249 unsigned long long file_offset = 0;
250 struct mem_file_hdr * hdrs = NULL;
257 8 bytes (number of files) +
258 num_files * (16+sizeof(unsigned long)) byte file header +
262 for (i = 0; i < num_files; i++) {
263 file_data_size += files[i].size;
266 guest_img_size = 8 + 4 + strlen(new_xml_str) + 8 + 8 +
267 (num_files * (16*sizeof(unsigned long))) + 8 + file_data_size;
270 guest_img_data = malloc(guest_img_size);
271 memset(guest_img_data, 0, guest_img_size);
274 // Dynamically built guests are version 1 by default now
276 memcpy(guest_img_data, "v3vee\0\0\1", 8);
279 *(unsigned int *)(guest_img_data + offset) = strlen(new_xml_str);
282 memcpy(guest_img_data + offset, new_xml_str, strlen(new_xml_str));
283 offset += strlen(new_xml_str);
285 memset(guest_img_data + offset, 0, 8);
288 *(unsigned long long *)(guest_img_data + offset) = num_files;
291 hdrs = guest_img_data + offset;
293 // The file offset starts at the end of the file list
294 file_offset = offset + ((sizeof(unsigned long) + 16) * num_files) + 8;
296 for (i = 0; i < num_files; i++) {
298 unsigned int *)(guest_img_data + offset) = i;
300 *(unsigned int *)(guest_img_data + offset) = files[i].size;
302 *(unsigned long long *)(guest_img_data + offset) = file_offset;
304 *(unsigned long *)(guest_img_data + offset) = 0;
305 offset += sizeof(unsigned long);
307 hdrs[i].file_idx = i;
308 hdrs[i].file_size = files[i].size;
309 hdrs[i].file_offset = file_offset;
310 hdrs[i].file_hash = 0;
312 offset += 16 + sizeof(unsigned long);
313 file_offset += files[i].size;
316 memset(guest_img_data + offset, 0, 8);
320 for (i = 0; i < num_files; i++) {
321 int fd = open(files[i].filename, O_RDONLY);
322 unsigned char * faddr = (unsigned char *)(guest_img_data + offset);
325 printf("Error: Could not open aux file (%s)\n", files[i].filename);
329 v3_read_file(fd, files[i].size, faddr);
331 /* store a hash of the file blob for integrity checking later */
332 hdrs[i].file_hash = v3_hash_buffer(faddr, files[i].size);
333 printf("File Hash: %llx\n", hdrs[i].file_hash);
337 offset += files[i].size;
345 printf("Guest Image Created (size=%u)\n", guest_img_size);
346 return create_vm(vm_name, guest_img_data, guest_img_size);
352 int main(int argc, char** argv) {
353 char * filename = NULL;
360 while (( c = getopt(argc, argv, "b")) != -1) {
368 if (argc - optind + 1 < 3)
369 v3_usage("[-b] <guest_img> <vm_name> [cfg options]\n");
371 filename = argv[optind];
372 name = argv[optind + 1];
375 if (build_flag == 1) {
376 int cfg_idx = optind + 2;
378 struct cfg_value * cfg_vals = NULL;
380 printf("Building VM Image (cfg=%s) (name=%s) (%d config options)\n", filename, name, argc - cfg_idx);
382 cfg_vals = malloc(sizeof(struct cfg_value) * argc - cfg_idx);
386 while (i < argc - cfg_idx) {
390 value = argv[cfg_idx + i];
392 tag = strsep(&value, "=");
396 printf("Invalid Option format: %s\n", argv[cfg_idx + i]);
400 cfg_vals[i].tag = tag;
401 cfg_vals[i].value = value;
403 printf("Config option: %s: %s\n", tag, value);
409 return build_image(name, filename, cfg_vals, argc - cfg_idx);
413 printf("Loading VM Image (img=%s) (name=%s)\n", filename, name);
414 return load_image(name, filename);