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.
* src/qemu/qemu_driver.c (qemuDomainBlockRebase): Allow REUSE_EXT
flag.
(qemuDomainBlockCopy): Wire up flag, and add some sanity checks.
---
v8: use backing chain for better analysis of external file
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 bcbece2..13cba61 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -12860,9 +12860,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;
@@ -12925,12 +12927,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