static int vhd_read_data(vhd_context_t *vhd, uint64_t sec, int count, int hex) { void *buf; uint64_t cur; int err, max, secs; if (vhd_sectors_to_bytes(sec + count) > vhd->footer.curr_size) return -ERANGE; max = MIN(vhd_sectors_to_bytes(count), VHD_BLOCK_SIZE); err = posix_memalign(&buf, VHD_SECTOR_SIZE, max); if (err) return -err; cur = sec; while (count) { int gcc; secs = MIN((max >> VHD_SECTOR_SHIFT), count); err = vhd_io_read(vhd, buf, cur, secs); if (err) break; gcc = write(STDOUT_FILENO, buf, vhd_sectors_to_bytes(secs)); if (gcc) ; cur += secs; count -= secs; } free(buf); return err; }
int vhd_util_fill(int argc, char **argv) { int err, c; char *name; void *buf; vhd_context_t vhd; uint64_t i, sec, secs, from_sector, to_sector; int init_bat; bool ignore_2tb_limit; buf = NULL; name = NULL; init_bat = 0; from_sector = ULLONG_MAX; to_sector = ULLONG_MAX; ignore_2tb_limit = false; if (!argc || !argv) goto usage; optind = 0; while ((c = getopt(argc, argv, "n:f:t:bBh")) != -1) { switch (c) { case 'n': name = optarg; break; case 'f': from_sector = strtoull(optarg, NULL, 10); break; case 't': to_sector = strtoull(optarg, NULL, 10); break; case 'b': init_bat = 1; break; case 'B': ignore_2tb_limit = true; break; case 'h': default: goto usage; } } if (!name || optind != argc) goto usage; if ((from_sector != ULLONG_MAX || to_sector != ULLONG_MAX) && !init_bat) { printf("-f/-t can only be used with -b\n"); goto usage; } if (from_sector != ULLONG_MAX && to_sector != ULLONG_MAX) { if (to_sector < from_sector) { printf("invalid sector range %llu-%llu\n", (unsigned long long)from_sector, (unsigned long long)to_sector); goto usage; } } if (ignore_2tb_limit && !init_bat) { printf("-B can only be used with -b\n"); goto usage; } err = vhd_open(&vhd, name, VHD_OPEN_RDWR); if (err) { printf("error opening %s: %d\n", name, err); return err; } err = vhd_get_bat(&vhd); if (err) goto done; if (init_bat) { uint32_t from_extent; uint32_t to_extent; if (from_sector != ULLONG_MAX) from_extent = from_sector / vhd.spb; else from_extent = 0; if (to_sector != ULLONG_MAX) to_extent = to_sector / vhd.spb; else to_extent = vhd.bat.entries - 1; err = vhd_io_allocate_blocks_fast(&vhd, from_extent, to_extent, ignore_2tb_limit); if (err) goto done; } else { err = posix_memalign(&buf, 4096, vhd.header.block_size); if (err) { err = -err; goto done; } sec = 0; secs = vhd.header.block_size >> VHD_SECTOR_SHIFT; for (i = 0; i < vhd.header.max_bat_size; i++) { err = vhd_io_read(&vhd, buf, sec, secs); if (err) goto done; err = vhd_io_write(&vhd, buf, sec, secs); if (err) goto done; sec += secs; } err = 0; } done: free(buf); vhd_close(&vhd); return err; usage: printf("options: <-n name> [-h help] [-b initialise the BAT and bitmaps, " "don't write to the data blocks (much faster)] [-f start " "intialisation from this sector, only usable with -b] [-t " "intialise up to this sector (inclusive), only usable with -b] " "[-B ignore the 2 TB limit, only usable with -b]\n"); return -EINVAL; }
int vhd_util_fill(int argc, char **argv) { int err, c; char *name; void *buf; vhd_context_t vhd; uint64_t i, sec, secs; buf = NULL; name = NULL; if (!argc || !argv) goto usage; optind = 0; while ((c = getopt(argc, argv, "n:h")) != -1) { switch (c) { case 'n': name = optarg; break; case 'h': default: goto usage; } } if (!name || optind != argc) goto usage; err = vhd_open(&vhd, name, VHD_OPEN_RDWR); if (err) { printf("error opening %s: %d\n", name, err); return err; } err = vhd_get_bat(&vhd); if (err) goto done; err = posix_memalign(&buf, 4096, vhd.header.block_size); if (err) { err = -err; goto done; } sec = 0; secs = vhd.header.block_size >> VHD_SECTOR_SHIFT; for (i = 0; i < vhd.header.max_bat_size; i++) { err = vhd_io_read(&vhd, buf, sec, secs); if (err) goto done; err = vhd_io_write(&vhd, buf, sec, secs); if (err) goto done; sec += secs; } err = 0; done: free(buf); vhd_close(&vhd); return err; usage: printf("options: <-n name> [-h help]\n"); return -EINVAL; }