1 /////////////////////////////////////////////////////////////////////////
2 // $Id: hdimage.cc 14229 2021-04-18 17:20:41Z vruppert $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 //  Copyright (C) 2002-2021  The Bochs Project
6 //
7 //  This library is free software; you can redistribute it and/or
8 //  modify it under the terms of the GNU Lesser General Public
9 //  License as published by the Free Software Foundation; either
10 //  version 2 of the License, or (at your option) any later version.
11 //
12 //  This library is distributed in the hope that it will be useful,
13 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 //  Lesser General Public License for more details.
16 //
17 //  You should have received a copy of the GNU Lesser General Public
18 //  License along with this library; if not, write to the Free Software
19 //  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
20 /////////////////////////////////////////////////////////////////////////
21 
22 #ifdef BXIMAGE
23 #include "config.h"
24 #include "misc/bxcompat.h"
25 #include "osdep.h"
26 #include "misc/bswap.h"
27 #else
28 #include "bochs.h"
29 #include "gui/siminterface.h"
30 #include "param_names.h"
31 #include "plugin.h"
32 #include "cdrom.h"
33 #include "cdrom_amigaos.h"
34 #include "cdrom_misc.h"
35 #include "cdrom_osx.h"
36 #include "cdrom_win32.h"
37 #endif
38 #include "hdimage.h"
39 
40 #if BX_HAVE_SYS_MMAN_H
41 #include <sys/mman.h>
42 #endif
43 #ifdef linux
44 #include <linux/fs.h>
45 #include <sys/ioctl.h>
46 #include <sys/wait.h>
47 #endif
48 
49 #ifndef O_ACCMODE
50 #define O_ACCMODE (O_WRONLY | O_RDWR)
51 #endif
52 
53 #define LOG_THIS bx_hdimage_ctl.
54 
55 #ifndef BXIMAGE
56 
57 bx_hdimage_ctl_c bx_hdimage_ctl;
58 
59 const Bit8u n_hdimage_builtin_modes = 7;
60 
61 const char *builtin_mode_names[n_hdimage_builtin_modes] = {
62   "flat",
63   "concat",
64   "sparse",
65   "dll",
66   "growing",
67   "undoable",
68   "volatile"
69 };
70 
71 const char **hdimage_mode_names;
72 
bx_hdimage_ctl_c()73 bx_hdimage_ctl_c::bx_hdimage_ctl_c()
74 {
75   put("hdimage", "IMG");
76 }
77 
init(void)78 void bx_hdimage_ctl_c::init(void)
79 {
80   Bit8u count = n_hdimage_builtin_modes;
81 
82   count += PLUG_get_plugins_count(PLUGTYPE_IMG);
83   hdimage_mode_names = (const char**) malloc((count + 1) * sizeof(char*));
84   for (Bit8u i = 0; i < n_hdimage_builtin_modes; i++) {
85     hdimage_mode_names[i] = builtin_mode_names[i];
86   }
87   Bit8u n = 0;
88   for (Bit8u i = n_hdimage_builtin_modes; i < count; i++) {
89     hdimage_mode_names[i] = PLUG_get_plugin_name(PLUGTYPE_IMG, n);
90     n++;
91   }
92   hdimage_mode_names[count] = NULL;
93 }
94 
get_mode_names(void)95 const char **bx_hdimage_ctl_c::get_mode_names(void)
96 {
97   return hdimage_mode_names;
98 }
99 
get_mode_id(const char * mode)100 int bx_hdimage_ctl_c::get_mode_id(const char *mode)
101 {
102   int i = 0;
103 
104   while (hdimage_mode_names[i] != NULL) {
105     if (!strcmp(mode, hdimage_mode_names[i])) return i;
106     i++;
107   }
108   return -1;
109 }
110 
list_modules(void)111 void bx_hdimage_ctl_c::list_modules(void)
112 {
113   char list[60];
114   Bit8u i = 0;
115   size_t len = 0, len1;
116 
117   BX_INFO(("Disk image modules"));
118   list[0] = 0;
119   while (hdimage_mode_names[i] != NULL) {
120     len1 = strlen(hdimage_mode_names[i]);
121     if ((len + len1 + 1) > 58) {
122       BX_INFO((" %s", list));
123       list[0] = 0;
124       len = 0;
125     }
126     strcat(list, " ");
127     strcat(list, hdimage_mode_names[i]);
128     len = strlen(list);
129     i++;
130   }
131   if (len > 0) {
132     BX_INFO((" %s", list));
133   }
134 }
135 
exit(void)136 void bx_hdimage_ctl_c::exit(void)
137 {
138   free(hdimage_mode_names);
139   hdimage_locator_c::cleanup();
140 }
141 
init_image(const char * image_mode,Bit64u disk_size,const char * journal)142 device_image_t* bx_hdimage_ctl_c::init_image(const char *image_mode, Bit64u disk_size, const char *journal)
143 {
144   device_image_t *hdimage = NULL;
145 
146   // instantiate the right class
147   if (!strcmp(image_mode, "flat")) {
148     hdimage = new flat_image_t();
149   } else if (!strcmp(image_mode, "concat")) {
150     hdimage = new concat_image_t();
151 #ifdef WIN32
152   } else if (!strcmp(image_mode, "dll")) {
153     hdimage = new dll_image_t();
154 #endif //DLL_HD_SUPPORT
155   } else if (!strcmp(image_mode, "sparse")) {
156     hdimage = new sparse_image_t();
157   } else if (!strcmp(image_mode, "undoable")) {
158     hdimage = new undoable_image_t(journal);
159   } else if (!strcmp(image_mode, "growing")) {
160     hdimage = new growing_image_t();
161   } else if (!strcmp(image_mode, "volatile")) {
162     hdimage = new volatile_image_t(journal);
163   } else {
164     if (!hdimage_locator_c::module_present(image_mode)) {
165 #if BX_PLUGINS
166       PLUG_load_plugin_var(image_mode, PLUGTYPE_IMG);
167 #else
168       BX_PANIC(("Disk image mode '%s' not available", image_mode));
169 #endif
170     }
171     hdimage = hdimage_locator_c::create(image_mode, disk_size, journal);
172   }
173   return hdimage;
174 }
175 
init_cdrom(const char * dev)176 cdrom_base_c* bx_hdimage_ctl_c::init_cdrom(const char *dev)
177 {
178 #if BX_SUPPORT_CDROM
179   return new LOWLEVEL_CDROM(dev);
180 #else
181   return new cdrom_base_c(dev);
182 #endif
183 }
184 
185 #endif // ifndef BXIMAGE
186 
187 hdimage_locator_c *hdimage_locator_c::all = NULL;
188 
189 //
190 // Each disk image module has a static locator class that registers
191 // here
192 //
hdimage_locator_c(const char * mode)193 hdimage_locator_c::hdimage_locator_c(const char *mode)
194 {
195   hdimage_locator_c *ptr;
196 
197   this->mode = mode;
198   this->next = NULL;
199   if (all == NULL) {
200     all = this;
201   } else {
202     ptr = all;
203     while (ptr->next) ptr = ptr->next;
204     ptr->next = this;
205   }
206 }
207 
~hdimage_locator_c()208 hdimage_locator_c::~hdimage_locator_c()
209 {
210   hdimage_locator_c *ptr = 0;
211 
212   if (this == all) {
213     all = all->next;
214   } else {
215     ptr = all;
216     while (ptr != NULL) {
217       if (ptr->next != this) {
218         ptr = ptr->next;
219       } else {
220         break;
221       }
222     }
223   }
224   if (ptr) {
225     ptr->next = this->next;
226   }
227 }
228 
module_present(const char * mode)229 bool hdimage_locator_c::module_present(const char *mode)
230 {
231   hdimage_locator_c *ptr;
232 
233   for (ptr = all; ptr != NULL; ptr = ptr->next) {
234     if (strcmp(mode, ptr->mode) == 0)
235       return 1;
236   }
237   return 0;
238 }
239 
cleanup()240 void hdimage_locator_c::cleanup()
241 {
242 #if BX_PLUGINS && !defined(BXIMAGE)
243   while (all != NULL) {
244     PLUG_unload_plugin_type(all->mode, PLUGTYPE_IMG);
245   }
246 #endif
247 }
248 
249 //
250 // Called by common hdimage code to locate and create a device_image_t
251 // object
252 //
253 device_image_t*
create(const char * mode,Bit64u disk_size,const char * journal)254 hdimage_locator_c::create(const char *mode, Bit64u disk_size, const char *journal)
255 {
256   hdimage_locator_c *ptr = 0;
257 
258   for (ptr = all; ptr != NULL; ptr = ptr->next) {
259     if (strcmp(mode, ptr->mode) == 0)
260       return (ptr->allocate(disk_size, journal));
261   }
262   return NULL;
263 }
264 
detect_image_mode(int fd,Bit64u disk_size,const char ** image_mode)265 bool hdimage_locator_c::detect_image_mode(int fd, Bit64u disk_size,
266                                           const char **image_mode)
267 {
268   hdimage_locator_c *ptr = 0;
269 
270   for (ptr = all; ptr != NULL; ptr = ptr->next) {
271     if (ptr->check_format(fd, disk_size) == HDIMAGE_FORMAT_OK) {
272       *image_mode = ptr->mode;
273       return 1;
274     }
275   }
276   return 0;
277 }
278 
279 // helper functions
280 
281 #ifdef BXIMAGE
bx_create_image_file(const char * filename)282 int bx_create_image_file(const char *filename)
283 {
284   int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC
285 #ifdef O_BINARY
286                 | O_BINARY
287 #endif
288                 , S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP
289                 );
290   return fd;
291 }
292 #endif
293 
bx_read_image(int fd,Bit64s offset,void * buf,int count)294 int bx_read_image(int fd, Bit64s offset, void *buf, int count)
295 {
296   if (lseek(fd, offset, SEEK_SET) == -1) {
297     return -1;
298   }
299   return read(fd, buf, count);
300 }
301 
bx_write_image(int fd,Bit64s offset,void * buf,int count)302 int bx_write_image(int fd, Bit64s offset, void *buf, int count)
303 {
304   if (lseek(fd, offset, SEEK_SET) == -1) {
305     return -1;
306   }
307   return write(fd, buf, count);
308 }
309 
bx_close_image(int fd,const char * pathname)310 int bx_close_image(int fd, const char *pathname)
311 {
312 #ifndef BXIMAGE
313   char lockfn[BX_PATHNAME_LEN];
314 
315   sprintf(lockfn, "%s.lock", pathname);
316   if (access(lockfn, F_OK) == 0) {
317     unlink(lockfn);
318   }
319 #endif
320   return ::close(fd);
321 }
322 
323 #ifndef WIN32
hdimage_open_file(const char * pathname,int flags,Bit64u * fsize,time_t * mtime)324 int hdimage_open_file(const char *pathname, int flags, Bit64u *fsize, time_t *mtime)
325 #else
326 int hdimage_open_file(const char *pathname, int flags, Bit64u *fsize, FILETIME *mtime)
327 #endif
328 {
329 #ifndef BXIMAGE
330   char lockfn[BX_PATHNAME_LEN];
331   int lockfd;
332 #endif
333 
334 #ifdef WIN32
335   if (fsize != NULL) {
336     HANDLE hFile = CreateFile(pathname, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL);
337     if (hFile != INVALID_HANDLE_VALUE) {
338       ULARGE_INTEGER FileSize;
339       FileSize.LowPart = GetFileSize(hFile, &FileSize.HighPart);
340       if (mtime != NULL) {
341         GetFileTime(hFile, NULL, NULL, mtime);
342       }
343       CloseHandle(hFile);
344       if ((FileSize.LowPart != INVALID_FILE_SIZE) || (GetLastError() == NO_ERROR)) {
345         *fsize = FileSize.QuadPart;
346       } else {
347         return -1;
348       }
349     } else {
350       return -1;
351     }
352   }
353 #endif
354 
355 #ifndef BXIMAGE
356   sprintf(lockfn, "%s.lock", pathname);
357   lockfd = ::open(lockfn, O_RDONLY);
358   if (lockfd >= 0) {
359     ::close(lockfd);
360     if (SIM->get_param_bool(BXPN_UNLOCK_IMAGES)->get()) {
361       // Remove lock file if requested
362       if (access(lockfn, F_OK) == 0) {
363         unlink(lockfn);
364       }
365     } else {
366       // Opening image must fail if lock file exists.
367       BX_ERROR(("image locked: '%s'", pathname));
368       return -1;
369     }
370   }
371 #endif
372 
373   int fd = ::open(pathname, flags
374 #ifdef O_BINARY
375               | O_BINARY
376 #endif
377               );
378 
379   if (fd < 0) {
380     return fd;
381   }
382 
383 #ifndef WIN32
384   if (fsize != NULL) {
385     struct stat stat_buf;
386     if (fstat(fd, &stat_buf)) {
387       BX_PANIC(("fstat() returns error!"));
388       return -1;
389     }
390 #ifdef linux
391     if (S_ISBLK(stat_buf.st_mode)) { // Is this a special device file (e.g. /dev/sde) ?
392       ioctl(fd, BLKGETSIZE64, fsize); // yes it's!
393     }
394     else
395 #endif
396     {
397       *fsize = (Bit64u)stat_buf.st_size; // standard unix procedure to get size of regular files
398     }
399     if (mtime != NULL) {
400       *mtime = stat_buf.st_mtime;
401     }
402   }
403 #endif
404 #ifndef BXIMAGE
405   if ((flags & O_ACCMODE) != O_RDONLY) {
406     lockfd = ::open(lockfn, O_CREAT | O_RDWR
407 #ifdef O_BINARY
408                 | O_BINARY
409 #endif
410                 , S_IWUSR | S_IRUSR | S_IRGRP | S_IWGRP);
411     if (lockfd >= 0) {
412       // lock this image
413       ::close(lockfd);
414     }
415   }
416 #endif
417   return fd;
418 }
419 
hdimage_detect_image_mode(const char * pathname,const char ** image_mode)420 bool hdimage_detect_image_mode(const char *pathname, const char **image_mode)
421 {
422   bool result = false;
423   Bit64u image_size = 0;
424 
425 #if BX_PLUGINS && !defined(BXIMAGE)
426   PLUG_load_plugin_var("*", PLUGTYPE_IMG);
427 #endif
428   int fd = hdimage_open_file(pathname, O_RDONLY, &image_size, NULL);
429   if (fd < 0) {
430     return result;
431   }
432 
433   if (sparse_image_t::check_format(fd, image_size) == HDIMAGE_FORMAT_OK) {
434     *image_mode = "sparse";
435     result = true;
436   } else if (growing_image_t::check_format(fd, image_size) == HDIMAGE_FORMAT_OK) {
437     *image_mode = "growing";
438     result = true;
439   } else if (hdimage_locator_c::detect_image_mode(fd, image_size, image_mode)) {
440     result = true;
441   } else if (flat_image_t::check_format(fd, image_size) == HDIMAGE_FORMAT_OK) {
442     *image_mode = "flat";
443     result = true;
444   }
445   ::close(fd);
446 
447   return result;
448 }
449 
450 // if return_time==0, this returns the fat_date, else the fat_time
451 #ifndef WIN32
fat_datetime(time_t time,int return_time)452 Bit16u fat_datetime(time_t time, int return_time)
453 {
454   struct tm* t;
455   struct tm t1;
456 
457   t = &t1;
458   localtime_r(&time, t);
459   if (return_time)
460     return htod16((t->tm_sec/2) | (t->tm_min<<5) | (t->tm_hour<<11));
461   return htod16((t->tm_mday) | ((t->tm_mon+1)<<5) | ((t->tm_year-80)<<9));
462 }
463 #else
fat_datetime(FILETIME time,int return_time)464 Bit16u fat_datetime(FILETIME time, int return_time)
465 {
466   SYSTEMTIME gmtsystime, systime;
467   TIME_ZONE_INFORMATION tzi;
468 
469   FileTimeToSystemTime(&time, &gmtsystime);
470   GetTimeZoneInformation(&tzi);
471   SystemTimeToTzSpecificLocalTime(&tzi, &gmtsystime, &systime);
472   if (return_time)
473     return htod16((systime.wSecond/2) | (systime.wMinute<<5) | (systime.wHour<<11));
474   return htod16((systime.wDay) | (systime.wMonth<<5) | ((systime.wYear-1980)<<9));
475 }
476 #endif
477 
478 #ifndef BXIMAGE
479 // generic save/restore functions
hdimage_save_handler(void * class_ptr,bx_param_c * param)480 Bit64s hdimage_save_handler(void *class_ptr, bx_param_c *param)
481 {
482   char imgname[BX_PATHNAME_LEN];
483   char path[BX_PATHNAME_LEN+1];
484 
485   param->get_param_path(imgname, BX_PATHNAME_LEN);
486   if (!strncmp(imgname, "bochs.", 6)) {
487     strcpy(imgname, imgname+6);
488   }
489   if (SIM->get_param_string(BXPN_RESTORE_PATH)->isempty()) {
490     return 0;
491   }
492   sprintf(path, "%s/%s", SIM->get_param_string(BXPN_RESTORE_PATH)->getptr(), imgname);
493   return ((device_image_t*)class_ptr)->save_state(path);
494 }
495 
hdimage_restore_handler(void * class_ptr,bx_param_c * param,Bit64s value)496 void hdimage_restore_handler(void *class_ptr, bx_param_c *param, Bit64s value)
497 {
498   char imgname[BX_PATHNAME_LEN];
499   char path[BX_PATHNAME_LEN+1];
500 
501   if (value != 0) {
502     param->get_param_path(imgname, BX_PATHNAME_LEN);
503     if (!strncmp(imgname, "bochs.", 6)) {
504       strcpy(imgname, imgname+6);
505     }
506     sprintf(path, "%s/%s", SIM->get_param_string(BXPN_RESTORE_PATH)->getptr(), imgname);
507     ((device_image_t*)class_ptr)->restore_state(path);
508   }
509 }
510 
hdimage_backup_file(int fd,const char * backup_fname)511 bool hdimage_backup_file(int fd, const char *backup_fname)
512 {
513   char *buf;
514   off_t offset;
515   int nread, size;
516   bool ret = 1;
517 
518   int backup_fd = ::open(backup_fname, O_RDWR | O_CREAT | O_TRUNC
519 #ifdef O_BINARY
520     | O_BINARY
521 #endif
522     , S_IWUSR | S_IRUSR | S_IRGRP | S_IWGRP);
523   if (backup_fd >= 0) {
524     offset = 0;
525     size = 0x20000;
526     buf = new char[size];
527     if (buf == NULL) {
528       ::close(backup_fd);
529       return 0;
530     }
531     while ((nread = bx_read_image(fd, offset, buf, size)) > 0) {
532       if (bx_write_image(backup_fd, offset, buf, nread) < 0) {
533         ret = 0;
534         break;
535       }
536       if (nread < size) {
537         break;
538       }
539       offset += size;
540     };
541     if (nread < 0) {
542       ret = 0;
543     }
544     delete [] buf;
545     ::close(backup_fd);
546     return ret;
547   }
548   return 0;
549 }
550 #endif
551 
hdimage_copy_file(const char * src,const char * dst)552 bool hdimage_copy_file(const char *src, const char *dst)
553 {
554 #ifdef WIN32
555   return (bool)CopyFile(src, dst, FALSE);
556 #elif defined(linux)
557   pid_t pid, ws;
558 
559   if ((src == NULL) || (dst == NULL)) {
560     return 0;
561   }
562 
563   if (!(pid = fork())) {
564     execl("/bin/cp", "/bin/cp", src, dst, (char *)0);
565     return 0;
566   }
567   wait(&ws);
568   if (!WIFEXITED(ws)) {
569     return -1;
570   }
571   return (WEXITSTATUS(ws) == 0);
572 #else
573   int fd1, fd2;
574   char *buf;
575   off_t offset;
576   int nread, size;
577   bool ret = 1;
578 
579   fd1 = ::open(src, O_RDONLY
580 #ifdef O_BINARY
581     | O_BINARY
582 #endif
583     );
584   if (fd1 < 0) return 0;
585   fd2 = ::open(dst, O_RDWR | O_CREAT | O_TRUNC
586 #ifdef O_BINARY
587     | O_BINARY
588 #endif
589     , S_IWUSR | S_IRUSR | S_IRGRP | S_IWGRP);
590   if (fd2 < 0) {
591     ::close(fd1);
592     return 0;
593   }
594   offset = 0;
595   size = 0x20000;
596   buf = new char[size];
597   if (buf == NULL) {
598     ::close(fd1);
599     ::close(fd2);
600     return 0;
601   }
602   while ((nread = bx_read_image(fd1, offset, buf, size)) > 0) {
603     if (bx_write_image(fd2, offset, buf, nread) < 0) {
604       ret = 0;
605       break;
606     }
607     if (nread < size) {
608       break;
609     }
610     offset += size;
611   };
612   if (nread < 0) {
613     ret = 0;
614   }
615   delete [] buf;
616   ::close(fd1);
617   ::close(fd2);
618   return ret;
619 #endif
620 }
621 
622 /*** base class device_image_t ***/
623 
device_image_t()624 device_image_t::device_image_t()
625 {
626   cylinders = 0;
627   hd_size = 0;
628   sect_size = 512;
629 }
630 
open(const char * _pathname)631 int device_image_t::open(const char* _pathname)
632 {
633   return open(_pathname, O_RDWR);
634 }
635 
get_capabilities()636 Bit32u device_image_t::get_capabilities()
637 {
638   return (cylinders == 0) ? HDIMAGE_AUTO_GEOMETRY : 0;
639 }
640 
get_timestamp()641 Bit32u device_image_t::get_timestamp()
642 {
643   return (fat_datetime(mtime, 1) | (fat_datetime(mtime, 0) << 16));
644 }
645 
646 #ifndef BXIMAGE
register_state(bx_list_c * parent)647 void device_image_t::register_state(bx_list_c *parent)
648 {
649   bx_param_bool_c *image = new bx_param_bool_c(parent, "image", NULL, NULL, 0);
650   image->set_sr_handlers(this, hdimage_save_handler, hdimage_restore_handler);
651 }
652 #endif
653 
654 /*** flat_image_t function definitions ***/
655 
open(const char * _pathname,int flags)656 int flat_image_t::open(const char* _pathname, int flags)
657 {
658   pathname = _pathname;
659   if ((fd = hdimage_open_file(pathname, flags, &hd_size, &mtime)) < 0) {
660     return -1;
661   }
662   BX_INFO(("hd_size: " FMT_LL "u", hd_size));
663   if (hd_size <= 0) BX_PANIC(("size of disk image not detected / invalid"));
664   if ((hd_size % sect_size) != 0) {
665     BX_PANIC(("size of disk image must be multiple of %d bytes", sect_size));
666   }
667   return fd;
668 }
669 
close()670 void flat_image_t::close()
671 {
672   if (fd > -1) {
673     bx_close_image(fd, pathname);
674   }
675 }
676 
lseek(Bit64s offset,int whence)677 Bit64s flat_image_t::lseek(Bit64s offset, int whence)
678 {
679   return (Bit64s)::lseek(fd, (off_t)offset, whence);
680 }
681 
read(void * buf,size_t count)682 ssize_t flat_image_t::read(void* buf, size_t count)
683 {
684   return ::read(fd, (char*) buf, count);
685 }
686 
write(const void * buf,size_t count)687 ssize_t flat_image_t::write(const void* buf, size_t count)
688 {
689   return ::write(fd, (char*) buf, count);
690 }
691 
check_format(int fd,Bit64u imgsize)692 int flat_image_t::check_format(int fd, Bit64u imgsize)
693 {
694   char buffer[512];
695 
696   if ((imgsize <= 0) || ((imgsize % 512) != 0)) {
697     return HDIMAGE_SIZE_ERROR;
698   } else if (bx_read_image(fd, 0, buffer, 512) < 0) {
699     return HDIMAGE_READ_ERROR;
700   } else {
701     return HDIMAGE_FORMAT_OK;
702   }
703 }
704 
705 #ifndef BXIMAGE
save_state(const char * backup_fname)706 bool flat_image_t::save_state(const char *backup_fname)
707 {
708   return hdimage_backup_file(fd, backup_fname);
709 }
710 
restore_state(const char * backup_fname)711 void flat_image_t::restore_state(const char *backup_fname)
712 {
713   close();
714   if (!hdimage_copy_file(backup_fname, pathname)) {
715     BX_PANIC(("Failed to restore image '%s'", pathname));
716     return;
717   }
718   if (device_image_t::open(pathname) < 0) {
719     BX_PANIC(("Failed to open restored image '%s'", pathname));
720   }
721 }
722 #endif
723 
724 // helper function for concat and sparse mode images
725 
increment_string(char * str,int diff)726 char increment_string(char *str, int diff)
727 {
728   // find the last character of the string, and increment it.
729   char *p = str;
730   while (*p != 0) p++;
731   BX_ASSERT(p>str);  // choke on zero length strings
732   p--;  // point to last character of the string
733   (*p) += diff;  // increment to next/previous ascii code.
734   BX_DEBUG(("increment string returning '%s'", str));
735   return (*p);
736 }
737 
738 /*** concat_image_t function definitions ***/
739 
concat_image_t()740 concat_image_t::concat_image_t()
741 {
742   curr_fd = -1;
743 }
744 
increment_string(char * str)745 void concat_image_t::increment_string(char *str)
746 {
747   ::increment_string(str, +1);
748 }
749 
open(const char * _pathname0,int flags)750 int concat_image_t::open(const char* _pathname0, int flags)
751 {
752   UNUSED(flags);
753   pathname0 = _pathname0;
754   char *pathname1 = new char[strlen(pathname0) + 1];
755   strcpy(pathname1, pathname0);
756   BX_DEBUG(("concat_image_t::open"));
757   Bit64s start_offset = 0;
758   for (int i=0; i<BX_CONCAT_MAX_IMAGES; i++) {
759     fd_table[i] = hdimage_open_file(pathname1, flags, &length_table[i], NULL);
760     if (fd_table[i] < 0) {
761       // open failed.
762       // if no FD was opened successfully, return -1 (fail).
763       if (i==0) return -1;
764       // otherwise, it only means that all images in the series have
765       // been opened.  Record the number of fds opened successfully.
766       maxfd = i;
767       break;
768     }
769     BX_INFO(("concat_image: open image #%d: '%s', (" FMT_LL "u bytes)", i, pathname1, length_table[i]));
770     struct stat stat_buf;
771     int ret = fstat(fd_table[i], &stat_buf);
772     if (ret) {
773       BX_PANIC(("fstat() returns error!"));
774     }
775 #ifdef S_ISBLK
776     if (S_ISBLK(stat_buf.st_mode)) {
777       BX_PANIC(("block devices should REALLY NOT be used as concat images"));
778     }
779 #endif
780     if ((stat_buf.st_size % sect_size) != 0) {
781       BX_PANIC(("size of disk image must be multiple of %d bytes", sect_size));
782     }
783     start_offset_table[i] = start_offset;
784     start_offset += length_table[i];
785     increment_string(pathname1);
786   }
787   delete [] pathname1;
788   // start up with first image selected
789   total_offset = 0;
790   index = 0;
791   curr_fd = fd_table[0];
792   curr_min = 0;
793   curr_max = length_table[0]-1;
794   hd_size = start_offset;
795   BX_INFO(("hd_size: " FMT_LL "u", hd_size));
796   return 0; // success.
797 }
798 
close()799 void concat_image_t::close()
800 {
801   BX_DEBUG(("concat_image_t.close"));
802   char *pathname1 = new char[strlen(pathname0) + 1];
803   strcpy(pathname1, pathname0);
804   for (int index = 0; index < maxfd; index++) {
805     if (fd_table[index] > -1) {
806       bx_close_image(fd_table[index], pathname1);
807     }
808     increment_string(pathname1);
809   }
810   delete [] pathname1;
811 }
812 
lseek(Bit64s offset,int whence)813 Bit64s concat_image_t::lseek(Bit64s offset, int whence)
814 {
815   if ((offset % sect_size) != 0)
816     BX_PANIC(("lseek HD with offset not multiple of %d", sect_size));
817   BX_DEBUG(("concat_image_t.lseek(%d)", whence));
818   switch (whence) {
819     case SEEK_SET:
820       total_offset = offset;
821       break;
822     case SEEK_CUR:
823       total_offset += offset;
824       break;
825     case SEEK_END:
826       total_offset = hd_size - offset;
827       break;
828     default:
829       return -1;
830   }
831   // is this offset in this disk image?
832   if (total_offset < curr_min) {
833     // no, look at previous images
834     for (int i=index-1; i>=0; i--) {
835       if (total_offset >= start_offset_table[i]) {
836         index = i;
837         curr_fd = fd_table[i];
838         curr_min = start_offset_table[i];
839         curr_max = curr_min + length_table[i] - 1;
840         BX_DEBUG(("concat_image_t.lseek to earlier image, index=%d", index));
841         break;
842       }
843     }
844   } else if (total_offset > curr_max) {
845     // no, look at later images
846     for (int i=index+1; i<maxfd; i++) {
847       if (total_offset < (start_offset_table[i] + length_table[i])) {
848         index = i;
849         curr_fd = fd_table[i];
850         curr_min = start_offset_table[i];
851         curr_max = curr_min + length_table[i] - 1;
852         BX_DEBUG(("concat_image_t.lseek to earlier image, index=%d", index));
853         break;
854       }
855     }
856   }
857   // now offset should be within the current image.
858   offset = total_offset - start_offset_table[index];
859   if ((offset < 0) || (offset >= (Bit64s)length_table[index])) {
860     BX_PANIC(("concat_image_t.lseek to byte %ld failed", (long)offset));
861     return -1;
862   }
863   return (Bit64s)::lseek(curr_fd, (off_t)offset, SEEK_SET);
864 }
865 
read(void * buf,size_t count)866 ssize_t concat_image_t::read(void* buf, size_t count)
867 {
868   size_t readmax, count1 = count;
869   ssize_t ret = -1;
870   char *buf1 = (char*)buf;
871 
872   BX_DEBUG(("concat_image_t.read %ld bytes", (long)count));
873   do {
874     readmax = (size_t)(curr_max - total_offset + 1);
875     if (count1 > readmax) {
876       ret = ::read(curr_fd, buf1, readmax);
877       if (ret >= 0) {
878         buf1 += readmax;
879         count1 -= readmax;
880         ret = lseek(curr_max + 1, SEEK_SET);
881       }
882     } else {
883       ret = ::read(curr_fd, buf1, count1);
884       if (ret >= 0) {
885         ret = lseek(count1, SEEK_CUR);
886       }
887       break;
888     }
889   } while (ret > 0);
890   return (ret < 0) ? ret : count;
891 }
892 
write(const void * buf,size_t count)893 ssize_t concat_image_t::write(const void* buf, size_t count)
894 {
895   size_t writemax, count1 = count;
896   ssize_t ret = -1;
897   char *buf1 = (char*)buf;
898 
899   BX_DEBUG(("concat_image_t.write %ld bytes", (long)count));
900   do {
901     writemax = (size_t)(curr_max - total_offset + 1);
902     if (count1 > writemax) {
903       ret = ::write(curr_fd, buf1, writemax);
904       if (ret >= 0) {
905         buf1 += writemax;
906         count1 -= writemax;
907         ret = lseek(curr_max + 1, SEEK_SET);
908       }
909     } else {
910       ret = ::write(curr_fd, buf1, count1);
911       if (ret >= 0) {
912         ret = lseek(count1, SEEK_CUR);
913       }
914       break;
915     }
916   } while (ret > 0);
917   return (ret < 0) ? ret : count;
918 }
919 
920 #ifndef BXIMAGE
save_state(const char * backup_fname)921 bool concat_image_t::save_state(const char *backup_fname)
922 {
923   bool ret = 1;
924   char tempfn[BX_PATHNAME_LEN];
925 
926   for (int index = 0; index < maxfd; index++) {
927     sprintf(tempfn, "%s%d", backup_fname, index);
928     ret &= hdimage_backup_file(fd_table[index], tempfn);
929     if (ret == 0) break;
930   }
931   return ret;
932 }
933 
restore_state(const char * backup_fname)934 void concat_image_t::restore_state(const char *backup_fname)
935 {
936   char tempfn[BX_PATHNAME_LEN];
937 
938   close();
939   char *image_name = new char[strlen(pathname0) + 1];
940   strcpy(image_name, pathname0);
941   for (int index = 0; index < maxfd; index++) {
942     sprintf(tempfn, "%s%d", backup_fname, index);
943     if (!hdimage_copy_file(tempfn, image_name)) {
944       BX_PANIC(("Failed to restore concat image '%s'", image_name));
945       delete [] image_name;
946       return;
947     }
948     increment_string(image_name);
949   }
950   delete [] image_name;
951   device_image_t::open(pathname0);
952 }
953 #endif
954 
955 /*** sparse_image_t function definitions ***/
956 
sparse_image_t()957 sparse_image_t::sparse_image_t()
958 {
959   fd = -1;
960   pathname = NULL;
961 #ifdef _POSIX_MAPPED_FILES
962   mmap_header = NULL;
963 #endif
964   pagetable = NULL;
965   parent_image = NULL;
966 }
967 
read_header()968 int sparse_image_t::read_header()
969 {
970   BX_ASSERT(sizeof(header) == SPARSE_HEADER_SIZE);
971 
972   int ret = check_format(fd, underlying_filesize);
973   if (ret != HDIMAGE_FORMAT_OK) {
974     switch (ret) {
975       case HDIMAGE_READ_ERROR:
976         BX_PANIC(("sparse: could not read entire header"));
977         break;
978       case HDIMAGE_NO_SIGNATURE:
979         BX_PANIC(("sparse: failed header magic check"));
980         break;
981       case HDIMAGE_VERSION_ERROR:
982         BX_PANIC(("sparse: unknown version in header"));
983         break;
984     }
985     return -1;
986   }
987 
988   ret = bx_read_image(fd, 0, &header, sizeof(header));
989   if (ret < 0) {
990     return -1;
991   }
992 
993   pagesize = dtoh32(header.pagesize);
994   Bit32u numpages = dtoh32(header.numpages);
995 
996   total_size = pagesize;
997   total_size *= numpages;
998 
999   pagesize_shift = 0;
1000   while ((pagesize >> pagesize_shift) > 1) pagesize_shift++;
1001 
1002   if ((Bit32u)(1 << pagesize_shift) != pagesize) {
1003     panic("failed block size header check");
1004   }
1005 
1006   pagesize_mask = pagesize - 1;
1007 
1008   size_t  preamble_size = (sizeof(Bit32u) * numpages) + sizeof(header);
1009   data_start = 0;
1010   while ((size_t)data_start < preamble_size) data_start += pagesize;
1011 
1012   bool did_mmap = 0;
1013 
1014 #ifdef _POSIX_MAPPED_FILES
1015   // Try to memory map from the beginning of the file (0 is trivially a page multiple)
1016   void *mmap_header = mmap(NULL, preamble_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
1017   if (mmap_header == MAP_FAILED) {
1018     BX_INFO(("failed to mmap sparse disk file - using conventional file access"));
1019     mmap_header = NULL;
1020   }
1021   else
1022   {
1023     mmap_length = preamble_size;
1024     did_mmap = 1;
1025     pagetable = ((Bit32u *) (((Bit8u *) mmap_header) + sizeof(header)));
1026     system_pagesize_mask = getpagesize() - 1;
1027   }
1028 #endif
1029 
1030   if (!did_mmap) {
1031     pagetable = new Bit32u[numpages];
1032 
1033     if (pagetable == NULL) {
1034       panic("could not allocate memory for sparse disk block table");
1035     }
1036 
1037     ret = ::read(fd, pagetable, sizeof(Bit32u) * numpages);
1038 
1039     if (ret < 0) {
1040       panic(strerror(errno));
1041     }
1042 
1043     if ((int)(sizeof(Bit32u) * numpages) != ret) {
1044       panic("could not read entire block table");
1045     }
1046   }
1047   return 0;
1048 }
1049 
open(const char * pathname0,int flags)1050 int sparse_image_t::open(const char* pathname0, int flags)
1051 {
1052   pathname = strdup(pathname0);
1053   BX_DEBUG(("sparse_image_t::open"));
1054 
1055   if ((fd = hdimage_open_file(pathname, flags, &underlying_filesize, &mtime)) < 0) {
1056     return -1;
1057   }
1058   BX_DEBUG(("sparse_image: open image %s", pathname));
1059 
1060   if (read_header() < 0) {
1061     return -1;
1062   }
1063 
1064   if ((underlying_filesize % pagesize) != 0)
1065     panic("size of sparse disk image is not multiple of page size");
1066 
1067   if ((pagesize % sect_size) != 0)
1068     panic("page size of sparse disk image is not multiple of sector size");
1069 
1070   underlying_current_filepos = 0;
1071   if (-1 == ::lseek(fd, 0, SEEK_SET))
1072     panic("error while seeking to start of file");
1073 
1074   lseek(0, SEEK_SET);
1075 
1076   char * parentpathname = strdup(pathname);
1077   char lastchar = ::increment_string(parentpathname, -1);
1078 
1079   if ((lastchar >= '0') && (lastchar <= '9'))
1080   {
1081     struct stat stat_buf;
1082     if (0 == stat(parentpathname, &stat_buf))
1083     {
1084       parent_image = new sparse_image_t();
1085       int ret = parent_image->open(parentpathname, flags);
1086       if (ret != 0) return ret;
1087       if (    (parent_image->pagesize != pagesize)
1088           ||  (parent_image->total_size != total_size))
1089       {
1090         panic("child drive image does not have same page count/page size configuration");
1091       }
1092     }
1093   }
1094 
1095   if (parentpathname != NULL) free(parentpathname);
1096 
1097   if (dtoh32(header.version) == SPARSE_HEADER_VERSION) {
1098     hd_size = dtoh64(header.disk);
1099     BX_INFO(("sparse: pagesize = 0x%x, data_start = 0x" FMT_LL "x", pagesize, data_start));
1100   }
1101 
1102   return 0; // success
1103 }
1104 
close()1105 void sparse_image_t::close()
1106 {
1107   BX_DEBUG(("concat_image_t.close"));
1108 #ifdef _POSIX_MAPPED_FILES
1109   if (mmap_header != NULL) {
1110     int ret = munmap(mmap_header, mmap_length);
1111     if (ret != 0)
1112       BX_INFO(("failed to un-memory map sparse disk file"));
1113   }
1114   pagetable = NULL; // We didn't malloc it
1115 #endif
1116   if (fd > -1) {
1117     bx_close_image(fd, pathname);
1118   }
1119   if (pathname != NULL) {
1120     free(pathname);
1121   }
1122   if (pagetable != NULL) {
1123     delete [] pagetable;
1124   }
1125   if (parent_image != NULL) {
1126     delete parent_image;
1127   }
1128 }
1129 
lseek(Bit64s offset,int whence)1130 Bit64s sparse_image_t::lseek(Bit64s offset, int whence)
1131 {
1132   if ((offset % sect_size) != 0)
1133     BX_PANIC(("lseek HD with offset not multiple of %d", sect_size));
1134   if (whence != SEEK_SET)
1135     BX_PANIC(("lseek HD with whence not SEEK_SET"));
1136 
1137   BX_DEBUG(("sparse_image_t::lseek(%d)", whence));
1138 
1139   if (offset > total_size)
1140   {
1141     BX_PANIC(("sparse_image_t.lseek to byte %ld failed", (long)offset));
1142     return -1;
1143   }
1144 
1145   set_virtual_page((Bit32u)(offset >> pagesize_shift));
1146   position_page_offset = (Bit32u)(offset & pagesize_mask);
1147 
1148   return 0;
1149 }
1150 
get_physical_offset()1151 inline Bit64s sparse_image_t::get_physical_offset()
1152 {
1153   Bit64s physical_offset = data_start;
1154   physical_offset += ((Bit64s)position_physical_page << pagesize_shift);
1155   physical_offset += position_page_offset;
1156   return physical_offset;
1157 }
1158 
set_virtual_page(Bit32u new_virtual_page)1159 void sparse_image_t::set_virtual_page(Bit32u new_virtual_page)
1160 {
1161   position_virtual_page = new_virtual_page;
1162   position_physical_page = dtoh32(pagetable[position_virtual_page]);
1163 }
1164 
read_page_fragment(Bit32u read_virtual_page,Bit32u read_page_offset,size_t read_size,void * buf)1165 ssize_t sparse_image_t::read_page_fragment(Bit32u read_virtual_page, Bit32u read_page_offset, size_t read_size, void * buf)
1166 {
1167   if (read_virtual_page != position_virtual_page)
1168   {
1169     set_virtual_page(read_virtual_page);
1170   }
1171 
1172   position_page_offset = read_page_offset;
1173 
1174   if (position_physical_page == SPARSE_PAGE_NOT_ALLOCATED)
1175   {
1176     if (parent_image != NULL)
1177     {
1178       return parent_image->read_page_fragment(read_virtual_page, read_page_offset, read_size, buf);
1179     }
1180     else
1181     {
1182       memset(buf, 0, read_size);
1183     }
1184   }
1185   else
1186   {
1187     Bit64s physical_offset = get_physical_offset();
1188 
1189     if (physical_offset != underlying_current_filepos)
1190     {
1191       off_t ret = ::lseek(fd, (off_t)physical_offset, SEEK_SET);
1192       // underlying_current_filepos update deferred
1193       if (ret == -1)
1194         panic(strerror(errno));
1195     }
1196 
1197     ssize_t readret = ::read(fd, buf, read_size);
1198 
1199     if (readret == -1)
1200     {
1201       panic(strerror(errno));
1202     }
1203 
1204     if ((size_t)readret != read_size)
1205     {
1206       panic("could not read block contents from file");
1207     }
1208 
1209     underlying_current_filepos = physical_offset + read_size;
1210   }
1211 
1212   return read_size;
1213 }
1214 
read(void * buf,size_t count)1215 ssize_t sparse_image_t::read(void* buf, size_t count)
1216 {
1217   ssize_t total_read = 0;
1218 
1219   BX_DEBUG(("sparse_image_t.read %ld bytes", (long)count));
1220 
1221   while (count != 0)
1222   {
1223     size_t can_read = pagesize - position_page_offset;
1224     if (count < can_read) can_read = count;
1225 
1226     BX_ASSERT (can_read != 0);
1227 
1228     size_t was_read = (size_t)read_page_fragment(position_virtual_page, position_page_offset, can_read, buf);
1229 
1230     if (was_read != can_read) {
1231       BX_PANIC(("could not read from sparse disk"));
1232     }
1233 
1234     total_read += can_read;
1235 
1236     position_page_offset += can_read;
1237     if (position_page_offset == pagesize)
1238     {
1239       position_page_offset = 0;
1240       set_virtual_page(position_virtual_page + 1);
1241     }
1242 
1243     BX_ASSERT(position_page_offset < pagesize);
1244 
1245     buf = (((Bit8u *) buf) + can_read);
1246     count -= can_read;
1247   }
1248 
1249   return total_read;
1250 }
1251 
panic(const char * message)1252 void sparse_image_t::panic(const char * message)
1253 {
1254   char buffer[1024];
1255   if (message == NULL)
1256   {
1257     snprintf(buffer, sizeof(buffer), "error with sparse disk image %s", pathname);
1258   }
1259   else
1260   {
1261     snprintf(buffer, sizeof(buffer), "error with sparse disk image %s - %s", pathname, message);
1262   }
1263   BX_PANIC(("%s", buffer));
1264 }
1265 
write(const void * buf,size_t count)1266 ssize_t sparse_image_t::write(const void* buf, size_t count)
1267 {
1268   ssize_t total_written = 0;
1269 
1270   Bit32u update_pagetable_start = position_virtual_page;
1271   Bit32u update_pagetable_count = 0;
1272 
1273   BX_DEBUG(("sparse_image_t.write %ld bytes", (long)count));
1274 
1275   while (count != 0)
1276   {
1277     size_t can_write = pagesize - position_page_offset;
1278     if (count < can_write) can_write = count;
1279 
1280     BX_ASSERT (can_write != 0);
1281 
1282     if (position_physical_page == SPARSE_PAGE_NOT_ALLOCATED)
1283     {
1284       // We just add on another page at the end of the file
1285       // Reclamation, compaction etc should currently be done off-line
1286 
1287       Bit64s data_size = underlying_filesize - data_start;
1288       BX_ASSERT((data_size % pagesize) == 0);
1289 
1290       Bit32u data_size_pages = (Bit32u)(data_size / pagesize);
1291       Bit32u next_data_page = data_size_pages;
1292 
1293       pagetable[position_virtual_page] = htod32(next_data_page);
1294       position_physical_page = next_data_page;
1295 
1296       Bit64s page_file_start = data_start + ((Bit64s)position_physical_page << pagesize_shift);
1297 
1298       if (parent_image != NULL)
1299       {
1300         // If we have a parent, we must merge our portion with the parent
1301         void *writebuffer = NULL;
1302 
1303         if (can_write == pagesize)
1304         {
1305           writebuffer = (void *) buf;
1306         }
1307         else
1308         {
1309           writebuffer = malloc(pagesize);
1310           if (writebuffer == NULL)
1311             panic("Cannot allocate sufficient memory for page-merge in write");
1312 
1313           // Read entire page - could optimize, but simple for now
1314           parent_image->read_page_fragment(position_virtual_page, 0, pagesize, writebuffer);
1315 
1316           void *dest_start = ((Bit8u *) writebuffer) + position_page_offset;
1317           memcpy(dest_start, buf, can_write);
1318         }
1319 
1320         int ret = (int)::lseek(fd, page_file_start, SEEK_SET);
1321         // underlying_current_filepos update deferred
1322         if (ret == -1) panic(strerror(errno));
1323 
1324         ret = ::write(fd, writebuffer, pagesize);
1325         if (ret == -1) panic(strerror(errno));
1326 
1327         if (pagesize != (Bit32u)ret) panic("failed to write entire merged page to disk");
1328 
1329         if (can_write != pagesize)
1330         {
1331           free(writebuffer);
1332         }
1333       }
1334       else
1335       {
1336         // We need to write a zero page because read has been returning zeroes
1337         // We seek as close to the page end as possible, and then write a little
1338         // This produces a sparse file which has blanks
1339         // Also very quick, even when pagesize is massive
1340         int ret = (int)::lseek(fd, page_file_start + pagesize - 4, SEEK_SET);
1341         // underlying_current_filepos update deferred
1342         if (ret == -1) panic(strerror(errno));
1343 
1344         Bit32u zero = 0;
1345         ret = ::write(fd, &zero, 4);
1346         if (ret == -1) panic(strerror(errno));
1347 
1348         if (ret != 4) panic("failed to write entire blank page to disk");
1349       }
1350 
1351       update_pagetable_count = (position_virtual_page - update_pagetable_start) + 1;
1352       underlying_filesize = underlying_current_filepos = page_file_start + pagesize;
1353     }
1354 
1355     BX_ASSERT(position_physical_page != SPARSE_PAGE_NOT_ALLOCATED);
1356 
1357     Bit64s physical_offset = get_physical_offset();
1358 
1359     if (physical_offset != underlying_current_filepos)
1360     {
1361       off_t ret = ::lseek(fd, (off_t)physical_offset, SEEK_SET);
1362       // underlying_current_filepos update deferred
1363       if (ret == -1)
1364         panic(strerror(errno));
1365     }
1366 
1367     ssize_t writeret = ::write(fd, buf, can_write);
1368 
1369     if (writeret == -1)
1370     {
1371       panic(strerror(errno));
1372     }
1373 
1374     if ((size_t)writeret != can_write)
1375     {
1376       panic("could not write block contents to file");
1377     }
1378 
1379     underlying_current_filepos = physical_offset + can_write;
1380 
1381     total_written += can_write;
1382 
1383     position_page_offset += can_write;
1384     if (position_page_offset == pagesize)
1385     {
1386       position_page_offset = 0;
1387       set_virtual_page(position_virtual_page + 1);
1388     }
1389 
1390     BX_ASSERT(position_page_offset < pagesize);
1391 
1392     buf = (((Bit8u *) buf) + can_write);
1393     count -= can_write;
1394   }
1395 
1396   if (update_pagetable_count != 0)
1397   {
1398     bool done = 0;
1399     off_t pagetable_write_from = sizeof(header) + (sizeof(Bit32u) * update_pagetable_start);
1400     size_t write_bytecount = update_pagetable_count * sizeof(Bit32u);
1401 
1402 #ifdef _POSIX_MAPPED_FILES
1403     if (mmap_header != NULL)
1404     {
1405       // Sync from the beginning of the page
1406       size_t system_page_offset = pagetable_write_from & system_pagesize_mask;
1407       void *start = ((Bit8u *) mmap_header + pagetable_write_from - system_page_offset);
1408 
1409       int ret = msync(start, system_page_offset + write_bytecount, MS_ASYNC);
1410 
1411       if (ret != 0)
1412         panic(strerror(errno));
1413 
1414       done = 1;
1415     }
1416 #endif
1417 
1418     if (!done)
1419     {
1420       int ret = (int)::lseek(fd, pagetable_write_from, SEEK_SET);
1421       // underlying_current_filepos update deferred
1422       if (ret == -1) panic(strerror(errno));
1423 
1424       ret = ::write(fd, &pagetable[update_pagetable_start], write_bytecount);
1425       if (ret == -1) panic(strerror(errno));
1426       if ((size_t)ret != write_bytecount) panic("could not write entire updated block header");
1427 
1428       underlying_current_filepos = pagetable_write_from + write_bytecount;
1429     }
1430   }
1431 
1432   return total_written;
1433 }
1434 
check_format(int fd,Bit64u imgsize)1435 int sparse_image_t::check_format(int fd, Bit64u imgsize)
1436 {
1437   sparse_header_t temp_header;
1438 
1439   int ret = ::read(fd, &temp_header, sizeof(temp_header));
1440   if (ret < 0) {
1441     return HDIMAGE_READ_ERROR;
1442   }
1443   if (ret != sizeof(temp_header)) {
1444     return HDIMAGE_READ_ERROR;
1445   }
1446 
1447   if (dtoh32(temp_header.magic) != SPARSE_HEADER_MAGIC) {
1448     return HDIMAGE_NO_SIGNATURE;
1449   }
1450 
1451   if ((dtoh32(temp_header.version) != SPARSE_HEADER_VERSION) &&
1452       (dtoh32(temp_header.version) != SPARSE_HEADER_V1)) {
1453     return HDIMAGE_VERSION_ERROR;
1454   }
1455 
1456   return HDIMAGE_FORMAT_OK;
1457 }
1458 
1459 #ifdef BXIMAGE
create_image(const char * pathname,Bit64u size)1460 int sparse_image_t::create_image(const char *pathname, Bit64u size)
1461 {
1462   Bit64u numpages;
1463   sparse_header_t header;
1464   size_t sizesofar;
1465   int padtopagesize;
1466 
1467   memset(&header, 0, sizeof(header));
1468   header.magic = htod32(SPARSE_HEADER_MAGIC);
1469   header.version = htod32(SPARSE_HEADER_VERSION);
1470 
1471   header.pagesize = htod32((1 << 10) * 32); // Use 32 KB Pages - could be configurable
1472   numpages = (size / dtoh32(header.pagesize)) + 1;
1473 
1474   header.numpages = htod32((Bit32u)numpages);
1475   header.disk = htod64(size);
1476 
1477   if (numpages != dtoh32(header.numpages)) {
1478     BX_FATAL(("ERROR: The disk image is too large for a sparse image!"));
1479     // Could increase page size here.
1480     // But note this only happens at 128 Terabytes!
1481   }
1482 
1483   int fd = bx_create_image_file(pathname);
1484   if (fd < 0)
1485     BX_FATAL(("ERROR: failed to create sparse image file"));
1486   if (bx_write_image(fd, 0, &header, sizeof(header)) != sizeof(header)) {
1487     ::close(fd);
1488     BX_FATAL(("ERROR: The disk image is not complete - could not write header!"));
1489   }
1490 
1491   Bit32u *pagetable = new Bit32u[dtoh32(header.numpages)];
1492   if (pagetable == NULL)
1493     BX_FATAL(("ERROR: The disk image is not complete - could not create pagetable!"));
1494   for (Bit32u i=0; i<dtoh32(header.numpages); i++)
1495     pagetable[i] = htod32(SPARSE_PAGE_NOT_ALLOCATED);
1496 
1497   if (bx_write_image(fd, sizeof(header), pagetable, 4 * dtoh32(header.numpages)) != (int)(4 * dtoh32(header.numpages))) {
1498     ::close(fd);
1499     BX_FATAL(("ERROR: The disk image is not complete - could not write pagetable!"));
1500   }
1501   delete [] pagetable;
1502 
1503   sizesofar = SPARSE_HEADER_SIZE + (4 * dtoh32(header.numpages));
1504   padtopagesize = dtoh32(header.pagesize) - (sizesofar & (dtoh32(header.pagesize) - 1));
1505 
1506   Bit8u *padding = new Bit8u[padtopagesize];
1507   memset(padding, 0, padtopagesize);
1508 
1509   if (bx_write_image(fd, sizesofar, padding, padtopagesize) != padtopagesize) {
1510     ::close(fd);
1511     BX_FATAL(("ERROR: The disk image is not complete - could not write padding!"));
1512   }
1513   delete [] padding;
1514   ::close(fd);
1515   return 0;
1516 }
1517 #else
save_state(const char * backup_fname)1518 bool sparse_image_t::save_state(const char *backup_fname)
1519 {
1520   return hdimage_backup_file(fd, backup_fname);
1521 }
1522 
restore_state(const char * backup_fname)1523 void sparse_image_t::restore_state(const char *backup_fname)
1524 {
1525   int backup_fd;
1526   Bit64u imgsize = 0;
1527   char *temp_pathname;
1528 
1529   if ((backup_fd = hdimage_open_file(backup_fname, O_RDONLY, &imgsize, NULL)) < 0) {
1530     BX_PANIC(("Could not open sparse image backup"));
1531     return;
1532   }
1533   if (check_format(backup_fd, imgsize) != HDIMAGE_FORMAT_OK) {
1534     ::close(backup_fd);
1535     BX_PANIC(("Could not detect sparse image header"));
1536     return;
1537   }
1538   ::close(backup_fd);
1539   temp_pathname = strdup(pathname);
1540   close();
1541   if (!hdimage_copy_file(backup_fname, temp_pathname)) {
1542     BX_PANIC(("Failed to restore sparse image '%s'", temp_pathname));
1543     free(temp_pathname);
1544     return;
1545   }
1546   if (device_image_t::open(temp_pathname) < 0) {
1547     BX_PANIC(("Failed to open restored image '%s'", temp_pathname));
1548   }
1549   free(temp_pathname);
1550 }
1551 #endif
1552 
1553 #ifdef WIN32
1554 
1555 /*** dll_image_t function definitions ***/
1556 
1557 typedef int  (CDECL *vdisk_open_t)  (const char *path, int flags);
1558 typedef BOOL (CDECL *vdisk_read_t)  (int vunit, LONGLONG blk, void *buf);
1559 typedef BOOL (CDECL *vdisk_write_t) (int vunit, LONGLONG blk, const void *buf);
1560 typedef void (CDECL *vdisk_close_t) (int vunit);
1561 typedef LONGLONG (CDECL *vdisk_get_size_t) (int vunit);
1562 
1563 HINSTANCE hlib_vdisk = NULL;
1564 vdisk_open_t vdisk_open = NULL;
1565 vdisk_read_t vdisk_read = NULL;
1566 vdisk_write_t vdisk_write = NULL;
1567 vdisk_close_t vdisk_close = NULL;
1568 vdisk_get_size_t vdisk_get_size = NULL;
1569 
dll_image_t()1570 dll_image_t::dll_image_t()
1571 {
1572   if (hlib_vdisk == NULL) {
1573     hlib_vdisk = LoadLibrary("vdisk.dll");
1574     if (hlib_vdisk != NULL) {
1575       vdisk_open =  (vdisk_open_t)        GetProcAddress(hlib_vdisk,"vdisk_open");
1576       vdisk_read =  (vdisk_read_t)        GetProcAddress(hlib_vdisk,"vdisk_read");
1577       vdisk_write = (vdisk_write_t)       GetProcAddress(hlib_vdisk,"vdisk_write");
1578       vdisk_close = (vdisk_close_t)       GetProcAddress(hlib_vdisk,"vdisk_close");
1579       vdisk_get_size = (vdisk_get_size_t) GetProcAddress(hlib_vdisk,"vdisk_get_size");
1580       if ((vdisk_open == NULL) || (vdisk_read == NULL) || (vdisk_write == NULL) ||
1581           (vdisk_close == NULL) || (vdisk_get_size == NULL)) {
1582         FreeLibrary(hlib_vdisk);
1583         hlib_vdisk = NULL;
1584       }
1585     }
1586   }
1587 }
1588 
open(const char * pathname,int flags)1589 int dll_image_t::open(const char* pathname, int flags)
1590 {
1591   if (hlib_vdisk != NULL) {
1592     vunit = vdisk_open(pathname, flags);
1593     if (vunit >= 0) {
1594       hd_size = (Bit64u)vdisk_get_size(vunit) << 9;
1595       sect_size = 512;
1596       vblk = 0;
1597     }
1598   } else {
1599     vunit = -2;
1600   }
1601   return vunit;
1602 }
1603 
close()1604 void dll_image_t::close()
1605 {
1606   if ((vunit >= 0) && (hlib_vdisk != NULL)) {
1607     vdisk_close(vunit);
1608   }
1609 }
1610 
lseek(Bit64s offset,int whence)1611 Bit64s dll_image_t::lseek(Bit64s offset, int whence)
1612 {
1613   if (whence == SEEK_SET) {
1614     vblk = offset >> 9;
1615   } else if (whence == SEEK_CUR) {
1616     vblk += offset >> 9;
1617   } else {
1618     BX_ERROR(("lseek: mode not supported yet"));
1619     return -1;
1620   }
1621   if (vblk >= (Bit64s)(hd_size >> 9))
1622     return -1;
1623   return 0;
1624 }
1625 
read(void * buf,size_t count)1626 ssize_t dll_image_t::read(void* buf, size_t count)
1627 {
1628   if ((vunit >= 0) && (hlib_vdisk != NULL)) {
1629     if (vdisk_read(vunit, vblk, buf)) {
1630       vblk++;
1631       return count;
1632     }
1633   }
1634   return -1;
1635 }
1636 
write(const void * buf,size_t count)1637 ssize_t dll_image_t::write(const void* buf, size_t count)
1638 {
1639   if ((vunit >= 0) && (hlib_vdisk != 0)) {
1640     if (vdisk_write(vunit, vblk, buf)) {
1641       vblk++;
1642       return count;
1643     }
1644   }
1645   return -1;
1646 }
1647 #endif // DLL_HD_SUPPORT
1648 
1649 // redolog implementation
redolog_t()1650 redolog_t::redolog_t()
1651 {
1652   fd = -1;
1653   pathname = NULL;
1654   catalog = NULL;
1655   bitmap = NULL;
1656   extent_index = (Bit32u)0;
1657   extent_offset = (Bit32u)0;
1658   extent_next = (Bit32u)0;
1659 }
1660 
print_header()1661 void redolog_t::print_header()
1662 {
1663   BX_INFO(("redolog : Standard Header : magic='%s', type='%s', subtype='%s', version = %d.%d",
1664            header.standard.magic, header.standard.type, header.standard.subtype,
1665            dtoh32(header.standard.version)/0x10000,
1666            dtoh32(header.standard.version)%0x10000));
1667   if (dtoh32(header.standard.version) == STANDARD_HEADER_VERSION) {
1668     BX_INFO(("redolog : Specific Header : #entries=%d, bitmap size=%d, exent size = %d disk size = " FMT_LL "d",
1669              dtoh32(header.specific.catalog),
1670              dtoh32(header.specific.bitmap),
1671              dtoh32(header.specific.extent),
1672              dtoh64(header.specific.disk)));
1673   } else if (dtoh32(header.standard.version) == STANDARD_HEADER_V1) {
1674     redolog_header_v1_t header_v1;
1675     memcpy(&header_v1, &header, STANDARD_HEADER_SIZE);
1676     BX_INFO(("redolog : Specific Header : #entries=%d, bitmap size=%d, exent size = %d disk size = " FMT_LL "d",
1677              dtoh32(header_v1.specific.catalog),
1678              dtoh32(header_v1.specific.bitmap),
1679              dtoh32(header_v1.specific.extent),
1680              dtoh64(header_v1.specific.disk)));
1681   }
1682 }
1683 
make_header(const char * type,Bit64u size)1684 int redolog_t::make_header(const char* type, Bit64u size)
1685 {
1686   Bit32u entries, extent_size, bitmap_size;
1687   Bit64u maxsize;
1688   Bit32u flip=0;
1689 
1690   // Set standard header values
1691   memset(&header, 0, sizeof(redolog_header_t));
1692   strcpy((char*)header.standard.magic, STANDARD_HEADER_MAGIC);
1693   strcpy((char*)header.standard.type, REDOLOG_TYPE);
1694   strcpy((char*)header.standard.subtype, type);
1695   header.standard.version = htod32(STANDARD_HEADER_VERSION);
1696   header.standard.header = htod32(STANDARD_HEADER_SIZE);
1697 
1698   entries = 512;
1699   bitmap_size = 1;
1700 
1701   // Compute #entries and extent size values
1702   do {
1703     extent_size = 8 * bitmap_size * 512;
1704 
1705     header.specific.catalog = htod32(entries);
1706     header.specific.bitmap = htod32(bitmap_size);
1707     header.specific.extent = htod32(extent_size);
1708 
1709     maxsize = (Bit64u)entries * (Bit64u)extent_size;
1710 
1711     flip++;
1712 
1713     if(flip&0x01) bitmap_size *= 2;
1714     else entries *= 2;
1715   } while (maxsize < size);
1716 
1717   header.specific.timestamp = 0;
1718   header.specific.disk = htod64(size);
1719 
1720   print_header();
1721 
1722   catalog = new Bit32u[dtoh32(header.specific.catalog)];
1723   bitmap =  new Bit8u[dtoh32(header.specific.bitmap)];
1724 
1725   if ((catalog == NULL) || (bitmap==NULL))
1726     BX_PANIC(("redolog : could not malloc catalog or bitmap"));
1727 
1728   for (Bit32u i=0; i<dtoh32(header.specific.catalog); i++)
1729     catalog[i] = htod32(REDOLOG_PAGE_NOT_ALLOCATED);
1730 
1731   bitmap_blocks = 1 + (dtoh32(header.specific.bitmap) - 1) / 512;
1732   extent_blocks = 1 + (dtoh32(header.specific.extent) - 1) / 512;
1733 
1734   BX_DEBUG(("redolog : each bitmap is %d blocks", bitmap_blocks));
1735   BX_DEBUG(("redolog : each extent is %d blocks", extent_blocks));
1736 
1737   return 0;
1738 }
1739 
create(const char * filename,const char * type,Bit64u size)1740 int redolog_t::create(const char* filename, const char* type, Bit64u size)
1741 {
1742 #ifndef BXIMAGE
1743   char lockfn[BX_PATHNAME_LEN];
1744 
1745   sprintf(lockfn, "%s.lock", filename);
1746   if (access(lockfn, F_OK) == 0) {
1747     return -1;
1748   }
1749 #endif
1750 
1751   BX_INFO(("redolog : creating redolog %s", filename));
1752 
1753   int filedes = ::open(filename, O_RDWR | O_CREAT | O_TRUNC
1754 #ifdef O_BINARY
1755             | O_BINARY
1756 #endif
1757             , S_IWUSR | S_IRUSR | S_IRGRP | S_IWGRP);
1758 
1759   return create(filedes, type, size);
1760 }
1761 
create(int filedes,const char * type,Bit64u size)1762 int redolog_t::create(int filedes, const char* type, Bit64u size)
1763 {
1764   fd = filedes;
1765 
1766   if (fd < 0)
1767   {
1768     return -1; // open failed
1769   }
1770 
1771   if (make_header(type, size) < 0)
1772   {
1773     return -1;
1774   }
1775 
1776   // Write header
1777   ::write(fd, &header, dtoh32(header.standard.header));
1778 
1779   // Write catalog
1780   // FIXME could mmap
1781   ::write(fd, catalog, dtoh32(header.specific.catalog) * sizeof (Bit32u));
1782 
1783   return 0;
1784 }
1785 
open(const char * filename,const char * type)1786 int redolog_t::open(const char* filename, const char *type)
1787 {
1788   return open(filename, type, O_RDWR);
1789 }
1790 
open(const char * filename,const char * type,int flags)1791 int redolog_t::open(const char* filename, const char *type, int flags)
1792 {
1793   Bit64u imgsize = 0;
1794 #ifndef WIN32
1795   time_t mtime;
1796 #else
1797   FILETIME mtime;
1798 #endif
1799 
1800   pathname = new char[strlen(filename) + 1];
1801   strcpy(pathname, filename);
1802   fd = hdimage_open_file(filename, flags, &imgsize, &mtime);
1803   if (fd < 0) {
1804     BX_INFO(("redolog : could not open image %s", filename));
1805     // open failed.
1806     return -1;
1807   }
1808   BX_INFO(("redolog : open image %s", filename));
1809 
1810   int res = check_format(fd, type);
1811   if (res != HDIMAGE_FORMAT_OK) {
1812     switch (res) {
1813       case HDIMAGE_READ_ERROR:
1814         BX_PANIC(("redolog : could not read header"));
1815         break;
1816       case HDIMAGE_NO_SIGNATURE:
1817         BX_PANIC(("redolog : Bad header magic"));
1818         break;
1819       case HDIMAGE_TYPE_ERROR:
1820         BX_PANIC(("redolog : Bad header type or subtype"));
1821         break;
1822       case HDIMAGE_VERSION_ERROR:
1823         BX_PANIC(("redolog : Bad header version"));
1824         break;
1825     }
1826     return -1;
1827   }
1828 
1829   if (bx_read_image(fd, 0, &header, sizeof(header)) < 0) {
1830     return -1;
1831   }
1832   print_header();
1833 
1834   if (dtoh32(header.standard.version) == STANDARD_HEADER_V1) {
1835     redolog_header_v1_t header_v1;
1836 
1837     memcpy(&header_v1, &header, STANDARD_HEADER_SIZE);
1838     header.specific.disk = header_v1.specific.disk;
1839   }
1840   if (!strcmp(type, REDOLOG_SUBTYPE_GROWING)) {
1841     set_timestamp(fat_datetime(mtime, 1) | (fat_datetime(mtime, 0) << 16));
1842   }
1843 
1844   catalog = new Bit32u[dtoh32(header.specific.catalog)];
1845 
1846   // FIXME could mmap
1847   res = bx_read_image(fd, dtoh32(header.standard.header), catalog, dtoh32(header.specific.catalog) * sizeof(Bit32u));
1848 
1849   if (res !=  (ssize_t)(dtoh32(header.specific.catalog) * sizeof(Bit32u)))
1850   {
1851     BX_PANIC(("redolog : could not read catalog %d=%d",res, dtoh32(header.specific.catalog)));
1852     return -1;
1853   }
1854 
1855   // check last used extent
1856   extent_next = 0;
1857   for (Bit32u i=0; i < dtoh32(header.specific.catalog); i++)
1858   {
1859     if (dtoh32(catalog[i]) != REDOLOG_PAGE_NOT_ALLOCATED)
1860     {
1861       if (dtoh32(catalog[i]) >= extent_next)
1862         extent_next = dtoh32(catalog[i]) + 1;
1863     }
1864   }
1865   BX_INFO(("redolog : next extent will be at index %d",extent_next));
1866 
1867   // memory used for storing bitmaps
1868   bitmap = new Bit8u[dtoh32(header.specific.bitmap)];
1869 
1870   bitmap_blocks = 1 + (dtoh32(header.specific.bitmap) - 1) / 512;
1871   extent_blocks = 1 + (dtoh32(header.specific.extent) - 1) / 512;
1872 
1873   BX_DEBUG(("redolog : each bitmap is %d blocks", bitmap_blocks));
1874   BX_DEBUG(("redolog : each extent is %d blocks", extent_blocks));
1875 
1876   imagepos = 0;
1877   bitmap_update = 1;
1878 
1879   return 0;
1880 }
1881 
close()1882 void redolog_t::close()
1883 {
1884   if (fd >= 0)
1885     bx_close_image(fd, pathname);
1886 
1887   if (pathname != NULL)
1888     delete [] pathname;
1889 
1890   if (catalog != NULL)
1891     delete [] catalog;
1892 
1893   if (bitmap != NULL)
1894     delete [] bitmap;
1895 }
1896 
get_size()1897 Bit64u redolog_t::get_size()
1898 {
1899   return dtoh64(header.specific.disk);
1900 }
1901 
get_timestamp()1902 Bit32u redolog_t::get_timestamp()
1903 {
1904   return dtoh32(header.specific.timestamp);
1905 }
1906 
set_timestamp(Bit32u timestamp)1907 bool redolog_t::set_timestamp(Bit32u timestamp)
1908 {
1909   header.specific.timestamp = htod32(timestamp);
1910   // Update header
1911   bx_write_image(fd, 0, &header, dtoh32(header.standard.header));
1912   return 1;
1913 }
1914 
lseek(Bit64s offset,int whence)1915 Bit64s redolog_t::lseek(Bit64s offset, int whence)
1916 {
1917   if ((offset % 512) != 0) {
1918     BX_PANIC(("redolog : lseek() offset not multiple of 512"));
1919     return -1;
1920   }
1921   if (whence == SEEK_SET) {
1922     imagepos = offset;
1923   } else if (whence == SEEK_CUR) {
1924     imagepos += offset;
1925   } else {
1926     BX_PANIC(("redolog: lseek() mode not supported yet"));
1927     return -1;
1928   }
1929   if (imagepos > (Bit64s)dtoh64(header.specific.disk)) {
1930     BX_PANIC(("redolog : lseek() to byte %ld failed", (long)offset));
1931     return -1;
1932   }
1933 
1934   Bit32u old_extent_index = extent_index;
1935   extent_index = (Bit32u)(imagepos / dtoh32(header.specific.extent));
1936   if (extent_index != old_extent_index) {
1937     bitmap_update = 1;
1938   }
1939   extent_offset = (Bit32u)((imagepos % dtoh32(header.specific.extent)) / 512);
1940 
1941   BX_DEBUG(("redolog : lseeking extent index %d, offset %d",extent_index, extent_offset));
1942 
1943   return imagepos;
1944 }
1945 
read(void * buf,size_t count)1946 ssize_t redolog_t::read(void* buf, size_t count)
1947 {
1948   Bit64s block_offset, bitmap_offset;
1949   ssize_t ret;
1950 
1951   if (count != 512) {
1952     BX_PANIC(("redolog : read() with count not 512"));
1953     return -1;
1954   }
1955 
1956   BX_DEBUG(("redolog : reading index %d, mapping to %d", extent_index, dtoh32(catalog[extent_index])));
1957 
1958   if (dtoh32(catalog[extent_index]) == REDOLOG_PAGE_NOT_ALLOCATED) {
1959     // page not allocated
1960     return 0;
1961   }
1962 
1963   bitmap_offset  = (Bit64s)STANDARD_HEADER_SIZE + (dtoh32(header.specific.catalog) * sizeof(Bit32u));
1964   bitmap_offset += (Bit64s)512 * dtoh32(catalog[extent_index]) * (extent_blocks + bitmap_blocks);
1965   block_offset    = bitmap_offset + ((Bit64s)512 * (bitmap_blocks + extent_offset));
1966 
1967   BX_DEBUG(("redolog : bitmap offset is %x", (Bit32u)bitmap_offset));
1968   BX_DEBUG(("redolog : block offset is %x", (Bit32u)block_offset));
1969 
1970   if (bitmap_update) {
1971     if (bx_read_image(fd, (off_t)bitmap_offset, bitmap,  dtoh32(header.specific.bitmap)) != (ssize_t)dtoh32(header.specific.bitmap)) {
1972       BX_PANIC(("redolog : failed to read bitmap for extent %d", extent_index));
1973       return -1;
1974     }
1975     bitmap_update = 0;
1976   }
1977 
1978   if (((bitmap[extent_offset/8] >> (extent_offset%8)) & 0x01) == 0x00) {
1979     BX_DEBUG(("read not in redolog"));
1980 
1981     // bitmap says block not in redolog
1982     return 0;
1983   }
1984 
1985   ret = bx_read_image(fd, (off_t)block_offset, buf, count);
1986   if (ret >= 0) lseek(512, SEEK_CUR);
1987 
1988   return ret;
1989 }
1990 
write(const void * buf,size_t count)1991 ssize_t redolog_t::write(const void* buf, size_t count)
1992 {
1993   Bit32u i;
1994   Bit64s block_offset, bitmap_offset, catalog_offset;
1995   ssize_t written;
1996   bool update_catalog = 0;
1997 
1998   if (count != 512) {
1999     BX_PANIC(("redolog : write() with count not 512"));
2000     return -1;
2001   }
2002 
2003   BX_DEBUG(("redolog : writing index %d, mapping to %d", extent_index, dtoh32(catalog[extent_index])));
2004 
2005   if (dtoh32(catalog[extent_index]) == REDOLOG_PAGE_NOT_ALLOCATED) {
2006     if (extent_next >= dtoh32(header.specific.catalog)) {
2007       BX_PANIC(("redolog : can't allocate new extent... catalog is full"));
2008       return -1;
2009     }
2010 
2011     BX_DEBUG(("redolog : allocating new extent at %d", extent_next));
2012 
2013     // Extent not allocated, allocate new
2014     catalog[extent_index] = htod32(extent_next);
2015 
2016     extent_next += 1;
2017 
2018     char *zerobuffer = new char[512];
2019     memset(zerobuffer, 0, 512);
2020 
2021     // Write bitmap
2022     bitmap_offset  = (Bit64s)STANDARD_HEADER_SIZE + (dtoh32(header.specific.catalog) * sizeof(Bit32u));
2023     bitmap_offset += (Bit64s)512 * dtoh32(catalog[extent_index]) * (extent_blocks + bitmap_blocks);
2024     ::lseek(fd, (off_t)bitmap_offset, SEEK_SET);
2025     for (i=0; i<bitmap_blocks; i++) {
2026       ::write(fd, zerobuffer, 512);
2027     }
2028     // Write extent
2029     for (i=0; i<extent_blocks; i++) {
2030       ::write(fd, zerobuffer, 512);
2031     }
2032 
2033     delete [] zerobuffer;
2034 
2035     update_catalog = 1;
2036   }
2037 
2038   bitmap_offset  = (Bit64s)STANDARD_HEADER_SIZE + (dtoh32(header.specific.catalog) * sizeof(Bit32u));
2039   bitmap_offset += (Bit64s)512 * dtoh32(catalog[extent_index]) * (extent_blocks + bitmap_blocks);
2040   block_offset    = bitmap_offset + ((Bit64s)512 * (bitmap_blocks + extent_offset));
2041 
2042   BX_DEBUG(("redolog : bitmap offset is %x", (Bit32u)bitmap_offset));
2043   BX_DEBUG(("redolog : block offset is %x", (Bit32u)block_offset));
2044 
2045   // Write block
2046   written = bx_write_image(fd, (off_t)block_offset, (void*)buf, count);
2047 
2048   // Write bitmap
2049   if (bitmap_update) {
2050     if (bx_read_image(fd, (off_t)bitmap_offset, bitmap,  dtoh32(header.specific.bitmap)) != (ssize_t)dtoh32(header.specific.bitmap)) {
2051       BX_PANIC(("redolog : failed to read bitmap for extent %d", extent_index));
2052       return 0;
2053     }
2054     bitmap_update = 0;
2055   }
2056 
2057   // If bloc does not belong to extent yet
2058   if (((bitmap[extent_offset/8] >> (extent_offset%8)) & 0x01) == 0x00) {
2059     bitmap[extent_offset/8] |= 1 << (extent_offset%8);
2060     bx_write_image(fd, (off_t)bitmap_offset, bitmap,  dtoh32(header.specific.bitmap));
2061   }
2062 
2063   // Write catalog
2064   if (update_catalog) {
2065     // FIXME if mmap
2066     catalog_offset  = (Bit64s)STANDARD_HEADER_SIZE + (extent_index * sizeof(Bit32u));
2067 
2068     BX_DEBUG(("redolog : writing catalog at offset %x", (Bit32u)catalog_offset));
2069 
2070     bx_write_image(fd, (off_t)catalog_offset, &catalog[extent_index], sizeof(Bit32u));
2071   }
2072 
2073   if (written >= 0) lseek(512, SEEK_CUR);
2074 
2075   return written;
2076 }
2077 
check_format(int fd,const char * subtype)2078 int redolog_t::check_format(int fd, const char *subtype)
2079 {
2080   redolog_header_t temp_header;
2081 
2082   int res = bx_read_image(fd, 0, &temp_header, sizeof(redolog_header_t));
2083   if (res != STANDARD_HEADER_SIZE) {
2084     return HDIMAGE_READ_ERROR;
2085   }
2086 
2087   if (strcmp((char*)temp_header.standard.magic, STANDARD_HEADER_MAGIC) != 0) {
2088     return HDIMAGE_NO_SIGNATURE;
2089   }
2090 
2091   if (strcmp((char*)temp_header.standard.type, REDOLOG_TYPE) != 0) {
2092     return HDIMAGE_TYPE_ERROR;
2093   }
2094   if (strcmp((char*)temp_header.standard.subtype, subtype) != 0) {
2095     return HDIMAGE_TYPE_ERROR;
2096   }
2097 
2098   if ((dtoh32(temp_header.standard.version) != STANDARD_HEADER_VERSION) &&
2099       (dtoh32(temp_header.standard.version) != STANDARD_HEADER_V1)) {
2100     return HDIMAGE_VERSION_ERROR;
2101   }
2102   return HDIMAGE_FORMAT_OK;
2103 }
2104 
2105 #ifdef BXIMAGE
commit(device_image_t * base_image)2106 int redolog_t::commit(device_image_t *base_image)
2107 {
2108   int ret = 0;
2109   Bit32u i;
2110   Bit8u buffer[512];
2111 
2112   printf("\nCommitting changes to base image file: [  0%%]");
2113 
2114   for (i = 0; i < dtoh32(header.specific.catalog); i++) {
2115     printf("\x8\x8\x8\x8\x8%3d%%]", (i+1)*100/dtoh32(header.specific.catalog));
2116     fflush(stdout);
2117 
2118     if (dtoh32(catalog[i]) != REDOLOG_PAGE_NOT_ALLOCATED) {
2119       Bit64s bitmap_offset;
2120       Bit32u bitmap_size, j;
2121 
2122       bitmap_offset  = (Bit64s)STANDARD_HEADER_SIZE + (dtoh32(header.specific.catalog) * sizeof(Bit32u));
2123       bitmap_offset += (Bit64s)512 * dtoh32(catalog[i]) * (extent_blocks + bitmap_blocks);
2124 
2125       // Read bitmap
2126       bitmap_size = dtoh32(header.specific.bitmap);
2127       if ((Bit32u)bx_read_image(fd, (off_t)bitmap_offset, bitmap, bitmap_size) != bitmap_size) {
2128         ret = -1;
2129         break;
2130       }
2131 
2132       for (j = 0; j < dtoh32(header.specific.bitmap); j++) {
2133         Bit32u bit;
2134 
2135         for (bit = 0; bit < 8; bit++) {
2136           if ( (bitmap[j] & (1 << bit)) != 0) {
2137             Bit64s base_offset, block_offset;
2138 
2139             block_offset = bitmap_offset + ((Bit64s)512 * (bitmap_blocks + ((j * 8) + bit)));
2140 
2141             if (bx_read_image(fd, (off_t)block_offset, buffer, 512) != 512) {
2142               ret = -1;
2143               break;
2144             }
2145 
2146             base_offset  = (Bit64s)i * (dtoh32(header.specific.extent));
2147             base_offset += (Bit64s)512 * ((j * 8) + bit);
2148 
2149             if (base_image->lseek(base_offset, SEEK_SET) < 0) {
2150               ret = -1;
2151               break;
2152             }
2153             if (base_image->write(buffer, 512) < 0) {
2154               ret = -1;
2155               break;
2156             }
2157           }
2158         }
2159       }
2160     }
2161   }
2162   return ret;
2163 }
2164 #endif
2165 
2166 #ifndef BXIMAGE
save_state(const char * backup_fname)2167 bool redolog_t::save_state(const char *backup_fname)
2168 {
2169   return hdimage_backup_file(fd, backup_fname);
2170 }
2171 #endif
2172 
2173 /*** growing_image_t function definitions ***/
2174 
growing_image_t()2175 growing_image_t::growing_image_t()
2176 {
2177   redolog = new redolog_t();
2178 }
2179 
~growing_image_t()2180 growing_image_t::~growing_image_t()
2181 {
2182   delete redolog;
2183 }
2184 
open(const char * _pathname,int flags)2185 int growing_image_t::open(const char* _pathname, int flags)
2186 {
2187   pathname = _pathname;
2188   int filedes = redolog->open(pathname, REDOLOG_SUBTYPE_GROWING, flags);
2189   hd_size = redolog->get_size();
2190   BX_INFO(("'growing' disk opened, growing file is '%s'", pathname));
2191   return filedes;
2192 }
2193 
close()2194 void growing_image_t::close()
2195 {
2196   redolog->close();
2197 }
2198 
lseek(Bit64s offset,int whence)2199 Bit64s growing_image_t::lseek(Bit64s offset, int whence)
2200 {
2201   return redolog->lseek(offset, whence);
2202 }
2203 
read(void * buf,size_t count)2204 ssize_t growing_image_t::read(void* buf, size_t count)
2205 {
2206   char *cbuf = (char*)buf;
2207   size_t n = 0;
2208   ssize_t ret = 0;
2209 
2210   memset(buf, 0, count);
2211   while (n < count) {
2212     ret = redolog->read(cbuf, 512);
2213     if (ret < 0) break;
2214     cbuf += 512;
2215     n += 512;
2216   }
2217   return (ret < 0) ? ret : count;
2218 }
2219 
write(const void * buf,size_t count)2220 ssize_t growing_image_t::write(const void* buf, size_t count)
2221 {
2222   char *cbuf = (char*)buf;
2223   size_t n = 0;
2224   ssize_t ret = 0;
2225 
2226   while (n < count) {
2227     ret = redolog->write(cbuf, 512);
2228     if (ret < 0) break;
2229     cbuf += 512;
2230     n += 512;
2231   }
2232   return (ret < 0) ? ret : count;
2233 }
2234 
get_timestamp()2235 Bit32u growing_image_t::get_timestamp()
2236 {
2237   return redolog->get_timestamp();
2238 }
2239 
check_format(int fd,Bit64u imgsize)2240 int growing_image_t::check_format(int fd, Bit64u imgsize)
2241 {
2242   return redolog_t::check_format(fd, REDOLOG_SUBTYPE_GROWING);
2243 }
2244 
2245 #ifdef BXIMAGE
create_image(const char * pathname,Bit64u size)2246 int growing_image_t::create_image(const char *pathname, Bit64u size)
2247 {
2248   redolog = new redolog_t;
2249   if (redolog->create(pathname, REDOLOG_SUBTYPE_GROWING, size) < 0)
2250     BX_FATAL(("Can't create growing mode image"));
2251   redolog->close();
2252   return 0;
2253 }
2254 #else
save_state(const char * backup_fname)2255 bool growing_image_t::save_state(const char *backup_fname)
2256 {
2257   return redolog->save_state(backup_fname);
2258 }
2259 
restore_state(const char * backup_fname)2260 void growing_image_t::restore_state(const char *backup_fname)
2261 {
2262   redolog_t *temp_redolog = new redolog_t();
2263   if (temp_redolog->open(backup_fname, REDOLOG_SUBTYPE_GROWING, O_RDONLY) < 0) {
2264     delete temp_redolog;
2265     BX_PANIC(("Can't open growing image backup '%s'", backup_fname));
2266     return;
2267   } else {
2268     bool okay = (temp_redolog->get_size() == redolog->get_size());
2269     temp_redolog->close();
2270     delete temp_redolog;
2271     if (!okay) {
2272       BX_PANIC(("size reported by backup doesn't match growing disk size"));
2273       return;
2274     }
2275   }
2276   redolog->close();
2277   if (!hdimage_copy_file(backup_fname, pathname)) {
2278     BX_PANIC(("Failed to restore growing image '%s'", pathname));
2279     return;
2280   }
2281   if (device_image_t::open(pathname) < 0) {
2282     BX_PANIC(("Failed to open restored growing image '%s'", pathname));
2283   }
2284 }
2285 #endif
2286 
2287 // compare hd_size and modification time of r/o disk and journal
2288 
coherency_check(device_image_t * ro_disk,redolog_t * redolog)2289 bool coherency_check(device_image_t *ro_disk, redolog_t *redolog)
2290 {
2291   Bit32u timestamp1, timestamp2;
2292   char buffer[24];
2293 
2294   if (ro_disk->hd_size != redolog->get_size()) {
2295     BX_PANIC(("size reported by redolog doesn't match r/o disk size"));
2296     return 0;
2297   }
2298   timestamp1 = ro_disk->get_timestamp();
2299   timestamp2 = redolog->get_timestamp();
2300   if (timestamp2 != 0) {
2301     if (timestamp1 != timestamp2) {
2302       sprintf(buffer, "%02d.%02d.%04d %02d:%02d:%02d", (timestamp2 >> 16) & 0x001f,
2303               (timestamp2 >> 21) & 0x000f, ((timestamp2 >> 25) & 0x007f) + 1980,
2304               (timestamp2 & 0xf800) >> 11, (timestamp2 & 0x07e0) >> 5,
2305               (timestamp2 & 0x001f) << 1);
2306       BX_PANIC(("unexpected modification time of the r/o disk (should be %s)", buffer));
2307       return 0;
2308     }
2309   } else if (timestamp1 != 0) {
2310     redolog->set_timestamp(timestamp1);
2311   }
2312   return 1;
2313 }
2314 
2315 /*** undoable_image_t function definitions ***/
2316 
undoable_image_t(const char * _redolog_name)2317 undoable_image_t::undoable_image_t(const char* _redolog_name)
2318 {
2319   redolog = new redolog_t();
2320   redolog_name = NULL;
2321   if (_redolog_name != NULL) {
2322     if ((strlen(_redolog_name) > 0) && (strcmp(_redolog_name,"none") != 0)) {
2323       redolog_name = new char[strlen(_redolog_name) + 1];
2324       strcpy(redolog_name, _redolog_name);
2325     }
2326   }
2327 }
2328 
~undoable_image_t()2329 undoable_image_t::~undoable_image_t()
2330 {
2331   delete redolog;
2332   delete ro_disk;
2333 }
2334 
open(const char * pathname,int flags)2335 int undoable_image_t::open(const char* pathname, int flags)
2336 {
2337   const char* image_mode = NULL;
2338 
2339   UNUSED(flags);
2340   if (access(pathname, F_OK) < 0) {
2341     BX_PANIC(("r/o disk image doesn't exist"));
2342   }
2343   if (!hdimage_detect_image_mode(pathname, &image_mode)) {
2344     BX_PANIC(("r/o disk image mode not detected"));
2345     return -1;
2346   } else {
2347     BX_INFO(("base image mode = '%s'", image_mode));
2348   }
2349   ro_disk = DEV_hdimage_init_image(image_mode, 0, NULL);
2350   if (ro_disk == NULL) {
2351     return -1;
2352   }
2353   if (ro_disk->open(pathname, O_RDONLY) < 0)
2354     return -1;
2355 
2356   hd_size = ro_disk->hd_size;
2357   if (ro_disk->get_capabilities() & HDIMAGE_HAS_GEOMETRY) {
2358     cylinders = ro_disk->cylinders;
2359     heads = ro_disk->heads;
2360     spt = ro_disk->spt;
2361     caps = HDIMAGE_HAS_GEOMETRY;
2362   } else if (cylinders == 0) {
2363     caps = HDIMAGE_AUTO_GEOMETRY;
2364   }
2365   sect_size = ro_disk->sect_size;
2366 
2367   // If not set, we make up the redolog filename from the pathname
2368   if (redolog_name == NULL) {
2369     redolog_name = new char[strlen(pathname) + UNDOABLE_REDOLOG_EXTENSION_LENGTH + 1];
2370     sprintf(redolog_name, "%s%s", pathname, UNDOABLE_REDOLOG_EXTENSION);
2371   }
2372 
2373   if (redolog->open(redolog_name, REDOLOG_SUBTYPE_UNDOABLE) < 0) {
2374     if (redolog->create(redolog_name, REDOLOG_SUBTYPE_UNDOABLE, hd_size) < 0) {
2375       BX_PANIC(("Can't open or create redolog '%s'",redolog_name));
2376       return -1;
2377     }
2378   }
2379   if (!coherency_check(ro_disk, redolog)) {
2380     close();
2381     return -1;
2382   }
2383 
2384   BX_INFO(("'undoable' disk opened: ro-file is '%s', redolog is '%s'", pathname, redolog_name));
2385 
2386   return 0;
2387 }
2388 
close()2389 void undoable_image_t::close()
2390 {
2391   redolog->close();
2392   ro_disk->close();
2393 
2394   if (redolog_name != NULL)
2395     delete [] redolog_name;
2396 }
2397 
lseek(Bit64s offset,int whence)2398 Bit64s undoable_image_t::lseek(Bit64s offset, int whence)
2399 {
2400   redolog->lseek(offset, whence);
2401   return ro_disk->lseek(offset, whence);
2402 }
2403 
read(void * buf,size_t count)2404 ssize_t undoable_image_t::read(void* buf, size_t count)
2405 {
2406   char *cbuf = (char*)buf;
2407   size_t n = 0;
2408   ssize_t ret = 0;
2409 
2410   while (n < count) {
2411     if ((size_t)redolog->read(cbuf, 512) != 512) {
2412       ret = ro_disk->read(cbuf, 512);
2413       if (ret < 0) break;
2414     }
2415     cbuf += 512;
2416     n += 512;
2417   }
2418   return (ret < 0) ? ret : count;
2419 }
2420 
write(const void * buf,size_t count)2421 ssize_t undoable_image_t::write(const void* buf, size_t count)
2422 {
2423   char *cbuf = (char*)buf;
2424   size_t n = 0;
2425   ssize_t ret = 0;
2426 
2427   while (n < count) {
2428     ret = redolog->write(cbuf, 512);
2429     if (ret < 0) break;
2430     cbuf += 512;
2431     n += 512;
2432   }
2433   return (ret < 0) ? ret : count;
2434 }
2435 
2436 #ifndef BXIMAGE
save_state(const char * backup_fname)2437 bool undoable_image_t::save_state(const char *backup_fname)
2438 {
2439   return redolog->save_state(backup_fname);
2440 }
2441 
restore_state(const char * backup_fname)2442 void undoable_image_t::restore_state(const char *backup_fname)
2443 {
2444   redolog_t *temp_redolog = new redolog_t();
2445   if (temp_redolog->open(backup_fname, REDOLOG_SUBTYPE_UNDOABLE, O_RDONLY) < 0) {
2446     delete temp_redolog;
2447     BX_PANIC(("Can't open undoable redolog backup '%s'", backup_fname));
2448     return;
2449   } else {
2450     bool okay = coherency_check(ro_disk, temp_redolog);
2451     temp_redolog->close();
2452     delete temp_redolog;
2453     if (!okay) return;
2454   }
2455   redolog->close();
2456   if (!hdimage_copy_file(backup_fname, redolog_name)) {
2457     BX_PANIC(("Failed to restore undoable redolog '%s'", redolog_name));
2458     return;
2459   } else {
2460     if (redolog->open(redolog_name, REDOLOG_SUBTYPE_UNDOABLE) < 0) {
2461       BX_PANIC(("Can't open restored undoable redolog '%s'", redolog_name));
2462     }
2463   }
2464 }
2465 #endif
2466 
2467 /*** volatile_image_t function definitions ***/
2468 
volatile_image_t(const char * _redolog_name)2469 volatile_image_t::volatile_image_t(const char* _redolog_name)
2470 {
2471   redolog = new redolog_t();
2472   redolog_temp = NULL;
2473   redolog_name = NULL;
2474   if (_redolog_name != NULL) {
2475     if ((strlen(_redolog_name) > 0) && (strcmp(_redolog_name,"none") != 0)) {
2476       redolog_name = new char[strlen(_redolog_name) + 1];
2477       strcpy(redolog_name, _redolog_name);
2478     }
2479   }
2480 }
2481 
~volatile_image_t()2482 volatile_image_t::~volatile_image_t()
2483 {
2484   delete redolog;
2485   delete ro_disk;
2486 }
2487 
open(const char * pathname,int flags)2488 int volatile_image_t::open(const char* pathname, int flags)
2489 {
2490   int filedes;
2491   Bit32u timestamp;
2492   const char* image_mode = NULL;
2493 
2494   UNUSED(flags);
2495   if (access(pathname, F_OK) < 0) {
2496     BX_PANIC(("r/o disk image doesn't exist"));
2497   }
2498   if (!hdimage_detect_image_mode(pathname, &image_mode)) {
2499     BX_PANIC(("r/o disk image mode not detected"));
2500     return -1;
2501   } else {
2502     BX_INFO(("base image mode = '%s'", image_mode));
2503   }
2504   ro_disk = DEV_hdimage_init_image(image_mode, 0, NULL);
2505   if (ro_disk == NULL) {
2506     return -1;
2507   }
2508   if (ro_disk->open(pathname, O_RDONLY)<0)
2509     return -1;
2510 
2511   hd_size = ro_disk->hd_size;
2512   if (ro_disk->get_capabilities() & HDIMAGE_HAS_GEOMETRY) {
2513     cylinders = ro_disk->cylinders;
2514     heads = ro_disk->heads;
2515     spt = ro_disk->spt;
2516     caps = HDIMAGE_HAS_GEOMETRY;
2517   } else if (cylinders == 0) {
2518     caps = HDIMAGE_AUTO_GEOMETRY;
2519   }
2520   sect_size = ro_disk->sect_size;
2521 
2522   // If not set, use pathname as template
2523   if (redolog_name == NULL) {
2524     redolog_name = new char[strlen(pathname) + 1];
2525     strcpy(redolog_name, pathname);
2526   }
2527 
2528   redolog_temp = new char[strlen(redolog_name) + VOLATILE_REDOLOG_EXTENSION_LENGTH + 1];
2529   sprintf(redolog_temp, "%s%s", redolog_name, VOLATILE_REDOLOG_EXTENSION);
2530 
2531   filedes = mkstemp(redolog_temp);
2532 
2533   if (filedes < 0) {
2534     BX_PANIC(("Can't create volatile redolog '%s'", redolog_temp));
2535     return -1;
2536   }
2537   if (redolog->create(filedes, REDOLOG_SUBTYPE_VOLATILE, hd_size) < 0) {
2538     BX_PANIC(("Can't create volatile redolog '%s'", redolog_temp));
2539     return -1;
2540   }
2541 
2542 #if (!defined(WIN32)) && !BX_WITH_MACOS
2543   // on unix it is legal to delete an open file
2544   unlink(redolog_temp);
2545 #endif
2546 
2547   // timestamp required for save/restore support
2548   timestamp = ro_disk->get_timestamp();
2549   redolog->set_timestamp(timestamp);
2550 
2551   BX_INFO(("'volatile' disk opened: ro-file is '%s', redolog is '%s'", pathname, redolog_temp));
2552 
2553   return 0;
2554 }
2555 
close()2556 void volatile_image_t::close()
2557 {
2558   redolog->close();
2559   ro_disk->close();
2560 
2561 #if defined(WIN32) || BX_WITH_MACOS
2562   // on non-unix we have to wait till the file is closed to delete it
2563   unlink(redolog_temp);
2564 #endif
2565   if (redolog_temp!=NULL)
2566     delete [] redolog_temp;
2567 
2568   if (redolog_name!=NULL)
2569     delete [] redolog_name;
2570 }
2571 
lseek(Bit64s offset,int whence)2572 Bit64s volatile_image_t::lseek(Bit64s offset, int whence)
2573 {
2574   redolog->lseek(offset, whence);
2575   return ro_disk->lseek(offset, whence);
2576 }
2577 
read(void * buf,size_t count)2578 ssize_t volatile_image_t::read(void* buf, size_t count)
2579 {
2580   char *cbuf = (char*)buf;
2581   size_t n = 0;
2582   ssize_t ret = 0;
2583 
2584   while (n < count) {
2585     if ((size_t)redolog->read(cbuf, 512) != 512) {
2586       ret = ro_disk->read(cbuf, 512);
2587       if (ret < 0) break;
2588     }
2589     cbuf += 512;
2590     n += 512;
2591   }
2592   return (ret < 0) ? ret : count;
2593 }
2594 
write(const void * buf,size_t count)2595 ssize_t volatile_image_t::write(const void* buf, size_t count)
2596 {
2597   char *cbuf = (char*)buf;
2598   size_t n = 0;
2599   ssize_t ret = 0;
2600 
2601   while (n < count) {
2602     ret = redolog->write(cbuf, 512);
2603     if (ret < 0) break;
2604     cbuf += 512;
2605     n += 512;
2606   }
2607   return (ret < 0) ? ret : count;
2608 }
2609 
2610 #ifndef BXIMAGE
save_state(const char * backup_fname)2611 bool volatile_image_t::save_state(const char *backup_fname)
2612 {
2613   return redolog->save_state(backup_fname);
2614 }
2615 
restore_state(const char * backup_fname)2616 void volatile_image_t::restore_state(const char *backup_fname)
2617 {
2618   redolog_t *temp_redolog = new redolog_t();
2619   if (temp_redolog->open(backup_fname, REDOLOG_SUBTYPE_VOLATILE, O_RDONLY) < 0) {
2620     delete temp_redolog;
2621     BX_PANIC(("Can't open volatile redolog backup '%s'", backup_fname));
2622     return;
2623   } else {
2624     bool okay = coherency_check(ro_disk, temp_redolog);
2625     temp_redolog->close();
2626     delete temp_redolog;
2627     if (!okay) return;
2628   }
2629   redolog->close();
2630   if (!hdimage_copy_file(backup_fname, redolog_temp)) {
2631     BX_PANIC(("Failed to restore volatile redolog '%s'", redolog_temp));
2632     return;
2633   } else {
2634     if (redolog->open(redolog_temp, REDOLOG_SUBTYPE_VOLATILE) < 0) {
2635       BX_PANIC(("Can't open restored volatile redolog '%s'", redolog_temp));
2636       return;
2637     }
2638   }
2639 #if (!defined(WIN32)) && !BX_WITH_MACOS
2640   // on unix it is legal to delete an open file
2641   unlink(redolog_temp);
2642 #endif
2643 }
2644 #endif
2645