mirror of
https://github.com/VARCem/MiniVHD.git
synced 2026-09-24 07:45:12 +00:00
Added initial raw image conversion
This commit is contained in:
@@ -21,7 +21,8 @@ typedef enum MVHDError {
|
||||
MVHD_ERR_PAR_NOT_FOUND,
|
||||
MVHD_ERR_INVALID_PAR_UUID,
|
||||
MVHD_ERR_INVALID_GEOM,
|
||||
MVHD_ERR_INVALID_PARAMS
|
||||
MVHD_ERR_INVALID_PARAMS,
|
||||
MVHD_ERR_CONV_SIZE
|
||||
} MVHDError;
|
||||
|
||||
typedef struct MVHDGeom {
|
||||
@@ -131,6 +132,39 @@ void mvhd_close(MVHDMeta* vhdm);
|
||||
*/
|
||||
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
|
||||
*
|
||||
|
||||
105
src/minivhd_convert.c
Normal file
105
src/minivhd_convert.c
Normal file
@@ -0,0 +1,105 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "minivhd_create.h"
|
||||
#include "minivhd_internal.h"
|
||||
#include "minivhd_util.h"
|
||||
#include "minivhd.h"
|
||||
|
||||
static FILE* mvhd_open_existing_raw_img(const char* utf8_raw_path, MVHDGeom* geom, int* err);
|
||||
|
||||
static FILE* mvhd_open_existing_raw_img(const char* utf8_raw_path, MVHDGeom* geom, int* err) {
|
||||
FILE *raw_img = mvhd_fopen(utf8_raw_path, "rb", err);
|
||||
if (raw_img == NULL) {
|
||||
*err = MVHD_ERR_FILE;
|
||||
return NULL;
|
||||
}
|
||||
if (geom == NULL) {
|
||||
*err = MVHD_ERR_INVALID_GEOM;
|
||||
return NULL;
|
||||
}
|
||||
fseeko64(raw_img, 0, SEEK_END);
|
||||
uint64_t size_bytes = (uint64_t)ftello64(raw_img);
|
||||
MVHDGeom new_geom = mvhd_calculate_geometry(size_bytes);
|
||||
if (mvhd_calc_size_bytes(&new_geom) != size_bytes) {
|
||||
*err = MVHD_ERR_CONV_SIZE;
|
||||
return NULL;
|
||||
}
|
||||
geom->cyl = new_geom.cyl;
|
||||
geom->heads = new_geom.heads;
|
||||
geom->spt = new_geom.spt;
|
||||
fseeko64(raw_img, 0, SEEK_SET);
|
||||
return raw_img;
|
||||
}
|
||||
|
||||
MVHDMeta* mvhd_convert_to_vhd_fixed(const char* utf8_raw_path, const char* utf8_vhd_path, int* err) {
|
||||
MVHDGeom geom;
|
||||
FILE *raw_img = mvhd_open_existing_raw_img(utf8_raw_path, &geom, err);
|
||||
if (raw_img == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
int pos;
|
||||
MVHDMeta *vhdm = mvhd_create_fixed_raw(utf8_vhd_path, raw_img, &geom, (volatile int*)&pos, err);
|
||||
if (vhdm == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return vhdm;
|
||||
}
|
||||
MVHDMeta* mvhd_convert_to_vhd_sparse(const char* utf8_raw_path, const char* utf8_vhd_path, int* err) {
|
||||
MVHDGeom geom;
|
||||
MVHDMeta *vhdm = NULL;
|
||||
FILE *raw_img = mvhd_open_existing_raw_img(utf8_raw_path, &geom, err);
|
||||
if (raw_img == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
vhdm = mvhd_create_sparse(utf8_vhd_path, geom, err);
|
||||
if (vhdm == NULL) {
|
||||
goto end;
|
||||
}
|
||||
uint8_t buff[4096] = {0}; // 8 sectors
|
||||
uint8_t empty_buff[4096] = {0};
|
||||
int total_sectors = mvhd_calc_size_sectors(&geom);
|
||||
int copy_sect = 0;
|
||||
for (int i = 0; i < total_sectors; i += 8) {
|
||||
copy_sect = 8;
|
||||
if ((i + 8) >= total_sectors) {
|
||||
copy_sect = total_sectors - i - 1;
|
||||
memset(buff, 0, sizeof buff);
|
||||
}
|
||||
fread(buff, MVHD_SECTOR_SIZE, copy_sect, raw_img);
|
||||
/* Only write data if there's data to write, to take advantage of the sparse VHD format */
|
||||
if (memcmp(buff, empty_buff, sizeof buff) != 0) {
|
||||
mvhd_write_sectors(vhdm, i, copy_sect, buff);
|
||||
}
|
||||
}
|
||||
end:
|
||||
fclose(raw_img);
|
||||
return vhdm;
|
||||
}
|
||||
FILE* mvhd_convert_to_raw(const char* utf8_vhd_path, const char* utf8_raw_path, int *err) {
|
||||
FILE *raw_img = mvhd_fopen(utf8_raw_path, "wb", err);
|
||||
if (raw_img == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
MVHDMeta *vhdm = mvhd_open(utf8_vhd_path, true, err);
|
||||
if (vhdm == NULL) {
|
||||
fclose(raw_img);
|
||||
return NULL;
|
||||
}
|
||||
uint8_t buff[4096] = {0}; // 8 sectors
|
||||
int total_sectors = mvhd_calc_size_sectors((MVHDGeom*)&vhdm->footer.geom);
|
||||
int copy_sect = 0;
|
||||
for (int i = 0; i < total_sectors; i += 8) {
|
||||
copy_sect = 8;
|
||||
if ((i + 8) >= total_sectors) {
|
||||
copy_sect = total_sectors - i - 1;
|
||||
}
|
||||
mvhd_read_sectors(vhdm, i, copy_sect, buff);
|
||||
fwrite(buff, MVHD_SECTOR_SIZE, copy_sect, raw_img);
|
||||
}
|
||||
mvhd_close(vhdm);
|
||||
fseeko64(raw_img, 0, SEEK_SET);
|
||||
return raw_img;
|
||||
}
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "minivhd_util.h"
|
||||
#include "minivhd_struct_rw.h"
|
||||
#include "minivhd_io.h"
|
||||
#include "minivhd_create.h"
|
||||
#include "minivhd.h"
|
||||
|
||||
static void mvhd_gen_footer(MVHDFooter* footer, MVHDGeom* geom, MVHDType type, uint64_t sparse_header_off);
|
||||
@@ -178,14 +179,30 @@ end:
|
||||
}
|
||||
|
||||
MVHDMeta* mvhd_create_fixed(const char* path, MVHDGeom geom, volatile int* pos, int* err) {
|
||||
uint8_t zero_data[MVHD_SECTOR_SIZE] = {0};
|
||||
return mvhd_create_fixed_raw(path, NULL, &geom, pos, err);
|
||||
}
|
||||
|
||||
/**
|
||||
* \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, MVHDGeom* geom, volatile int* pos, int* err) {
|
||||
uint8_t img_data[MVHD_SECTOR_SIZE] = {0};
|
||||
uint8_t footer_buff[MVHD_FOOTER_SIZE] = {0};
|
||||
MVHDMeta* vhdm = calloc(1, sizeof *vhdm);
|
||||
if (vhdm == NULL) {
|
||||
*err = MVHD_ERR_MEM;
|
||||
goto end;
|
||||
}
|
||||
if (geom.cyl == 0 || geom.heads == 0 || geom.spt == 0) {
|
||||
if (raw_img == NULL && geom == NULL) {
|
||||
*err = MVHD_ERR_INVALID_GEOM;
|
||||
goto cleanup_vhdm;
|
||||
}
|
||||
if (geom != NULL && (geom->cyl == 0 || geom->heads == 0 || geom->spt == 0)) {
|
||||
*err = MVHD_ERR_INVALID_GEOM;
|
||||
goto cleanup_vhdm;
|
||||
}
|
||||
@@ -194,13 +211,34 @@ MVHDMeta* mvhd_create_fixed(const char* path, MVHDGeom geom, volatile int* pos,
|
||||
goto cleanup_vhdm;
|
||||
}
|
||||
fseeko64(f, 0, SEEK_SET);
|
||||
mvhd_gen_footer(&vhdm->footer, &geom, MVHD_TYPE_FIXED, 0);
|
||||
uint32_t size_sectors = mvhd_calc_size_sectors(&geom);
|
||||
for (uint32_t s = 0; s < size_sectors; s++) {
|
||||
if (pos != NULL) {
|
||||
*pos = (int)s;
|
||||
uint32_t size_sectors, s;
|
||||
if (raw_img != NULL) {
|
||||
fseeko64(raw_img, 0, SEEK_END);
|
||||
uint64_t raw_size = (uint64_t)ftello64(raw_img);
|
||||
MVHDGeom raw_geom = mvhd_calculate_geometry(raw_size);
|
||||
if (mvhd_calc_size_bytes(&raw_geom) != raw_size) {
|
||||
*err = MVHD_ERR_CONV_SIZE;
|
||||
goto cleanup_vhdm;
|
||||
}
|
||||
mvhd_gen_footer(&vhdm->footer, geom, MVHD_TYPE_FIXED, 0);
|
||||
size_sectors = mvhd_calc_size_sectors(geom);
|
||||
fseeko64(raw_img, 0, SEEK_SET);
|
||||
for (s = 0; s < size_sectors; s++) {
|
||||
if (pos != NULL) {
|
||||
*pos = (int)s;
|
||||
}
|
||||
fread(img_data, sizeof img_data, 1, raw_img);
|
||||
fwrite(img_data, sizeof img_data, 1, f);
|
||||
}
|
||||
} else {
|
||||
mvhd_gen_footer(&vhdm->footer, geom, MVHD_TYPE_FIXED, 0);
|
||||
size_sectors = mvhd_calc_size_sectors(geom);
|
||||
for (s = 0; s < size_sectors; s++) {
|
||||
if (pos != NULL) {
|
||||
*pos = (int)s;
|
||||
}
|
||||
fwrite(img_data, sizeof img_data, 1, f);
|
||||
}
|
||||
fwrite(zero_data, sizeof zero_data, 1, f);
|
||||
}
|
||||
mvhd_footer_to_buffer(&vhdm->footer, footer_buff);
|
||||
fwrite(footer_buff, sizeof footer_buff, 1, f);
|
||||
|
||||
8
src/minivhd_create.h
Normal file
8
src/minivhd_create.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef MINIVHD_CREATE_H
|
||||
#define MINIVHD_CREATE_H
|
||||
#include <stdio.h>
|
||||
#include "minivhd.h"
|
||||
|
||||
MVHDMeta* mvhd_create_fixed_raw(const char* path, FILE* raw_img, MVHDGeom* geom, volatile int* pos, int* err);
|
||||
|
||||
#endif
|
||||
@@ -170,6 +170,8 @@ const char* mvhd_strerr(MVHDError err) {
|
||||
return "invalid geometry detected";
|
||||
case MVHD_ERR_INVALID_PARAMS:
|
||||
return "invalid parameters passed to function";
|
||||
case MVHD_ERR_CONV_SIZE:
|
||||
return "error converting image. Size mismatch detechted";
|
||||
default:
|
||||
return "unknown error";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user