Add VHD hard disc image support. Patch from shermanp.
This commit is contained in:
parent
d1021b5b6b
commit
602d6f1ce6
31 changed files with 6559 additions and 1073 deletions
189
src/hdd_file.c
189
src/hdd_file.c
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
#include "ibm.h"
|
||||
#include "hdd_file.h"
|
||||
#include "minivhd/minivhd.h"
|
||||
#include "minivhd/minivhd_util.h"
|
||||
|
||||
void hdd_load_ext(hdd_file_t *hdd, const char *fn, int spt, int hpc, int tracks, int read_only)
|
||||
{
|
||||
|
|
@ -12,17 +14,52 @@ void hdd_load_ext(hdd_file_t *hdd, const char *fn, int spt, int hpc, int tracks,
|
|||
{
|
||||
/* Try to open existing hard disk image */
|
||||
if (read_only)
|
||||
hdd->f = fopen64(fn, "rb");
|
||||
hdd->f = (void*)fopen64(fn, "rb");
|
||||
else
|
||||
hdd->f = (void*)fopen64(fn, "rb+");
|
||||
if (hdd->f != NULL)
|
||||
{
|
||||
hdd->img_type = HDD_IMG_RAW;
|
||||
/* Check if the file we opened is a VHD */
|
||||
if (mvhd_file_is_vhd((FILE*)hdd->f))
|
||||
{
|
||||
int err;
|
||||
fclose((FILE*)hdd->f);
|
||||
MVHDMeta *vhdm = mvhd_open(fn, (bool)read_only, &err);
|
||||
if (vhdm == NULL)
|
||||
{
|
||||
hdd->f = NULL;
|
||||
if (err == MVHD_ERR_FILE)
|
||||
{
|
||||
pclog("Cannot open VHD file '%s' : %s",
|
||||
fn, strerror(mvhd_errno));
|
||||
}
|
||||
else
|
||||
{
|
||||
pclog("Cannot open VHD file '%s' : %s",
|
||||
fn, mvhd_strerr(err));
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (err == MVHD_ERR_TIMESTAMP)
|
||||
{
|
||||
pclog("VHD: Parent/child timestamp mismatch");
|
||||
mvhd_close(vhdm);
|
||||
hdd->f = NULL;
|
||||
return;
|
||||
}
|
||||
hdd->f = (void*)vhdm;
|
||||
hdd->img_type = HDD_IMG_VHD;
|
||||
}
|
||||
}
|
||||
else
|
||||
hdd->f = fopen64(fn, "rb+");
|
||||
if (hdd->f == NULL)
|
||||
{
|
||||
/* Failed to open existing hard disk image */
|
||||
if (errno == ENOENT && !read_only)
|
||||
{
|
||||
/* Failed because it does not exist,
|
||||
so try to create new file */
|
||||
hdd->f = fopen64(fn, "wb+");
|
||||
hdd->f = (void*)fopen64(fn, "wb+");
|
||||
if (hdd->f == NULL)
|
||||
{
|
||||
pclog("Cannot create file '%s': %s",
|
||||
|
|
@ -37,13 +74,24 @@ void hdd_load_ext(hdd_file_t *hdd, const char *fn, int spt, int hpc, int tracks,
|
|||
fn, strerror(errno));
|
||||
return;
|
||||
}
|
||||
hdd->img_type = HDD_IMG_RAW;
|
||||
}
|
||||
}
|
||||
|
||||
hdd->spt = spt;
|
||||
hdd->hpc = hpc;
|
||||
hdd->tracks = tracks;
|
||||
hdd->sectors = spt * hpc * tracks;
|
||||
if (hdd->img_type == HDD_IMG_VHD)
|
||||
{
|
||||
MVHDMeta *vhdm = (MVHDMeta*)hdd->f;
|
||||
MVHDGeom geom = mvhd_get_geometry(vhdm);
|
||||
hdd->spt = geom.spt;
|
||||
hdd->hpc = geom.heads;
|
||||
hdd->tracks = geom.cyl;
|
||||
}
|
||||
else if (hdd->img_type == HDD_IMG_RAW)
|
||||
{
|
||||
hdd->spt = spt;
|
||||
hdd->hpc = hpc;
|
||||
hdd->tracks = tracks;
|
||||
}
|
||||
hdd->sectors = hdd->spt * hdd->hpc * hdd->tracks;
|
||||
hdd->read_only = read_only;
|
||||
}
|
||||
|
||||
|
|
@ -56,68 +104,99 @@ void hdd_close(hdd_file_t *hdd)
|
|||
{
|
||||
if (hdd->f)
|
||||
{
|
||||
fclose(hdd->f);
|
||||
hdd->f = NULL;
|
||||
if (hdd->img_type == HDD_IMG_VHD)
|
||||
mvhd_close((MVHDMeta*)hdd->f);
|
||||
else if (hdd->img_type == HDD_IMG_RAW)
|
||||
fclose((FILE*)hdd->f);
|
||||
}
|
||||
hdd->img_type = HDD_IMG_RAW;
|
||||
hdd->f = NULL;
|
||||
}
|
||||
|
||||
int hdd_read_sectors(hdd_file_t *hdd, int offset, int nr_sectors, void *buffer)
|
||||
{
|
||||
off64_t addr;
|
||||
int transfer_sectors = nr_sectors;
|
||||
if (hdd->img_type == HDD_IMG_VHD)
|
||||
{
|
||||
return mvhd_read_sectors((MVHDMeta*)hdd->f, offset, nr_sectors, buffer);
|
||||
}
|
||||
else if (hdd->img_type == HDD_IMG_RAW)
|
||||
{
|
||||
off64_t addr;
|
||||
int transfer_sectors = nr_sectors;
|
||||
|
||||
if ((hdd->sectors - offset) < transfer_sectors)
|
||||
transfer_sectors = hdd->sectors - offset;
|
||||
addr = (uint64_t)offset * 512;
|
||||
if ((hdd->sectors - offset) < transfer_sectors)
|
||||
transfer_sectors = hdd->sectors - offset;
|
||||
addr = (uint64_t)offset * 512;
|
||||
|
||||
fseeko64(hdd->f, addr, SEEK_SET);
|
||||
fread(buffer, transfer_sectors*512, 1, hdd->f);
|
||||
|
||||
if (nr_sectors != transfer_sectors)
|
||||
return 1;
|
||||
return 0;
|
||||
fseeko64((FILE*)hdd->f, addr, SEEK_SET);
|
||||
fread(buffer, transfer_sectors*512, 1, (FILE*)hdd->f);
|
||||
|
||||
if (nr_sectors != transfer_sectors)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
/* Keep the compiler happy */
|
||||
return 1;
|
||||
}
|
||||
|
||||
int hdd_write_sectors(hdd_file_t *hdd, int offset, int nr_sectors, void *buffer)
|
||||
{
|
||||
off64_t addr;
|
||||
int transfer_sectors = nr_sectors;
|
||||
|
||||
if (hdd->read_only)
|
||||
return 1;
|
||||
if (hdd->img_type == HDD_IMG_VHD)
|
||||
{
|
||||
return mvhd_write_sectors((MVHDMeta*)hdd->f, offset, nr_sectors, buffer);
|
||||
}
|
||||
else if (hdd->img_type == HDD_IMG_RAW)
|
||||
{
|
||||
off64_t addr;
|
||||
int transfer_sectors = nr_sectors;
|
||||
|
||||
if ((hdd->sectors - offset) < transfer_sectors)
|
||||
transfer_sectors = hdd->sectors - offset;
|
||||
addr = (uint64_t)offset * 512;
|
||||
if (hdd->read_only)
|
||||
return 1;
|
||||
|
||||
fseeko64(hdd->f, addr, SEEK_SET);
|
||||
fwrite(buffer, transfer_sectors*512, 1, hdd->f);
|
||||
|
||||
if (nr_sectors != transfer_sectors)
|
||||
return 1;
|
||||
return 0;
|
||||
if ((hdd->sectors - offset) < transfer_sectors)
|
||||
transfer_sectors = hdd->sectors - offset;
|
||||
addr = (uint64_t)offset * 512;
|
||||
|
||||
fseeko64((FILE*)hdd->f, addr, SEEK_SET);
|
||||
fwrite(buffer, transfer_sectors*512, 1, (FILE*)hdd->f);
|
||||
|
||||
if (nr_sectors != transfer_sectors)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
/* Keep the compiler happy */
|
||||
return 1;
|
||||
}
|
||||
|
||||
int hdd_format_sectors(hdd_file_t *hdd, int offset, int nr_sectors)
|
||||
{
|
||||
off64_t addr;
|
||||
int c;
|
||||
uint8_t zero_buffer[512];
|
||||
int transfer_sectors = nr_sectors;
|
||||
|
||||
if (hdd->read_only)
|
||||
return 1;
|
||||
if (hdd->img_type == HDD_IMG_VHD)
|
||||
{
|
||||
return mvhd_format_sectors((MVHDMeta*)hdd->f, offset, nr_sectors);
|
||||
}
|
||||
else if (hdd->img_type == HDD_IMG_RAW)
|
||||
{
|
||||
off64_t addr;
|
||||
int c;
|
||||
uint8_t zero_buffer[512];
|
||||
int transfer_sectors = nr_sectors;
|
||||
|
||||
memset(zero_buffer, 0, 512);
|
||||
|
||||
if ((hdd->sectors - offset) < transfer_sectors)
|
||||
transfer_sectors = hdd->sectors - offset;
|
||||
addr = (uint64_t)offset * 512;
|
||||
fseeko64(hdd->f, addr, SEEK_SET);
|
||||
for (c = 0; c < transfer_sectors; c++)
|
||||
fwrite(zero_buffer, 512, 1, hdd->f);
|
||||
|
||||
if (nr_sectors != transfer_sectors)
|
||||
return 1;
|
||||
return 0;
|
||||
if (hdd->read_only)
|
||||
return 1;
|
||||
|
||||
memset(zero_buffer, 0, 512);
|
||||
|
||||
if ((hdd->sectors - offset) < transfer_sectors)
|
||||
transfer_sectors = hdd->sectors - offset;
|
||||
addr = (uint64_t)offset * 512;
|
||||
fseeko64((FILE*)hdd->f, addr, SEEK_SET);
|
||||
for (c = 0; c < transfer_sectors; c++)
|
||||
fwrite(zero_buffer, 512, 1, (FILE*)hdd->f);
|
||||
|
||||
if (nr_sectors != transfer_sectors)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
/* Keep the compiler happy */
|
||||
return 1;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue