diff --git a/bochs/iodev/hdimage.cc b/bochs/iodev/hdimage.cc index 4d16bfdba..fd047a42a 100644 --- a/bochs/iodev/hdimage.cc +++ b/bochs/iodev/hdimage.cc @@ -159,6 +159,7 @@ int default_image_t::open(const char* pathname, int flags) if (hFile != INVALID_HANDLE_VALUE) { ULARGE_INTEGER FileSize; FileSize.LowPart = GetFileSize(hFile, &FileSize.HighPart); + GetFileTime(hFile, NULL, NULL, &mtime); CloseHandle(hFile); if ((FileSize.LowPart != INVALID_FILE_SIZE) || (GetLastError() == NO_ERROR)) { hd_size = FileSize.QuadPart; @@ -195,6 +196,7 @@ int default_image_t::open(const char* pathname, int flags) { hd_size = (Bit64u)stat_buf.st_size; // standard unix procedure to get size of regular files } + mtime = stat_buf.st_mtime; #endif BX_INFO(("hd_size: "FMT_LL"u", hd_size)); if (hd_size <= 0) BX_PANIC(("size of disk image not detected / invalid")); @@ -224,6 +226,11 @@ ssize_t default_image_t::write(const void* buf, size_t count) return ::write(fd, (char*) buf, count); } +Bit32u default_image_t::get_timestamp() +{ + return (fat_datetime(mtime, 1) | (fat_datetime(mtime, 0) << 16)); +} + char increment_string(char *str, int diff) { // find the last character of the string, and increment it. @@ -1032,6 +1039,7 @@ int redolog_t::make_header(const char* type, Bit64u size) else entries *= 2; } while (maxsize < size); + header.specific.timestamp = 0; header.specific.disk = htod64(size); print_header(); @@ -1201,6 +1209,20 @@ Bit64u redolog_t::get_size() return dtoh64(header.specific.disk); } +Bit32u redolog_t::get_timestamp() +{ + return dtoh32(header.specific.timestamp); +} + +bx_bool redolog_t::set_timestamp(Bit32u timestamp) +{ + header.specific.timestamp = htod32(timestamp); + // Update header + ::lseek(fd, 0, SEEK_SET); + ::write(fd, &header, dtoh32(header.standard.header)); + return 1; +} + Bit64s redolog_t::lseek(Bit64s offset, int whence) { if ((offset % 512) != 0) { @@ -1444,6 +1466,7 @@ undoable_image_t::~undoable_image_t() int undoable_image_t::open(const char* pathname) { char *logname=NULL; + Bit32u timestamp1, timestamp2; if (ro_disk->open(pathname, O_RDONLY)<0) return -1; @@ -1463,19 +1486,27 @@ int undoable_image_t::open(const char* pathname) sprintf(logname, "%s%s", pathname, UNDOABLE_REDOLOG_EXTENSION); } - if (redolog->open(logname,REDOLOG_SUBTYPE_UNDOABLE) < 0) - { - if (redolog->create(logname, REDOLOG_SUBTYPE_UNDOABLE, hd_size) < 0) - { + if (redolog->open(logname,REDOLOG_SUBTYPE_UNDOABLE) < 0) { + if (redolog->create(logname, REDOLOG_SUBTYPE_UNDOABLE, hd_size) < 0) { BX_PANIC(("Can't open or create redolog '%s'",logname)); return -1; } - if (hd_size != redolog->get_size()) - { - BX_PANIC(("size reported by redolog doesn't match r/o disk size")); + } + if (hd_size != redolog->get_size()) { + BX_PANIC(("size reported by redolog doesn't match r/o disk size")); + free(logname); + return -1; + } + timestamp1 = ro_disk->get_timestamp(); + timestamp2 = redolog->get_timestamp(); + if (timestamp2 != 0) { + if (timestamp1 != timestamp2) { + BX_PANIC(("unexpected modification time of the r/o disk")); free(logname); return -1; } + } else if (timestamp1 != 0) { + redolog->set_timestamp(timestamp1); } BX_INFO(("'undoable' disk opened: ro-file is '%s', redolog is '%s'", pathname, logname)); @@ -1484,7 +1515,7 @@ int undoable_image_t::open(const char* pathname) return 0; } -void undoable_image_t::close () +void undoable_image_t::close() { redolog->close(); ro_disk->close(); diff --git a/bochs/iodev/hdimage.h b/bochs/iodev/hdimage.h index f2b8648f9..d0404be64 100644 --- a/bochs/iodev/hdimage.h +++ b/bochs/iodev/hdimage.h @@ -78,7 +78,7 @@ Bit32u catalog; // #entries in the catalog Bit32u bitmap; // bitmap size in bytes Bit32u extent; // extent size in bytes - Bit32u reserved; // for data alignment + Bit32u timestamp; // modification time in FAT format (subtype 'undoable' only) Bit64u disk; // disk size in bytes } redolog_specific_header_t; @@ -182,8 +182,16 @@ class default_image_t : public device_image_t // written (count). ssize_t write(const void* buf, size_t count); + // Get modification time in FAT format + Bit32u get_timestamp(); + private: int fd; +#ifndef WIN32 + time_t mtime; +#else + FILETIME mtime; +#endif }; // CONCAT MODE @@ -349,6 +357,8 @@ class redolog_t int open(const char* filename, const char* type); void close(); Bit64u get_size(); + Bit32u get_timestamp(); + bx_bool set_timestamp(Bit32u timestamp); Bit64s lseek(Bit64s offset, int whence); ssize_t read(void* buf, size_t count); diff --git a/bochs/iodev/vvfat.cc b/bochs/iodev/vvfat.cc index d3cf2b641..4772f37f3 100644 --- a/bochs/iodev/vvfat.cc +++ b/bochs/iodev/vvfat.cc @@ -487,7 +487,7 @@ static inline Bit8u fat_chksum(const direntry_t* entry) // if return_time==0, this returns the fat_date, else the fat_time #ifndef WIN32 -static Bit16u fat_datetime(time_t time, int return_time) +Bit16u fat_datetime(time_t time, int return_time) { struct tm* t; struct tm t1; @@ -499,7 +499,7 @@ static Bit16u fat_datetime(time_t time, int return_time) return htod16((t->tm_mday) | ((t->tm_mon+1)<<5) | ((t->tm_year-80)<<9)); } #else -static Bit16u fat_datetime(FILETIME time, int return_time) +Bit16u fat_datetime(FILETIME time, int return_time) { FILETIME localtime; SYSTEMTIME systime; diff --git a/bochs/iodev/vvfat.h b/bochs/iodev/vvfat.h index f96ad24f9..253420663 100644 --- a/bochs/iodev/vvfat.h +++ b/bochs/iodev/vvfat.h @@ -106,6 +106,12 @@ typedef struct mapping_t { int read_only; } mapping_t; +#ifndef WIN32 +Bit16u fat_datetime(time_t time, int return_time); +#else +Bit16u fat_datetime(FILETIME time, int return_time); +#endif + class vvfat_image_t : public device_image_t { public: