int virStorageFileGetMetadata(const char *path, virStorageFileMetadata *meta) { int fd, ret; if ((fd = open(path, O_RDONLY)) < 0) { virReportSystemError(errno, _("cannot open file '%s'"), path); return -1; } ret = virStorageFileGetMetadataFromFD(path, fd, meta); close(fd); return ret; }
virStorageBackendProbeTarget(virStorageVolTargetPtr target, char **backingStore, int *backingStoreFormat, unsigned long long *allocation, unsigned long long *capacity, virStorageEncryptionPtr *encryption) { int fd = -1; int ret = -1; virStorageFileMetadata *meta; if (VIR_ALLOC(meta) < 0) { virReportOOMError(); return ret; } *backingStore = NULL; *backingStoreFormat = VIR_STORAGE_FILE_AUTO; if (encryption) *encryption = NULL; if ((ret = virStorageBackendVolOpenCheckMode(target->path, VIR_STORAGE_VOL_FS_REFRESH_FLAGS)) < 0) goto error; /* Take care to propagate ret, it is not always -1 */ fd = ret; if ((ret = virStorageBackendUpdateVolTargetInfoFD(target, fd, allocation, capacity)) < 0) { goto error; } if ((target->format = virStorageFileProbeFormatFromFD(target->path, fd)) < 0) { ret = -1; goto error; } if (virStorageFileGetMetadataFromFD(target->path, fd, target->format, meta) < 0) { ret = -1; goto error; } VIR_FORCE_CLOSE(fd); if (meta->backingStore) { *backingStore = meta->backingStore; meta->backingStore = NULL; if (meta->backingStoreFormat == VIR_STORAGE_FILE_AUTO) { if ((ret = virStorageFileProbeFormat(*backingStore)) < 0) { /* If the backing file is currently unavailable, only log an error, * but continue. Returning -1 here would disable the whole storage * pool, making it unavailable for even maintenance. */ virStorageReportError(VIR_ERR_INTERNAL_ERROR, _("cannot probe backing volume format: %s"), *backingStore); ret = -3; } else { *backingStoreFormat = ret; ret = 0; } } else { *backingStoreFormat = meta->backingStoreFormat; ret = 0; } } else { ret = 0; } if (capacity && meta->capacity) *capacity = meta->capacity; if (encryption != NULL && meta->encrypted) { if (VIR_ALLOC(*encryption) < 0) { virReportOOMError(); goto cleanup; } 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 guarantee 'conn' is non-NULL * at this point in time :-( So we only fill * in secrets when someone first queries a vol */ } virStorageFileFreeMetadata(meta); return ret; error: VIR_FORCE_CLOSE(fd); cleanup: virStorageFileFreeMetadata(meta); return ret; }
static int virStorageBackendProbeTarget(virStorageVolTargetPtr target, char **backingStore, unsigned long long *allocation, unsigned long long *capacity, virStorageEncryptionPtr *encryption) { int fd, ret; virStorageFileMetadata meta; if (encryption) *encryption = NULL; if ((ret = virStorageBackendVolOpenCheckMode(target->path, (VIR_STORAGE_VOL_OPEN_DEFAULT & ~VIR_STORAGE_VOL_OPEN_ERROR))) < 0) return ret; /* Take care to propagate ret, it is not always -1 */ fd = ret; if ((ret = virStorageBackendUpdateVolTargetInfoFD(target, fd, allocation, capacity)) < 0) { close(fd); return -1; } memset(&meta, 0, sizeof(meta)); if (virStorageFileGetMetadataFromFD(target->path, fd, &meta) < 0) { close(fd); return -1; } close(fd); target->format = meta.format; if (backingStore) { *backingStore = meta.backingStore; meta.backingStore = NULL; } VIR_FREE(meta.backingStore); if (capacity && meta.capacity) *capacity = meta.capacity; if (encryption != NULL && meta.encrypted) { if (VIR_ALLOC(*encryption) < 0) { virReportOOMError(); 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; }
static int virStorageBackendProbeTarget(virStorageSourcePtr target, virStorageEncryptionPtr *encryption) { int backingStoreFormat; int fd = -1; int ret = -1; int rc; virStorageSourcePtr meta = NULL; struct stat sb; if (encryption) *encryption = NULL; if ((rc = virStorageBackendVolOpen(target->path, &sb, VIR_STORAGE_VOL_FS_PROBE_FLAGS)) < 0) return rc; /* Take care to propagate rc, it is not always -1 */ fd = rc; if (virStorageBackendUpdateVolTargetInfoFD(target, fd, &sb) < 0) goto cleanup; if (S_ISDIR(sb.st_mode)) { target->format = VIR_STORAGE_FILE_DIR; ret = 0; goto cleanup; } if (!(meta = virStorageFileGetMetadataFromFD(target->path, fd, VIR_STORAGE_FILE_AUTO, &backingStoreFormat))) goto cleanup; if (meta->backingStoreRaw) { if (!(target->backingStore = virStorageSourceNewFromBacking(meta))) goto cleanup; target->backingStore->format = backingStoreFormat; /* XXX: Remote storage doesn't play nicely with volumes backed by * remote storage. To avoid trouble, just fake the backing store is RAW * and put the string from the metadata as the path of the target. */ if (!virStorageSourceIsLocalStorage(target->backingStore)) { virStorageSourceFree(target->backingStore); if (VIR_ALLOC(target->backingStore) < 0) goto cleanup; target->backingStore->type = VIR_STORAGE_TYPE_NETWORK; target->backingStore->path = meta->backingStoreRaw; meta->backingStoreRaw = NULL; target->backingStore->format = VIR_STORAGE_FILE_RAW; } if (target->backingStore->format == VIR_STORAGE_FILE_AUTO) { if ((rc = virStorageFileProbeFormat(target->backingStore->path, -1, -1)) < 0) { /* If the backing file is currently unavailable or is * accessed via remote protocol only log an error, fake the * format as RAW and continue. Returning -1 here would * disable the whole storage pool, making it unavailable for * even maintenance. */ target->backingStore->format = VIR_STORAGE_FILE_RAW; virReportError(VIR_ERR_INTERNAL_ERROR, _("cannot probe backing volume format: %s"), target->backingStore->path); } else { target->backingStore->format = rc; } } } target->format = meta->format; /* Default to success below this point */ ret = 0; if (meta->capacity) target->capacity = meta->capacity; if (encryption && meta->encryption) { *encryption = meta->encryption; meta->encryption = NULL; 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 guarantee 'conn' is non-NULL * at this point in time :-( So we only fill * in secrets when someone first queries a vol */ } virBitmapFree(target->features); target->features = meta->features; meta->features = NULL; if (meta->compat) { VIR_FREE(target->compat); target->compat = meta->compat; meta->compat = NULL; } cleanup: VIR_FORCE_CLOSE(fd); virStorageSourceFree(meta); return ret; }