From 2184a982f83c54dcbb1600fb7c82131e2d270331 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Tue, 29 Oct 2024 15:14:27 -0300 Subject: [PATCH] MiniVHD: Report read/write errors --- src/disk/hdd_image.c | 17 ++++++-- src/disk/minivhd/internal.h | 3 +- src/disk/minivhd/minivhd_io.c | 80 +++++++++++++++++++++++------------ 3 files changed, 69 insertions(+), 31 deletions(-) diff --git a/src/disk/hdd_image.c b/src/disk/hdd_image.c index 4607e2b14..402140408 100644 --- a/src/disk/hdd_image.c +++ b/src/disk/hdd_image.c @@ -529,8 +529,11 @@ hdd_image_read(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer) size_t num_read; if (hdd_images[id].type == HDD_IMAGE_VHD) { - non_transferred_sectors = mvhd_read_sectors(hdd_images[id].vhd, sector, count, buffer); - hdd_images[id].pos = sector + count - non_transferred_sectors - 1; + hdd_images[id].vhd->error = 0; + non_transferred_sectors = mvhd_read_sectors(hdd_images[id].vhd, sector, count, buffer); + hdd_images[id].pos = sector + count - non_transferred_sectors - 1; + if (hdd_images[id].vhd->error) + return -1; } else { if (!hdd_images[id].file || (fseeko64(hdd_images[id].file, ((uint64_t) (sector) << 9LL) + hdd_images[id].base, SEEK_SET) == -1)) { hdd_image_log("Hard disk image %i: Read error during seek\n", id); @@ -582,8 +585,11 @@ hdd_image_write(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer) size_t num_write; if (hdd_images[id].type == HDD_IMAGE_VHD) { - non_transferred_sectors = mvhd_write_sectors(hdd_images[id].vhd, sector, count, buffer); - hdd_images[id].pos = sector + count - non_transferred_sectors - 1; + hdd_images[id].vhd->error = 0; + non_transferred_sectors = mvhd_write_sectors(hdd_images[id].vhd, sector, count, buffer); + hdd_images[id].pos = sector + count - non_transferred_sectors - 1; + if (hdd_images[id].vhd->error) + return -1; } else { if (!hdd_images[id].file || (fseeko64(hdd_images[id].file, ((uint64_t) (sector) << 9LL) + hdd_images[id].base, SEEK_SET) == -1)) { hdd_image_log("Hard disk image %i: Write error during seek\n", id); @@ -621,8 +627,11 @@ int hdd_image_zero(uint8_t id, uint32_t sector, uint32_t count) { if (hdd_images[id].type == HDD_IMAGE_VHD) { + hdd_images[id].vhd->error = 0; int non_transferred_sectors = mvhd_format_sectors(hdd_images[id].vhd, sector, count); hdd_images[id].pos = sector + count - non_transferred_sectors - 1; + if (hdd_images[id].vhd->error) + return -1; } else { memset(empty_sector, 0, 512); diff --git a/src/disk/minivhd/internal.h b/src/disk/minivhd/internal.h index d3f930110..4caef7c47 100644 --- a/src/disk/minivhd/internal.h +++ b/src/disk/minivhd/internal.h @@ -115,6 +115,7 @@ typedef struct MVHDSparseHeader { struct MVHDMeta { FILE* f; bool readonly; + bool error; char filename[MVHD_MAX_PATH_BYTES]; struct MVHDMeta* parent; MVHDFooter footer; @@ -271,7 +272,7 @@ struct MVHDMeta* mvhd_create_fixed_raw(const char* path, FILE* raw_img, uint64_t * \param [in] f File to write sectors to * \param [in] sector_count The number of sectors to write */ -void mvhd_write_empty_sectors(FILE* f, int sector_count); +bool mvhd_write_empty_sectors(FILE* f, int sector_count); /** * \brief Read a fixed VHD image diff --git a/src/disk/minivhd/minivhd_io.c b/src/disk/minivhd/minivhd_io.c index 1a349dbc4..cdf6694a8 100644 --- a/src/disk/minivhd/minivhd_io.c +++ b/src/disk/minivhd/minivhd_io.c @@ -82,15 +82,18 @@ check_sectors(uint32_t offset, int num_sectors, uint32_t total_sectors, int *tra } } -void +bool mvhd_write_empty_sectors(FILE *f, int sector_count) { uint8_t zero_bytes[MVHD_SECTOR_SIZE] = {0}; - for (int i = 0; i < sector_count; i++) - fwrite(zero_bytes, sizeof zero_bytes, 1, f); + for (int i = 0; i < sector_count; i++) { + if (!fwrite(zero_bytes, sizeof zero_bytes, 1, f)) + return 0; + } fflush(f); + return 1; } /** @@ -107,7 +110,8 @@ read_sect_bitmap(MVHDMeta *vhdm, int blk) { if (vhdm->block_offset[blk] != MVHD_SPARSE_BLK) { mvhd_fseeko64(vhdm->f, (uint64_t)vhdm->block_offset[blk] * MVHD_SECTOR_SIZE, SEEK_SET); - (void) !fread(vhdm->bitmap.curr_bitmap, vhdm->bitmap.sector_count * MVHD_SECTOR_SIZE, 1, vhdm->f); + if (!fread(vhdm->bitmap.curr_bitmap, vhdm->bitmap.sector_count * MVHD_SECTOR_SIZE, 1, vhdm->f)) + vhdm->error = 1; } else memset(vhdm->bitmap.curr_bitmap, 0, vhdm->bitmap.sector_count * MVHD_SECTOR_SIZE); @@ -124,8 +128,10 @@ write_curr_sect_bitmap(MVHDMeta* vhdm) { if (vhdm->bitmap.curr_block >= 0) { int64_t abs_offset = (int64_t)vhdm->block_offset[vhdm->bitmap.curr_block] * MVHD_SECTOR_SIZE; - mvhd_fseeko64(vhdm->f, abs_offset, SEEK_SET); - fwrite(vhdm->bitmap.curr_bitmap, MVHD_SECTOR_SIZE, vhdm->bitmap.sector_count, vhdm->f); + if (mvhd_fseeko64(vhdm->f, abs_offset, SEEK_SET) == -1) + vhdm->error = 1; + if (!fwrite(vhdm->bitmap.curr_bitmap, MVHD_SECTOR_SIZE, vhdm->bitmap.sector_count, vhdm->f)) + vhdm->error = 1; } } @@ -141,8 +147,10 @@ write_bat_entry(MVHDMeta *vhdm, int blk) uint64_t table_offset = vhdm->sparse.bat_offset + ((uint64_t)blk * sizeof *vhdm->block_offset); uint32_t offset = mvhd_to_be32(vhdm->block_offset[blk]); - mvhd_fseeko64(vhdm->f, table_offset, SEEK_SET); - fwrite(&offset, sizeof offset, 1, vhdm->f); + if (mvhd_fseeko64(vhdm->f, table_offset, SEEK_SET) == -1) + vhdm->error = 1; + if (!fwrite(&offset, sizeof offset, 1, vhdm->f)) + vhdm->error = 1; fflush(vhdm->f); } @@ -173,7 +181,8 @@ create_block(MVHDMeta *vhdm, int blk) if (!mvhd_is_conectix_str(footer)) { /* Oh dear. We use the header instead, since something has gone wrong at the footer */ mvhd_fseeko64(vhdm->f, 0, SEEK_SET); - (void) !fread(footer, sizeof footer, 1, vhdm->f); + if (!fread(footer, sizeof footer, 1, vhdm->f)) + vhdm->error = 1; mvhd_fseeko64(vhdm->f, 0, SEEK_END); } @@ -182,20 +191,25 @@ create_block(MVHDMeta *vhdm, int blk) /* Yikes! We're supposed to be on a sector boundary. Add some padding */ int64_t padding_amount = ((int64_t) MVHD_SECTOR_SIZE) - (abs_offset % MVHD_SECTOR_SIZE); uint8_t zero_byte = 0; - for (int i = 0; i < padding_amount; i++) - fwrite(&zero_byte, sizeof zero_byte, 1, vhdm->f); + for (int i = 0; i < padding_amount; i++) { + if (!fwrite(&zero_byte, sizeof zero_byte, 1, vhdm->f)) + vhdm->error = 1; + } abs_offset += padding_amount; } uint32_t sect_offset = (uint32_t)(abs_offset / MVHD_SECTOR_SIZE); int blk_size_sectors = vhdm->sparse.block_sz / MVHD_SECTOR_SIZE; - mvhd_write_empty_sectors(vhdm->f, vhdm->bitmap.sector_count + blk_size_sectors); + if (!mvhd_write_empty_sectors(vhdm->f, vhdm->bitmap.sector_count + blk_size_sectors)) + vhdm->error = 1; /* Add a bit of padding. That's what Windows appears to do, although it's not strictly necessary... */ - mvhd_write_empty_sectors(vhdm->f, 5); + if (!mvhd_write_empty_sectors(vhdm->f, 5)) + vhdm->error = 1; /* And we finish with the footer */ - fwrite(footer, sizeof footer, 1, vhdm->f); + if (!fwrite(footer, sizeof footer, 1, vhdm->f)) + vhdm->error = 1; /* We no longer have a sparse block. Update that BAT! */ vhdm->block_offset[blk] = sect_offset; @@ -214,8 +228,10 @@ mvhd_fixed_read(MVHDMeta *vhdm, uint32_t offset, int num_sectors, void *out_buff check_sectors(offset, num_sectors, total_sectors, &transfer_sectors, &truncated_sectors); addr = ((int64_t) offset) * MVHD_SECTOR_SIZE; - mvhd_fseeko64(vhdm->f, addr, SEEK_SET); - (void) !fread(out_buff, transfer_sectors * MVHD_SECTOR_SIZE, 1, vhdm->f); + if (mvhd_fseeko64(vhdm->f, addr, SEEK_SET) == -1) + vhdm->error = 1; + if (!fread(out_buff, transfer_sectors * MVHD_SECTOR_SIZE, 1, vhdm->f)) + vhdm->error = 1; return truncated_sectors; } @@ -245,17 +261,20 @@ mvhd_sparse_read(MVHDMeta *vhdm, uint32_t offset, int num_sectors, void *out_buf prev_blk = blk; if (vhdm->bitmap.curr_block != blk) { read_sect_bitmap(vhdm, blk); - mvhd_fseeko64(vhdm->f, (uint64_t)sib * MVHD_SECTOR_SIZE, SEEK_CUR); + if (mvhd_fseeko64(vhdm->f, (uint64_t)sib * MVHD_SECTOR_SIZE, SEEK_CUR) == -1) + vhdm->error = 1; } else { addr = (((int64_t) vhdm->block_offset[blk]) + vhdm->bitmap.sector_count + sib) * MVHD_SECTOR_SIZE; - mvhd_fseeko64(vhdm->f, addr, SEEK_SET); + if (mvhd_fseeko64(vhdm->f, addr, SEEK_SET) == -1) + vhdm->error = 1; } } - if (VHD_TESTBIT(vhdm->bitmap.curr_bitmap, sib)) - (void) !fread(buff, MVHD_SECTOR_SIZE, 1, vhdm->f); - else { + if (VHD_TESTBIT(vhdm->bitmap.curr_bitmap, sib)) { + if (!fread(buff, MVHD_SECTOR_SIZE, 1, vhdm->f)) + vhdm->error = 1; + } else { memset(buff, 0, MVHD_SECTOR_SIZE); mvhd_fseeko64(vhdm->f, MVHD_SECTOR_SIZE, SEEK_CUR); } @@ -301,6 +320,10 @@ mvhd_diff_read(MVHDMeta *vhdm, uint32_t offset, int num_sectors, void *out_buff) mvhd_sparse_read(curr_vhdm, s, 1, buff); else mvhd_fixed_read(curr_vhdm, s, 1, buff); + if (curr_vhdm->error) { + curr_vhdm->error = 0; + vhdm->error = 1; + } curr_vhdm = vhdm; buff += MVHD_SECTOR_SIZE; @@ -320,8 +343,10 @@ mvhd_fixed_write(MVHDMeta *vhdm, uint32_t offset, int num_sectors, void *in_buff check_sectors(offset, num_sectors, total_sectors, &transfer_sectors, &truncated_sectors); addr = (int64_t)offset * MVHD_SECTOR_SIZE; - mvhd_fseeko64(vhdm->f, addr, SEEK_SET); - fwrite(in_buff, transfer_sectors * MVHD_SECTOR_SIZE, 1, vhdm->f); + if (mvhd_fseeko64(vhdm->f, addr, SEEK_SET) == -1) + vhdm->error = 1; + if (!fwrite(in_buff, transfer_sectors * MVHD_SECTOR_SIZE, 1, vhdm->f)) + vhdm->error = 1; fflush(vhdm->f); return truncated_sectors; @@ -364,16 +389,19 @@ mvhd_sparse_diff_write(MVHDMeta *vhdm, uint32_t offset, int num_sectors, void *i if (blk != prev_blk) { if (vhdm->bitmap.curr_block != blk) { read_sect_bitmap(vhdm, blk); - mvhd_fseeko64(vhdm->f, (uint64_t)sib * MVHD_SECTOR_SIZE, SEEK_CUR); + if (mvhd_fseeko64(vhdm->f, (uint64_t)sib * MVHD_SECTOR_SIZE, SEEK_CUR) == -1) + vhdm->error = 1; } else { addr = (((int64_t) vhdm->block_offset[blk]) + vhdm->bitmap.sector_count + sib) * MVHD_SECTOR_SIZE; - mvhd_fseeko64(vhdm->f, addr, SEEK_SET); + if (mvhd_fseeko64(vhdm->f, addr, SEEK_SET) == -1) + vhdm->error = 1; } prev_blk = blk; } - fwrite(buff, MVHD_SECTOR_SIZE, 1, vhdm->f); + if (!fwrite(buff, MVHD_SECTOR_SIZE, 1, vhdm->f)) + vhdm->error = 1; VHD_SETBIT(vhdm->bitmap.curr_bitmap, sib); buff += MVHD_SECTOR_SIZE; }