diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c index a6f87d9608b734840aeb05534b8f57cbb39ba2d1..f5fe8adde62f49c33e96af6984fe14a051368b4d 100644 --- a/src/util/virstoragefile.c +++ b/src/util/virstoragefile.c @@ -789,6 +789,13 @@ virStorageFileGetMetadataInternal(const char *path, VIR_DEBUG("path=%s, canonPath=%s, dir=%s, buf=%p, len=%zu, format=%d", path, canonPath, directory, buf, len, format); + if (VIR_STRDUP(meta->path, path) < 0) + goto cleanup; + if (VIR_STRDUP(meta->canonPath, canonPath) < 0) + goto cleanup; + if (VIR_STRDUP(meta->relDir, directory) < 0) + goto cleanup; + if (format == VIR_STORAGE_FILE_AUTO) format = virStorageFileProbeFormatFromBuf(path, buf, len); @@ -798,6 +805,7 @@ virStorageFileGetMetadataInternal(const char *path, format); goto cleanup; } + meta->format = format; /* XXX we should consider moving virStorageBackendUpdateVolInfo * code into this method, for non-magic files @@ -1020,8 +1028,14 @@ virStorageFileGetMetadataFromFDInternal(const char *path, return -1; } - /* No header to probe for directories, but also no backing file */ if (S_ISDIR(sb.st_mode)) { + /* No header to probe for directories, but also no backing + * file; therefore, no inclusion loop is possible, and we + * don't need canonName or relDir. */ + if (VIR_STRDUP(meta->path, path) < 0) + goto cleanup; + meta->type = VIR_STORAGE_TYPE_DIR; + meta->format = VIR_STORAGE_FILE_DIR; ret = 0; goto cleanup; } @@ -1039,6 +1053,12 @@ virStorageFileGetMetadataFromFDInternal(const char *path, ret = virStorageFileGetMetadataInternal(path, canonPath, directory, buf, len, format, meta); + if (ret == 0) { + if (S_ISREG(sb.st_mode)) + meta->type = VIR_STORAGE_TYPE_FILE; + else if (S_ISBLK(sb.st_mode)) + meta->type = VIR_STORAGE_TYPE_BLOCK; + } cleanup: VIR_FREE(buf); return ret; @@ -1266,6 +1286,10 @@ virStorageFileFreeMetadata(virStorageFileMetadata *meta) if (!meta) return; + VIR_FREE(meta->path); + VIR_FREE(meta->canonPath); + VIR_FREE(meta->relDir); + virStorageFileFreeMetadata(meta->backingMeta); VIR_FREE(meta->backingStore); VIR_FREE(meta->backingStoreRaw); diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h index 7cb0f2ba8f2563193bd1fa8529e2000b68b9c7a8..41921406a3d4d35d5e6787144ed3079ca9005d46 100644 --- a/src/util/virstoragefile.h +++ b/src/util/virstoragefile.h @@ -112,17 +112,43 @@ struct _virStorageTimestamps { typedef struct _virStorageFileMetadata virStorageFileMetadata; typedef virStorageFileMetadata *virStorageFileMetadataPtr; struct _virStorageFileMetadata { - char *backingStore; /* Canonical name (absolute file, or protocol) */ - char *backingStoreRaw; /* If file, original name, possibly relative */ - char *directory; /* The directory containing basename of backingStoreRaw */ - int backingStoreFormat; /* enum virStorageFileFormat */ - bool backingStoreIsFile; + /* Name of the current file as spelled by the user (top level) or + * metadata of the overlay (if this is a backing store). */ + char *path; + /* Canonical name of the current file, used to detect loops in the + * backing store chain. */ + char *canonPath; + /* Directory to start from if backingStoreRaw is a relative file + * name. */ + char *relDir; + /* Name of the child backing store recorded in metadata of the + * current file. */ + char *backingStoreRaw; + + /* Backing chain. In the common case, the child's + * backingMeta->path will be a duplicate of this file's + * backingStoreRaw; this setup makes it possible to detect missing + * backing files: if backingStoreRaw is NULL, this field should be + * NULL. If this field is NULL and backingStoreRaw is non-NULL, + * there was an error following the chain (such as a missing + * file). Otherwise, information about the child is here. */ virStorageFileMetadataPtr backingMeta; + /* Details about the current image */ + int type; /* enum virStorageType */ + int format; /* enum virStorageFileFormat */ virStorageEncryptionPtr encryption; unsigned long long capacity; virBitmapPtr features; /* bits described by enum virStorageFileFeature */ char *compat; + + /* Fields I'm trying to delete, because it is confusing to have to + * query the parent metadata for details about the backing + * store. */ + char *backingStore; /* Canonical name (absolute file, or protocol). Should be same as backingMeta->canonPath */ + char *directory; /* The directory containing basename of backingStoreRaw. Should be same as backingMeta->relDir */ + int backingStoreFormat; /* enum virStorageFileFormat. Should be same as backingMeta->format */ + bool backingStoreIsFile; /* Should be same as backingMeta->type < VIR_STORAGE_TYPE_NETWORK */ };