vpc-img: implemented check_format() for image autodetection

This commit is contained in:
Volker Ruppert 2012-10-03 21:25:20 +00:00
parent be1642e02e
commit d6bdc0c18f
3 changed files with 41 additions and 29 deletions

View File

@ -234,7 +234,7 @@ int hdimage_detect_image_mode(const char *pathname)
result = BX_HDIMAGE_MODE_VMWARE4; result = BX_HDIMAGE_MODE_VMWARE4;
} else if (growing_image_t::check_format(fd, image_size) == HDIMAGE_FORMAT_OK) { } else if (growing_image_t::check_format(fd, image_size) == HDIMAGE_FORMAT_OK) {
result = BX_HDIMAGE_MODE_GROWING; 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; result = BX_HDIMAGE_MODE_VPC;
} else if (default_image_t::check_format(fd, image_size) == HDIMAGE_FORMAT_OK) { } else if (default_image_t::check_format(fd, image_size) == HDIMAGE_FORMAT_OK) {
result = BX_HDIMAGE_MODE_FLAT; result = BX_HDIMAGE_MODE_FLAT;

View File

@ -52,44 +52,31 @@
#define cpu_to_be32(val) (val) #define cpu_to_be32(val) (val)
#endif #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; Bit8u temp_footer_buf[HEADER_SIZE];
Bit64u imgsize;
vhd_footer_t *footer; vhd_footer_t *footer;
int vpc_disk_type = VHD_DYNAMIC;
vpc_disk_type = VHD_DYNAMIC; if (bx_read_image(fd, 0, (char*)temp_footer_buf, HEADER_SIZE) != HEADER_SIZE) {
return HDIMAGE_READ_ERROR;
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(filedes, 0, (char*)footer_buf, HEADER_SIZE) != HEADER_SIZE) { footer = (vhd_footer_t*)temp_footer_buf;
BX_ERROR(("VPC: cannot read image file header", _pathname));
return -1;
}
footer = (vhd_footer_t*)footer_buf;
if (strncmp((char*)footer->creator, "conectix", 8)) { if (strncmp((char*)footer->creator, "conectix", 8)) {
if (imgsize < HEADER_SIZE) { if (imgsize < HEADER_SIZE) {
BX_ERROR(("VPC: signature missed", _pathname)); return HDIMAGE_NO_SIGNATURE;
return -1;
} }
// If a fixed disk, the footer is found only at the end of the file // 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) { if (bx_read_image(fd, imgsize-HEADER_SIZE, (char*)temp_footer_buf, HEADER_SIZE) != HEADER_SIZE) {
return -1; return HDIMAGE_READ_ERROR;
} }
if (strncmp((char*)footer->creator, "conectix", 8)) { if (strncmp((char*)footer->creator, "conectix", 8)) {
BX_ERROR(("VPC: signature missed", _pathname)); return HDIMAGE_NO_SIGNATURE;
return -1;
} }
vpc_disk_type = VHD_FIXED; vpc_disk_type = VHD_FIXED;
} }
if (disk_type != NULL) { return vpc_disk_type;
*disk_type = vpc_disk_type;
}
return filedes;
} }
int vpc_image_t::open(const char* _pathname) 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; vhd_dyndisk_header_t *dyndisk_header;
Bit8u buf[HEADER_SIZE]; Bit8u buf[HEADER_SIZE];
Bit32u checksum; Bit32u checksum;
Bit64u imgsize = 0;
int disk_type; int disk_type;
pathname = _pathname; pathname = _pathname;
if ((fd = vpc_check_header(pathname, &disk_type)) < 0) { if ((fd = hdimage_open_file(pathname, O_RDWR, &imgsize, NULL)) < 0) {
::close(fd); 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; return -1;
} }
footer = (vhd_footer_t*)footer_buf; 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) void vpc_image_t::restore_state(const char *backup_fname)
{ {
int temp_fd; 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); ::close(temp_fd);
BX_PANIC(("Could not detect vpc image header")); BX_PANIC(("Could not detect vpc image header"));
return; return;
} }
::close(temp_fd);
close(); close();
if (!hdimage_copy_file(backup_fname, pathname)) { if (!hdimage_copy_file(backup_fname, pathname)) {
BX_PANIC(("Failed to restore vpc image '%s'", pathname)); BX_PANIC(("Failed to restore vpc image '%s'", pathname));

View File

@ -143,12 +143,14 @@ class vpc_image_t : public device_image_t
Bit64s lseek(Bit64s offset, int whence); Bit64s lseek(Bit64s offset, int whence);
ssize_t read(void* buf, size_t count); ssize_t read(void* buf, size_t count);
ssize_t write(const void* buf, size_t count); ssize_t write(const void* buf, size_t count);
Bit32u get_capabilities(); Bit32u get_capabilities();
static int check_format(int fd, Bit64u imgsize);
bx_bool save_state(const char *backup_fname); bx_bool save_state(const char *backup_fname);
void restore_state(const char *backup_fname); void restore_state(const char *backup_fname);
private: private:
int vpc_check_header(const char* pathname, int *disk_type);
Bit32u vpc_checksum(Bit8u *buf, size_t size); Bit32u vpc_checksum(Bit8u *buf, size_t size);
Bit64s get_sector_offset(Bit64s sector_num, int write); Bit64s get_sector_offset(Bit64s sector_num, int write);
int rewrite_footer(void); int rewrite_footer(void);