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:
Mark McLoughlin 2009-09-29 09:07:14 +01:00
parent 00fd3ff49b
commit f5fc670638

View File

@ -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;
} }