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.


8131df3376e679775d8a3b2c6b37b6f4ff1e5510
[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
251         /* Image size is: 
252            8 byte header + 
253            4 byte xml length + 
254            xml strlen + 
255            8 bytes of zeros + 
256            8 bytes (number of files) + 
257            num_files * 16 byte file header + 
258            8 bytes of zeroes + 
259            file data
260         */
261         for (i = 0; i < num_files; i++) {
262             file_data_size += files[i].size;
263         }
264
265         guest_img_size = 8 + 4 + strlen(new_xml_str) + 8 + 8 + 
266             (num_files * 16) + 8 + file_data_size;
267             
268
269         guest_img_data = malloc(guest_img_size);
270         memset(guest_img_data, 0, guest_img_size);
271
272         memcpy(guest_img_data, "v3vee\0\0\0", 8);
273         offset += 8;
274
275         *(unsigned int *)(guest_img_data + offset) = strlen(new_xml_str);
276         offset += 4;
277
278         memcpy(guest_img_data + offset, new_xml_str, strlen(new_xml_str));
279         offset += strlen(new_xml_str);
280
281         memset(guest_img_data + offset, 0, 8);
282         offset += 8;
283         
284         *(unsigned long long *)(guest_img_data + offset) = num_files;
285         offset += 8;
286
287         
288         // The file offset starts at the end of the file list
289         file_offset = offset + (16 * num_files) + 8;
290
291         for (i = 0; i < num_files; i++) {
292             *(unsigned int *)(guest_img_data + offset) = i;
293             offset += 4;
294             *(unsigned int *)(guest_img_data + offset) = files[i].size;
295             offset += 4;
296             *(unsigned long long *)(guest_img_data + offset) = file_offset;
297             offset += 8;
298
299             file_offset += files[i].size;
300
301         }
302
303         memset(guest_img_data + offset, 0, 8);
304         offset += 8;
305
306
307         for (i = 0; i < num_files; i++) {
308             int fd = open(files[i].filename, O_RDONLY);
309
310             if (fd == -1) {
311                 printf("Error: Could not open aux file (%s)\n", files[i].filename);
312                 return -1;
313             }
314
315             v3_read_file(fd, files[i].size, (unsigned char *)(guest_img_data + offset));
316
317             close(fd);
318
319             offset += files[i].size;
320
321         }
322         
323         free(new_xml_str);
324
325     }
326
327     printf("Guest Image Created (size=%u)\n", guest_img_size);
328     return create_vm(vm_name, guest_img_data, guest_img_size);
329 }
330
331
332
333
334 int main(int argc, char** argv) {
335     char * filename = NULL;
336     char * name = NULL;
337     int build_flag  = 0;
338     int c = 0;
339
340     opterr = 0;
341
342     while (( c = getopt(argc, argv, "b")) != -1) {
343         switch (c) {
344         case 'b':
345             build_flag = 1;
346             break;
347         }
348     }
349
350     if (argc - optind + 1 < 3) 
351         v3_usage("[-b] <guest_img> <vm_name> [cfg options]\n");
352
353     filename = argv[optind];
354     name = argv[optind + 1];
355
356
357     if (build_flag == 1) {
358         int cfg_idx = optind + 2;
359         int i = 0;
360         struct cfg_value * cfg_vals = NULL;
361         
362         printf("Building VM Image (cfg=%s) (name=%s) (%d config options)\n", filename, name, argc - cfg_idx);
363
364         cfg_vals = malloc(sizeof(struct cfg_value) * argc - cfg_idx);
365         
366         
367
368         while (i < argc - cfg_idx) {
369             char * tag = NULL;
370             char * value = NULL;
371
372             value = argv[cfg_idx + i];
373
374             tag = strsep(&value, "=");
375             // parse
376
377             if (value == NULL) {
378                 printf("Invalid Option format: %s\n", argv[cfg_idx + i]);
379                 return -1;
380             }
381
382             cfg_vals[i].tag = tag;
383             cfg_vals[i].value = value;
384
385             printf("Config option: %s: %s\n", tag, value);
386
387
388             i++;
389         }
390
391         return build_image(name, filename, cfg_vals, argc - cfg_idx);
392
393
394     } else {
395         printf("Loading VM Image (img=%s) (name=%s)\n", filename, name);
396         return load_image(name, filename);
397     }
398
399     return 0; 
400