mirror of
https://github.com/libvirt/libvirt.git
synced 2025-02-25 18:55:26 -06:00
conf: track user vs. canonical name through full chain lookup
The previous patch started a separation of error messages reported against the user-specified name, vs. tracking the canonical path that was actually opened. This patch extends that notion, by hoisting directory detection up front, passing the canonical path through the entire call chain, and simplifying lower-level functions that can now assume that a canonical path and directory have been supplied. * src/util/virstoragefile.c (virStorageFileGetMetadataFromFDInternal) (virStorageFileGetMetadataInternal): Add parameter, require directory. (virFindBackingFile): Require directory. (virStorageFileGetMetadataFromFD): Pass canonical path. (virStorageFileGetMetadataFromBuf): Likewise. (virStorageFileGetMetadata): Determine initial directory. Signed-off-by: Eric Blake <eblake@redhat.com>
This commit is contained in:
parent
90dbdff2ac
commit
79f11b35c7
@ -558,14 +558,15 @@ qedGetBackingStore(char **res,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a starting point START (either an original file name, or the
|
* Given a starting point START (a directory containing the original
|
||||||
* directory containing the original name, depending on START_IS_DIR)
|
* file, if the original file was opened via a relative path; ignored
|
||||||
* and a possibly relative backing file NAME, compute the relative
|
* if NAME is absolute), determine the location of the backing file
|
||||||
* DIRECTORY (optional) and CANONICAL (mandatory) location of the
|
* NAME (possibly relative), and compute the relative DIRECTORY
|
||||||
* backing file. Return 0 on success, negative on error.
|
* (optional) and CANONICAL (mandatory) location of the backing file.
|
||||||
|
* Return 0 on success, negative on error.
|
||||||
*/
|
*/
|
||||||
static int ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(5)
|
static int ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(4)
|
||||||
virFindBackingFile(const char *start, bool start_is_dir, const char *path,
|
virFindBackingFile(const char *start, const char *path,
|
||||||
char **directory, char **canonical)
|
char **directory, char **canonical)
|
||||||
{
|
{
|
||||||
char *combined = NULL;
|
char *combined = NULL;
|
||||||
@ -574,19 +575,8 @@ virFindBackingFile(const char *start, bool start_is_dir, const char *path,
|
|||||||
if (*path == '/') {
|
if (*path == '/') {
|
||||||
/* Safe to cast away const */
|
/* Safe to cast away const */
|
||||||
combined = (char *)path;
|
combined = (char *)path;
|
||||||
} else {
|
} else if (virAsprintf(&combined, "%s/%s", start, path) < 0) {
|
||||||
size_t d_len = start_is_dir ? strlen(start) : dir_len(start);
|
goto cleanup;
|
||||||
|
|
||||||
if (d_len > INT_MAX) {
|
|
||||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
||||||
_("name too long: '%s'"), start);
|
|
||||||
goto cleanup;
|
|
||||||
} else if (d_len == 0) {
|
|
||||||
start = ".";
|
|
||||||
d_len = 1;
|
|
||||||
}
|
|
||||||
if (virAsprintf(&combined, "%.*s/%s", (int)d_len, start, path) < 0)
|
|
||||||
goto cleanup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (directory && !(*directory = mdir_name(combined))) {
|
if (directory && !(*directory = mdir_name(combined))) {
|
||||||
@ -779,22 +769,24 @@ qcow2GetFeatures(virBitmapPtr *features,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Given a header in BUF with length LEN, as parsed from the file
|
/* Given a header in BUF with length LEN, as parsed from the file with
|
||||||
* located at PATH, and optionally opened from a given DIRECTORY,
|
* user-provided name PATH and opened from CANONPATH, and where any
|
||||||
* return metadata about that file, assuming it has the given
|
* relative backing file will be opened from DIRECTORY, return
|
||||||
* FORMAT. */
|
* metadata about that file, assuming it has the given FORMAT. */
|
||||||
static virStorageFileMetadataPtr
|
static virStorageFileMetadataPtr ATTRIBUTE_NONNULL(1)
|
||||||
|
ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4)
|
||||||
virStorageFileGetMetadataInternal(const char *path,
|
virStorageFileGetMetadataInternal(const char *path,
|
||||||
|
const char *canonPath,
|
||||||
|
const char *directory,
|
||||||
char *buf,
|
char *buf,
|
||||||
size_t len,
|
size_t len,
|
||||||
const char *directory,
|
|
||||||
int format)
|
int format)
|
||||||
{
|
{
|
||||||
virStorageFileMetadata *meta = NULL;
|
virStorageFileMetadata *meta = NULL;
|
||||||
virStorageFileMetadata *ret = NULL;
|
virStorageFileMetadata *ret = NULL;
|
||||||
|
|
||||||
VIR_DEBUG("path=%s, buf=%p, len=%zu, directory=%s, format=%d",
|
VIR_DEBUG("path=%s, canonPath=%s, dir=%s, buf=%p, len=%zu, format=%d",
|
||||||
path, buf, len, NULLSTR(directory), format);
|
path, canonPath, directory, buf, len, format);
|
||||||
|
|
||||||
if (VIR_ALLOC(meta) < 0)
|
if (VIR_ALLOC(meta) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -864,8 +856,7 @@ virStorageFileGetMetadataInternal(const char *path,
|
|||||||
meta->backingStoreIsFile = true;
|
meta->backingStoreIsFile = true;
|
||||||
meta->backingStoreRaw = meta->backingStore;
|
meta->backingStoreRaw = meta->backingStore;
|
||||||
meta->backingStore = NULL;
|
meta->backingStore = NULL;
|
||||||
if (virFindBackingFile(directory ? directory : path,
|
if (virFindBackingFile(directory, backing,
|
||||||
!!directory, backing,
|
|
||||||
&meta->directory,
|
&meta->directory,
|
||||||
&meta->backingStore) < 0) {
|
&meta->backingStore) < 0) {
|
||||||
/* the backing file is (currently) unavailable, treat this
|
/* the backing file is (currently) unavailable, treat this
|
||||||
@ -990,15 +981,27 @@ virStorageFileGetMetadataFromBuf(const char *path,
|
|||||||
size_t len,
|
size_t len,
|
||||||
int format)
|
int format)
|
||||||
{
|
{
|
||||||
return virStorageFileGetMetadataInternal(path, buf, len, NULL, format);
|
virStorageFileMetadataPtr ret;
|
||||||
|
char *canonPath;
|
||||||
|
|
||||||
|
if (!(canonPath = canonicalize_file_name(path))) {
|
||||||
|
virReportSystemError(errno, _("unable to resolve '%s'"), path);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = virStorageFileGetMetadataInternal(path, canonPath, ".", buf, len,
|
||||||
|
format);
|
||||||
|
VIR_FREE(canonPath);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Internal version that also supports a containing directory name. */
|
/* Internal version that also supports a containing directory name. */
|
||||||
static virStorageFileMetadataPtr
|
static virStorageFileMetadataPtr
|
||||||
virStorageFileGetMetadataFromFDInternal(const char *path,
|
virStorageFileGetMetadataFromFDInternal(const char *path,
|
||||||
int fd,
|
const char *canonPath,
|
||||||
const char *directory,
|
const char *directory,
|
||||||
|
int fd,
|
||||||
int format)
|
int format)
|
||||||
{
|
{
|
||||||
char *buf = NULL;
|
char *buf = NULL;
|
||||||
@ -1029,7 +1032,8 @@ virStorageFileGetMetadataFromFDInternal(const char *path,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = virStorageFileGetMetadataInternal(path, buf, len, directory, format);
|
ret = virStorageFileGetMetadataInternal(path, canonPath, directory,
|
||||||
|
buf, len, format);
|
||||||
cleanup:
|
cleanup:
|
||||||
VIR_FREE(buf);
|
VIR_FREE(buf);
|
||||||
return ret;
|
return ret;
|
||||||
@ -1059,7 +1063,17 @@ virStorageFileGetMetadataFromFD(const char *path,
|
|||||||
int fd,
|
int fd,
|
||||||
int format)
|
int format)
|
||||||
{
|
{
|
||||||
return virStorageFileGetMetadataFromFDInternal(path, fd, NULL, format);
|
virStorageFileMetadataPtr ret;
|
||||||
|
char *canonPath;
|
||||||
|
|
||||||
|
if (!(canonPath = canonicalize_file_name(path))) {
|
||||||
|
virReportSystemError(errno, _("unable to resolve '%s'"), path);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ret = virStorageFileGetMetadataFromFDInternal(path, canonPath, ".",
|
||||||
|
fd, format);
|
||||||
|
VIR_FREE(canonPath);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1091,7 +1105,8 @@ virStorageFileGetMetadataRecurse(const char *path, const char *canonPath,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = virStorageFileGetMetadataFromFDInternal(path, fd, directory, format);
|
ret = virStorageFileGetMetadataFromFDInternal(path, canonPath, directory,
|
||||||
|
fd, format);
|
||||||
|
|
||||||
if (VIR_CLOSE(fd) < 0)
|
if (VIR_CLOSE(fd) < 0)
|
||||||
VIR_WARN("could not close file %s", path);
|
VIR_WARN("could not close file %s", path);
|
||||||
@ -1150,7 +1165,8 @@ virStorageFileGetMetadata(const char *path, int format,
|
|||||||
|
|
||||||
virHashTablePtr cycle = virHashCreate(5, NULL);
|
virHashTablePtr cycle = virHashCreate(5, NULL);
|
||||||
virStorageFileMetadataPtr ret = NULL;
|
virStorageFileMetadataPtr ret = NULL;
|
||||||
char *canonPath;
|
char *canonPath = NULL;
|
||||||
|
char *directory = NULL;
|
||||||
|
|
||||||
if (!cycle)
|
if (!cycle)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -1159,13 +1175,18 @@ virStorageFileGetMetadata(const char *path, int format,
|
|||||||
virReportSystemError(errno, _("unable to resolve '%s'"), path);
|
virReportSystemError(errno, _("unable to resolve '%s'"), path);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
if (!(directory = mdir_name(path))) {
|
||||||
|
virReportOOMError();
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
if (format <= VIR_STORAGE_FILE_NONE)
|
if (format <= VIR_STORAGE_FILE_NONE)
|
||||||
format = allow_probe ? VIR_STORAGE_FILE_AUTO : VIR_STORAGE_FILE_RAW;
|
format = allow_probe ? VIR_STORAGE_FILE_AUTO : VIR_STORAGE_FILE_RAW;
|
||||||
ret = virStorageFileGetMetadataRecurse(path, canonPath, NULL, format,
|
ret = virStorageFileGetMetadataRecurse(path, canonPath, directory, format,
|
||||||
uid, gid, allow_probe, cycle);
|
uid, gid, allow_probe, cycle);
|
||||||
cleanup:
|
cleanup:
|
||||||
VIR_FREE(canonPath);
|
VIR_FREE(canonPath);
|
||||||
|
VIR_FREE(directory);
|
||||||
virHashFree(cycle);
|
virHashFree(cycle);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -1464,7 +1485,7 @@ virStorageFileChainLookup(virStorageFileMetadataPtr chain, const char *start,
|
|||||||
break;
|
break;
|
||||||
} else if (owner->backingStoreIsFile) {
|
} else if (owner->backingStoreIsFile) {
|
||||||
char *absName = NULL;
|
char *absName = NULL;
|
||||||
if (virFindBackingFile(owner->directory, true, name,
|
if (virFindBackingFile(owner->directory, name,
|
||||||
NULL, &absName) < 0)
|
NULL, &absName) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
if (absName && STREQ(absName, owner->backingStore)) {
|
if (absName && STREQ(absName, owner->backingStore)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user