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
* it is, and info about its capacity if available.
*/
static int virStorageBackendProbeTarget(virConnectPtr conn,
virStorageVolTargetPtr target,
char **backingStore,
unsigned long long *allocation,
unsigned long long *capacity,
virStorageEncryptionPtr *encryption) {
int fd;
static int
virStorageGetMetadataFromFD(virConnectPtr conn,
const char *path,
int fd,
int *format,
bool *encrypted,
char **backingStore,
unsigned long long *capacity)
{
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)
*backingStore = NULL;
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 */
}
/* Do not overwrite capacity
* if (capacity)
* *capacity = 0;
*/
if ((len = read(fd, head, sizeof(head))) < 0) {
virReportSystemError(conn, errno,
_("cannot read header '%s'"),
target->path);
close(fd);
virReportSystemError(conn, errno, _("cannot read header '%s'"), path);
return -1;
}
close(fd);
/* First check file magic */
for (i = 0 ; i < ARRAY_CARDINALITY(fileTypeInfo) ; i++) {
int mlen;
bool encrypted_qcow = false;
if (fileTypeInfo[i].magic == NULL)
continue;
@ -385,18 +373,19 @@ static int virStorageBackendProbeTarget(virConnectPtr conn,
*capacity *= fileTypeInfo[i].sizeMultiplier;
}
if (fileTypeInfo[i].qcowCryptOffset != -1) {
if (fileTypeInfo[i].qcowCryptOffset != -1 && encrypted) {
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;
*encrypted = crypt_format != 0;
}
/* 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) {
char *base;
@ -411,8 +400,7 @@ static int virStorageBackendProbeTarget(virConnectPtr conn,
return -1;
}
if (base != NULL) {
*backingStore
= absolutePathFromBaseFile(target->path, base);
*backingStore = absolutePathFromBaseFile(path, base);
VIR_FREE(base);
if (*backingStore == NULL) {
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;
}
@ -445,15 +416,78 @@ static int virStorageBackendProbeTarget(virConnectPtr conn,
if (fileTypeInfo[i].extension == NULL)
continue;
if (!virFileHasSuffix(target->path, fileTypeInfo[i].extension))
if (!virFileHasSuffix(path, fileTypeInfo[i].extension))
continue;
target->format = fileTypeInfo[i].type;
if (format)
*format = fileTypeInfo[i].type;
return 0;
}
/* All fails, so call it a raw file */
target->format = VIR_STORAGE_FILE_RAW;
return 0;
}
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;
}