Support the REUSE_EXT flag, in part by copying sanity checks from
snapshot code. This code introduces a case of probing an external
file for its type; such an action would be a security risk if the
existing file is supposed to be raw but the contents resemble some
other format; however, since the virDomainBlockRebase API has a
flag to force treating the file as raw rather than probe, we can
assume that probing is safe in all other instances. Besides, if
we don't probe or force raw, then qemu will.
* src/qemu/qemu_driver.c (qemuDomainBlockRebase): Allow REUSE_EXT
flag.
(qemuDomainBlockCopy): Wire up flag, and add some sanity checks.
---
src/qemu/qemu_driver.c | 40 +++++++++++++++++++++++++++++++++++-----
1 file changed, 35 insertions(+), 5 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 539664f..d13bff2 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -12861,9 +12861,11 @@ qemuDomainBlockCopy(virDomainPtr dom, const char *path,
int ret = -1;
int idx;
bool reopen;
+ struct stat st;
/* Preliminaries: find the disk we are editing, sanity checks */
- virCheckFlags(VIR_DOMAIN_BLOCK_REBASE_SHALLOW, -1);
+ virCheckFlags(VIR_DOMAIN_BLOCK_REBASE_SHALLOW |
+ VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT, -1);
if (!(vm = qemuDomObjFromDomain(dom)))
goto cleanup;
@@ -12926,12 +12928,39 @@ qemuDomainBlockCopy(virDomainPtr dom, const char *path,
}
/* Prepare the destination file. */
+ if (stat(dest, &st) < 0) {
+ if (errno != ENOENT) {
+ virReportSystemError(errno, _("unable to stat for disk %s: %s"),
+ disk->dst, dest);
+ goto endjob;
+ } else if (flags & VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT) {
+ virReportSystemError(errno,
+ _("missing destination file for disk %s:
%s"),
+ disk->dst, dest);
+ goto endjob;
+ }
+ } else if (!S_ISBLK(st.st_mode) && st.st_size &&
+ !(flags & VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("external destination file for disk %s already "
+ "exists and is not a block device: %s"),
+ disk->dst, dest);
+ goto endjob;
+ }
+
/* XXX We also need to add security labeling, lock manager lease,
- * and auditing of those events, as well as to support reuse of
- * existing images, including probing the existing format of an
- * existing image. */
+ * and auditing of those events. */
if (!format) {
- disk->mirrorFormat = disk->format;
+ if (flags & VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT) {
+ /* If the user passed the REUSE_EXT flag, then either they
+ * also passed the RAW flag (and format is non-NULL), or
+ * it is safe for us to probe the format from the file
+ * that we will be using. */
+ disk->mirrorFormat = virStorageFileProbeFormat(dest, driver->user,
+ driver->group);
+ } else {
+ disk->mirrorFormat = disk->format;
+ }
if (disk->mirrorFormat > 0)
format = virStorageFileFormatTypeToString(disk->mirrorFormat);
} else {
@@ -12975,6 +13004,7 @@ qemuDomainBlockRebase(virDomainPtr dom, const char *path, const
char *base,
unsigned long bandwidth, unsigned int flags)
{
virCheckFlags(VIR_DOMAIN_BLOCK_REBASE_SHALLOW |
+ VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT |
VIR_DOMAIN_BLOCK_REBASE_COPY |
VIR_DOMAIN_BLOCK_REBASE_COPY_RAW, -1);
--
1.7.11.7