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.


HVM synchronous operation facility
[palacios.git] / utils / guest_creator / main.c
index 140bbb3..c98637d 100644 (file)
@@ -4,18 +4,42 @@
 #include <getopt.h>
 #include <unistd.h>
 #include <string.h>
+#include <fcntl.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <errno.h>
 
+#include <v3_ctrl.h>
 
 #define MAX_FILES 256
 
+/*
 struct file_info {
     int size;
     char filename[2048];
     char id[256];
 };
+*/
+
+/*
+
+   The Palacios cookie encodes "v3vee" followed by a 
+   3 byte version code.   There are currently two versions:
+
+    \0\0\0 => original (no checksum)
+    \0\0\1 => checksum
+*/
+
+#define COOKIE "v3vee\0\0\0"
+#define COOKIE_LEN            8
+#define COOKIE_VERSION_OFFSET 5
+#define COOKIE_VERSION_LEN    3
+
+int version = 1; // default version is now 1
+
 
 int num_files = 0;
 struct file_info files[MAX_FILES];
@@ -28,7 +52,7 @@ int write_output(char * filename, ezxml_t cfg_output);
 int copy_file(int file_index, FILE * data_file);
 
 void usage() {
-    printf("Usage: build_vm <infile> [-o outfile]\n");
+    printf("Usage: build_vm <infile> [-v version] [-o outfile]\n");
 }
 
 int main(int argc, char ** argv) {
@@ -36,16 +60,18 @@ int main(int argc, char ** argv) {
     char * outfile = NULL;
     char * infile = NULL;
 
-
     memset((char *)files, 0, sizeof(files));
 
     opterr = 0;
 
-    while ((c = getopt(argc, argv, "ho:")) != -1) {
+    while ((c = getopt(argc, argv, "ho:v:")) != -1) {
        switch (c) {
            case 'o':
                outfile = optarg;
                break;
+           case 'v':
+                version = atoi(optarg);
+                break;
            case 'h':
                usage();
                return 1;
@@ -59,12 +85,33 @@ int main(int argc, char ** argv) {
        return 1;
     }
 
+    if (version != 0 && version != 1) { 
+       printf("Only versions 0 and 1 are supported\n");
+       return 1;
+    }
+
     infile = argv[optind];
 
 
-    printf("Input file: %s\n", infile);
+    if (outfile == NULL) {
+       char * endptr = rindex(infile, '.');
+
+       outfile = malloc(strlen(infile) + strlen(".dat") + 1);
+
+       strncpy(outfile, infile, endptr - infile);
+
+       sprintf(outfile, "%s.dat", outfile);
+    }
+
+
+
+    printf("Input: [%s] ==>>  Output: [%s]\n", infile, outfile);
 
     ezxml_t cfg_input = ezxml_parse_file(infile);
+    if (strcmp("", ezxml_error(cfg_input)) != 0) {
+       printf("%s\n", ezxml_error(cfg_input));
+       return -1;
+    }
 
     if (cfg_input == NULL) {
        printf("Could not open configuration input file: %s\n", infile);
@@ -86,17 +133,6 @@ int main(int argc, char ** argv) {
 
     // write output
 
-    if (outfile == NULL) {
-       char * endptr = rindex(infile, '.');
-
-       outfile = malloc(strlen(infile) + strlen(".dat") + 1);
-
-       if (endptr) {
-           *endptr = '\0';
-       }
-
-       sprintf(outfile, "%s.dat", infile);
-    }
 
 
     write_output(outfile, cfg_input);
@@ -158,6 +194,77 @@ int parse_config_input(ezxml_t cfg_input) {
 }
 
 
+static int generate_file_hashes (char * filename,
+                                 unsigned long long hdr_offset,
+                                 int num_files) {
+    unsigned char * file_data;
+    unsigned char * out_data;
+    struct mem_file_hdr * hdrs = NULL;
+    int i, fd, out_fd;
+    struct stat st;
+
+    out_fd = open(filename, O_RDWR);
+    if (!out_fd) {
+        fprintf(stderr, "Couldn't open output file %s\n", filename);
+        return -1;
+    }
+    fstat(out_fd, &st);
+
+    /* mmap the out file, easy access to file headers */
+    if ((out_data = mmap(0,
+                         st.st_size,
+                         PROT_READ|PROT_WRITE,
+                         MAP_SHARED,
+                         out_fd,
+                         0)) == MAP_FAILED) {
+        fprintf(stderr, "Error mapping output file (%d)\n", errno);
+        return -1;
+    }
+
+    hdrs = (struct mem_file_hdr *)(out_data + hdr_offset);
+
+    /* mmap each file, then update it's hash */
+    for (i = 0; i < num_files; i++) {
+
+        fd = open(files[i].filename, O_RDONLY);
+        if (!fd) {
+            fprintf(stderr, "Error opening file %s\n",
+                    files[i].filename);
+            return -1;
+        }
+
+        if ((file_data = mmap(0, 
+                              hdrs[i].file_size, 
+                              PROT_READ,
+                              MAP_PRIVATE,
+                              fd,
+                              0)) == MAP_FAILED) {
+            fprintf(stderr, "Could not mmap file for hashing\n");
+            return -1;
+         }
+
+         /* generate the hash and save it */
+        hdrs[i].file_hash = v3_hash_buffer(file_data, hdrs[i].file_size);
+        printf("Generating hash for file %s (hash=0x%lx)\n", 
+                files[i].filename, hdrs[i].file_hash);
+
+        munmap(file_data, hdrs[i].file_size);
+        close(fd);
+    }
+
+    munmap(out_data, st.st_size);
+    return 0;
+}
+
+void gen_cookie(char *dest)
+{
+    memcpy(dest,COOKIE,COOKIE_LEN);
+    dest[COOKIE_VERSION_OFFSET]   = (((unsigned)version) >> 16) & 0xff;
+    dest[COOKIE_VERSION_OFFSET+1] = (((unsigned)version) >>  8) & 0xff;
+    dest[COOKIE_VERSION_OFFSET+2] = (((unsigned)version) >>  0) & 0xff;
+}
+
+
 int write_output(char * filename, ezxml_t cfg_output) {
     FILE * data_file = fopen(filename, "w+");
     char * new_cfg_str = ezxml_toxml(cfg_output);
@@ -166,9 +273,13 @@ int write_output(char * filename, ezxml_t cfg_output) {
     int i = 0;
     unsigned long long offset = 0;
     unsigned long long file_cnt = num_files;
+    unsigned long long hdr_offset = 0;
+    char cookie[COOKIE_LEN];
 
-    fwrite("v3vee\0\0\0", 8, 1, data_file);
-    offset += 8;
+    gen_cookie(cookie);
+
+    fwrite(cookie, COOKIE_LEN, 1, data_file);
+    offset += COOKIE_LEN;
 
     //  printf("New config: \n%s\n", new_cfg_str);
     
@@ -186,14 +297,30 @@ int write_output(char * filename, ezxml_t cfg_output) {
     fwrite(&file_cnt, 8, 1, data_file);
     offset += 8;
 
-    // each index entry is 16 bytes long plus end padding
-    offset += (16 * num_files) + 8;
 
+    if (version==0) { 
+       // for version 0, we simply have the file num, offset, size list
+       // each index entry is 16 bytes long plus end padding
+       offset += (16 * num_files) + 8;
+    } else if (version==1) { 
+       // For a version 1, we have the file num, offset, size, and hash list
+       // We need to remember where this begins in the file, though...
+       hdr_offset = offset;
+
+       // each index entry is (16+sizeof(unsigned long)) bytes long plus end padding
+       offset += ((16 + sizeof(unsigned long)) * num_files) + 8;
+    }
+    
     for (i = 0; i < num_files; i++) {
        fwrite(&i, 4, 1, data_file);
        fwrite(&(files[i].size), 4, 1, data_file);
        fwrite(&offset, 8, 1, data_file);
 
+       if (version==1) { 
+           /* we can't generate the hash yet, zero for now */
+           fwrite(&zero, sizeof(unsigned long), 1, data_file);
+       }
+
        offset += files[i].size;
     }
 
@@ -205,9 +332,18 @@ int write_output(char * filename, ezxml_t cfg_output) {
        
     }
     
+    fclose(data_file);
 
+    if (version==1) { 
+       // We now will go back and place the hashes
+       if (generate_file_hashes(filename,
+                                hdr_offset,
+                                num_files) < 0) {
+           fprintf(stderr, "Error generating file hashes\n");
+           return -1;
+       }
+    }
 
-    fclose(data_file);
 
     return 0;
 }
@@ -271,15 +407,15 @@ int copy_file(int file_index, FILE * data_file) {
            memset(cons_line, 0, 256);
            snprintf(cons_line, 256, "\r(%s) [", files[file_index].id);
            
-           for (i = 0; i < num_dots; i++) {
+           for (i = 0; i <= num_dots; i++) {
                strcat(cons_line, "=");
            }
            
-           for (i = 0; i < num_blanks; i++) {
+           for (i = 0; i < num_blanks - 1; i++) {
                strcat(cons_line, " ");
            }
            
-           strcat(cons_line, "]");
+           strcat(cons_line, "] ");
 
            //  printf("console width = %d\n", wsz.ws_col);
            write(STDIO_FD, cons_line, wsz.ws_col);