Example #1
0
static int
vhd_util_find_snapshot_target(const char *name, char **result, int *parent_raw)
{
	int i, err;
	char *target;
	vhd_context_t vhd;

	*parent_raw = 0;
	*result     = NULL;

	target = strdup(name);
	if (!target)
		return -ENOMEM;

	for (;;) {
		err = vhd_open(&vhd, target, VHD_OPEN_RDONLY);
		if (err) {
			free(target);
			return err;
		}

		if (vhd.footer.type != HD_TYPE_DIFF)
			goto out;

		err = vhd_get_bat(&vhd);
		if (err)
			goto out;

		for (i = 0; i < vhd.bat.entries; i++)
			if (vhd.bat.bat[i] != DD_BLK_UNUSED)
				goto out;

		free(target);
		err = vhd_parent_locator_get(&vhd, &target);
		if (err)
			goto out;

		if (vhd_parent_raw(&vhd)) {
			*parent_raw = 1;
			goto out;
		}

		vhd_close(&vhd);
	}

out:
	vhd_close(&vhd);
	if (err)
		free(target);
	else
		*result = target;

	return err;
}
Example #2
0
int
vhd_util_read(int argc, char **argv)
{
	char *name;
	vhd_context_t vhd;
	int c, err, headers, hex, bat_str, cache, flags;
	uint64_t bat, bitmap, tbitmap, ebitmap, batmap, tbatmap, data, lsec, count, read;
	uint64_t bread;

	err     = 0;
	hex     = 0;
	cache   = 0;
	headers = 0;
	bat_str = 0;
	count   = 1;
	bat     = -1;
	bitmap  = -1;
	tbitmap = -1;
	ebitmap = -1;
	batmap  = -1;
	tbatmap = -1;
	data    = -1;
	lsec    = -1;
	read    = -1;
	bread   = -1;
	name    = NULL;

	if (!argc || !argv)
		goto usage;

	optind = 0;
	while ((c = getopt(argc, argv, "n:pt:b:Bm:i:e:aj:d:c:r:R:xCh")) != -1) {
		switch(c) {
		case 'n':
			name = optarg;
			break;
		case 'p':
			headers = 1;
			break;
		case 'C':
			cache = 1;
			break;
		case 'B':
			bat_str = 1;
			break;
		case 't':
			lsec = strtoul(optarg, NULL, 10);
			break;
		case 'b':
			bat = strtoull(optarg, NULL, 10);
			break;
		case 'm':
			bitmap = strtoull(optarg, NULL, 10);
			break;
		case 'i':
			tbitmap = strtoul(optarg, NULL, 10);
			break;
		case 'e':
			ebitmap = strtoul(optarg, NULL, 10);
			break;
		case 'a':
			batmap = 1;
			break;
		case 'j':
			tbatmap = strtoull(optarg, NULL, 10);
			break;
		case 'd':
			data = strtoull(optarg, NULL, 10);
			break;
		case 'r':
			read = strtoull(optarg, NULL, 10);
			break;
		case 'R':
			bread = strtoull(optarg, NULL, 10);
			break;
		case 'c':
			count = strtoul(optarg, NULL, 10);
			break;
		case 'x':
			hex = 1;
			break;
		case 'h':
		default:
			goto usage;
		}
	}

	if (!name || optind != argc)
		goto usage;

	flags = VHD_OPEN_RDONLY | VHD_OPEN_IGNORE_DISABLED;
	if (cache)
		flags |= VHD_OPEN_CACHED | VHD_OPEN_FAST;
	err = vhd_open(&vhd, name, flags);
	if (err) {
		printf("Failed to open %s: %d\n", name, err);
		vhd_dump_headers(name, hex);
		return err;
	}

	err = vhd_get_bat(&vhd);
	if (err) {
		printf("Failed to get bat for %s: %d\n", name, err);
		goto out;
	}

	if (headers)
		vhd_print_headers(&vhd, hex);

	if (lsec != -1) {
		err = vhd_print_logical_to_physical(&vhd, lsec, count, hex);
		if (err)
			goto out;
	}

	if (bat != -1) {
		err = vhd_print_bat(&vhd, bat, count, hex);
		if (err)
			goto out;
	}

	if (bat_str) {
		err = vhd_print_bat_str(&vhd);
		if (err)
			goto out;
	}

	if (bitmap != -1) {
		err = vhd_print_bitmap(&vhd, bitmap, count, hex);
		if (err)
			goto out;
	}

	if (tbitmap != -1) {
		err = vhd_test_bitmap(&vhd, tbitmap, count, hex);
		if (err)
			goto out;
	}

	if (ebitmap != -1) {
		err = vhd_print_bitmap_extents(&vhd, ebitmap, count, hex);
		if (err)
			goto out;
	}

	if (batmap != -1) {
		err = vhd_print_batmap(&vhd);
		if (err)
			goto out;
	}

	if (tbatmap != -1) {
		err = vhd_test_batmap(&vhd, tbatmap, count, hex);
		if (err)
			goto out;
	}

	if (data != -1) {
		err = vhd_print_data(&vhd, data, count, hex);
		if (err)
			goto out;
	}

	if (read != -1) {
		err = vhd_read_data(&vhd, read, count, hex);
		if (err)
			goto out;
	}

	if (bread != -1) {
		err = vhd_read_bytes(&vhd, bread, count, hex);
		if (err)
			goto out;
	}

	err = 0;

 out:
	vhd_close(&vhd);
	return err;

 usage:
	printf("options:\n"
	       "-h          help\n"
	       "-n          name\n"
	       "-p          print VHD headers\n"
	       "-t sec      translate logical sector to VHD location\n"
	       "-b blk      print bat entry\n"
	       "-B          print entire bat as a bitmap\n"
	       "-m blk      print bitmap\n"
	       "-i sec      test bitmap for logical sector\n"
	       "-e sec      output extent list of allocated logical sectors\n"
	       "-a          print batmap\n"
	       "-j blk      test batmap for block\n"
	       "-d blk      print data\n"
	       "-c num      num units\n"
	       "-r sec      read num sectors at sec\n"
	       "-R byte     read num bytes at byte\n"
	       "-x          print in hex\n");
	return EINVAL;
}
Example #3
0
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;
}
Example #4
0
int
vhd_journal_add_block(vhd_journal_t *j, uint32_t block, char mode)
{
	int err;
	char *buf;
	off64_t off;
	size_t size;
	uint64_t blk;
	vhd_context_t *vhd;

	buf = NULL;
	vhd = &j->vhd;

	if (!vhd_type_dynamic(vhd))
		return -EINVAL;

	err = vhd_get_bat(vhd);
	if (err)
		return err;

	if (block >= vhd->bat.entries)
		return -ERANGE;

	blk = vhd->bat.bat[block];
	if (blk == DD_BLK_UNUSED)
		return 0;

	off = vhd_sectors_to_bytes(blk);

	if (mode & VHD_JOURNAL_METADATA) {
		size = vhd_sectors_to_bytes(vhd->bm_secs);

		err  = vhd_read_bitmap(vhd, block, &buf);
		if (err)
			return err;

		err  = vhd_journal_update(j, off, buf, size,
					  VHD_JOURNAL_ENTRY_TYPE_DATA);

		free(buf);

		if (err)
			return err;
	}

	if (mode & VHD_JOURNAL_DATA) {
		off += vhd_sectors_to_bytes(vhd->bm_secs);
		size = vhd_sectors_to_bytes(vhd->spb);

		err  = vhd_read_block(vhd, block, &buf);
		if (err)
			return err;

		err  = vhd_journal_update(j, off, buf, size,
					  VHD_JOURNAL_ENTRY_TYPE_DATA);
		free(buf);

		if (err)
			return err;
	}

	return vhd_journal_sync(j);
}
Example #5
0
int
vhd_journal_create(vhd_journal_t *j, const char *file, const char *jfile)
{
	int err;

	memset(j, 0, sizeof(vhd_journal_t));
	j->jfd = -1;

	j->jname = strdup(jfile);
	if (j->jname == NULL) {
		err = -ENOMEM;
		goto fail1;
	}

	if (access(j->jname, F_OK) == 0) {
		err = vhd_test_file_fixed(j->jname, &j->is_block);
		if (err)
			goto fail1;

		if (!j->is_block) {
			err = -EEXIST;
			goto fail1;
		}
	}

	if (j->is_block)
		j->jfd = open(j->jname, O_LARGEFILE | O_RDWR, 0644);
	else
		j->jfd = open(j->jname,
			      O_CREAT | O_TRUNC | O_LARGEFILE | O_RDWR, 0644);
	if (j->jfd == -1) {
		err = -errno;
		goto fail1;
	}

	err = vhd_open(&j->vhd, file, VHD_OPEN_RDWR | VHD_OPEN_STRICT);
	if (err)
		goto fail1;

	err = vhd_get_bat(&j->vhd);
	if (err)
		goto fail2;

	if (vhd_has_batmap(&j->vhd)) {
		err = vhd_get_batmap(&j->vhd);
		if (err)
			goto fail2;
	}

	err = vhd_journal_add_journal_header(j);
	if (err)
		goto fail2;

	err = vhd_journal_add_metadata(j);
	if (err)
		goto fail2;

	err = vhd_journal_disable_vhd(j);
	if (err)
		goto fail2;

	err = vhd_journal_sync(j);
	if (err)
		goto fail2;

	return 0;

fail1:
	if (j->jfd != -1) {
		close(j->jfd);
		if (!j->is_block)
			unlink(j->jname);
	}
	free(j->jname);
	memset(j, 0, sizeof(vhd_journal_t));

	return err;

fail2:
	vhd_journal_remove(j);
	return err;
}
Example #6
0
int
vhd_journal_open(vhd_journal_t *j, const char *file, const char *jfile)
{
	int err;
	vhd_context_t *vhd;

	memset(j, 0, sizeof(vhd_journal_t));

	j->jfd = -1;
	vhd    = &j->vhd;

	j->jname = strdup(jfile);
	if (j->jname == NULL)
		return -ENOMEM;

	j->jfd = open(j->jname, O_LARGEFILE | O_RDWR);
	if (j->jfd == -1) {
		err = -errno;
		goto fail;
	}

	err = vhd_test_file_fixed(j->jname, &j->is_block);
	if (err)
		goto fail;

	vhd->fd = open(file, O_LARGEFILE | O_RDWR | O_DIRECT);
	if (vhd->fd == -1) {
		err = -errno;
		goto fail;
	}

	err = vhd_test_file_fixed(file, &vhd->is_block);
	if (err)
		goto fail;

	err = vhd_journal_read_journal_header(j, &j->header);
	if (err)
		goto fail;

	err = vhd_journal_restore_metadata(j);
	if (err)
		goto fail;

	close(vhd->fd);
	free(vhd->bat.bat);
	free(vhd->batmap.map);

	err = vhd_open(vhd, file, VHD_OPEN_RDWR);
	if (err)
		goto fail;

	err = vhd_get_bat(vhd);
	if (err)
		goto fail;

	if (vhd_has_batmap(vhd)) {
		err = vhd_get_batmap(vhd);
		if (err)
			goto fail;
	}

	err = vhd_journal_disable_vhd(j);
	if (err)
		goto fail;

	return 0;

fail:
	vhd_journal_close(j);
	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;

	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;
}