Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Linux user updates for more recent distros (Ubuntu 14.04 as target)
[palacios.git] / linux_usr / v3_create.c
1 /* 
2  * V3 Control utility
3  * (c) Jack lange, 2010
4  */
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <fcntl.h> 
9 #include <sys/ioctl.h> 
10 #include <sys/stat.h> 
11 #include <sys/types.h> 
12 #include <unistd.h> 
13 #include <string.h>
14 #include <getopt.h> 
15
16
17 #include "v3_ctrl.h"
18 #include "ezxml.h"
19
20
21 #define MAX_FILES 256
22 unsigned long long num_files = 0;
23 struct file_info files[MAX_FILES];
24
25
26 int create_vm(char * vm_name, void * img_data, unsigned int img_size) {
27     struct v3_guest_img guest_img;
28     int v3_fd = 0;
29     int dev_idx = 0;
30
31     memset(&guest_img, 0, sizeof(struct v3_guest_img));
32
33     guest_img.size = img_size;
34     guest_img.guest_data = img_data;
35     strncpy(guest_img.name, vm_name, 127);
36
37     dev_idx = v3_dev_ioctl(V3_CREATE_GUEST, &guest_img); 
38
39     if (dev_idx < 0) {
40         printf("Error (%d) creating VM\n", dev_idx);
41         return -1;
42     }
43
44     printf("VM (%s) created at /dev/v3-vm%d\n", vm_name, dev_idx);
45     return 0;
46 }
47
48
49 int load_image(char * vm_name, char * filename) {
50     int guest_fd = 0;
51     struct stat guest_stats;
52     int img_size = 0;
53     void * img_data = NULL;
54
55     guest_fd = open(filename, O_RDONLY); 
56
57     if (guest_fd == -1) {
58         printf("Error Opening guest image: %s\n", filename);
59         return -1;
60     }
61
62     if (fstat(guest_fd, &guest_stats) == -1) {
63         printf("ERROR: Could not stat guest image file -- %s\n", filename);
64         return -1;
65     }
66     
67     img_size = guest_stats.st_size;
68
69     // load guest image into user memory
70     img_data = malloc(img_size);
71
72     v3_read_file(guest_fd, img_size, img_data);
73     
74     close(guest_fd);
75
76     printf("Guest image Loaded (size=%u)\n", img_size);
77     return create_vm(vm_name, img_data, img_size);
78
79 }
80
81
82 ezxml_t open_xml_file(char * filename) {
83
84     ezxml_t xml_input = ezxml_parse_file(filename);
85     
86     if (xml_input == NULL) {
87         printf("Error: Could not open XML input file (%s)\n", filename);
88         return NULL;
89     } else if (strcmp("", ezxml_error(xml_input)) != 0) {
90         printf("%s\n", ezxml_error(xml_input));
91         return NULL;
92     }
93
94     return xml_input;
95 }
96
97
98 int find_xml_options(ezxml_t xml,  struct xml_option ** opts) {
99     int num_opts = 0;
100     ezxml_t child = xml->child;
101     struct xml_option * next_opt = NULL;
102
103     char * opt = (char *)ezxml_attr(xml, "opt_tag");
104
105     if (opt) {
106         next_opt = malloc(sizeof(struct xml_option));
107
108         memset(next_opt, 0, sizeof(struct xml_option));
109
110         next_opt->tag = opt;
111         next_opt->location = xml;
112         next_opt->next = NULL;
113
114 //      printf("Option found: %s\n", opt);
115
116         *opts = next_opt;
117         num_opts++;
118     }
119
120
121     while (child) {
122
123         fflush(stdout);
124
125         if (next_opt != 0x0) {
126             num_opts += find_xml_options(child, &(next_opt->next));
127         } else {
128             num_opts += find_xml_options(child, opts);
129
130             if (*opts) {
131                 next_opt = *opts;
132             }
133         }
134
135         if (next_opt) {
136             while (next_opt->next) {
137                 next_opt = next_opt->next;
138             }
139         }
140
141         child = child->ordered;
142     }
143     
144     return num_opts;
145
146 }
147
148
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);
152
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));
156         exit(-1);
157     }
158
159     return (attrib == NULL) ? ezxml_txt(txt) : attrib;
160 }
161
162
163 int parse_aux_files(ezxml_t cfg_input) {
164     ezxml_t file_tags = NULL;
165     ezxml_t tmp_file_tag = NULL;
166
167     // files are transformed into blobs that are slapped to the end of the file
168         
169     file_tags = ezxml_child(cfg_input, "files");
170
171     tmp_file_tag = ezxml_child(file_tags, "file");
172
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");
177         char index_buf[256];
178
179
180         if (stat(filename, &file_stats) != 0) {
181             perror(filename);
182             exit(-1);
183         }
184
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);
188
189         snprintf(index_buf, 256, "%llu", num_files);
190         ezxml_set_attr_d(tmp_file_tag, "index", index_buf);
191
192         num_files++;
193         tmp_file_tag = ezxml_next(tmp_file_tag);
194     }
195
196
197     return 0;
198 }
199
200 int build_image(char * vm_name, char * filename, struct cfg_value * cfg_vals, int num_options) {
201     int i = 0;
202     ezxml_t xml = NULL;
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;
207
208
209     xml = open_xml_file(filename);
210     
211     // parse options
212     num_xml_opts = find_xml_options(xml, &xml_opts);
213     
214     //  printf("%d options\n", num_xml_opts);
215
216     // apply options
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;
220
221         while (xml_opt) {
222             if (strcasecmp(cfg_val->tag, xml_opt->tag) == 0) {
223                 break;
224             }
225             
226             xml_opt = xml_opt->next;
227         }
228
229
230         if (!xml_opt) {
231             printf("Could not find Config option (%s) in XML file\n", cfg_val->tag);
232             return -1;
233         }
234
235         ezxml_set_txt(xml_opt->location, cfg_val->value);
236     }
237     
238
239
240     // parse files
241     parse_aux_files(xml);
242     
243     // create image data blob
244     {
245         char * new_xml_str = ezxml_toxml(xml);
246         int file_data_size = 0;
247         int i = 0;
248         int offset = 0;
249         unsigned long long file_offset = 0;
250         struct mem_file_hdr * hdrs = NULL;
251
252         /* Image size is: 
253            8 byte header + 
254            4 byte xml length + 
255            xml strlen + 
256            8 bytes of zeros + 
257            8 bytes (number of files) + 
258            num_files * (16+sizeof(unsigned long)) byte file header + 
259            8 bytes of zeroes + 
260            file data
261         */
262         for (i = 0; i < num_files; i++) {
263             file_data_size += files[i].size;
264         }
265
266         guest_img_size = 8 + 4 + strlen(new_xml_str) + 8 + 8 + 
267             (num_files * (16*sizeof(unsigned long))) + 8 + file_data_size;
268             
269
270         guest_img_data = malloc(guest_img_size);
271         memset(guest_img_data, 0, guest_img_size);
272
273         //
274         // Dynamically built guests are version 1 by default now
275         //
276         memcpy(guest_img_data, "v3vee\0\0\1", 8);
277         offset += 8;
278
279         *(unsigned int *)(guest_img_data + offset) = strlen(new_xml_str);
280         offset += 4;
281
282         memcpy(guest_img_data + offset, new_xml_str, strlen(new_xml_str));
283         offset += strlen(new_xml_str);
284
285         memset(guest_img_data + offset, 0, 8);
286         offset += 8;
287         
288         *(unsigned long long *)(guest_img_data + offset) = num_files;
289         offset += 8;
290
291         hdrs = guest_img_data + offset;
292         
293         // The file offset starts at the end of the file list
294         file_offset = offset + ((sizeof(unsigned long) + 16) * num_files) + 8;
295
296         for (i = 0; i < num_files; i++) {
297             /*
298             unsigned int *)(guest_img_data + offset) = i;
299             offset += 4;
300             *(unsigned int *)(guest_img_data + offset) = files[i].size;
301             offset += 4;
302             *(unsigned long long *)(guest_img_data + offset) = file_offset;
303             offset += 8;
304             *(unsigned long *)(guest_img_data + offset) = 0;
305             offset += sizeof(unsigned long);
306             */
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;
311
312             offset +=  16 + sizeof(unsigned long);
313             file_offset += files[i].size;
314         }
315
316         memset(guest_img_data + offset, 0, 8);
317         offset += 8;
318
319
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);
323
324             if (fd == -1) {
325                 printf("Error: Could not open aux file (%s)\n", files[i].filename);
326                 return -1;
327             }
328
329             v3_read_file(fd, files[i].size, faddr);
330
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: %lx\n", hdrs[i].file_hash);
334
335             close(fd);
336
337             offset += files[i].size;
338
339         }
340         
341         free(new_xml_str);
342
343     }
344
345     printf("Guest Image Created (size=%u)\n", guest_img_size);
346     return create_vm(vm_name, guest_img_data, guest_img_size);
347 }
348
349
350
351
352 int main(int argc, char** argv) {
353     char * filename = NULL;
354     char * name = NULL;
355     int build_flag  = 0;
356     int c = 0;
357
358     opterr = 0;
359
360     while (( c = getopt(argc, argv, "b")) != -1) {
361         switch (c) {
362         case 'b':
363             build_flag = 1;
364             break;
365         }
366     }
367
368     if (argc - optind + 1 < 3) 
369         v3_usage("[-b] <guest_img> <vm_name> [cfg options]\n");
370
371     filename = argv[optind];
372     name = argv[optind + 1];
373
374
375     if (build_flag == 1) {
376         int cfg_idx = optind + 2;
377         int i = 0;
378         struct cfg_value * cfg_vals = NULL;
379         
380         printf("Building VM Image (cfg=%s) (name=%s) (%d config options)\n", filename, name, argc - cfg_idx);
381
382         cfg_vals = malloc(sizeof(struct cfg_value) * argc - cfg_idx);
383         
384         
385
386         while (i < argc - cfg_idx) {
387             char * tag = NULL;
388             char * value = NULL;
389
390             value = argv[cfg_idx + i];
391
392             tag = strsep(&value, "=");
393             // parse
394
395             if (value == NULL) {
396                 printf("Invalid Option format: %s\n", argv[cfg_idx + i]);
397                 return -1;
398             }
399
400             cfg_vals[i].tag = tag;
401             cfg_vals[i].value = value;
402
403             printf("Config option: %s: %s\n", tag, value);
404
405
406             i++;
407         }
408
409         return build_image(name, filename, cfg_vals, argc - cfg_idx);
410
411
412     } else {
413         printf("Loading VM Image (img=%s) (name=%s)\n", filename, name);
414         return load_image(name, filename);
415     }
416
417     return 0; 
418