summaryrefslogtreecommitdiff
path: root/usr.sbin/vmd/vioqcow2.c
diff options
context:
space:
mode:
authorReyk Floeter <reyk@cvs.openbsd.org>2018-10-19 10:12:40 +0000
committerReyk Floeter <reyk@cvs.openbsd.org>2018-10-19 10:12:40 +0000
commite014ce92dbc428864aef9723a6d3bde4319f06bc (patch)
tree72a90057790b5a8544c1402e812405577dfbe64f /usr.sbin/vmd/vioqcow2.c
parentdc388d4163b5f0cf447d8f1d605a6b3bd1da6346 (diff)
Add support to create and convert disk images from existing images
The -i option to vmctl create (eg. vmctl create output.qcow2 -i input.img) lets you create a new image from an input file and convert it if it is a different format. This allows to convert qcow2 images from raw images, raw from qcow2, or even qcow2 from qcow2 and raw from raw to re-optimize the disk. This re-uses Ori's vioqcow2.c from vmd by reaching into it and compiling it in. The API has been adjust to be used from both vmctl and vmd accordingly. OK mlarkin@
Diffstat (limited to 'usr.sbin/vmd/vioqcow2.c')
-rw-r--r--usr.sbin/vmd/vioqcow2.c51
1 files changed, 41 insertions, 10 deletions
diff --git a/usr.sbin/vmd/vioqcow2.c b/usr.sbin/vmd/vioqcow2.c
index 8f56d2172d4..3a215599d49 100644
--- a/usr.sbin/vmd/vioqcow2.c
+++ b/usr.sbin/vmd/vioqcow2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vioqcow2.c,v 1.8 2018/10/08 16:32:01 reyk Exp $ */
+/* $OpenBSD: vioqcow2.c,v 1.9 2018/10/19 10:12:39 reyk Exp $ */
/*
* Copyright (c) 2018 Ori Bernstein <ori@eigenstate.org>
@@ -27,6 +27,7 @@
#include <unistd.h>
#include <fcntl.h>
#include <assert.h>
+#include <libgen.h>
#include <err.h>
#include "vmd.h"
@@ -137,11 +138,13 @@ virtio_init_qcow2(struct virtio_backing *file, off_t *szp, int *fd, size_t nfd)
}
ssize_t
-virtio_qcow2_get_base(int fd, char *path, size_t npath)
+virtio_qcow2_get_base(int fd, char *path, size_t npath, const char *dpath)
{
+ char expanded[PATH_MAX];
struct qcheader header;
uint64_t backingoff;
uint32_t backingsz;
+ char *s = NULL;
if (pread(fd, &header, sizeof(header), 0) != sizeof(header)) {
log_warnx("%s: short read on header", __func__);
@@ -153,19 +156,47 @@ virtio_qcow2_get_base(int fd, char *path, size_t npath)
}
backingoff = be64toh(header.backingoff);
backingsz = be32toh(header.backingsz);
- if (backingsz != 0) {
- if (backingsz >= npath - 1) {
- log_warn("%s: snapshot path too long", __func__);
+ if (backingsz == 0)
+ return 0;
+
+ if (backingsz >= npath - 1) {
+ log_warn("%s: snapshot path too long", __func__);
+ return -1;
+ }
+ if (pread(fd, path, backingsz, backingoff) != backingsz) {
+ log_warnx("%s: could not read snapshot base name",
+ __func__);
+ return -1;
+ }
+ path[backingsz] = '\0';
+
+ /*
+ * Relative paths should be interpreted relative to the disk image,
+ * rather than relative to the directory vmd happens to be running in,
+ * since this is the only userful interpretation.
+ */
+ if (path[0] == '/') {
+ if (realpath(path, expanded) == NULL ||
+ strlcpy(path, expanded, npath) >= npath) {
+ log_warn("unable to resolve %s", path);
return -1;
}
- if (pread(fd, path, backingsz, backingoff) != backingsz) {
- log_warnx("%s: could not read snapshot base name",
- __func__);
+ } else {
+ s = dirname(dpath);
+ if (snprintf(expanded, sizeof(expanded),
+ "%s/%s", s, path) >= (int)sizeof(expanded)) {
+ log_warn("path too long: %s/%s",
+ s, path);
+ return -1;
+ }
+ if (npath < PATH_MAX ||
+ realpath(expanded, path) == NULL) {
+ log_warn("unable to resolve %s", path);
return -1;
}
- path[backingsz] = '\0';
}
- return backingsz;
+
+ return strlen(path);
}
static int