提交 79f11b35 编写于 作者: E Eric Blake

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: NEric Blake <eblake@redhat.com>
上级 90dbdff2
...@@ -558,14 +558,15 @@ qedGetBackingStore(char **res, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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)) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册