diff --git a/src/main.c b/src/main.c index abf0d34..01c8d10 100644 --- a/src/main.c +++ b/src/main.c @@ -196,7 +196,7 @@ #define MAIN int main(int argc, char **argv) #endif -//TODO: Consider hashing strings for faster lookups +//TODO: Consider hashing strings for faster lookups when parsing CLI // Either SuperFastHash [1] or xxHash [2] // [1] http://www.azillionmonkeys.com/qed/hash.html // [2] https://github.com/Cyan4973/xxHash diff --git a/src/vdisk.c b/src/vdisk.c index 25f0d2b..8cf81a1 100644 --- a/src/vdisk.c +++ b/src/vdisk.c @@ -179,7 +179,7 @@ vd->u32blockcount = 1; uint32_t bsize = vd->u32blockcount << 2; if ((vd->u32block = malloc(bsize)) == NULL) - return vdisk_i_err(vd, VVD_EALLOC, LINE_BEFORE); + return vdisk_i_err(vd, VVD_ENOMEM, LINE_BEFORE); vd->vdiv1.blockstotal = vd->u32blockcount; vd->vdiv1.disksize = capacity; switch (vd->vdiv1.type) { @@ -189,7 +189,7 @@ break; case VDI_DISK_FIXED: if ((buffer = malloc(vd->vdiv1.blocksize)) == NULL) - return vdisk_i_err(vd, VVD_EALLOC, LINE_BEFORE); + return vdisk_i_err(vd, VVD_ENOMEM, LINE_BEFORE); os_fseek(vd->fd, vd->vdiv1.offData, SEEK_SET); for (size_t i = 0; i < vd->vdiv1.blockstotal; ++i) { vd->u32block[i] = VDI_BLOCK_FREE; diff --git a/src/vdisk.h b/src/vdisk.h index 3e80d06..2435f93 100644 --- a/src/vdisk.h +++ b/src/vdisk.h @@ -23,6 +23,7 @@ VDISK_FORMAT_RAW = 0xAAAAAAAA, // Raw files and devices VDISK_FORMAT_VDI = 0x203C3C3C, // "<<< " VirtualBox VDISK_FORMAT_VMDK = 0x564D444B, // "VMDK" VMware + VDISK_FORMAT_VMDK_COW = 0x44574F43, // "COWD" VMware EXSi COW disk VDISK_FORMAT_VHD = 0x656E6F63, // "cone" VirtualPC/Hyper-V VDISK_FORMAT_VHDX = 0x78646876, // "vhdx" Hyper-V VDISK_FORMAT_QED = 0x00444551, // "QED\0" QEMU Enhanced Disk @@ -66,7 +67,7 @@ VVD_EOK = 0, // VDISK OK VVD_EOS = -2, // OS/CRT related error VVD_ENULL = -3, // Input pointer is NULL - VVD_EALLOC = -4, // Could not allocate memory + VVD_ENOMEM = -4, // Could not allocate memory VVD_EVDFORMAT = -10, // Invalid VDISK format VVD_EVDMAGIC = -11, // Invalid VDISK magic signature VVD_EVDVERSION = -12, // Unsupported VDISK version (major) @@ -218,7 +219,7 @@ * * \param vd VDISK structure * \param path OS string path - * \param flags Flags + * \param flags Opening flags * * \returns Exit status */ @@ -231,7 +232,7 @@ * \param path OS string path * \param format Virtual disk format * \param capacity Virtual disk capacity - * \param flags Flags + * \param flags Creation flags * * \returns Exit status */ diff --git a/src/vdisk/bochs.h b/src/vdisk/bochs.h index 29f1241..cad22c6 100644 --- a/src/vdisk/bochs.h +++ b/src/vdisk/bochs.h @@ -5,16 +5,20 @@ * * Little-endian * - * http://bochs.sourceforge.net/cgi-bin/topper.pl?name=New+Bochs+Documentation&url=http://bochs.sourceforge.net/doc/docbook/development/index.html + * http://bochs.sourceforge.net/doc/docbook/development/harddisk-redologs.html * ยง2.10 */ #include +static const uint32_t BOCHS_VERSION = 0x00020000; +static const uint32_t BOCHS_V1 = 0x00010000; +static const uint32_t BOCHS_UNALLOC = 0xffffffff; + typedef struct { char signacture[32]; // "Bochs Virtual HD Image" char type[16]; // "Redolog" - char subtype[16]; // "Undoable", "Volatile", "Growing" + char subtype[16]; // "Undoable", "Volatile", "Growing", "vvfat" uint32_t version; // 0x00010000, 0x00020000 uint32_t hdrsize; // 512 } BOCH_HDR; diff --git a/src/vdisk/qed.c b/src/vdisk/qed.c index b39d6ef..56d04dd 100644 --- a/src/vdisk/qed.c +++ b/src/vdisk/qed.c @@ -31,9 +31,9 @@ uint32_t tablebits = fpow2(table_entries); if ((vd->qed_L1 = malloc(table_size)) == NULL) - return vdisk_i_err(vd, VVD_EALLOC, LINE_BEFORE); + return vdisk_i_err(vd, VVD_ENOMEM, LINE_BEFORE); if ((vd->qed_L2.offsets = malloc(table_size)) == NULL) - return vdisk_i_err(vd, VVD_EALLOC, LINE_BEFORE); + return vdisk_i_err(vd, VVD_ENOMEM, LINE_BEFORE); if (os_fseek(vd->fd, vd->qed.cluster_size, SEEK_SET)) return vdisk_i_err(vd, VVD_EOS, LINE_BEFORE); if (os_fread(vd->fd, vd->qed_L1, table_size)) diff --git a/src/vdisk/vdi.c b/src/vdisk/vdi.c index 861b9e0..af2d796 100644 --- a/src/vdisk/vdi.c +++ b/src/vdisk/vdi.c @@ -63,7 +63,7 @@ return vdisk_i_err(vd, VVD_EOS, LINE_BEFORE); int bsize = vd->vdiv1.blockstotal << 2; // * sizeof(u32) if ((vd->u32block = malloc(bsize)) == NULL) - return vdisk_i_err(vd, VVD_EALLOC, LINE_BEFORE); + return vdisk_i_err(vd, VVD_ENOMEM, LINE_BEFORE); if (os_fread(vd->fd, vd->u32block, bsize)) return vdisk_i_err(vd, VVD_EOS, LINE_BEFORE); @@ -122,38 +122,37 @@ if (vd->vdiv1.type != VDI_DISK_DYN) return vdisk_i_err(vd, VVD_EVDTYPE, LINE_BEFORE); - if (vd->vdiv1.blocksalloc == 0) + uint32_t *block2; // back resolving array + uint32_t bk_alloc; // blocks allocated + + // 1. Allocate block array for back resolving. + + uint64_t fsize; + if (os_fsize(vd->fd, &fsize)) + return vdisk_i_err(vd, VVD_EVDMISC, LINE_BEFORE); + + // This verifies that there are actually data blocks available + bk_alloc = (uint32_t)((fsize - vd->vdiv1.offData - vd->vdiv1.offBlocks) >> vd->vdi_blockshift); + if (bk_alloc == 0 || vd->vdiv1.blocksalloc == 0) return 0; - uint32_t stat_unalloc = 0; // unallocated blocks - uint32_t stat_occupied = 0; // allocated blocks with data - uint32_t stat_zero = 0; // blocks with no data inside - uint32_t stat_alloc = 0; // allocated blocks - - uint32_t *block2 = malloc(vd->vdiv1.blocksalloc << 2); // * 4 - if (block2) - return vdisk_i_err(vd, VVD_EALLOC, LINE_BEFORE); - for (uint32_t i; i < vd->vdiv1.blocksalloc; ++i) + block2 = malloc(bk_alloc << 2); + if (block2 == NULL) + return vdisk_i_err(vd, VVD_ENOMEM, LINE_BEFORE); + for (uint32_t i; i < n; ++i) block2[i] = VDI_BLOCK_FREE; -/* char strbsize[BINSTR_LENGTH]; - bintostr(strbsize, vd->vdiv1.blocksize); - printf("vvd_compact: writing (%s/block, %u checks/%u bytes)...\n", - strbsize, (uint32_t)oblocksize, (uint32_t)sizeof(size_t));*/ - uint32_t d = 0; uint32_t i = 0; - // Check and fix allocation errors before compacting + // 2. Check and fix allocation errors before compacting + for (; i < vd->u32blockcount; ++i) { uint32_t bi = vd->u32block[i]; // block index if (bi >= VDI_BLOCK_FREE) { - ++stat_unalloc; continue; } - if (cb) cb(VVD_NOTIF_VDISK_CURRENT_BLOCK, &i); - if (bi < vd->vdiv1.blocksalloc) { if (vd->u32block[bi] == VDI_BLOCK_FREE) { vd->u32block[bi] = i; @@ -170,16 +169,21 @@ //vdisk_write_block_at(vd, buffer, i, d++); } } - // Find redundant information and update the block pointers accordingly + + // 3. Find redundant information and update the block pointers accordingly + for (i = 0; i < vd->u32blockcount; ++i) { uint32_t bi = vd->u32block[i]; // block index if (bi >= VDI_BLOCK_FREE) { - ++stat_unalloc; continue; } } - // Fill bubbles with other data if available -// for (i = 0; o < vd->vdi.blocksalloc + + // 4. Fill bubbles with other data if available + +// for (i = 0; o < vd->vdi.blocksalloc + + // 5. Update fields in-memory and on-disk return 0; } diff --git a/src/vdisk/vdi.h b/src/vdisk/vdi.h index fffe413..9050307 100644 --- a/src/vdisk/vdi.h +++ b/src/vdisk/vdi.h @@ -14,13 +14,13 @@ * Block marked as free is not allocated in image file, read from this * block may returns any random data. */ -static const uint32_t VDI_BLOCK_FREE = ~0; +static const uint32_t VDI_BLOCK_FREE = 0xffffffff; /** * Block marked as zero is not allocated in image file, read from this * block returns zeroes. */ -static const uint32_t VDI_BLOCK_ZERO = ~1; +static const uint32_t VDI_BLOCK_ZERO = 0xfffffffe; enum { VDI_HEADER_MAGIC = 0xBEDA107F, @@ -93,4 +93,4 @@ int vdisk_vdi_read_sector(struct VDISK *vd, void *buffer, uint64_t index); -int vdisk_vdi_compact(struct VDISK *vd, void(*cb_progress)(uint32_t type, void *data)); +int vdisk_vdi_compact(struct VDISK *vd, void(*cb)(uint32_t type, void *data)); diff --git a/src/vdisk/vhd.c b/src/vdisk/vhd.c index b65322b..8309650 100644 --- a/src/vdisk/vhd.c +++ b/src/vdisk/vhd.c @@ -101,7 +101,7 @@ int batsize = vd->u32blockcount << 2; // "* 4" if ((vd->u32block = malloc(batsize)) == NULL) - return vdisk_i_err(vd, VVD_EALLOC, LINE_BEFORE); + return vdisk_i_err(vd, VVD_ENOMEM, LINE_BEFORE); if (os_fread(vd->fd, vd->u32block, batsize)) return vdisk_i_err(vd, VVD_EOS, LINE_BEFORE); #if ENDIAN_LITTLE