X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=utils%2Fguest_creator%2Fmain.c;h=c98637d84565dc9234d265bd7d09750c2287bdd9;hb=4b7f19c51325601d7e7569e6101c7bfcdf984ef7;hp=15b85ce755140ff0e17536291044927318c2700b;hpb=9800aba2ad371b0114b6fbd328f56598e92746ae;p=palacios.git diff --git a/utils/guest_creator/main.c b/utils/guest_creator/main.c index 15b85ce..c98637d 100644 --- a/utils/guest_creator/main.c +++ b/utils/guest_creator/main.c @@ -4,18 +4,42 @@ #include #include #include +#include #include #include #include +#include +#include +#include +#include #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 [-o outfile]\n"); + printf("Usage: build_vm [-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; }