diff --git a/.vs/MiniVHD/v16/.suo b/.vs/MiniVHD/v16/.suo deleted file mode 100644 index 9254e15..0000000 Binary files a/.vs/MiniVHD/v16/.suo and /dev/null differ diff --git a/.vs/MiniVHD/v16/Browse.VC.db b/.vs/MiniVHD/v16/Browse.VC.db deleted file mode 100644 index 9a760c8..0000000 Binary files a/.vs/MiniVHD/v16/Browse.VC.db and /dev/null differ diff --git a/.vs/MiniVHD/v16/ipch/AutoPCH/aec064f3b1413ba4/MINIVHD_CREATE.ipch b/.vs/MiniVHD/v16/ipch/AutoPCH/aec064f3b1413ba4/MINIVHD_CREATE.ipch deleted file mode 100644 index 8c6c4a0..0000000 Binary files a/.vs/MiniVHD/v16/ipch/AutoPCH/aec064f3b1413ba4/MINIVHD_CREATE.ipch and /dev/null differ diff --git a/.vs/MiniVHD/v16/ipch/AutoPCH/bbb46fed585231f1/MINIVHD_CONVERT.ipch b/.vs/MiniVHD/v16/ipch/AutoPCH/bbb46fed585231f1/MINIVHD_CONVERT.ipch deleted file mode 100644 index 7459a46..0000000 Binary files a/.vs/MiniVHD/v16/ipch/AutoPCH/bbb46fed585231f1/MINIVHD_CONVERT.ipch and /dev/null differ diff --git a/.vs/ProjectSettings.json b/.vs/ProjectSettings.json deleted file mode 100644 index 0cf5ea5..0000000 --- a/.vs/ProjectSettings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "CurrentProjectSetting": "No Configurations" -} \ No newline at end of file diff --git a/.vs/VSWorkspaceState.json b/.vs/VSWorkspaceState.json deleted file mode 100644 index b439506..0000000 --- a/.vs/VSWorkspaceState.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ExpandedNodes": [ - "" - ], - "SelectedNode": "\\CREDITS.md", - "PreviewInSolutionExplorer": false -} \ No newline at end of file diff --git a/.vs/slnx.sqlite b/.vs/slnx.sqlite deleted file mode 100644 index c9826c8..0000000 Binary files a/.vs/slnx.sqlite and /dev/null differ diff --git a/src/minivhd.h b/src/minivhd.h index d18bc64..59dc838 100644 --- a/src/minivhd.h +++ b/src/minivhd.h @@ -21,44 +21,20 @@ typedef enum MVHDError { MVHD_ERR_PAR_NOT_FOUND, MVHD_ERR_INVALID_PAR_UUID, MVHD_ERR_INVALID_GEOM, - MVHD_ERR_INVALID_SIZE, - MVHD_ERR_INVALID_BLOCK_SIZE, - MVHD_ERR_INVALID_PARAMS, + MVHD_ERR_INVALID_PARAMS, MVHD_ERR_CONV_SIZE } MVHDError; -typedef enum MVHDType { - MVHD_TYPE_FIXED = 2, - MVHD_TYPE_DYNAMIC = 3, - MVHD_TYPE_DIFF = 4 -} MVHDType; - -typedef enum MVHDBlockSize { - MVHD_BLOCK_DEFAULT = 0, /**< 2 MB blocks */ - MVHD_BLOCK_SMALL = 1024, /**< 512 KB blocks */ - MVHD_BLOCK_LARGE = 4096 /**< 2 MB blocks */ -} MVHDBlockSize; - typedef struct MVHDGeom { uint16_t cyl; uint8_t heads; uint8_t spt; } MVHDGeom; -typedef void (*mvhd_progress_callback)(uint32_t current_sector, uint32_t total_sectors); - -typedef struct MVHDCreationOptions { - int type; /** MVHD_TYPE_FIXED, MVHD_TYPE_DYNAMIC, or MVHD_TYPE_DIFF */ - char* path; /** Absolute path of the new VHD file */ - char* parent_path; /** For MVHD_TYPE_DIFF, this is the absolute path of the VHD's parent. For non-diff VHDs, this should be NULL. */ - uint64_t size_in_bytes; /** Total size of the VHD's virtual disk in bytes. Must be a multiple of 512. If 0, the size is auto-calculated from the geometry field. Ignored for MVHD_TYPE_DIFF. */ - MVHDGeom geometry; /** The geometry of the VHD. If set to 0, the geometry is auto-calculated from the size_in_bytes field. */ - uint32_t block_size_in_sectors; /** MVHD_BLOCK_LARGE or MVHD_BLOCK_SMALL, or 0 for the default value. The number of sectors per block. */ - mvhd_progress_callback progress_callback; /** Optional; if not NULL, gets called to indicate progress on the creation operation. Only applies to MVHD_TYPE_FIXED. */ -} MVHDCreationOptions; - typedef struct MVHDMeta MVHDMeta; +typedef void (*mvhd_progress_callback)(uint32_t current_sector, uint32_t total_sectors); + /** * \brief Output a string from a MiniVHD error number * @@ -104,9 +80,10 @@ MVHDMeta* mvhd_open(const char* path, bool readonly, int* err); * \param [in] path is the absolute path to the image to create * \param [in] geom is the HDD geometry of the image to create. Determines final image size * \param [out] err indicates what error occurred, if any - * \param [out] progress_callback optional; if not NULL, gets called to indicate progress on the creation operation + * \param [out] progress_callback optional; if not NULL, gets called to indicate progress on the creation operation * - * \retval NULL if an error occurrs. Check value of *err for actual error. Otherwise returns pointer to a MVHDMeta struct + * \retval 0 if success + * \retval < 0 if an error occurrs. Check value of *err for actual error */ MVHDMeta* mvhd_create_fixed(const char* path, MVHDGeom geom, int* err, mvhd_progress_callback progress_callback); @@ -132,18 +109,6 @@ MVHDMeta* mvhd_create_sparse(const char* path, MVHDGeom geom, int* err); */ MVHDMeta* mvhd_create_diff(const char* path, const char* par_path, int* err); -/** - * \brief Create a VHD using the provided options - * - * Use mvhd_create_ex if you want more control over the VHD's options. For quick creation, you can use mvhd_create_fixed, mvhd_create_sparse, or mvhd_create_diff. - * - * \param [in] options the VHD creation options. - * \param [out] err indicates what error occurred, if any - * - * \retval NULL if an error occurrs. Check value of *err for actual error. Otherwise returns pointer to a MVHDMeta struct - */ -MVHDMeta* mvhd_create_ex(MVHDCreationOptions options, int* err); - /** * \brief Safely close a VHD image * @@ -157,9 +122,7 @@ void mvhd_close(MVHDMeta* vhdm); * The VHD format uses Cylinder, Heads, Sectors per Track (CHS) when accessing the disk. * The size of the disk can be determined from C * H * S * sector_size. * - * Note, maximum geometry size (in bytes) is 65535 * 16 * 255 * 512, which is 127GB. - * However, the maximum VHD size is 2040GB. For VHDs larger than 127GB, the geometry size will be - * smaller than the actual VHD size. + * Note, maximum VHD size (in bytes) is 65535 * 16 * 255 * 512, which is 127GB * * This function determines the appropriate CHS geometry from a provided size in bytes. * The calculations used are those provided in "Appendix: CHS Calculation" from the document @@ -216,7 +179,7 @@ FILE* mvhd_convert_to_raw(const char* utf8_vhd_path, const char* utf8_raw_path, * * \return the number of sectors that were not read, or zero */ -int mvhd_read_sectors(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_buff); +int mvhd_read_sectors(MVHDMeta* vhdm, int offset, int num_sectors, void* out_buff); /** * \brief Write sectors to VHD file @@ -230,7 +193,7 @@ int mvhd_read_sectors(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* ou * * \return the number of sectors that were not written, or zero */ -int mvhd_write_sectors(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* in_buff); +int mvhd_write_sectors(MVHDMeta* vhdm, int offset, int num_sectors, void* in_buff); /** * \brief Write zeroed sectors to VHD file @@ -245,5 +208,5 @@ int mvhd_write_sectors(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* i * * \return the number of sectors that were not written, or zero */ -int mvhd_format_sectors(MVHDMeta* vhdm, uint32_t offset, int num_sectors); +int mvhd_format_sectors(MVHDMeta* vhdm, int offset, int num_sectors); #endif \ No newline at end of file diff --git a/src/minivhd_convert.c b/src/minivhd_convert.c index 231e0f9..067863c 100644 --- a/src/minivhd_convert.c +++ b/src/minivhd_convert.c @@ -40,8 +40,7 @@ MVHDMeta* mvhd_convert_to_vhd_fixed(const char* utf8_raw_path, const char* utf8_ if (raw_img == NULL) { return NULL; } - uint64_t size_in_bytes = mvhd_calc_size_bytes(&geom); - MVHDMeta *vhdm = mvhd_create_fixed_raw(utf8_vhd_path, raw_img, size_in_bytes, &geom, err, NULL); + MVHDMeta *vhdm = mvhd_create_fixed_raw(utf8_vhd_path, raw_img, &geom, err, NULL); if (vhdm == NULL) { return NULL; } diff --git a/src/minivhd_create.c b/src/minivhd_create.c index 5f68d3d..37b6715 100644 --- a/src/minivhd_create.c +++ b/src/minivhd_create.c @@ -12,8 +12,8 @@ #include "minivhd_create.h" #include "minivhd.h" -static void mvhd_gen_footer(MVHDFooter* footer, uint64_t size_in_bytes, MVHDGeom* geom, MVHDType type, uint64_t sparse_header_off); -static void mvhd_gen_sparse_header(MVHDSparseHeader* header, uint32_t num_blks, uint64_t bat_offset, uint32_t block_size_in_sectors); +static void mvhd_gen_footer(MVHDFooter* footer, MVHDGeom* geom, MVHDType type, uint64_t sparse_header_off); +static void mvhd_gen_sparse_header(MVHDSparseHeader* header, uint32_t num_blks, uint64_t bat_offset); static int mvhd_gen_par_loc(MVHDSparseHeader* header, const char* child_path, const char* par_path, @@ -21,18 +21,17 @@ static int mvhd_gen_par_loc(MVHDSparseHeader* header, mvhd_utf16* w2ku_path_buff, mvhd_utf16* w2ru_path_buff, MVHDError* err); -static MVHDMeta* mvhd_create_sparse_diff(const char* path, const char* par_path, uint64_t size_in_bytes, MVHDGeom* geom, uint32_t block_size_in_sectors, int* err); +static MVHDMeta* mvhd_create_sparse_diff(const char* path, const char* par_path, MVHDGeom* geom, int* err); /** * \brief Populate a VHD footer * * \param [in] footer to populate - * \param [in] size_in_bytes is the total size of the virtual hard disk in bytes * \param [in] geom to use * \param [in] type of HVD that is being created * \param [in] sparse_header_off, an absolute file offset to the sparse header. Not used for fixed VHD images */ -static void mvhd_gen_footer(MVHDFooter* footer, uint64_t size_in_bytes, MVHDGeom* geom, MVHDType type, uint64_t sparse_header_off) { +static void mvhd_gen_footer(MVHDFooter* footer, MVHDGeom* geom, MVHDType type, uint64_t sparse_header_off) { memcpy(footer->cookie, "conectix", sizeof footer->cookie); footer->features = 0x00000002; footer->fi_fmt_vers = 0x00010000; @@ -41,7 +40,7 @@ static void mvhd_gen_footer(MVHDFooter* footer, uint64_t size_in_bytes, MVHDGeom memcpy(footer->cr_app, "mvhd", sizeof footer->cr_app); footer->cr_vers = 0x000e0000; memcpy(footer->cr_host_os, "Wi2k", sizeof footer->cr_host_os); - footer->orig_sz = footer->curr_sz = size_in_bytes; + footer->orig_sz = footer->curr_sz = mvhd_calc_size_bytes(geom); footer->geom.cyl = geom->cyl; footer->geom.heads = geom->heads; footer->geom.spt = geom->spt; @@ -56,15 +55,14 @@ static void mvhd_gen_footer(MVHDFooter* footer, uint64_t size_in_bytes, MVHDGeom * \param [in] header for sparse and differencing images * \param [in] num_blks is the number of data blocks that the image contains * \param [in] bat_offset is the absolute file offset for start of the Block Allocation Table - * \param [in] block_size_in_sectors is the block size in sectors. */ -static void mvhd_gen_sparse_header(MVHDSparseHeader* header, uint32_t num_blks, uint64_t bat_offset, uint32_t block_size_in_sectors) { +static void mvhd_gen_sparse_header(MVHDSparseHeader* header, uint32_t num_blks, uint64_t bat_offset) { memcpy(header->cookie, "cxsparse", sizeof header->cookie); header->data_offset = 0xffffffffffffffff; header->bat_offset = bat_offset; header->head_vers = 0x00010000; header->max_bat_ent = num_blks; - header->block_sz = block_size_in_sectors * (uint32_t)MVHD_SECTOR_SIZE; + header->block_sz = (uint32_t)MVHD_SECT_PER_BLOCK * (uint32_t)MVHD_SECTOR_SIZE; header->checksum = mvhd_gen_sparse_checksum(header); } @@ -167,8 +165,7 @@ end: } MVHDMeta* mvhd_create_fixed(const char* path, MVHDGeom geom, int* err, mvhd_progress_callback progress_callback) { - uint64_t size_in_bytes = mvhd_calc_size_bytes(&geom); - return mvhd_create_fixed_raw(path, NULL, size_in_bytes, &geom, err, progress_callback); + return mvhd_create_fixed_raw(path, NULL, &geom, err, progress_callback); } /** @@ -179,7 +176,7 @@ MVHDMeta* mvhd_create_fixed(const char* path, MVHDGeom geom, int* err, mvhd_prog * * \param [in] raw_image file handle to a raw disk image to populate VHD */ -MVHDMeta* mvhd_create_fixed_raw(const char* path, FILE* raw_img, uint64_t size_in_bytes, MVHDGeom* geom, int* err, mvhd_progress_callback progress_callback) { +MVHDMeta* mvhd_create_fixed_raw(const char* path, FILE* raw_img, MVHDGeom* geom, int* err, mvhd_progress_callback progress_callback) { uint8_t img_data[MVHD_SECTOR_SIZE] = {0}; uint8_t footer_buff[MVHD_FOOTER_SIZE] = {0}; MVHDMeta* vhdm = calloc(1, sizeof *vhdm); @@ -200,7 +197,7 @@ MVHDMeta* mvhd_create_fixed_raw(const char* path, FILE* raw_img, uint64_t size_i goto cleanup_vhdm; } mvhd_fseeko64(f, 0, SEEK_SET); - uint32_t size_sectors = (uint32_t)(size_in_bytes / MVHD_SECTOR_SIZE); + uint32_t size_sectors = mvhd_calc_size_sectors(geom); uint32_t s; if (progress_callback) progress_callback(0, size_sectors); @@ -212,7 +209,7 @@ MVHDMeta* mvhd_create_fixed_raw(const char* path, FILE* raw_img, uint64_t size_i *err = MVHD_ERR_CONV_SIZE; goto cleanup_vhdm; } - mvhd_gen_footer(&vhdm->footer, raw_size, geom, MVHD_TYPE_FIXED, 0); + mvhd_gen_footer(&vhdm->footer, geom, MVHD_TYPE_FIXED, 0); mvhd_fseeko64(raw_img, 0, SEEK_SET); for (s = 0; s < size_sectors; s++) { fread(img_data, sizeof img_data, 1, raw_img); @@ -221,7 +218,7 @@ MVHDMeta* mvhd_create_fixed_raw(const char* path, FILE* raw_img, uint64_t size_i progress_callback(s + 1, size_sectors); } } else { - mvhd_gen_footer(&vhdm->footer, size_in_bytes, geom, MVHD_TYPE_FIXED, 0); + mvhd_gen_footer(&vhdm->footer, geom, MVHD_TYPE_FIXED, 0); for (s = 0; s < size_sectors; s++) { fwrite(img_data, sizeof img_data, 1, f); if (progress_callback) @@ -248,14 +245,12 @@ end: * * \param [in] path is the absolute path to the VHD file to create * \param [in] par_path is the absolute path to a parent image. If NULL, a sparse image is created, otherwise create a differencing image - * \param [in] size_in_bytes is the total size in bytes of the virtual hard disk image * \param [in] geom is the HDD geometry of the image to create. Determines final image size - * \param [in] block_size_in_sectors is the block size in sectors * \param [out] err indicates what error occurred, if any * * \return NULL if an error occurrs. Check value of *err for actual error. Otherwise returns pointer to a MVHDMeta struct */ -static MVHDMeta* mvhd_create_sparse_diff(const char* path, const char* par_path, uint64_t size_in_bytes, MVHDGeom* geom, uint32_t block_size_in_sectors, int* err) { +static MVHDMeta* mvhd_create_sparse_diff(const char* path, const char* par_path, MVHDGeom* geom, int* err) { uint8_t footer_buff[MVHD_FOOTER_SIZE] = {0}; uint8_t sparse_buff[MVHD_SPARSE_SIZE] = {0}; uint8_t bat_sect[MVHD_SECTOR_SIZE]; @@ -283,7 +278,6 @@ static MVHDMeta* mvhd_create_sparse_diff(const char* path, const char* par_path, par_geom.heads = par_vhdm->footer.geom.heads; par_geom.spt = par_vhdm->footer.geom.spt; geom = &par_geom; - size_in_bytes = par_vhdm->footer.curr_sz; } else if (geom != NULL && (geom->cyl == 0 || geom->heads == 0 || geom->spt == 0)) { *err = MVHD_ERR_INVALID_GEOM; goto cleanup_vhdm; @@ -299,22 +293,21 @@ static MVHDMeta* mvhd_create_sparse_diff(const char* path, const char* par_path, mvhd_fseeko64(f, 0, SEEK_SET); /* Note, the sparse header follows the footer copy at the beginning of the file */ if (par_path == NULL) { - mvhd_gen_footer(&vhdm->footer, size_in_bytes, geom, MVHD_TYPE_DYNAMIC, MVHD_FOOTER_SIZE); + mvhd_gen_footer(&vhdm->footer, geom, MVHD_TYPE_DYNAMIC, MVHD_FOOTER_SIZE); } else { - mvhd_gen_footer(&vhdm->footer, size_in_bytes, geom, MVHD_TYPE_DIFF, MVHD_FOOTER_SIZE); + mvhd_gen_footer(&vhdm->footer, geom, MVHD_TYPE_DIFF, MVHD_FOOTER_SIZE); } mvhd_footer_to_buffer(&vhdm->footer, footer_buff); /* As mentioned, start with a copy of the footer */ fwrite(footer_buff, sizeof footer_buff, 1, f); /** - * Calculate the number of (2MB or 512KB) data blocks required to store the entire + * Calculate the number of (2MB) data blocks required to store the entire * contents of the disk image, followed by the number of sectors the * BAT occupies in the image. Note, the BAT is sector aligned, and is padded * to the next sector boundary * */ - uint32_t size_in_sectors = (uint32_t)(size_in_bytes / MVHD_SECTOR_SIZE); - uint32_t num_blks = size_in_sectors / block_size_in_sectors; - if (size_in_sectors % block_size_in_sectors != 0) { + uint32_t num_blks = mvhd_calc_size_sectors(geom) / MVHD_SECT_PER_BLOCK; + if (mvhd_calc_size_sectors(geom) % MVHD_SECT_PER_BLOCK != 0) { num_blks += 1; } uint32_t num_bat_sect = num_blks / MVHD_BAT_ENT_PER_SECT; @@ -351,7 +344,7 @@ static MVHDMeta* mvhd_create_sparse_diff(const char* path, const char* par_path, goto cleanup_vhdm; } } - mvhd_gen_sparse_header(&vhdm->sparse, num_blks, bat_offset, block_size_in_sectors); + mvhd_gen_sparse_header(&vhdm->sparse, num_blks, bat_offset); mvhd_header_to_buffer(&vhdm->sparse, sparse_buff); fwrite(sparse_buff, sizeof sparse_buff, 1, f); /* The BAT sectors need to be filled with 0xffffffff */ @@ -405,80 +398,9 @@ end: } MVHDMeta* mvhd_create_sparse(const char* path, MVHDGeom geom, int* err) { - uint64_t size_in_bytes = mvhd_calc_size_bytes(&geom); - return mvhd_create_sparse_diff(path, NULL, size_in_bytes, &geom, MVHD_BLOCK_LARGE, err); + return mvhd_create_sparse_diff(path, NULL, &geom, err); } MVHDMeta* mvhd_create_diff(const char* path, const char* par_path, int* err) { - return mvhd_create_sparse_diff(path, par_path, 0, NULL, MVHD_BLOCK_LARGE, err); -} - -MVHDMeta* mvhd_create_ex(MVHDCreationOptions options, int* err) { - uint32_t geom_sector_size; - switch (options.type) - { - case MVHD_TYPE_FIXED: - case MVHD_TYPE_DYNAMIC: - geom_sector_size = mvhd_calc_size_sectors(&(options.geometry)); - if ((options.size_in_bytes > 0 && (options.size_in_bytes % MVHD_SECTOR_SIZE) > 0) - || (options.size_in_bytes > MVHD_MAX_SIZE_IN_BYTES) - || (options.size_in_bytes == 0 && geom_sector_size == 0)) - { - *err = MVHD_ERR_INVALID_SIZE; - return NULL; - } - - if (options.size_in_bytes > 0 && ((uint64_t)geom_sector_size * MVHD_SECTOR_SIZE) > options.size_in_bytes) - { - *err = MVHD_ERR_INVALID_GEOM; - return NULL; - } - - if (options.size_in_bytes == 0) - options.size_in_bytes = (uint64_t)geom_sector_size * MVHD_SECTOR_SIZE; - - if (geom_sector_size == 0) - options.geometry = mvhd_calculate_geometry(options.size_in_bytes); - break; - case MVHD_TYPE_DIFF: - if (options.parent_path == NULL) - { - *err = MVHD_ERR_FILE; - return NULL; - } - break; - default: - *err = MVHD_ERR_TYPE; - return NULL; - } - - if (options.path == NULL) - { - *err = MVHD_ERR_FILE; - return NULL; - } - - if (options.type != MVHD_TYPE_FIXED) - { - if (options.block_size_in_sectors == MVHD_BLOCK_DEFAULT) - options.block_size_in_sectors = MVHD_BLOCK_LARGE; - - if (options.block_size_in_sectors != MVHD_BLOCK_LARGE && options.block_size_in_sectors != MVHD_BLOCK_SMALL) - { - *err = MVHD_ERR_INVALID_BLOCK_SIZE; - return NULL; - } - } - - switch (options.type) - { - case MVHD_TYPE_FIXED: - return mvhd_create_fixed_raw(options.path, NULL, options.size_in_bytes, &(options.geometry), err, options.progress_callback); - case MVHD_TYPE_DYNAMIC: - return mvhd_create_sparse_diff(options.path, NULL, options.size_in_bytes, &(options.geometry), options.block_size_in_sectors, err); - case MVHD_TYPE_DIFF: - return mvhd_create_sparse_diff(options.path, options.parent_path, 0, NULL, options.block_size_in_sectors, err); - } - - return NULL; /* Make the compiler happy */ + return mvhd_create_sparse_diff(path, par_path, NULL, err); } \ No newline at end of file diff --git a/src/minivhd_create.h b/src/minivhd_create.h index 9840d19..3db1f3f 100644 --- a/src/minivhd_create.h +++ b/src/minivhd_create.h @@ -3,6 +3,6 @@ #include #include "minivhd.h" -MVHDMeta* mvhd_create_fixed_raw(const char* path, FILE* raw_img, uint64_t size_in_bytes, MVHDGeom* geom, int* err, mvhd_progress_callback progress_callback); +MVHDMeta* mvhd_create_fixed_raw(const char* path, FILE* raw_img, MVHDGeom* geom, int* err, mvhd_progress_callback progress_callback); #endif \ No newline at end of file diff --git a/src/minivhd_internal.h b/src/minivhd_internal.h index ea75284..a0e795d 100644 --- a/src/minivhd_internal.h +++ b/src/minivhd_internal.h @@ -8,10 +8,9 @@ #define MVHD_SPARSE_SIZE 1024 #define MVHD_SECTOR_SIZE 512 +#define MVHD_SECT_PER_BLOCK 4096 /* 2MB block size */ #define MVHD_BAT_ENT_PER_SECT 128 -#define MVHD_MAX_SIZE_IN_BYTES 0x1fe00000000 - #define MVHD_SPARSE_BLK 0xffffffff /* For simplicity, we don't handle paths longer than this * Note, this is the max path in characters, as that is what @@ -23,6 +22,12 @@ #define MVHD_DIF_LOC_W2RU 0x57327275 #define MVHD_DIF_LOC_W2KU 0x57326B75 +typedef enum MVHDType { + MVHD_TYPE_FIXED = 2, + MVHD_TYPE_DYNAMIC = 3, + MVHD_TYPE_DIFF = 4 +} MVHDType; + typedef struct MVHDSectorBitmap { uint8_t* curr_bitmap; int sector_count; @@ -85,8 +90,8 @@ struct MVHDMeta { uint32_t* block_offset; int sect_per_block; MVHDSectorBitmap bitmap; - int (*read_sectors)(MVHDMeta*, uint32_t, int, void*); - int (*write_sectors)(MVHDMeta*, uint32_t, int, void*); + int (*read_sectors)(MVHDMeta*, int, int, void*); + int (*write_sectors)(MVHDMeta*, int, int, void*); struct { uint8_t* zero_data; int sector_count; diff --git a/src/minivhd_io.c b/src/minivhd_io.c index 8e9172e..cd366a5 100644 --- a/src/minivhd_io.c +++ b/src/minivhd_io.c @@ -15,7 +15,7 @@ #define VHD_CLEARBIT(A,k) ( A[(k/8)] &= ~(0x80 >> (k%8)) ) #define VHD_TESTBIT(A,k) ( A[(k/8)] & (0x80 >> (k%8)) ) -static inline void mvhd_check_sectors(uint32_t offset, int num_sectors, uint32_t total_sectors, int* transfer_sect, int* trunc_sect); +static inline void mvhd_check_sectors(int offset, int num_sectors, int total_sectors, int* transfer_sect, int* trunc_sect); static void mvhd_read_sect_bitmap(MVHDMeta* vhdm, int blk); static void mvhd_write_bat_entry(MVHDMeta* vhdm, int blk); static void mvhd_create_block(MVHDMeta* vhdm, int blk); @@ -31,10 +31,10 @@ static void mvhd_write_curr_sect_bitmap(MVHDMeta* vhdm); * This may be lower than num_sectors if offset + num_sectors >= total_sectors * \param [out] trunc_sectors The number of sectors truncated if transfer_sectors < num_sectors */ -static inline void mvhd_check_sectors(uint32_t offset, int num_sectors, uint32_t total_sectors, int* transfer_sect, int* trunc_sect) { +static inline void mvhd_check_sectors(int offset, int num_sectors, int total_sectors, int* transfer_sect, int* trunc_sect) { *transfer_sect = num_sectors; *trunc_sect = 0; - if ((total_sectors - offset) < (uint32_t)*transfer_sect) { + if ((total_sectors - offset) < *transfer_sect) { *transfer_sect = total_sectors - offset; *trunc_sect = num_sectors - *transfer_sect; } @@ -128,7 +128,7 @@ static void mvhd_create_block(MVHDMeta* vhdm, int blk) { } abs_offset += padding_amount; } - uint32_t sect_offset = (uint32_t)(abs_offset / MVHD_SECTOR_SIZE); + int sect_offset = (int)(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); /* Add a bit of padding. That's what Windows appears to do, although it's not strictly necessary... */ @@ -140,10 +140,10 @@ static void mvhd_create_block(MVHDMeta* vhdm, int blk) { mvhd_write_bat_entry(vhdm, blk); } -int mvhd_fixed_read(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_buff) { +int mvhd_fixed_read(MVHDMeta* vhdm, int offset, int num_sectors, void* out_buff) { int64_t addr; int transfer_sectors, truncated_sectors; - uint32_t total_sectors = (uint32_t)(vhdm->footer.curr_sz / MVHD_SECTOR_SIZE); + int total_sectors = vhdm->footer.geom.cyl * vhdm->footer.geom.heads * vhdm->footer.geom.spt; mvhd_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); @@ -151,14 +151,13 @@ int mvhd_fixed_read(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_ return truncated_sectors; } -int mvhd_sparse_read(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_buff) { +int mvhd_sparse_read(MVHDMeta* vhdm, int offset, int num_sectors, void* out_buff) { int transfer_sectors, truncated_sectors; - uint32_t total_sectors = (uint32_t)(vhdm->footer.curr_sz / MVHD_SECTOR_SIZE); + int total_sectors = vhdm->footer.geom.cyl * vhdm->footer.geom.heads * vhdm->footer.geom.spt; mvhd_check_sectors(offset, num_sectors, total_sectors, &transfer_sectors, &truncated_sectors); uint8_t* buff = (uint8_t*)out_buff; int64_t addr; - uint32_t s, ls; - int blk, prev_blk, sib; + int s, ls, blk, prev_blk, sib; ls = offset + transfer_sectors; prev_blk = -1; for (s = offset; s < ls; s++) { @@ -185,14 +184,13 @@ int mvhd_sparse_read(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out return truncated_sectors; } -int mvhd_diff_read(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_buff) { +int mvhd_diff_read(MVHDMeta* vhdm, int offset, int num_sectors, void* out_buff) { int transfer_sectors, truncated_sectors; - uint32_t total_sectors = (uint32_t)(vhdm->footer.curr_sz / MVHD_SECTOR_SIZE); + int total_sectors = vhdm->footer.geom.cyl * vhdm->footer.geom.heads * vhdm->footer.geom.spt; mvhd_check_sectors(offset, num_sectors, total_sectors, &transfer_sectors, &truncated_sectors); uint8_t* buff = (uint8_t*)out_buff; MVHDMeta* curr_vhdm = vhdm; - uint32_t s, ls; - int blk, sib; + int s, ls, blk, sib; ls = offset + transfer_sectors; for (s = offset; s < ls; s++) { while (curr_vhdm->footer.disk_type == MVHD_TYPE_DIFF) { @@ -218,10 +216,10 @@ int mvhd_diff_read(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_b return truncated_sectors; } -int mvhd_fixed_write(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* in_buff) { +int mvhd_fixed_write(MVHDMeta* vhdm, int offset, int num_sectors, void* in_buff) { int64_t addr; int transfer_sectors, truncated_sectors; - uint32_t total_sectors = (uint32_t)(vhdm->footer.curr_sz / MVHD_SECTOR_SIZE); + int total_sectors = vhdm->footer.geom.cyl * vhdm->footer.geom.heads * vhdm->footer.geom.spt; mvhd_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); @@ -229,14 +227,13 @@ int mvhd_fixed_write(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* in_ return truncated_sectors; } -int mvhd_sparse_diff_write(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* in_buff) { +int mvhd_sparse_diff_write(MVHDMeta* vhdm, int offset, int num_sectors, void* in_buff) { int transfer_sectors, truncated_sectors; - uint32_t total_sectors = (uint32_t)(vhdm->footer.curr_sz / MVHD_SECTOR_SIZE); + int total_sectors = vhdm->footer.geom.cyl * vhdm->footer.geom.heads * vhdm->footer.geom.spt; mvhd_check_sectors(offset, num_sectors, total_sectors, &transfer_sectors, &truncated_sectors); uint8_t* buff = (uint8_t*)in_buff; int64_t addr; - uint32_t s, ls; - int blk, prev_blk, sib; + int s, ls, blk, prev_blk, sib; ls = offset + transfer_sectors; prev_blk = -1; for (s = offset; s < ls; s++) { @@ -271,6 +268,6 @@ int mvhd_sparse_diff_write(MVHDMeta* vhdm, uint32_t offset, int num_sectors, voi return truncated_sectors; } -int mvhd_noop_write(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* in_buff) { +int mvhd_noop_write(MVHDMeta* vhdm, int offset, int num_sectors, void* in_buff) { return 0; } \ No newline at end of file diff --git a/src/minivhd_io.h b/src/minivhd_io.h index cdbfa6d..7301e72 100644 --- a/src/minivhd_io.h +++ b/src/minivhd_io.h @@ -28,7 +28,7 @@ void mvhd_write_empty_sectors(FILE* f, int sector_count); * \retval 0 num_sectors were read from file * \retval >0 < num_sectors were read from file */ -int mvhd_fixed_read(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_buff); +int mvhd_fixed_read(MVHDMeta* vhdm, int offset, int num_sectors, void* out_buff); /** * \brief Read a sparse VHD image @@ -48,7 +48,7 @@ int mvhd_fixed_read(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_ * \retval 0 num_sectors were read from file * \retval >0 < num_sectors were read from file */ -int mvhd_sparse_read(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_buff); +int mvhd_sparse_read(MVHDMeta* vhdm, int offset, int num_sectors, void* out_buff); /** * \brief Read a differencing VHD image @@ -71,7 +71,7 @@ int mvhd_sparse_read(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out * \retval 0 num_sectors were read from file * \retval >0 < num_sectors were read from file */ -int mvhd_diff_read(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_buff); +int mvhd_diff_read(MVHDMeta* vhdm, int offset, int num_sectors, void* out_buff); /** * \brief Write to a fixed VHD image @@ -88,7 +88,7 @@ int mvhd_diff_read(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_b * \retval 0 num_sectors were written to file * \retval >0 < num_sectors were written to file */ -int mvhd_fixed_write(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* in_buff); +int mvhd_fixed_write(MVHDMeta* vhdm, int offset, int num_sectors, void* in_buff); /** * \brief Write to a sparse or differencing VHD image @@ -113,7 +113,7 @@ int mvhd_fixed_write(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* in_ * \retval 0 num_sectors were written to file * \retval >0 < num_sectors were written to file */ -int mvhd_sparse_diff_write(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* in_buff); +int mvhd_sparse_diff_write(MVHDMeta* vhdm, int offset, int num_sectors, void* in_buff); /** * \brief A no-op function to "write" to read-only VHD images @@ -127,6 +127,6 @@ int mvhd_sparse_diff_write(MVHDMeta* vhdm, uint32_t offset, int num_sectors, voi * \retval 0 num_sectors were written to file * \retval >0 < num_sectors were written to file */ -int mvhd_noop_write(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* in_buff); +int mvhd_noop_write(MVHDMeta* vhdm, int offset, int num_sectors, void* in_buff); #endif \ No newline at end of file diff --git a/src/minivhd_manage.c b/src/minivhd_manage.c index 6c4384d..ed5e564 100644 --- a/src/minivhd_manage.c +++ b/src/minivhd_manage.c @@ -328,18 +328,19 @@ bool mvhd_file_is_vhd(FILE* f) { MVHDGeom mvhd_calculate_geometry(uint64_t size) { MVHDGeom chs; - uint32_t ts = (uint32_t)(size / MVHD_SECTOR_SIZE); + uint64_t ts = size / MVHD_SECTOR_SIZE; uint32_t spt, heads, cyl, cth; if (ts > 65535 * 16 * 255) { ts = 65535 * 16 * 255; } - if (ts >= 65535 * 16 * 63) { + if (ts >= 65535 * 16 * 63) { + ts = 65535 * 16 * 63; spt = 255; heads = 16; - cth = ts / spt; + cth = (uint32_t)ts / spt; } else { spt = 17; - cth = ts / spt; + cth = (uint32_t)ts / spt; heads = (cth + 1023) / 1024; if (heads < 4) { heads = 4; @@ -347,12 +348,12 @@ MVHDGeom mvhd_calculate_geometry(uint64_t size) { if (cth >= (heads * 1024) || heads > 16) { spt = 31; heads = 16; - cth = ts / spt; + cth = (uint32_t)ts / spt; } if (cth >= (heads * 1024)) { spt = 63; heads = 16; - cth = ts / spt; + cth = (uint32_t)ts / spt; } } cyl = cth / heads; @@ -474,20 +475,19 @@ void mvhd_close(MVHDMeta* vhdm) { } } -int mvhd_read_sectors(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_buff) { +int mvhd_read_sectors(MVHDMeta* vhdm, int offset, int num_sectors, void* out_buff) { return vhdm->read_sectors(vhdm, offset, num_sectors, out_buff); } -int mvhd_write_sectors(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* in_buff) { +int mvhd_write_sectors(MVHDMeta* vhdm, int offset, int num_sectors, void* in_buff) { return vhdm->write_sectors(vhdm, offset, num_sectors, in_buff); } -int mvhd_format_sectors(MVHDMeta* vhdm, uint32_t offset, int num_sectors) { +int mvhd_format_sectors(MVHDMeta* vhdm, int offset, int num_sectors) { int num_full = num_sectors / vhdm->format_buffer.sector_count; int remain = num_sectors % vhdm->format_buffer.sector_count; for (int i = 0; i < num_full; i++) { vhdm->write_sectors(vhdm, offset, vhdm->format_buffer.sector_count, vhdm->format_buffer.zero_data); - offset += vhdm->format_buffer.sector_count; } vhdm->write_sectors(vhdm, offset, remain, vhdm->format_buffer.zero_data); return 0; diff --git a/src/minivhd_util.c b/src/minivhd_util.c index 5e1475e..7fdfcda 100644 --- a/src/minivhd_util.c +++ b/src/minivhd_util.c @@ -225,10 +225,6 @@ const char* mvhd_strerr(MVHDError err) { return "UUID mismatch between child and parent VHD"; case MVHD_ERR_INVALID_GEOM: return "invalid geometry detected"; - case MVHD_ERR_INVALID_SIZE: - return "invalid size"; - case MVHD_ERR_INVALID_BLOCK_SIZE: - return "invalid block size"; case MVHD_ERR_INVALID_PARAMS: return "invalid parameters passed to function"; case MVHD_ERR_CONV_SIZE: