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;
} 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;

View File

@ -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));

View File

@ -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);