diff --git a/src/storage_backend_fs.c b/src/storage_backend_fs.c index ca6d32932a548956237c1bfeb0002ef38b756a79..5568b207807d77eb7f9d88136409702eddbc989c 100644 --- a/src/storage_backend_fs.c +++ b/src/storage_backend_fs.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -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; } @@ -868,7 +899,8 @@ virStorageBackendFileSystemRefresh(virConnectPtr conn, &vol->target, &backingStore, &vol->allocation, - &vol->capacity) < 0)) { + &vol->capacity, + &vol->target.encryption) < 0)) { if (ret == -1) goto cleanup; else { @@ -908,7 +940,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 {