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.


Avoid strict-aliasing related issues when compiling with optimization
[palacios.git] / utils / guest_creator / main.c
index 15b85ce..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,6 +85,11 @@ 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];
 
 
@@ -163,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);
@@ -171,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);
     
@@ -191,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;
     }
 
@@ -210,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;
 }