3 * $Id: bxcommit.c,v 1.13 2008/02/05 22:57:42 sshwarts Exp $
5 * Commits a redolog file in a flat file for bochs images.
31 /* XXX use real snprintf */
32 /* if they don't have snprintf, just use sprintf */
33 int snprintf (char *s
, size_t maxlen
, const char *format
, ...)
38 va_start (arg
, format
);
39 done
= vsprintf (s
, format
, arg
);
44 #endif /* !BX_HAVE_SNPRINTF */
48 #define HDIMAGE_HEADERS_ONLY 1
49 #include "../iodev/hdimage.h"
51 char *EOF_ERR
= "ERROR: End of input";
52 char *rcsid
= "$Id: bxcommit.c,v 1.13 2008/02/05 22:57:42 sshwarts Exp $";
53 char *divider
= "========================================================================";
55 void myexit (int code
)
58 printf ("\nPress any key to continue\n");
64 /* stolen from main.cc */
65 void bx_center_print (FILE *file
, char *line
, int maxwidth
)
69 imax
= (maxwidth
- strlen(line
)) >> 1;
70 for (i
=0; i
<imax
; i
++) fputc (' ', file
);
77 printf ("%s\n", divider
);
78 bx_center_print (stdout
, "bxcommit\n", 72);
79 bx_center_print (stdout
, "Undoable Disk Image Commit Tool for Bochs\n", 72);
80 bx_center_print (stdout
, rcsid
, 72);
81 printf ("\n%s\n", divider
);
84 /* this is how we crash */
91 /* remove leading spaces, newline junk at end. returns pointer to
92 cleaned string, which is between s0 and the null */
94 clean_string (char *s0
)
98 /* find first nonblank */
101 /* truncate string at first non-alphanumeric */
103 while (isprint (*ptr
))
109 /* returns 0 on success, -1 on failure. The value goes into out. */
111 ask_int (char *prompt
, int min
, int max
, int the_default
, int *out
)
118 printf ("%s", prompt
);
119 printf ("[%d] ", the_default
);
120 if (!fgets (buffer
, sizeof(buffer
), stdin
))
122 clean
= clean_string (buffer
);
123 if (strlen(clean
) < 1) {
124 // empty line, use the default
128 illegal
= (1 != sscanf (buffer
, "%d", &n
));
129 if (illegal
|| n
<min
|| n
>max
) {
130 printf ("Your choice (%s) was not an integer between %d and %d.\n\n",
141 ask_menu (char *prompt
, int n_choices
, char *choice
[], int the_default
, int *out
)
148 printf ("%s", prompt
);
149 printf ("[%s] ", choice
[the_default
]);
150 if (!fgets (buffer
, sizeof(buffer
), stdin
))
152 clean
= clean_string (buffer
);
153 if (strlen(clean
) < 1) {
154 // empty line, use the default
158 for (i
=0; i
<n_choices
; i
++) {
159 if (!strcmp (choice
[i
], clean
)) {
160 // matched, return the choice number
165 printf ("Your choice (%s) did not match any of the choices:\n", clean
);
166 for (i
=0; i
<n_choices
; i
++) {
167 if (i
>0) printf (", ");
168 printf ("%s", choice
[i
]);
175 ask_yn (char *prompt
, int the_default
, int *out
)
181 printf ("%s", prompt
);
182 printf ("[%s] ", the_default
?"yes":"no");
183 if (!fgets (buffer
, sizeof(buffer
), stdin
))
185 clean
= clean_string (buffer
);
186 if (strlen(clean
) < 1) {
187 // empty line, use the default
191 switch (tolower(clean
[0])) {
192 case 'y': *out
=1; return 0;
193 case 'n': *out
=0; return 0;
195 printf ("Please type either yes or no.\n");
200 ask_string (char *prompt
, char *the_default
, char *out
)
205 printf ("%s", prompt
);
206 printf ("[%s] ", the_default
);
207 if (!fgets (buffer
, sizeof(buffer
), stdin
))
209 clean
= clean_string (buffer
);
210 if (strlen(clean
) < 1) {
211 // empty line, use the default
212 strcpy (out
, the_default
);
219 /* produce the image file */
220 int commit_redolog (char *flatname
, char *redologname
)
222 int flatfd
, redologfd
;
223 redolog_header_t header
;
224 Bit32u
*catalog
, catalog_size
;
226 Bit32u i
, bitmap_blocs
, extent_blocs
;
229 // check if flat file exists
230 flatfd
= open (flatname
, O_WRONLY
236 fatal ("ERROR: flat file not found or not writable");
239 // Check if redolog exists
240 printf("%s\n",redologname
);
241 redologfd
= open (redologname
, O_RDONLY
247 fatal ("ERROR: redolog file not found");
250 printf ("\nReading redolog header: [");
252 if (read(redologfd
, &header
, STANDARD_HEADER_SIZE
) != STANDARD_HEADER_SIZE
)
253 fatal ("\nERROR: while reading redolog header!");
255 // Print infos on redlog
256 printf("Type='%s', Subtype='%s', Version=%d.%d] Done.",
257 header
.standard
.type
, header
.standard
.subtype
,
258 dtoh32(header
.standard
.version
)/0x10000,
259 dtoh32(header
.standard
.version
)%0x10000);
261 printf ("\nChecking redolog header: [");
263 if (strcmp((char *)header
.standard
.magic
, STANDARD_HEADER_MAGIC
) != 0)
264 fatal ("\nERROR: bad magic in redolog header!");
266 if (strcmp((char *)header
.standard
.type
, REDOLOG_TYPE
) != 0)
267 fatal ("\nERROR: bad type in redolog header!");
269 if (strcmp((char *)header
.standard
.subtype
, REDOLOG_SUBTYPE_UNDOABLE
) != 0)
270 fatal ("\nERROR: bad subtype in redolog header!");
272 if (header
.standard
.version
!= htod32(STANDARD_HEADER_VERSION
))
273 fatal ("\nERROR: bad version in redolog header!");
275 printf("#entries=%d, bitmap size=%d, exent size = %d] Done.",
276 dtoh32(header
.specific
.catalog
),
277 dtoh32(header
.specific
.bitmap
),
278 dtoh32(header
.specific
.extent
));
280 catalog
= (Bit32u
*)malloc(dtoh32(header
.specific
.catalog
) * sizeof(Bit32u
));
281 bitmap
= (Bit8u
*)malloc(dtoh32(header
.specific
.bitmap
));
282 printf ("\nReading Catalog: [");
284 lseek(redologfd
, dtoh32(header
.standard
.header
), SEEK_SET
);
286 catalog_size
= dtoh32(header
.specific
.catalog
) * sizeof(Bit32u
);
287 if ((Bit32u
) read(redologfd
, catalog
, catalog_size
) != catalog_size
)
288 fatal ("\nERROR: while reading redolog catalog!");
292 printf ("\nCommitting changes to flat file: [ 0%%]");
294 bitmap_blocs
= 1 + (dtoh32(header
.specific
.bitmap
) - 1) / 512;
295 extent_blocs
= 1 + (dtoh32(header
.specific
.extent
) - 1) / 512;
297 for(i
=0; i
<dtoh32(header
.specific
.catalog
); i
++)
299 printf("\x8\x8\x8\x8\x8%3d%%]", (i
+1)*100/dtoh32(header
.specific
.catalog
));
302 if (dtoh32(catalog
[i
]) != REDOLOG_PAGE_NOT_ALLOCATED
)
304 Bit64s bitmap_offset
;
305 Bit32u bitmap_size
, j
;
307 bitmap_offset
= (Bit64s
)STANDARD_HEADER_SIZE
+ (dtoh32(header
.specific
.catalog
) * sizeof(Bit32u
));
308 bitmap_offset
+= (Bit64s
)512 * dtoh32(catalog
[i
]) * (extent_blocs
+ bitmap_blocs
);
311 lseek(redologfd
, bitmap_offset
, SEEK_SET
);
313 bitmap_size
= dtoh32(header
.specific
.bitmap
);
314 if ((Bit32u
) read(redologfd
, bitmap
, bitmap_size
) != bitmap_size
)
315 fatal ("\nERROR: while reading bitmap from redolog !");
317 for(j
=0; j
<dtoh32(header
.specific
.bitmap
); j
++)
321 for(bit
=0; bit
<8; bit
++)
323 if ( (bitmap
[j
] & (1<<bit
)) != 0)
325 Bit64s flat_offset
, bloc_offset
;
327 bloc_offset
= bitmap_offset
+ ((Bit64s
)512 * (bitmap_blocs
+ ((j
*8)+bit
)));
329 lseek(redologfd
, (off_t
)bloc_offset
, SEEK_SET
);
331 if (read(redologfd
, buffer
, 512) != 512)
332 fatal ("\nERROR: while reading bloc from redolog !");
334 flat_offset
= (Bit64s
)i
* (dtoh32(header
.specific
.extent
));
335 flat_offset
+= (Bit64s
)512 * ((j
* 8) + bit
);
337 lseek(flatfd
, (off_t
)flat_offset
, SEEK_SET
);
339 if (write(flatfd
, buffer
, 512) != 512)
340 fatal ("\nERROR: while writing bloc in flatfile !");
358 char tmplogname
[256];
359 char redologname
[256];
366 if (ask_string("\nWhat is the flat image name?\n", "c.img", filename
) < 0)
369 snprintf(tmplogname
,256,"%s%s", filename
, UNDOABLE_REDOLOG_EXTENSION
);
371 if (ask_string("\nWhat is the redolog name?\n", tmplogname
, redologname
) < 0)
374 if (ask_yn("\nShall I remove the redolog afterwards?\n", 1, &remove
) < 0)
377 commit_redolog(filename
, redologname
);
380 if (unlink(redologname
) != 0)
381 fatal ("ERROR: while removing the redolog !\n");
384 // make picky compilers (c++, gcc) happy,
385 // even though we leave via 'myexit' just above