/* * misc/bximage.c * $Id$ * * Commits a redolog file in a flat file for bochs images. * */ #include #include #include #ifndef _MSC_VER #include #else #include #endif #include #include #include #include #include #ifdef WIN32 # include #endif #include "config.h" #include #if !BX_HAVE_SNPRINTF #include /* XXX use real snprintf */ /* if they don't have snprintf, just use sprintf */ int snprintf(char *s, size_t maxlen, const char *format, ...) { va_list arg; int done; va_start(arg, format); done = vsprintf(s, format, arg); va_end(arg); return done; } #endif /* !BX_HAVE_SNPRINTF */ #include "../osdep.h" #include "bswap.h" #define HDIMAGE_HEADERS_ONLY 1 #include "../iodev/hdimage.h" #define BXCOMMIT_MODE_COMMIT_UNDOABLE 1 #define BXCOMMIT_MODE_GROWING_TO_FLAT 2 int bxcommit_mode; int bx_remove; int bx_interactive; char bx_flat_filename[256]; char bx_redolog_name[256]; char *EOF_ERR = "ERROR: End of input"; char *svnid = "$Id$"; char *divider = "========================================================================"; const char *main_menu_prompt = "\n" "1. Commit 'undoable' redolog to 'flat' file\n" "2. Create 'flat' disk image from 'growing' disk image\n" "\n" "0. Quit\n" "\n" "Please choose one "; void myexit(int code) { #ifdef WIN32 printf("\nPress any key to continue\n"); getch(); #endif exit(code); } /* stolen from main.cc */ void bx_center_print(FILE *file, char *line, int maxwidth) { int imax; int i; imax = (maxwidth - strlen(line)) >> 1; for (i=0; imax) { printf("Your choice (%s) was not an integer between %d and %d.\n\n", clean, min, max); } else { // choice is okay *out = n; return 0; } } } int ask_menu(const char *prompt, int n_choices, char *choice[], int the_default, int *out) { char buffer[1024]; char *clean; int i; *out = -1; while (1) { printf("%s", prompt); printf("[%s] ", choice[the_default]); if (!fgets(buffer, sizeof(buffer), stdin)) return -1; clean = clean_string(buffer); if (strlen(clean) < 1) { // empty line, use the default *out = the_default; return 0; } for (i=0; i0) printf(", "); printf("%s", choice[i]); } printf("\n"); } } int ask_yn(const char *prompt, int the_default, int *out) { char buffer[16]; char *clean; *out = -1; while (1) { printf("%s", prompt); printf("[%s] ", the_default?"yes":"no"); if (!fgets(buffer, sizeof(buffer), stdin)) return -1; clean = clean_string(buffer); if (strlen(clean) < 1) { // empty line, use the default *out = the_default; return 0; } switch (tolower(clean[0])) { case 'y': *out=1; return 0; case 'n': *out=0; return 0; } printf("Please type either yes or no.\n"); } } int ask_string(const char *prompt, char *the_default, char *out) { char buffer[1024]; char *clean; printf("%s", prompt); printf("[%s] ", the_default); if (!fgets(buffer, sizeof(buffer), stdin)) return -1; clean = clean_string(buffer); if (strlen(clean) < 1) { // empty line, use the default strcpy(out, the_default); return 0; } strcpy(out, clean); return 0; } /* produce the image file */ int commit_redolog() { int flatfd = -1, redologfd; redolog_header_t header; Bit32u *catalog, catalog_size; Bit8u *bitmap; Bit32u i, bitmap_blocks, extent_blocks; Bit8u buffer[512]; if (bxcommit_mode == BXCOMMIT_MODE_COMMIT_UNDOABLE) { // check if flat file exists flatfd = open(bx_flat_filename, O_WRONLY #ifdef O_BINARY | O_BINARY #endif ); if (flatfd < 0) { fatal("ERROR: flat file not found or not writable"); } } // Check if redolog exists printf("\nOpening '%s'\n", bx_redolog_name); redologfd = open(bx_redolog_name, O_RDONLY #ifdef O_BINARY | O_BINARY #endif ); if (redologfd < 0) { fatal("ERROR: redolog file not found"); } printf ("\nReading redolog header: ["); if (read(redologfd, &header, STANDARD_HEADER_SIZE) != STANDARD_HEADER_SIZE) fatal("\nERROR: while reading redolog header!"); // Print infos on redlog printf("Type='%s', Subtype='%s', Version=%d.%d] Done.", header.standard.type, header.standard.subtype, dtoh32(header.standard.version)/0x10000, dtoh32(header.standard.version)%0x10000); printf("\nChecking redolog header: ["); if (strcmp((char *)header.standard.magic, STANDARD_HEADER_MAGIC) != 0) fatal("\nERROR: bad magic in redolog header!"); if (strcmp((char *)header.standard.type, REDOLOG_TYPE) != 0) fatal("\nERROR: bad type in redolog header!"); if (bxcommit_mode == BXCOMMIT_MODE_COMMIT_UNDOABLE) { if (strcmp((char *)header.standard.subtype, REDOLOG_SUBTYPE_UNDOABLE) != 0) fatal("\nERROR: bad subtype in redolog header!"); } else if (bxcommit_mode == BXCOMMIT_MODE_GROWING_TO_FLAT) { if (strcmp((char *)header.standard.subtype, REDOLOG_SUBTYPE_GROWING) != 0) fatal("\nERROR: bad subtype in redolog header!"); } else { fatal("\nERROR: unknown bxcommit mode!"); } if (header.standard.version != htod32(STANDARD_HEADER_VERSION)) fatal("\nERROR: bad version in redolog header!"); printf("#entries=%d, bitmap size=%d, exent size = %d] Done.", dtoh32(header.specific.catalog), dtoh32(header.specific.bitmap), dtoh32(header.specific.extent)); if (bxcommit_mode == BXCOMMIT_MODE_GROWING_TO_FLAT) { flatfd = open(bx_flat_filename, O_RDONLY #ifdef O_BINARY | O_BINARY #endif ); if (flatfd >= 0) { close(flatfd); fatal("ERROR: flat file already exists"); } printf("\nCreating flat image file: ["); flatfd = open(bx_flat_filename, O_WRONLY | O_CREAT #ifdef O_BINARY | O_BINARY #endif , S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP ); if (flatfd < 0) { fatal("ERROR: flat file is not writable"); } lseek(flatfd, dtoh64(header.specific.disk) - 512, SEEK_SET); if (write(flatfd, buffer, 512) != 512) fatal("ERROR: while writing block in flat file !"); printf("...] Done."); } catalog = (Bit32u*)malloc(dtoh32(header.specific.catalog) * sizeof(Bit32u)); bitmap = (Bit8u*)malloc(dtoh32(header.specific.bitmap)); printf("\nReading Catalog: ["); lseek(redologfd, dtoh32(header.standard.header), SEEK_SET); catalog_size = dtoh32(header.specific.catalog) * sizeof(Bit32u); if ((Bit32u) read(redologfd, catalog, catalog_size) != catalog_size) fatal("\nERROR: while reading redolog catalog!"); printf("...] Done."); printf("\nCommitting changes to flat file: [ 0%%]"); bitmap_blocks = 1 + (dtoh32(header.specific.bitmap) - 1) / 512; extent_blocks = 1 + (dtoh32(header.specific.extent) - 1) / 512; for(i=0; i