mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-24 14:45:24 +00:00
Split virStorageGetMetadataFromFD() from virStorageBackendProbeTarget()
Prepare the code probing a file's format and associated metadata for moving into libvirt_util. * src/storage/storage_backend_fs.c: re-factor the format and metadata probing code in preparation for moving it
This commit is contained in:
parent
00fd3ff49b
commit
f5fc670638
@ -283,49 +283,37 @@ static char *absolutePathFromBaseFile(const char *base_file, const char *path)
|
|||||||
* Probe the header of a file to determine what type of disk image
|
* Probe the header of a file to determine what type of disk image
|
||||||
* it is, and info about its capacity if available.
|
* it is, and info about its capacity if available.
|
||||||
*/
|
*/
|
||||||
static int virStorageBackendProbeTarget(virConnectPtr conn,
|
static int
|
||||||
virStorageVolTargetPtr target,
|
virStorageGetMetadataFromFD(virConnectPtr conn,
|
||||||
char **backingStore,
|
const char *path,
|
||||||
unsigned long long *allocation,
|
int fd,
|
||||||
unsigned long long *capacity,
|
int *format,
|
||||||
virStorageEncryptionPtr *encryption) {
|
bool *encrypted,
|
||||||
int fd;
|
char **backingStore,
|
||||||
|
unsigned long long *capacity)
|
||||||
|
{
|
||||||
unsigned char head[20*512]; /* vmdk4GetBackingStore needs this much. */
|
unsigned char head[20*512]; /* vmdk4GetBackingStore needs this much. */
|
||||||
int len, i, ret;
|
int len, i;
|
||||||
|
|
||||||
|
if (format) /* If all else fails, call it a raw file */
|
||||||
|
*format = VIR_STORAGE_FILE_RAW;
|
||||||
|
if (encrypted)
|
||||||
|
*encrypted = false;
|
||||||
if (backingStore)
|
if (backingStore)
|
||||||
*backingStore = NULL;
|
*backingStore = NULL;
|
||||||
if (encryption)
|
/* Do not overwrite capacity
|
||||||
*encryption = NULL;
|
* if (capacity)
|
||||||
|
* *capacity = 0;
|
||||||
if ((fd = open(target->path, O_RDONLY)) < 0) {
|
*/
|
||||||
virReportSystemError(conn, errno,
|
|
||||||
_("cannot open volume '%s'"),
|
|
||||||
target->path);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((ret = virStorageBackendUpdateVolTargetInfoFD(conn, target, fd,
|
|
||||||
allocation,
|
|
||||||
capacity)) < 0) {
|
|
||||||
close(fd);
|
|
||||||
return ret; /* Take care to propagate ret, it is not always -1 */
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((len = read(fd, head, sizeof(head))) < 0) {
|
if ((len = read(fd, head, sizeof(head))) < 0) {
|
||||||
virReportSystemError(conn, errno,
|
virReportSystemError(conn, errno, _("cannot read header '%s'"), path);
|
||||||
_("cannot read header '%s'"),
|
|
||||||
target->path);
|
|
||||||
close(fd);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
close(fd);
|
|
||||||
|
|
||||||
/* First check file magic */
|
/* First check file magic */
|
||||||
for (i = 0 ; i < ARRAY_CARDINALITY(fileTypeInfo) ; i++) {
|
for (i = 0 ; i < ARRAY_CARDINALITY(fileTypeInfo) ; i++) {
|
||||||
int mlen;
|
int mlen;
|
||||||
bool encrypted_qcow = false;
|
|
||||||
|
|
||||||
if (fileTypeInfo[i].magic == NULL)
|
if (fileTypeInfo[i].magic == NULL)
|
||||||
continue;
|
continue;
|
||||||
@ -385,18 +373,19 @@ static int virStorageBackendProbeTarget(virConnectPtr conn,
|
|||||||
*capacity *= fileTypeInfo[i].sizeMultiplier;
|
*capacity *= fileTypeInfo[i].sizeMultiplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fileTypeInfo[i].qcowCryptOffset != -1) {
|
if (fileTypeInfo[i].qcowCryptOffset != -1 && encrypted) {
|
||||||
int crypt_format;
|
int crypt_format;
|
||||||
|
|
||||||
crypt_format = (head[fileTypeInfo[i].qcowCryptOffset] << 24) |
|
crypt_format = (head[fileTypeInfo[i].qcowCryptOffset] << 24) |
|
||||||
(head[fileTypeInfo[i].qcowCryptOffset+1] << 16) |
|
(head[fileTypeInfo[i].qcowCryptOffset+1] << 16) |
|
||||||
(head[fileTypeInfo[i].qcowCryptOffset+2] << 8) |
|
(head[fileTypeInfo[i].qcowCryptOffset+2] << 8) |
|
||||||
head[fileTypeInfo[i].qcowCryptOffset+3];
|
head[fileTypeInfo[i].qcowCryptOffset+3];
|
||||||
encrypted_qcow = crypt_format != 0;
|
*encrypted = crypt_format != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Validation passed, we know the file format now */
|
/* Validation passed, we know the file format now */
|
||||||
target->format = fileTypeInfo[i].type;
|
if (format)
|
||||||
|
*format = fileTypeInfo[i].type;
|
||||||
if (fileTypeInfo[i].getBackingStore != NULL && backingStore) {
|
if (fileTypeInfo[i].getBackingStore != NULL && backingStore) {
|
||||||
char *base;
|
char *base;
|
||||||
|
|
||||||
@ -411,8 +400,7 @@ static int virStorageBackendProbeTarget(virConnectPtr conn,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (base != NULL) {
|
if (base != NULL) {
|
||||||
*backingStore
|
*backingStore = absolutePathFromBaseFile(path, base);
|
||||||
= absolutePathFromBaseFile(target->path, base);
|
|
||||||
VIR_FREE(base);
|
VIR_FREE(base);
|
||||||
if (*backingStore == NULL) {
|
if (*backingStore == NULL) {
|
||||||
virReportOOMError(conn);
|
virReportOOMError(conn);
|
||||||
@ -420,23 +408,6 @@ 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;
|
|
||||||
/* XXX ideally we'd fill in secret UUID here
|
|
||||||
* but we cannot guarentee 'conn' is non-NULL
|
|
||||||
* at this point in time :-( So we only fill
|
|
||||||
* in secrets when someone first queries a vol
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -445,15 +416,78 @@ static int virStorageBackendProbeTarget(virConnectPtr conn,
|
|||||||
if (fileTypeInfo[i].extension == NULL)
|
if (fileTypeInfo[i].extension == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!virFileHasSuffix(target->path, fileTypeInfo[i].extension))
|
if (!virFileHasSuffix(path, fileTypeInfo[i].extension))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
target->format = fileTypeInfo[i].type;
|
if (format)
|
||||||
|
*format = fileTypeInfo[i].type;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* All fails, so call it a raw file */
|
return 0;
|
||||||
target->format = VIR_STORAGE_FILE_RAW;
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
virStorageBackendProbeTarget(virConnectPtr conn,
|
||||||
|
virStorageVolTargetPtr target,
|
||||||
|
char **backingStore,
|
||||||
|
unsigned long long *allocation,
|
||||||
|
unsigned long long *capacity,
|
||||||
|
virStorageEncryptionPtr *encryption)
|
||||||
|
{
|
||||||
|
int fd, ret;
|
||||||
|
bool encrypted;
|
||||||
|
|
||||||
|
if (encryption)
|
||||||
|
*encryption = NULL;
|
||||||
|
|
||||||
|
if ((fd = open(target->path, O_RDONLY)) < 0) {
|
||||||
|
virReportSystemError(conn, errno,
|
||||||
|
_("cannot open volume '%s'"),
|
||||||
|
target->path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ret = virStorageBackendUpdateVolTargetInfoFD(conn, target, fd,
|
||||||
|
allocation,
|
||||||
|
capacity)) < 0) {
|
||||||
|
close(fd);
|
||||||
|
return ret; /* Take care to propagate ret, it is not always -1 */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virStorageGetMetadataFromFD(conn, target->path, fd,
|
||||||
|
&target->format, &encrypted,
|
||||||
|
backingStore, capacity) < 0) {
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
if (encryption != NULL && encrypted) {
|
||||||
|
if (VIR_ALLOC(*encryption) < 0) {
|
||||||
|
virReportOOMError(conn);
|
||||||
|
if (backingStore)
|
||||||
|
VIR_FREE(*backingStore);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (target->format) {
|
||||||
|
case VIR_STORAGE_FILE_QCOW:
|
||||||
|
case VIR_STORAGE_FILE_QCOW2:
|
||||||
|
(*encryption)->format = VIR_STORAGE_ENCRYPTION_FORMAT_QCOW;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* XXX ideally we'd fill in secret UUID here
|
||||||
|
* but we cannot guarentee 'conn' is non-NULL
|
||||||
|
* at this point in time :-( So we only fill
|
||||||
|
* in secrets when someone first queries a vol
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user