(The implementation is not very generic, but that can be very
easily rectified if/when new encryption formats appear.)
---
src/storage_backend_fs.c | 61 +++++++++++++++++++++++++++++++++++----------
1 files changed, 47 insertions(+), 14 deletions(-)
diff --git a/src/storage_backend_fs.c b/src/storage_backend_fs.c
index 8cfc462..0219eb6 100644
--- a/src/storage_backend_fs.c
+++ b/src/storage_backend_fs.c
@@ -26,6 +26,7 @@
#include <sys/statvfs.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <stdbool.h>
#include <stdio.h>
#include <dirent.h>
#include <errno.h>
@@ -81,6 +82,9 @@ struct FileTypeInfo {
/* Store a COW base image path (possibly relative),
* or NULL if there is no COW base image, to RES;
* return BACKING_STORE_* */
+ int qcowCryptOffset; /* Byte offset from start of file
+ * where to find encryption mode,
+ * -1 if encryption is not used */
int (*getBackingStore)(virConnectPtr conn, char **res,
const unsigned char *buf, size_t buf_size);
};
@@ -89,54 +93,54 @@ struct FileTypeInfo const fileTypeInfo[] = {
/* XXX Untested
{ VIR_STORAGE_VOL_FILE_BOCHS, "Bochs Virtual HD Image", NULL,
LV_LITTLE_ENDIAN, 64, 0x20000,
- 32+16+16+4+4+4+4+4, 8, 1, NULL },*/
+ 32+16+16+4+4+4+4+4, 8, 1, -1, NULL },*/
/* CLoop */
/* XXX Untested
{ VIR_STORAGE_VOL_CLOOP, "#!/bin/sh\n#V2.0 Format\nmodprobe cloop file=$0
&& mount -r -t iso9660 /dev/cloop $1\n", NULL,
LV_LITTLE_ENDIAN, -1, 0,
- -1, 0, 0, NULL }, */
+ -1, 0, 0, -1, NULL }, */
/* Cow */
{ VIR_STORAGE_VOL_FILE_COW, "OOOM", NULL,
LV_BIG_ENDIAN, 4, 2,
- 4+4+1024+4, 8, 1, cowGetBackingStore },
+ 4+4+1024+4, 8, 1, -1, cowGetBackingStore },
/* DMG */
/* XXX QEMU says there's no magic for dmg, but we should check... */
{ VIR_STORAGE_VOL_FILE_DMG, NULL, ".dmg",
0, -1, 0,
- -1, 0, 0, NULL },
+ -1, 0, 0, -1, NULL },
/* XXX there's probably some magic for iso we can validate too... */
{ VIR_STORAGE_VOL_FILE_ISO, NULL, ".iso",
0, -1, 0,
- -1, 0, 0, NULL },
+ -1, 0, 0, -1, NULL },
/* Parallels */
/* XXX Untested
{ VIR_STORAGE_VOL_FILE_PARALLELS, "WithoutFreeSpace", NULL,
LV_LITTLE_ENDIAN, 16, 2,
- 16+4+4+4+4, 4, 512, NULL },
+ 16+4+4+4+4, 4, 512, -1, NULL },
*/
/* QCow */
{ VIR_STORAGE_VOL_FILE_QCOW, "QFI", NULL,
LV_BIG_ENDIAN, 4, 1,
- 4+4+8+4+4, 8, 1, qcowXGetBackingStore },
+ 4+4+8+4+4, 8, 1, 4+4+8+4+4+8+1+1+2, qcowXGetBackingStore },
/* QCow 2 */
{ VIR_STORAGE_VOL_FILE_QCOW2, "QFI", NULL,
LV_BIG_ENDIAN, 4, 2,
- 4+4+8+4+4, 8, 1, qcowXGetBackingStore },
+ 4+4+8+4+4, 8, 1, 4+4+8+4+4+8, qcowXGetBackingStore },
/* VMDK 3 */
/* XXX Untested
{ VIR_STORAGE_VOL_FILE_VMDK, "COWD", NULL,
LV_LITTLE_ENDIAN, 4, 1,
- 4+4+4, 4, 512, NULL },
+ 4+4+4, 4, 512, -1, NULL },
*/
/* VMDK 4 */
{ VIR_STORAGE_VOL_FILE_VMDK, "KDMV", NULL,
LV_LITTLE_ENDIAN, 4, 1,
- 4+4+4, 8, 512, vmdk4GetBackingStore },
+ 4+4+4, 8, 512, -1, vmdk4GetBackingStore },
/* Connectix / VirtualPC */
/* XXX Untested
{ VIR_STORAGE_VOL_FILE_VPC, "conectix", NULL,
LV_BIG_ENDIAN, -1, 0,
- -1, 0, 0, NULL},
+ -1, 0, 0, -1, NULL},
*/
};
@@ -282,13 +286,16 @@ static int virStorageBackendProbeTarget(virConnectPtr conn,
virStorageVolTargetPtr target,
char **backingStore,
unsigned long long *allocation,
- unsigned long long *capacity) {
+ unsigned long long *capacity,
+ virStorageEncryptionPtr *encryption) {
int fd;
unsigned char head[20*512]; /* vmdk4GetBackingStore needs this much. */
int len, i, ret;
if (backingStore)
*backingStore = NULL;
+ if (encryption)
+ *encryption = NULL;
if ((fd = open(target->path, O_RDONLY)) < 0) {
virReportSystemError(conn, errno,
@@ -317,6 +324,8 @@ static int virStorageBackendProbeTarget(virConnectPtr conn,
/* First check file magic */
for (i = 0 ; i < ARRAY_CARDINALITY(fileTypeInfo) ; i++) {
int mlen;
+ bool encrypted_qcow = false;
+
if (fileTypeInfo[i].magic == NULL)
continue;
@@ -375,6 +384,16 @@ static int virStorageBackendProbeTarget(virConnectPtr conn,
*capacity *= fileTypeInfo[i].sizeMultiplier;
}
+ if (fileTypeInfo[i].qcowCryptOffset != -1) {
+ int crypt_format;
+
+ crypt_format = (head[fileTypeInfo[i].qcowCryptOffset] << 24) |
+ (head[fileTypeInfo[i].qcowCryptOffset+1] << 16) |
+ (head[fileTypeInfo[i].qcowCryptOffset+2] << 8) |
+ head[fileTypeInfo[i].qcowCryptOffset+3];
+ encrypted_qcow = crypt_format != 0;
+ }
+
/* Validation passed, we know the file format now */
target->format = fileTypeInfo[i].type;
if (fileTypeInfo[i].getBackingStore != NULL && backingStore) {
@@ -400,6 +419,18 @@ static int virStorageBackendProbeTarget(virConnectPtr conn,
}
}
}
+ if (encryption != NULL && encrypted_qcow) {
+ virStorageEncryptionPtr enc;
+
+ if (VIR_ALLOC(enc) < 0) {
+ virReportOOMError(conn);
+ if (backingStore)
+ VIR_FREE(*backingStore);
+ return -1;
+ }
+ enc->format = VIR_STORAGE_ENCRYPTION_FORMAT_QCOW;
+ *encryption = enc;
+ }
return 0;
}
@@ -836,7 +867,8 @@ virStorageBackendFileSystemRefresh(virConnectPtr conn,
&vol->target,
&backingStore,
&vol->allocation,
- &vol->capacity) < 0)) {
+ &vol->capacity,
+ &vol->encryption) < 0)) {
if (ret == -1)
goto cleanup;
else {
@@ -876,7 +908,8 @@ virStorageBackendFileSystemRefresh(virConnectPtr conn,
if ((ret = virStorageBackendProbeTarget(conn,
&vol->backingStore,
- NULL, NULL, NULL)) < 0) {
+ NULL, NULL, NULL,
+ NULL)) < 0) {
if (ret == -1)
goto cleanup;
else {
--
1.6.2.5