mirror of
https://github.com/VARCem/MiniVHD.git
synced 2026-09-23 07:15:01 +00:00
Implement differencing read function
This commit is contained in:
@@ -59,6 +59,7 @@ typedef struct MVHDSparseHeader {
|
||||
typedef struct MVHDBlock {
|
||||
uint8_t* bitmap;
|
||||
uint32_t offset;
|
||||
bool bitmap_cached;
|
||||
} MVHDBlock;
|
||||
|
||||
bool mvhd_is_conectix_str(const void* buffer);
|
||||
|
||||
@@ -3,6 +3,13 @@
|
||||
#include "minivhd_internal.h"
|
||||
#include "minivhd.h"
|
||||
|
||||
/* 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)) )
|
||||
#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(int offset, int num_sectors, int total_sectors, int* transfer_sect, int* trunc_sect) {
|
||||
*transfer_sect = num_sectors;
|
||||
*trunc_sect = 0;
|
||||
@@ -11,6 +18,20 @@ static inline void mvhd_check_sectors(int offset, int num_sectors, int total_sec
|
||||
*trunc_sect = num_sectors - *transfer_sect;
|
||||
}
|
||||
}
|
||||
|
||||
static void mvhd_read_sect_bitmap(MVHDMeta* vhdm, int blk) {
|
||||
if (!vhdm->block[blk].bitmap_cached) {
|
||||
if (vhdm->block[blk].bitmap == NULL) {
|
||||
vhdm->block[blk].bitmap = calloc(vhdm->bm_sect_count, MVHD_SECTOR_SIZE);
|
||||
}
|
||||
if (vhdm->block[blk].offset != MVHD_SPARSE_BLK) {
|
||||
fseeko64(vhdm->f, vhdm->block[blk].offset * MVHD_SECTOR_SIZE, SEEK_SET);
|
||||
fread(vhdm->block[blk].bitmap, vhdm->bm_sect_count * MVHD_SECTOR_SIZE, 1, vhdm->f);
|
||||
}
|
||||
vhdm->block[blk].bitmap_cached = true;
|
||||
}
|
||||
}
|
||||
|
||||
int mvhd_fixed_read(MVHDMeta* vhdm, int offset, int num_sectors, void* out_buff) {
|
||||
int64_t addr;
|
||||
int transfer_sectors, truncated_sectors;
|
||||
@@ -47,4 +68,34 @@ int mvhd_sparse_read(MVHDMeta* vhdm, int offset, int num_sectors, void* out_buff
|
||||
buff += MVHD_SECTOR_SIZE;
|
||||
}
|
||||
return truncated_sectors;
|
||||
}
|
||||
|
||||
int mvhd_diff_read(MVHDMeta* vhdm, int offset, int num_sectors, void* out_buff) {
|
||||
int transfer_sectors, truncated_sectors;
|
||||
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;
|
||||
int s, ls, blk, sib;
|
||||
ls = offset + transfer_sectors;
|
||||
for (s = offset; s <= ls; s++) {
|
||||
blk = s / vhdm->sect_per_block;
|
||||
sib = s % vhdm->sect_per_block;
|
||||
while (curr_vhdm->footer.disk_type == MVHD_TYPE_DIFF) {
|
||||
mvhd_read_sect_bitmap(vhdm, blk);
|
||||
if (VHD_TESTBIT(curr_vhdm->block[blk].bitmap, sib)) {
|
||||
curr_vhdm = curr_vhdm->parent;
|
||||
} else { break; }
|
||||
}
|
||||
/* We handle actual sector reading using the fixed or sparse functions,
|
||||
as a differencing VHD is also a sparse VHD */
|
||||
if (curr_vhdm->footer.disk_type == MVHD_TYPE_DIFF || curr_vhdm->footer.disk_type == MVHD_TYPE_DYNAMIC) {
|
||||
mvhd_sparse_read(curr_vhdm, s, 1, buff);
|
||||
} else {
|
||||
mvhd_fixed_read(curr_vhdm, s, 1, buff);
|
||||
}
|
||||
curr_vhdm = vhdm;
|
||||
buff += MVHD_SECTOR_SIZE;
|
||||
}
|
||||
return truncated_sectors;
|
||||
}
|
||||
@@ -83,6 +83,7 @@ static MVHDBlock* mvhd_read_bat(MVHDMeta *vhdm, MVHDError* err) {
|
||||
for (uint32_t i = 0; i < vhdm->sparse.max_bat_ent; i++) {
|
||||
fread(&vhdm->block[i].offset, sizeof vhdm->block[i].offset, 1, vhdm->f);
|
||||
vhdm->block[i].bitmap = NULL;
|
||||
vhdm->block[i].bitmap_cached = false;
|
||||
}
|
||||
return vhdm->block;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user