More newline and whitespace cleanups
This commit is contained in:
@@ -18,7 +18,7 @@
|
||||
* daniel@veillard.com
|
||||
*
|
||||
* Original code for IsoLatin1 and UTF-16 by "Martin J. Duerst" <duerst@w3.org>
|
||||
*
|
||||
*
|
||||
* Adapted and abridged for MiniVHD by Sherman Perry
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
@@ -26,7 +26,7 @@
|
||||
static int xmlLittleEndian = 1;
|
||||
|
||||
/* Note: extracted from original 'void xmlInitCharEncodingHandlers(void)' function */
|
||||
void xmlEncodingInit(void)
|
||||
void xmlEncodingInit(void)
|
||||
{
|
||||
unsigned short int tst = 0x1234;
|
||||
unsigned char *ptr = (unsigned char *) &tst;
|
||||
@@ -426,7 +426,7 @@ int UTF8ToUTF16BE(unsigned char* outb, int *outlen,
|
||||
return(*outlen);
|
||||
}
|
||||
|
||||
/* This file is licenced under the MIT licence as follows:
|
||||
/* This file is licenced under the MIT licence as follows:
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -23,7 +23,7 @@ typedef enum MVHDError {
|
||||
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,
|
||||
MVHD_ERR_TIMESTAMP
|
||||
} MVHDError;
|
||||
@@ -62,18 +62,18 @@ typedef struct MVHDMeta MVHDMeta;
|
||||
|
||||
/**
|
||||
* \brief Output a string from a MiniVHD error number
|
||||
*
|
||||
*
|
||||
* \param [in] err is the error number to return string from
|
||||
*
|
||||
*
|
||||
* \return Error string
|
||||
*/
|
||||
const char* mvhd_strerr(MVHDError err);
|
||||
|
||||
/**
|
||||
* \brief A simple test to see if a given file is a VHD
|
||||
*
|
||||
*
|
||||
* \param [in] f file to test
|
||||
*
|
||||
*
|
||||
* \retval true if f is a VHD
|
||||
* \retval false if f is not a VHD
|
||||
*/
|
||||
@@ -81,20 +81,20 @@ bool mvhd_file_is_vhd(FILE* f);
|
||||
|
||||
/**
|
||||
* \brief Open a VHD image for reading and/or writing
|
||||
*
|
||||
* The returned pointer contains all required values and structures (and files) to
|
||||
*
|
||||
* The returned pointer contains all required values and structures (and files) to
|
||||
* read and write to a VHD file.
|
||||
*
|
||||
*
|
||||
* Remember to call mvhd_close() when you are finished.
|
||||
*
|
||||
*
|
||||
* \param [in] Absolute path to VHD file. Relative path will cause issues when opening
|
||||
* a differencing VHD file
|
||||
* \param [in] readonly set this to true to open the VHD in a read only manner
|
||||
* \param [out] err will be set if the VHD fails to open. Value could be one of
|
||||
* MVHD_ERR_MEM, MVHD_ERR_FILE, MVHD_ERR_NOT_VHD, MVHD_ERR_FOOTER_CHECKSUM, MVHD_ERR_SPARSE_CHECKSUM,
|
||||
* \param [out] err will be set if the VHD fails to open. Value could be one of
|
||||
* MVHD_ERR_MEM, MVHD_ERR_FILE, MVHD_ERR_NOT_VHD, MVHD_ERR_FOOTER_CHECKSUM, MVHD_ERR_SPARSE_CHECKSUM,
|
||||
* MVHD_ERR_TYPE, MVHD_ERR_TIMESTAMP
|
||||
* If MVHD_ERR_FILE is set, mvhd_errno will be set to the appropriate system errno value
|
||||
*
|
||||
*
|
||||
* \return MVHDMeta pointer. If NULL, check err. err may also be set to MVHD_ERR_TIMESTAMP if
|
||||
* opening a differencing VHD.
|
||||
*/
|
||||
@@ -102,52 +102,52 @@ MVHDMeta* mvhd_open(const char* path, bool readonly, int* err);
|
||||
|
||||
/**
|
||||
* \brief Update the parent modified timestamp in the VHD file
|
||||
*
|
||||
*
|
||||
* Differencing VHD's use a parent last modified timestamp to try and detect if the
|
||||
* parent has been modified after the child has been created. However, this is rather
|
||||
* fragile and can be broken by moving/copying the parent. Also, MS DiskPart does not
|
||||
* set this timestamp in the child :(
|
||||
*
|
||||
*
|
||||
* Be careful when using this function that you don't update the timestamp after the
|
||||
* parent actually has been modified.
|
||||
*
|
||||
*
|
||||
* \param [in] vhdm Differencing VHD to update.
|
||||
* \param [out] err will be set if the timestamp could not be updated
|
||||
*
|
||||
*
|
||||
* \return non-zero on error, 0 on success
|
||||
*/
|
||||
int mvhd_diff_update_par_timestamp(MVHDMeta* vhdm, int* err);
|
||||
|
||||
/**
|
||||
* \brief Create a fixed VHD image
|
||||
*
|
||||
*
|
||||
* \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
|
||||
*/
|
||||
MVHDMeta* mvhd_create_fixed(const char* path, MVHDGeom geom, int* err, mvhd_progress_callback progress_callback);
|
||||
|
||||
/**
|
||||
* \brief Create sparse (dynamic) VHD image.
|
||||
*
|
||||
*
|
||||
* \param [in] path is the absolute path to the VHD file 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] 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
|
||||
*/
|
||||
MVHDMeta* mvhd_create_sparse(const char* path, MVHDGeom geom, int* err);
|
||||
|
||||
/**
|
||||
* \brief Create differencing VHD imagee.
|
||||
*
|
||||
*
|
||||
* \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 [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
|
||||
*/
|
||||
MVHDMeta* mvhd_create_diff(const char* path, const char* par_path, int* err);
|
||||
@@ -166,103 +166,103 @@ MVHDMeta* mvhd_create_ex(MVHDCreationOptions options, int* err);
|
||||
|
||||
/**
|
||||
* \brief Safely close a VHD image
|
||||
*
|
||||
*
|
||||
* \param [in] vhdm MiniVHD data structure to close
|
||||
*/
|
||||
void mvhd_close(MVHDMeta* vhdm);
|
||||
|
||||
/**
|
||||
* \brief Calculate hard disk geometry from a provided size
|
||||
*
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* The calculations used are those provided in "Appendix: CHS Calculation" from the document
|
||||
* "Virtual Hard Disk Image Format Specification" provided by Microsoft.
|
||||
*
|
||||
*
|
||||
* \param [in] size the desired VHD image size, in bytes
|
||||
*
|
||||
*
|
||||
* \return MVHDGeom the calculated geometry. This can be used in the appropriate create functions.
|
||||
*/
|
||||
MVHDGeom mvhd_calculate_geometry(uint64_t size);
|
||||
|
||||
/**
|
||||
* \brief Convert a raw disk image to a fixed VHD image
|
||||
*
|
||||
*
|
||||
* \param [in] utf8_raw_path is the path of the raw image to convert
|
||||
* \param [in] utf8_vhd_path is the path of the VHD to create
|
||||
* \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
|
||||
*/
|
||||
MVHDMeta* mvhd_convert_to_vhd_fixed(const char* utf8_raw_path, const char* utf8_vhd_path, int* err);
|
||||
|
||||
/**
|
||||
* \brief Convert a raw disk image to a sparse VHD image
|
||||
*
|
||||
*
|
||||
* \param [in] utf8_raw_path is the path of the raw image to convert
|
||||
* \param [in] utf8_vhd_path is the path of the VHD to create
|
||||
* \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
|
||||
*/
|
||||
MVHDMeta* mvhd_convert_to_vhd_sparse(const char* utf8_raw_path, const char* utf8_vhd_path, int* err);
|
||||
|
||||
/**
|
||||
* \brief Convert a VHD image to a raw disk image
|
||||
*
|
||||
*
|
||||
* \param [in] utf8_vhd_path is the path of the VHD to convert
|
||||
* \param [in] utf8_raw_path is the path of the raw image to create
|
||||
* \param [out] err indicates what error occurred, if any
|
||||
*
|
||||
*
|
||||
* \return NULL if an error occurrs. Check value of *err for actual error. Otherwise returns the raw disk image FILE pointer
|
||||
*/
|
||||
FILE* mvhd_convert_to_raw(const char* utf8_vhd_path, const char* utf8_raw_path, int *err);
|
||||
|
||||
/**
|
||||
* \brief Read sectors from VHD file
|
||||
*
|
||||
*
|
||||
* Read num_sectors, beginning at offset from the VHD file into a buffer
|
||||
*
|
||||
*
|
||||
* \param [in] vhdm MiniVHD data structure
|
||||
* \param [in] offset the sector offset from which to start reading from
|
||||
* \param [in] num_sectors the number of sectors to read
|
||||
* \param [out] out_buff the buffer to write sector data to
|
||||
*
|
||||
*
|
||||
* \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);
|
||||
|
||||
/**
|
||||
* \brief Write sectors to VHD file
|
||||
*
|
||||
*
|
||||
* Write num_sectors, beginning at offset from a buffer VHD file into the VHD file
|
||||
*
|
||||
*
|
||||
* \param [in] vhdm MiniVHD data structure
|
||||
* \param [in] offset the sector offset from which to start writing to
|
||||
* \param [in] num_sectors the number of sectors to write
|
||||
* \param [in] in_buffer the buffer to write sector data to
|
||||
*
|
||||
*
|
||||
* \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);
|
||||
|
||||
/**
|
||||
* \brief Write zeroed sectors to VHD file
|
||||
*
|
||||
* Write num_sectors, beginning at offset, of zero data into the VHD file.
|
||||
* We reuse the existing write functions, with a preallocated zero buffer as
|
||||
*
|
||||
* Write num_sectors, beginning at offset, of zero data into the VHD file.
|
||||
* We reuse the existing write functions, with a preallocated zero buffer as
|
||||
* our source buffer.
|
||||
*
|
||||
*
|
||||
* \param [in] vhdm MiniVHD data structure
|
||||
* \param [in] offset the sector offset from which to start writing to
|
||||
* \param [in] num_sectors the number of sectors to write
|
||||
*
|
||||
*
|
||||
* \return the number of sectors that were not written, or zero
|
||||
*/
|
||||
int mvhd_format_sectors(MVHDMeta* vhdm, uint32_t offset, int num_sectors);
|
||||
|
||||
@@ -42,7 +42,7 @@ MVHDMeta* mvhd_convert_to_vhd_fixed(const char* utf8_raw_path, const char* utf8_
|
||||
FILE *raw_img = mvhd_open_existing_raw_img(utf8_raw_path, &geom, err);
|
||||
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);
|
||||
if (vhdm == NULL) {
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
|
||||
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 int mvhd_gen_par_loc(MVHDSparseHeader* header,
|
||||
const char* child_path,
|
||||
const char* par_path,
|
||||
uint64_t start_offset,
|
||||
static int mvhd_gen_par_loc(MVHDSparseHeader* header,
|
||||
const char* child_path,
|
||||
const char* par_path,
|
||||
uint64_t start_offset,
|
||||
mvhd_utf16* w2ku_path_buff,
|
||||
mvhd_utf16* w2ru_path_buff,
|
||||
MVHDError* err);
|
||||
@@ -28,7 +28,7 @@ static MVHDMeta* mvhd_create_sparse_diff(const char* path, const char* par_path,
|
||||
|
||||
/**
|
||||
* \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
|
||||
@@ -55,7 +55,7 @@ static void mvhd_gen_footer(MVHDFooter* footer, uint64_t size_in_bytes, MVHDGeom
|
||||
|
||||
/**
|
||||
* \brief Populate a VHD sparse header
|
||||
*
|
||||
*
|
||||
* \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
|
||||
@@ -73,7 +73,7 @@ static void mvhd_gen_sparse_header(MVHDSparseHeader* header, uint32_t num_blks,
|
||||
|
||||
/**
|
||||
* \brief Generate parent locators for differencing VHD images
|
||||
*
|
||||
*
|
||||
* \param [in] header the sparse header to populate with parent locator entries
|
||||
* \param [in] child_path is the full path to the VHD being created
|
||||
* \param [in] par_path is the full path to the parent image
|
||||
@@ -81,14 +81,14 @@ static void mvhd_gen_sparse_header(MVHDSparseHeader* header, uint32_t num_blks,
|
||||
* \param [out] w2ku_path_buff is a buffer containing the full path to the parent, encoded as UTF16-LE
|
||||
* \param [out] w2ru_path_buff is a buffer containing the relative path to the parent, encoded as UTF16-LE
|
||||
* \param [out] err indicates what error occurred, if any
|
||||
*
|
||||
*
|
||||
* \retval 0 if success
|
||||
* \retval < 0 if an error occurrs. Check value of *err for actual error
|
||||
*/
|
||||
static int mvhd_gen_par_loc(MVHDSparseHeader* header,
|
||||
const char* child_path,
|
||||
const char* par_path,
|
||||
uint64_t start_offset,
|
||||
static int mvhd_gen_par_loc(MVHDSparseHeader* header,
|
||||
const char* child_path,
|
||||
const char* par_path,
|
||||
uint64_t start_offset,
|
||||
mvhd_utf16* w2ku_path_buff,
|
||||
mvhd_utf16* w2ru_path_buff,
|
||||
MVHDError* err) {
|
||||
@@ -97,7 +97,7 @@ static int mvhd_gen_par_loc(MVHDSparseHeader* header,
|
||||
int rv = 0;
|
||||
char* par_filename;
|
||||
size_t par_fn_len;
|
||||
char rel_path[MVHD_MAX_PATH_BYTES] = {0};
|
||||
char rel_path[MVHD_MAX_PATH_BYTES] = {0};
|
||||
char child_dir[MVHD_MAX_PATH_BYTES] = {0};
|
||||
size_t child_dir_len;
|
||||
if (strlen(child_path) < sizeof child_dir) {
|
||||
@@ -115,18 +115,18 @@ static int mvhd_gen_par_loc(MVHDSparseHeader* header,
|
||||
*err = MVHD_ERR_PATH_LEN;
|
||||
rv = -1;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
/* We have our paths, now store the parent filename directly in the sparse header. */
|
||||
int outlen = sizeof header->par_utf16_name;
|
||||
int outlen = sizeof header->par_utf16_name;
|
||||
int utf_ret;
|
||||
utf_ret = UTF8ToUTF16BE((unsigned char*)header->par_utf16_name, &outlen, (const unsigned char*)par_filename, (int*)&par_fn_len);
|
||||
utf_ret = UTF8ToUTF16BE((unsigned char*)header->par_utf16_name, &outlen, (const unsigned char*)par_filename, (int*)&par_fn_len);
|
||||
if (utf_ret < 0) {
|
||||
mvhd_set_encoding_err(utf_ret, (int*)err);
|
||||
rv = -1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* And encode the paths to UTF16-LE */
|
||||
|
||||
/* And encode the paths to UTF16-LE */
|
||||
size_t par_path_len = strlen(par_path);
|
||||
outlen = sizeof *w2ku_path_buff * MVHD_MAX_PATH_CHARS;
|
||||
utf_ret = UTF8ToUTF16LE((unsigned char*)w2ku_path_buff, &outlen, (const unsigned char*)par_path, (int*)&par_path_len);
|
||||
@@ -136,7 +136,7 @@ static int mvhd_gen_par_loc(MVHDSparseHeader* header,
|
||||
goto end;
|
||||
}
|
||||
int w2ku_len = utf_ret;
|
||||
outlen = sizeof *w2ru_path_buff * MVHD_MAX_PATH_CHARS;
|
||||
outlen = sizeof *w2ru_path_buff * MVHD_MAX_PATH_CHARS;
|
||||
utf_ret = UTF8ToUTF16LE((unsigned char*)w2ru_path_buff, &outlen, (const unsigned char*)rel_path, (int*)&rel_len);
|
||||
if (utf_ret < 0) {
|
||||
mvhd_set_encoding_err(utf_ret, (int*)err);
|
||||
@@ -144,16 +144,16 @@ static int mvhd_gen_par_loc(MVHDSparseHeader* header,
|
||||
goto end;
|
||||
}
|
||||
int w2ru_len = utf_ret;
|
||||
/**
|
||||
/**
|
||||
* Finally populate the parent locaters in the sparse header.
|
||||
* This is the information needed to find the paths saved elsewhere
|
||||
* in the VHD image
|
||||
* in the VHD image
|
||||
*/
|
||||
|
||||
/* Note about the plat_data_space field: The VHD spec says this field stores the number of sectors needed to store the locator path.
|
||||
* However, Hyper-V and VPC store the number of bytes, not the number of sectors, and will refuse to open VHDs which have the
|
||||
* However, Hyper-V and VPC store the number of bytes, not the number of sectors, and will refuse to open VHDs which have the
|
||||
* number of sectors in this field.
|
||||
* See https://stackoverflow.com/questions/40760181/mistake-in-virtual-hard-disk-image-format-specification
|
||||
* See https://stackoverflow.com/questions/40760181/mistake-in-virtual-hard-disk-image-format-specification
|
||||
*/
|
||||
header->par_loc_entry[0].plat_code = MVHD_DIF_LOC_W2KU;
|
||||
header->par_loc_entry[0].plat_data_len = (uint32_t)w2ku_len;
|
||||
@@ -176,13 +176,13 @@ MVHDMeta* mvhd_create_fixed(const char* path, MVHDGeom geom, int* err, mvhd_prog
|
||||
|
||||
/**
|
||||
* \brief internal function that implements public mvhd_create_fixed() functionality
|
||||
*
|
||||
*
|
||||
* Contains one more parameter than the public function, to allow using an existing
|
||||
* raw disk image as the data source for the new fixed VHD.
|
||||
*
|
||||
*
|
||||
* \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, uint64_t size_in_bytes, 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);
|
||||
@@ -211,17 +211,17 @@ 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, raw_size, geom, MVHD_TYPE_FIXED, 0);
|
||||
mvhd_fseeko64(raw_img, 0, SEEK_SET);
|
||||
for (s = 0; s < size_sectors; s++) {
|
||||
for (s = 0; s < size_sectors; s++) {
|
||||
fread(img_data, sizeof img_data, 1, raw_img);
|
||||
fwrite(img_data, sizeof img_data, 1, f);
|
||||
if (progress_callback)
|
||||
progress_callback(s + 1, size_sectors);
|
||||
}
|
||||
} else {
|
||||
mvhd_gen_footer(&vhdm->footer, size_in_bytes, geom, MVHD_TYPE_FIXED, 0);
|
||||
for (s = 0; s < size_sectors; s++) {
|
||||
mvhd_gen_footer(&vhdm->footer, size_in_bytes, geom, MVHD_TYPE_FIXED, 0);
|
||||
for (s = 0; s < size_sectors; s++) {
|
||||
fwrite(img_data, sizeof img_data, 1, f);
|
||||
if (progress_callback)
|
||||
progress_callback(s + 1, size_sectors);
|
||||
@@ -244,14 +244,14 @@ end:
|
||||
|
||||
/**
|
||||
* \brief Create sparse or differencing VHD image.
|
||||
*
|
||||
*
|
||||
* \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) {
|
||||
@@ -290,8 +290,8 @@ static MVHDMeta* mvhd_create_sparse_diff(const char* path, const char* par_path,
|
||||
} else if (geom == NULL || (geom->cyl == 0 || geom->heads == 0 || geom->spt == 0)) {
|
||||
*err = MVHD_ERR_INVALID_GEOM;
|
||||
goto cleanup_vhdm;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
FILE* f = mvhd_fopen(path, "wb+", err);
|
||||
if (f == NULL) {
|
||||
goto cleanup_vhdm;
|
||||
@@ -308,9 +308,9 @@ static MVHDMeta* mvhd_create_sparse_diff(const char* path, const char* par_path,
|
||||
fwrite(footer_buff, sizeof footer_buff, 1, f);
|
||||
/**
|
||||
* Calculate the number of (2MB or 512KB) data blocks required to store the entire
|
||||
* contents of the disk image, followed by the number of sectors the
|
||||
* 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
|
||||
* 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;
|
||||
@@ -323,10 +323,10 @@ static MVHDMeta* mvhd_create_sparse_diff(const char* path, const char* par_path,
|
||||
}
|
||||
/* Storing the BAT directly following the footer and header */
|
||||
uint64_t bat_offset = MVHD_FOOTER_SIZE + MVHD_SPARSE_SIZE;
|
||||
uint64_t par_loc_offset = 0;
|
||||
uint64_t par_loc_offset = 0;
|
||||
|
||||
/**
|
||||
* If creating a differencing VHD, populate the sparse header with additional
|
||||
* If creating a differencing VHD, populate the sparse header with additional
|
||||
* data about the parent image, and where to find it, and it's last modified timestamp
|
||||
* */
|
||||
if (par_vhdm != NULL) {
|
||||
@@ -337,12 +337,12 @@ static MVHDMeta* mvhd_create_sparse_diff(const char* path, const char* par_path,
|
||||
*/
|
||||
w2ku_path_buff = calloc(MVHD_MAX_PATH_CHARS, sizeof * w2ku_path_buff);
|
||||
if (w2ku_path_buff == NULL) {
|
||||
*err = MVHD_ERR_MEM;
|
||||
*err = MVHD_ERR_MEM;
|
||||
goto end;
|
||||
}
|
||||
w2ru_path_buff = calloc(MVHD_MAX_PATH_CHARS, sizeof * w2ru_path_buff);
|
||||
if (w2ru_path_buff == NULL) {
|
||||
*err = MVHD_ERR_MEM;
|
||||
*err = MVHD_ERR_MEM;
|
||||
goto end;
|
||||
}
|
||||
memcpy(vhdm->sparse.par_uuid, par_vhdm->footer.uuid, sizeof vhdm->sparse.par_uuid);
|
||||
@@ -362,7 +362,7 @@ static MVHDMeta* mvhd_create_sparse_diff(const char* path, const char* par_path,
|
||||
mvhd_write_empty_sectors(f, 5);
|
||||
/**
|
||||
* If creating a differencing VHD, the paths to the parent image need to be written
|
||||
* tp the file. Both absolute and relative paths are written
|
||||
* tp the file. Both absolute and relative paths are written
|
||||
* */
|
||||
if (par_vhdm != NULL) {
|
||||
uint64_t curr_pos = (uint64_t)mvhd_ftello64(f);
|
||||
@@ -399,9 +399,9 @@ cleanup_par_vhdm:
|
||||
if (par_vhdm != NULL) {
|
||||
mvhd_close(par_vhdm);
|
||||
}
|
||||
end:
|
||||
free(w2ku_path_buff);
|
||||
free(w2ru_path_buff);
|
||||
end:
|
||||
free(w2ku_path_buff);
|
||||
free(w2ru_path_buff);
|
||||
return vhdm;
|
||||
}
|
||||
|
||||
@@ -415,7 +415,7 @@ MVHDMeta* mvhd_create_diff(const char* path, const char* par_path, int* err) {
|
||||
}
|
||||
|
||||
MVHDMeta* mvhd_create_ex(MVHDCreationOptions options, int* err) {
|
||||
uint32_t geom_sector_size;
|
||||
uint32_t geom_sector_size;
|
||||
switch (options.type)
|
||||
{
|
||||
case MVHD_TYPE_FIXED:
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#define MVHD_MAX_SIZE_IN_BYTES 0x1fe00000000
|
||||
|
||||
#define MVHD_SPARSE_BLK 0xffffffff
|
||||
/* For simplicity, we don't handle paths longer than this
|
||||
/* For simplicity, we don't handle paths longer than this
|
||||
* Note, this is the max path in characters, as that is what
|
||||
* Windows uses
|
||||
*/
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#include "minivhd_internal.h"
|
||||
#include "minivhd_util.h"
|
||||
|
||||
/* The following bit array macros adapted from
|
||||
/* The following bit array macros adapted from
|
||||
http://www.mathcs.emory.edu/~cheung/Courses/255/Syllabus/1-C-intro/bit-array.html */
|
||||
|
||||
#define VHD_SETBIT(A,k) ( A[(k/8)] |= (0x80 >> (k%8)) )
|
||||
@@ -26,11 +26,11 @@ static void mvhd_write_curr_sect_bitmap(MVHDMeta* vhdm);
|
||||
|
||||
/**
|
||||
* \brief Check that we will not be overflowing buffers
|
||||
*
|
||||
*
|
||||
* \param [in] offset The offset from which we are beginning from
|
||||
* \param [in] num_sectors The number of sectors which we desire to read/write
|
||||
* \param [in] total_sectors The total number of sectors available
|
||||
* \param [out] transfer_sect The number of sectors to actually write.
|
||||
* \param [out] transfer_sect The number of sectors to actually write.
|
||||
* 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
|
||||
*/
|
||||
@@ -52,10 +52,10 @@ void mvhd_write_empty_sectors(FILE* f, int sector_count) {
|
||||
|
||||
/**
|
||||
* \brief Read the sector bitmap for a block.
|
||||
*
|
||||
* If the block is sparse, the sector bitmap in memory will be
|
||||
*
|
||||
* If the block is sparse, the sector bitmap in memory will be
|
||||
* zeroed. Otherwise, the sector bitmap is read from the VHD file.
|
||||
*
|
||||
*
|
||||
* \param [in] vhdm MiniVHD data structure
|
||||
* \param [in] blk The block for which to read the sector bitmap from
|
||||
*/
|
||||
@@ -71,7 +71,7 @@ static void mvhd_read_sect_bitmap(MVHDMeta* vhdm, int blk) {
|
||||
|
||||
/**
|
||||
* \brief Write the current sector bitmap in memory to file
|
||||
*
|
||||
*
|
||||
* \param [in] vhdm MiniVHD data structure
|
||||
*/
|
||||
static void mvhd_write_curr_sect_bitmap(MVHDMeta* vhdm) {
|
||||
@@ -84,7 +84,7 @@ static void mvhd_write_curr_sect_bitmap(MVHDMeta* vhdm) {
|
||||
|
||||
/**
|
||||
* \brief Write block offset from memory into file
|
||||
*
|
||||
*
|
||||
* \param [in] vhdm MiniVHD data structure
|
||||
* \param [in] blk The block for which to write the offset for
|
||||
*/
|
||||
@@ -97,15 +97,15 @@ static void mvhd_write_bat_entry(MVHDMeta* vhdm, int blk) {
|
||||
|
||||
/**
|
||||
* \brief Create an empty block in a sparse or differencing VHD image
|
||||
*
|
||||
* VHD images store data in blocks, which are typically 4096 sectors in size
|
||||
* (~2MB). These blocks may be stored on disk in any order. Blocks are created
|
||||
*
|
||||
* VHD images store data in blocks, which are typically 4096 sectors in size
|
||||
* (~2MB). These blocks may be stored on disk in any order. Blocks are created
|
||||
* on demand when required.
|
||||
*
|
||||
* This function creates new, empty blocks, by replacing the footer at the end of the file
|
||||
*
|
||||
* This function creates new, empty blocks, by replacing the footer at the end of the file
|
||||
* and then re-inserting the footer at the new file end. The BAT table entry for the
|
||||
* new block is updated with the new offset.
|
||||
*
|
||||
*
|
||||
* \param [in] vhdm MiniVHD data structure
|
||||
* \param [in] blk The block number to create
|
||||
*/
|
||||
@@ -176,7 +176,7 @@ int mvhd_sparse_read(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out
|
||||
addr = ((int64_t)vhdm->block_offset[blk] + vhdm->bitmap.sector_count + sib) * MVHD_SECTOR_SIZE;
|
||||
mvhd_fseeko64(vhdm->f, addr, SEEK_SET);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (VHD_TESTBIT(vhdm->bitmap.curr_bitmap, sib)) {
|
||||
fread(buff, MVHD_SECTOR_SIZE, 1, vhdm->f);
|
||||
} else {
|
||||
@@ -245,7 +245,7 @@ int mvhd_sparse_diff_write(MVHDMeta* vhdm, uint32_t offset, int num_sectors, voi
|
||||
for (s = offset; s < ls; s++) {
|
||||
blk = s / vhdm->sect_per_block;
|
||||
sib = s % vhdm->sect_per_block;
|
||||
if (vhdm->bitmap.curr_block != blk && prev_blk >= 0) {
|
||||
if (vhdm->bitmap.curr_block != blk && prev_blk >= 0) {
|
||||
/* Write the sector bitmap for the previous block, before we replace it. */
|
||||
mvhd_write_curr_sect_bitmap(vhdm);
|
||||
}
|
||||
@@ -254,9 +254,9 @@ int mvhd_sparse_diff_write(MVHDMeta* vhdm, uint32_t offset, int num_sectors, voi
|
||||
zero either way */
|
||||
mvhd_read_sect_bitmap(vhdm, blk);
|
||||
mvhd_create_block(vhdm, blk);
|
||||
}
|
||||
}
|
||||
if (blk != prev_blk) {
|
||||
if (vhdm->bitmap.curr_block != blk) {
|
||||
if (vhdm->bitmap.curr_block != blk) {
|
||||
mvhd_read_sect_bitmap(vhdm, blk);
|
||||
mvhd_fseeko64(vhdm->f, (uint64_t)sib * MVHD_SECTOR_SIZE, SEEK_CUR);
|
||||
} else {
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
|
||||
/**
|
||||
* \brief Write zero filled sectors to file.
|
||||
*
|
||||
* Note, the caller should set the file position before calling this
|
||||
*
|
||||
* Note, the caller should set the file position before calling this
|
||||
* function for correct operation.
|
||||
*
|
||||
*
|
||||
* \param [in] f File to write sectors to
|
||||
* \param [in] sector_count The number of sectors to write
|
||||
*/
|
||||
@@ -15,16 +15,16 @@ void mvhd_write_empty_sectors(FILE* f, int sector_count);
|
||||
|
||||
/**
|
||||
* \brief Read a fixed VHD image
|
||||
*
|
||||
* Fixed VHD images are essentially raw image files with a footer tacked on
|
||||
*
|
||||
* Fixed VHD images are essentially raw image files with a footer tacked on
|
||||
* the end. They are therefore straightforward to write
|
||||
*
|
||||
*
|
||||
* \param [in] vhdm MiniVHD data structure
|
||||
* \param [in] offset Sector offset to read from
|
||||
* \param [in] num_sectors The desired number of sectors to read
|
||||
* \param [out] out_buff An output buffer to store read sectors. Must be
|
||||
* \param [out] out_buff An output buffer to store read sectors. Must be
|
||||
* large enough to hold num_sectors worth of sectors.
|
||||
*
|
||||
*
|
||||
* \retval 0 num_sectors were read from file
|
||||
* \retval >0 < num_sectors were read from file
|
||||
*/
|
||||
@@ -32,19 +32,19 @@ int mvhd_fixed_read(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_
|
||||
|
||||
/**
|
||||
* \brief Read a sparse VHD image
|
||||
*
|
||||
* Sparse, or dynamic images are VHD images that grow as data is written to them.
|
||||
*
|
||||
* This function implements the logic to read sectors from the file, taking into
|
||||
* account the fact that blocks may be stored on disk in any order, and that the
|
||||
*
|
||||
* Sparse, or dynamic images are VHD images that grow as data is written to them.
|
||||
*
|
||||
* This function implements the logic to read sectors from the file, taking into
|
||||
* account the fact that blocks may be stored on disk in any order, and that the
|
||||
* read could cross block boundaries.
|
||||
*
|
||||
*
|
||||
* \param [in] vhdm MiniVHD data structure
|
||||
* \param [in] offset Sector offset to read from
|
||||
* \param [in] num_sectors The desired number of sectors to read
|
||||
* \param [out] out_buff An output buffer to store read sectors. Must be
|
||||
* \param [out] out_buff An output buffer to store read sectors. Must be
|
||||
* large enough to hold num_sectors worth of sectors.
|
||||
*
|
||||
*
|
||||
* \retval 0 num_sectors were read from file
|
||||
* \retval >0 < num_sectors were read from file
|
||||
*/
|
||||
@@ -52,22 +52,22 @@ int mvhd_sparse_read(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out
|
||||
|
||||
/**
|
||||
* \brief Read a differencing VHD image
|
||||
*
|
||||
* Differencing images are a variant of a sparse image. They contain the grow-on-demand
|
||||
* properties of sparse images, but also reference a parent image. Data is read from the
|
||||
*
|
||||
* Differencing images are a variant of a sparse image. They contain the grow-on-demand
|
||||
* properties of sparse images, but also reference a parent image. Data is read from the
|
||||
* child image only if it is newer than the data stored in the parent image.
|
||||
*
|
||||
* This function implements the logic to read sectors from the child, or a parent image.
|
||||
* Differencing images may have a differencing image as a parent, creating a chain of images.
|
||||
* There is no theoretical chain length limit, although I do not consider long chains to be
|
||||
*
|
||||
* This function implements the logic to read sectors from the child, or a parent image.
|
||||
* Differencing images may have a differencing image as a parent, creating a chain of images.
|
||||
* There is no theoretical chain length limit, although I do not consider long chains to be
|
||||
* advisable. Verifying the parent-child relationship is not very robust.
|
||||
*
|
||||
*
|
||||
* \param [in] vhdm MiniVHD data structure
|
||||
* \param [in] offset Sector offset to read from
|
||||
* \param [in] num_sectors The desired number of sectors to read
|
||||
* \param [out] out_buff An output buffer to store read sectors. Must be
|
||||
* \param [out] out_buff An output buffer to store read sectors. Must be
|
||||
* large enough to hold num_sectors worth of sectors.
|
||||
*
|
||||
*
|
||||
* \retval 0 num_sectors were read from file
|
||||
* \retval >0 < num_sectors were read from file
|
||||
*/
|
||||
@@ -75,16 +75,16 @@ int mvhd_diff_read(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_b
|
||||
|
||||
/**
|
||||
* \brief Write to a fixed VHD image
|
||||
*
|
||||
* Fixed VHD images are essentially raw image files with a footer tacked on
|
||||
*
|
||||
* Fixed VHD images are essentially raw image files with a footer tacked on
|
||||
* the end. They are therefore straightforward to write
|
||||
*
|
||||
*
|
||||
* \param [in] vhdm MiniVHD data structure
|
||||
* \param [in] offset Sector offset to write to
|
||||
* \param [in] num_sectors The desired number of sectors to write
|
||||
* \param [in] in_buff A source buffer to write sectors from. Must be
|
||||
* \param [in] in_buff A source buffer to write sectors from. Must be
|
||||
* large enough to hold num_sectors worth of sectors.
|
||||
*
|
||||
*
|
||||
* \retval 0 num_sectors were written to file
|
||||
* \retval >0 < num_sectors were written to file
|
||||
*/
|
||||
@@ -92,24 +92,24 @@ int mvhd_fixed_write(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* in_
|
||||
|
||||
/**
|
||||
* \brief Write to a sparse or differencing VHD image
|
||||
*
|
||||
* Sparse, or dynamic images are VHD images that grow as data is written to them.
|
||||
*
|
||||
* Differencing images are a variant of a sparse image. They contain the grow-on-demand
|
||||
* properties of sparse images, but also reference a parent image. Data is always written
|
||||
* to the child image. This makes writing to differencing images essentially identical to
|
||||
*
|
||||
* Sparse, or dynamic images are VHD images that grow as data is written to them.
|
||||
*
|
||||
* Differencing images are a variant of a sparse image. They contain the grow-on-demand
|
||||
* properties of sparse images, but also reference a parent image. Data is always written
|
||||
* to the child image. This makes writing to differencing images essentially identical to
|
||||
* writing to sparse images, hence they use the same function.
|
||||
*
|
||||
* This function implements the logic to write sectors to the file, taking into
|
||||
* account the fact that blocks may be stored on disk in any order, and that the
|
||||
*
|
||||
* This function implements the logic to write sectors to the file, taking into
|
||||
* account the fact that blocks may be stored on disk in any order, and that the
|
||||
* write operation could cross block boundaries.
|
||||
*
|
||||
*
|
||||
* \param [in] vhdm MiniVHD data structure
|
||||
* \param [in] offset Sector offset to write to
|
||||
* \param [in] num_sectors The desired number of sectors to write
|
||||
* \param [in] in_buff A source buffer to write sectors from. Must be
|
||||
* \param [in] in_buff A source buffer to write sectors from. Must be
|
||||
* large enough to hold num_sectors worth of sectors.
|
||||
*
|
||||
*
|
||||
* \retval 0 num_sectors were written to file
|
||||
* \retval >0 < num_sectors were written to file
|
||||
*/
|
||||
@@ -117,13 +117,13 @@ int mvhd_sparse_diff_write(MVHDMeta* vhdm, uint32_t offset, int num_sectors, voi
|
||||
|
||||
/**
|
||||
* \brief A no-op function to "write" to read-only VHD images
|
||||
*
|
||||
*
|
||||
* \param [in] vhdm MiniVHD data structure
|
||||
* \param [in] offset Sector offset to write to
|
||||
* \param [in] num_sectors The desired number of sectors to write
|
||||
* \param [in] in_buff A source buffer to write sectors from. Must be
|
||||
* \param [in] in_buff A source buffer to write sectors from. Must be
|
||||
* large enough to hold num_sectors worth of sectors.
|
||||
*
|
||||
*
|
||||
* \retval 0 num_sectors were written to file
|
||||
* \retval >0 < num_sectors were written to file
|
||||
*/
|
||||
|
||||
@@ -39,7 +39,7 @@ static int mvhd_init_sector_bitmap(MVHDMeta* vhdm, MVHDError* err);
|
||||
|
||||
/**
|
||||
* \brief Populate data stuctures with content from a VHD footer
|
||||
*
|
||||
*
|
||||
* \param [in] vhdm MiniVHD data structure
|
||||
*/
|
||||
static void mvhd_read_footer(MVHDMeta* vhdm) {
|
||||
@@ -51,7 +51,7 @@ static void mvhd_read_footer(MVHDMeta* vhdm) {
|
||||
|
||||
/**
|
||||
* \brief Populate data stuctures with content from a VHD sparse header
|
||||
*
|
||||
*
|
||||
* \param [in] vhdm MiniVHD data structure
|
||||
*/
|
||||
static void mvhd_read_sparse_header(MVHDMeta* vhdm) {
|
||||
@@ -63,9 +63,9 @@ static void mvhd_read_sparse_header(MVHDMeta* vhdm) {
|
||||
|
||||
/**
|
||||
* \brief Validate VHD footer checksum
|
||||
*
|
||||
*
|
||||
* This works by generating a checksum from the footer, and comparing it against the stored checksum.
|
||||
*
|
||||
*
|
||||
* \param [in] vhdm MiniVHD data structure
|
||||
*/
|
||||
static bool mvhd_footer_checksum_valid(MVHDMeta* vhdm) {
|
||||
@@ -74,9 +74,9 @@ static bool mvhd_footer_checksum_valid(MVHDMeta* vhdm) {
|
||||
|
||||
/**
|
||||
* \brief Validate VHD sparse header checksum
|
||||
*
|
||||
*
|
||||
* This works by generating a checksum from the sparse header, and comparing it against the stored checksum.
|
||||
*
|
||||
*
|
||||
* \param [in] vhdm MiniVHD data structure
|
||||
*/
|
||||
static bool mvhd_sparse_checksum_valid(MVHDMeta* vhdm) {
|
||||
@@ -85,14 +85,14 @@ static bool mvhd_sparse_checksum_valid(MVHDMeta* vhdm) {
|
||||
|
||||
/**
|
||||
* \brief Read BAT into MiniVHD data structure
|
||||
*
|
||||
* The Block Allocation Table (BAT) is the structure in a sparse and differencing VHD which stores
|
||||
*
|
||||
* The Block Allocation Table (BAT) is the structure in a sparse and differencing VHD which stores
|
||||
* the 4-byte sector offsets for each data block. This function allocates enough memory to contain
|
||||
* the entire BAT, and then reads the contents of the BAT into the buffer.
|
||||
*
|
||||
*
|
||||
* \param [in] vhdm MiniVHD data structure
|
||||
* \param [out] err this is populated with MVHD_ERR_MEM if the calloc fails
|
||||
*
|
||||
*
|
||||
* \retval -1 if an error occurrs. Check value of err in this case
|
||||
* \retval 0 if the function call succeeds
|
||||
*/
|
||||
@@ -112,7 +112,7 @@ static int mvhd_read_bat(MVHDMeta *vhdm, MVHDError* err) {
|
||||
|
||||
/**
|
||||
* \brief Perform a one-time calculation of some sparse VHD values
|
||||
*
|
||||
*
|
||||
* \param [in] vhdm MiniVHD data structure
|
||||
*/
|
||||
static void mvhd_calc_sparse_values(MVHDMeta* vhdm) {
|
||||
@@ -126,14 +126,14 @@ static void mvhd_calc_sparse_values(MVHDMeta* vhdm) {
|
||||
|
||||
/**
|
||||
* \brief Allocate memory for a sector bitmap.
|
||||
*
|
||||
*
|
||||
* Each data block is preceded by a sector bitmap. Each bit indicates whether the corresponding sector
|
||||
* is considered 'clean' or 'dirty' (for sparse VHD images), or whether to read from the parent or current
|
||||
* is considered 'clean' or 'dirty' (for sparse VHD images), or whether to read from the parent or current
|
||||
* image (for differencing images).
|
||||
*
|
||||
*
|
||||
* \param [in] vhdm MiniVHD data structure
|
||||
* \param [out] err this is populated with MVHD_ERR_MEM if the calloc fails
|
||||
*
|
||||
*
|
||||
* \retval -1 if an error occurrs. Check value of err in this case
|
||||
* \retval 0 if the function call succeeds
|
||||
*/
|
||||
@@ -149,17 +149,17 @@ static int mvhd_init_sector_bitmap(MVHDMeta* vhdm, MVHDError* err) {
|
||||
|
||||
/**
|
||||
* \brief Check if the path for a given platform code exists
|
||||
*
|
||||
* From the available paths, both relative and absolute, construct a full path
|
||||
*
|
||||
* From the available paths, both relative and absolute, construct a full path
|
||||
* and attempt to open a file at that path.
|
||||
*
|
||||
* Note, this function makes no attempt to verify that the path is the correct
|
||||
*
|
||||
* Note, this function makes no attempt to verify that the path is the correct
|
||||
* VHD image, or even a VHD image at all.
|
||||
*
|
||||
*
|
||||
* \param [in] paths a struct containing all available paths to work with
|
||||
* \param [in] the platform code to try and obtain a path for. Setting this to zero
|
||||
* \param [in] the platform code to try and obtain a path for. Setting this to zero
|
||||
* will try using the directory of the child image
|
||||
*
|
||||
*
|
||||
* \retval true if a file is found
|
||||
* \retval false if a file is not found
|
||||
*/
|
||||
@@ -195,23 +195,23 @@ static bool mvhd_parent_path_exists(struct MVHDPaths* paths, uint32_t plat_code)
|
||||
|
||||
/**
|
||||
* \brief attempt to obtain a file path to a file that may be a valid VHD image
|
||||
*
|
||||
* Differential VHD images store both a UTF-16BE file name (or path), and up to
|
||||
* eight "parent locator" entries. Using this information, this function tries to
|
||||
*
|
||||
* Differential VHD images store both a UTF-16BE file name (or path), and up to
|
||||
* eight "parent locator" entries. Using this information, this function tries to
|
||||
* find a parent image.
|
||||
*
|
||||
*
|
||||
* This function does not verify if the path returned is a valid parent image.
|
||||
*
|
||||
*
|
||||
* \param [in] vhdm current MiniVHD data structure
|
||||
* \param [out] err any errors that may occurr. Check this if NULL is returned
|
||||
*
|
||||
* \return a pointer to the global string `tmp_open_path`, or NULL if a path could
|
||||
*
|
||||
* \return a pointer to the global string `tmp_open_path`, or NULL if a path could
|
||||
* not be found, or some error occurred
|
||||
*/
|
||||
static char* mvhd_get_diff_parent_path(MVHDMeta* vhdm, int* err) {
|
||||
int utf_outlen, utf_inlen, utf_ret;
|
||||
char* par_fp = NULL;
|
||||
/* We can't resolve relative paths if we don't have an absolute
|
||||
/* We can't resolve relative paths if we don't have an absolute
|
||||
path to work with */
|
||||
if (!cwk_path_is_absolute((const char*)vhdm->filename)) {
|
||||
*err = MVHD_ERR_PATH_REL;
|
||||
@@ -255,7 +255,7 @@ static char* mvhd_get_diff_parent_path(MVHDMeta* vhdm, int* err) {
|
||||
}
|
||||
mvhd_fseeko64(vhdm->f, vhdm->sparse.par_loc_entry[i].plat_data_offset, SEEK_SET);
|
||||
fread(paths->tmp_src_path, sizeof (uint8_t), utf_inlen, vhdm->f);
|
||||
/* Note, the W2*u parent locators are UTF-16LE, unlike the filename field previously obtained,
|
||||
/* Note, the W2*u parent locators are UTF-16LE, unlike the filename field previously obtained,
|
||||
which is UTF-16BE */
|
||||
utf_ret = UTF16LEToUTF8(loc_path, &utf_outlen, (const unsigned char*)paths->tmp_src_path, &utf_inlen);
|
||||
if (utf_ret < 0) {
|
||||
@@ -282,7 +282,7 @@ static char* mvhd_get_diff_parent_path(MVHDMeta* vhdm, int* err) {
|
||||
/* If we reach this point, we could not find a path with a valid file */
|
||||
par_fp = NULL;
|
||||
*err = MVHD_ERR_PAR_NOT_FOUND;
|
||||
|
||||
|
||||
paths_cleanup:
|
||||
free(paths);
|
||||
paths = NULL;
|
||||
@@ -292,10 +292,10 @@ end:
|
||||
|
||||
/**
|
||||
* \brief Attach the read/write function pointers to read/write functions
|
||||
*
|
||||
* Depending on the VHD type, different sector reading and writing functions are used.
|
||||
*
|
||||
* Depending on the VHD type, different sector reading and writing functions are used.
|
||||
* The functions are called via function pointers stored in the vhdm struct.
|
||||
*
|
||||
*
|
||||
* \param [in] vhdm MiniVHD data structure
|
||||
*/
|
||||
static void mvhd_assign_io_funcs(MVHDMeta* vhdm) {
|
||||
@@ -336,7 +336,7 @@ MVHDGeom mvhd_calculate_geometry(uint64_t size) {
|
||||
if (ts > 65535 * 16 * 255) {
|
||||
ts = 65535 * 16 * 255;
|
||||
}
|
||||
if (ts >= 65535 * 16 * 63) {
|
||||
if (ts >= 65535 * 16 * 63) {
|
||||
spt = 255;
|
||||
heads = 16;
|
||||
cth = ts / spt;
|
||||
|
||||
@@ -24,7 +24,7 @@ static void mvhd_next_struct_to_buffer(void* struct_memb, size_t memb_size, bool
|
||||
|
||||
/**
|
||||
* \brief Get the next field from a buffer and store it in a struct member, converting endian if necessary
|
||||
*
|
||||
*
|
||||
* \param [out] struct_memb struct member to save the field to
|
||||
* \param [in] memb_size the size of struct_memb, in bytes
|
||||
* \param [in] req_endian is the field a value that requires endian conversion (eg: uint16, uint32)
|
||||
@@ -50,7 +50,7 @@ static void mvhd_next_buffer_to_struct(void* struct_memb, size_t memb_size, bool
|
||||
|
||||
/**
|
||||
* \brief Save a struct member into a buffer, converting endian if necessary
|
||||
*
|
||||
*
|
||||
* \param [in] struct_memb struct member read from
|
||||
* \param [in] memb_size the size of struct_memb, in bytes
|
||||
* \param [in] req_endian is the field a value that requires endian conversion (eg: uint16, uint32)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
/**
|
||||
* \brief Save the contents of a VHD footer from a buffer to a struct
|
||||
*
|
||||
*
|
||||
* \param [out] footer save contents of buffer into footer
|
||||
* \param [in] buffer VHD footer in raw bytes
|
||||
*/
|
||||
@@ -13,7 +13,7 @@ void mvhd_buffer_to_footer(MVHDFooter* footer, uint8_t* buffer);
|
||||
|
||||
/**
|
||||
* \brief Save the contents of a VHD sparse header from a buffer to a struct
|
||||
*
|
||||
*
|
||||
* \param [out] header save contents of buffer into header
|
||||
* \param [in] buffer VHD header in raw bytes
|
||||
*/
|
||||
@@ -21,7 +21,7 @@ void mvhd_buffer_to_header(MVHDSparseHeader* header, uint8_t* buffer);
|
||||
|
||||
/**
|
||||
* \brief Save the contents of a VHD footer struct to a buffer
|
||||
*
|
||||
*
|
||||
* \param [in] footer save contents of struct into buffer
|
||||
* \param [out] buffer VHD footer in raw bytes
|
||||
*/
|
||||
@@ -29,7 +29,7 @@ void mvhd_footer_to_buffer(MVHDFooter* footer, uint8_t* buffer);
|
||||
|
||||
/**
|
||||
* \brief Save the contents of a VHD sparse header struct to a buffer
|
||||
*
|
||||
*
|
||||
* \param [in] header save contents of struct into buffer
|
||||
* \param [out] buffer VHD sparse header in raw bytes
|
||||
*/
|
||||
|
||||
@@ -20,9 +20,9 @@ uint64_t mvhd_to_be64(uint64_t val);
|
||||
|
||||
/**
|
||||
* \brief Check if provided buffer begins with the string "conectix"
|
||||
*
|
||||
*
|
||||
* \param [in] buffer The buffer to compare. Must be at least 8 bytes in length
|
||||
*
|
||||
*
|
||||
* \return true if the buffer begins with "conectix"
|
||||
* \return false if the buffer does not begin with "conectix"
|
||||
*/
|
||||
@@ -30,7 +30,7 @@ bool mvhd_is_conectix_str(const void* buffer);
|
||||
|
||||
/**
|
||||
* \brief Generate a raw 16 byte UUID
|
||||
*
|
||||
*
|
||||
* \param [out] uuid A 16 byte buffer in which the generated UUID will be stored to
|
||||
*/
|
||||
void mvhd_generate_uuid(uint8_t *uuid);
|
||||
@@ -42,9 +42,9 @@ uint32_t vhd_calc_timestamp(void);
|
||||
|
||||
/**
|
||||
* \brief Convert an epoch timestamp to a VHD timestamp
|
||||
*
|
||||
*
|
||||
* \param [in] ts epoch timestamp to convert.
|
||||
*
|
||||
*
|
||||
* \return The adjusted timestamp, or 0 if the input timestamp is
|
||||
* earlier that 1 Janurary 2000
|
||||
*/
|
||||
@@ -52,26 +52,26 @@ uint32_t mvhd_epoch_to_vhd_ts(time_t ts);
|
||||
|
||||
/**
|
||||
* \brief Return the created time from a VHD image
|
||||
*
|
||||
*
|
||||
* \param [in] vhdm Pointer to the MiniVHD metadata structure
|
||||
*
|
||||
*
|
||||
* \return The created time, as a Unix timestamp
|
||||
*/
|
||||
time_t vhd_get_created_time(MVHDMeta *vhdm);
|
||||
|
||||
/**
|
||||
* \brief Cross platform, unicode filepath opening
|
||||
*
|
||||
* This function accounts for the fact that fopen() handles file paths differently compared to other
|
||||
* operating systems. Windows version of fopen() will not handle multi byte encoded text like UTF-8.
|
||||
*
|
||||
* Unicode filepath support on Windows requires using the _wfopen() function, which expects UTF-16LE
|
||||
*
|
||||
* This function accounts for the fact that fopen() handles file paths differently compared to other
|
||||
* operating systems. Windows version of fopen() will not handle multi byte encoded text like UTF-8.
|
||||
*
|
||||
* Unicode filepath support on Windows requires using the _wfopen() function, which expects UTF-16LE
|
||||
* encoded path and modestring.
|
||||
*
|
||||
*
|
||||
* \param [in] path The filepath to open as a UTF-8 string
|
||||
* \param [in] mode The mode string to use (eg: "rb+"")
|
||||
* \param [out] err The error value, if an error occurrs
|
||||
*
|
||||
*
|
||||
* \return a FILE pointer if successful, NULL otherwise. If NULL, check the value of err
|
||||
*/
|
||||
FILE* mvhd_fopen(const char* path, const char* mode, int* err);
|
||||
@@ -83,52 +83,52 @@ MVHDGeom mvhd_get_geometry(MVHDMeta* vhdm);
|
||||
|
||||
/**
|
||||
* \brief Generate VHD footer checksum
|
||||
*
|
||||
*
|
||||
* \param [in] vhdm MiniVHD data structure
|
||||
*/
|
||||
uint32_t mvhd_gen_footer_checksum(MVHDFooter* footer);
|
||||
|
||||
/**
|
||||
* \brief Generate VHD sparse header checksum
|
||||
*
|
||||
*
|
||||
* \param [in] vhdm MiniVHD data structure
|
||||
*/
|
||||
uint32_t mvhd_gen_sparse_checksum(MVHDSparseHeader* header);
|
||||
|
||||
/**
|
||||
* \brief Get current position in file stream
|
||||
*
|
||||
* This is a portable version of the POSIX ftello64(). *
|
||||
*
|
||||
* This is a portable version of the POSIX ftello64(). *
|
||||
*/
|
||||
int64_t mvhd_ftello64(FILE* stream);
|
||||
|
||||
/**
|
||||
* \brief Reposition the file stream's position
|
||||
*
|
||||
* This is a portable version of the POSIX fseeko64(). *
|
||||
*
|
||||
* This is a portable version of the POSIX fseeko64(). *
|
||||
*/
|
||||
int mvhd_fseeko64(FILE* stream, int64_t offset, int origin);
|
||||
|
||||
/**
|
||||
* \brief Calculate the CRC32 of a data buffer.
|
||||
*
|
||||
*
|
||||
* This function can be used for verifying data integrity.
|
||||
*
|
||||
*
|
||||
* \param [in] data The data buffer
|
||||
* \param [in] n_bytes The size of the data buffer in bytes
|
||||
*
|
||||
*
|
||||
* \return The CRC32 of the data buffer
|
||||
*/
|
||||
uint32_t mvhd_crc32(const void* data, size_t n_bytes);
|
||||
|
||||
/**
|
||||
* \brief Calculate the file modification timestamp.
|
||||
*
|
||||
*
|
||||
* This function is primarily to help protect differencing VHD's
|
||||
*
|
||||
*
|
||||
* \param [in] path the UTF-8 file path
|
||||
* \param [out] err The error value, if an error occurrs
|
||||
*
|
||||
*
|
||||
* \return The file modified timestamp, in VHD compatible timestamp.
|
||||
* 'err' will be set to non-zero on error
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user