diff --git a/bochs/iodev/hdimage/hdimage.cc b/bochs/iodev/hdimage/hdimage.cc index ad7616842..781011fd4 100644 --- a/bochs/iodev/hdimage/hdimage.cc +++ b/bochs/iodev/hdimage/hdimage.cc @@ -234,7 +234,7 @@ int hdimage_detect_image_mode(const char *pathname) result = BX_HDIMAGE_MODE_VMWARE4; } else if (growing_image_t::check_format(fd, image_size) == HDIMAGE_FORMAT_OK) { result = BX_HDIMAGE_MODE_GROWING; - } else if (vpc_image_t::check_format(fd, image_size) == HDIMAGE_FORMAT_OK) { + } else if (vpc_image_t::check_format(fd, image_size) >= HDIMAGE_FORMAT_OK) { result = BX_HDIMAGE_MODE_VPC; } else if (default_image_t::check_format(fd, image_size) == HDIMAGE_FORMAT_OK) { result = BX_HDIMAGE_MODE_FLAT; diff --git a/bochs/iodev/hdimage/vpc-img.cc b/bochs/iodev/hdimage/vpc-img.cc index 970c7c9b4..8650dd40a 100644 --- a/bochs/iodev/hdimage/vpc-img.cc +++ b/bochs/iodev/hdimage/vpc-img.cc @@ -52,44 +52,31 @@ #define cpu_to_be32(val) (val) #endif -int vpc_image_t::vpc_check_header(const char* _pathname, int* disk_type) +int vpc_image_t::check_format(int fd, Bit64u imgsize) { - int filedes, vpc_disk_type; - Bit64u imgsize; + Bit8u temp_footer_buf[HEADER_SIZE]; vhd_footer_t *footer; + int vpc_disk_type = VHD_DYNAMIC; - vpc_disk_type = VHD_DYNAMIC; - - if ((filedes = hdimage_open_file(_pathname, O_RDWR, &imgsize, NULL)) < 0) { - BX_ERROR(("VPC: cannot open hdimage file", _pathname)); - return -1; + if (bx_read_image(fd, 0, (char*)temp_footer_buf, HEADER_SIZE) != HEADER_SIZE) { + return HDIMAGE_READ_ERROR; } - if (bx_read_image(filedes, 0, (char*)footer_buf, HEADER_SIZE) != HEADER_SIZE) { - BX_ERROR(("VPC: cannot read image file header", _pathname)); - return -1; - } - - footer = (vhd_footer_t*)footer_buf; + footer = (vhd_footer_t*)temp_footer_buf; if (strncmp((char*)footer->creator, "conectix", 8)) { if (imgsize < HEADER_SIZE) { - BX_ERROR(("VPC: signature missed", _pathname)); - return -1; + return HDIMAGE_NO_SIGNATURE; } // If a fixed disk, the footer is found only at the end of the file - if (bx_read_image(filedes, imgsize-HEADER_SIZE, (char*)footer_buf, HEADER_SIZE) != HEADER_SIZE) { - return -1; + if (bx_read_image(fd, imgsize-HEADER_SIZE, (char*)temp_footer_buf, HEADER_SIZE) != HEADER_SIZE) { + return HDIMAGE_READ_ERROR; } if (strncmp((char*)footer->creator, "conectix", 8)) { - BX_ERROR(("VPC: signature missed", _pathname)); - return -1; + return HDIMAGE_NO_SIGNATURE; } vpc_disk_type = VHD_FIXED; } - if (disk_type != NULL) { - *disk_type = vpc_disk_type; - } - return filedes; + return vpc_disk_type; } int vpc_image_t::open(const char* _pathname) @@ -99,11 +86,27 @@ int vpc_image_t::open(const char* _pathname) vhd_dyndisk_header_t *dyndisk_header; Bit8u buf[HEADER_SIZE]; Bit32u checksum; + Bit64u imgsize = 0; int disk_type; pathname = _pathname; - if ((fd = vpc_check_header(pathname, &disk_type)) < 0) { - ::close(fd); + if ((fd = hdimage_open_file(pathname, O_RDWR, &imgsize, NULL)) < 0) { + BX_ERROR(("VPC: cannot open hdimage file '%s'", pathname)); + return -1; + } + + disk_type = check_format(fd, imgsize); + if (disk_type < 0) { + switch (disk_type) { + case HDIMAGE_READ_ERROR: + BX_ERROR(("VPC: cannot read image file header of '%s'", _pathname)); + return -1; + case HDIMAGE_NO_SIGNATURE: + BX_ERROR(("VPC: signature missed in file '%s'", _pathname)); + return -1; + } + } + if (bx_read_image(fd, 0, (char*)footer_buf, HEADER_SIZE) != HEADER_SIZE) { return -1; } footer = (vhd_footer_t*)footer_buf; @@ -288,12 +291,19 @@ bx_bool vpc_image_t::save_state(const char *backup_fname) void vpc_image_t::restore_state(const char *backup_fname) { int temp_fd; + Bit64u imgsize; - if ((temp_fd = vpc_check_header(backup_fname, NULL)) < 0) { + if ((temp_fd = hdimage_open_file(backup_fname, O_RDWR, &imgsize, NULL)) < 0) { + BX_PANIC(("cannot open vpc image backup '%s'", backup_fname)); + return; + } + + if (check_format(temp_fd, imgsize) < HDIMAGE_FORMAT_OK) { ::close(temp_fd); BX_PANIC(("Could not detect vpc image header")); return; } + ::close(temp_fd); close(); if (!hdimage_copy_file(backup_fname, pathname)) { BX_PANIC(("Failed to restore vpc image '%s'", pathname)); diff --git a/bochs/iodev/hdimage/vpc-img.h b/bochs/iodev/hdimage/vpc-img.h index 79efb877e..6e3f1992d 100644 --- a/bochs/iodev/hdimage/vpc-img.h +++ b/bochs/iodev/hdimage/vpc-img.h @@ -143,12 +143,14 @@ class vpc_image_t : public device_image_t Bit64s lseek(Bit64s offset, int whence); ssize_t read(void* buf, size_t count); ssize_t write(const void* buf, size_t count); + Bit32u get_capabilities(); + static int check_format(int fd, Bit64u imgsize); + bx_bool save_state(const char *backup_fname); void restore_state(const char *backup_fname); private: - int vpc_check_header(const char* pathname, int *disk_type); Bit32u vpc_checksum(Bit8u *buf, size_t size); Bit64s get_sector_offset(Bit64s sector_num, int write); int rewrite_footer(void);