}
/**
- * Given a starting point START (either an original file name, or the
- * directory containing the original name, depending on START_IS_DIR)
- * and a possibly relative backing file NAME, compute the relative
- * DIRECTORY (optional) and CANONICAL (mandatory) location of the
- * backing file. Return 0 on success, negative on error.
+ * Given a starting point START (a directory containing the original
+ * file, if the original file was opened via a relative path; ignored
+ * if NAME is absolute), determine the location of the backing file
+ * NAME (possibly relative), and compute the relative DIRECTORY
+ * (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)
-virFindBackingFile(const char *start, bool start_is_dir, const char *path,
+static int ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(4)
+virFindBackingFile(const char *start, const char *path,
char **directory, char **canonical)
{
char *combined = NULL;
if (*path == '/') {
/* Safe to cast away const */
combined = (char *)path;
- } else {
- size_t d_len = start_is_dir ? strlen(start) : dir_len(start);
-
- 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;
+ } else if (virAsprintf(&combined, "%s/%s", start, path) < 0) {
+ goto cleanup;
}
if (directory && !(*directory = mdir_name(combined))) {
}
-/* Given a header in BUF with length LEN, as parsed from the file
- * located at PATH, and optionally opened from a given DIRECTORY,
- * return metadata about that file, assuming it has the given
- * FORMAT. */
-static virStorageFileMetadataPtr
+/* Given a header in BUF with length LEN, as parsed from the file with
+ * user-provided name PATH and opened from CANONPATH, and where any
+ * relative backing file will be opened from DIRECTORY, return
+ * metadata about that file, assuming it has the given FORMAT. */
+static virStorageFileMetadataPtr ATTRIBUTE_NONNULL(1)
+ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4)
virStorageFileGetMetadataInternal(const char *path,
+ const char *canonPath,
+ const char *directory,
char *buf,
size_t len,
- const char *directory,
int format)
{
virStorageFileMetadata *meta = NULL;
virStorageFileMetadata *ret = NULL;
- VIR_DEBUG("path=%s, buf=%p, len=%zu, directory=%s, format=%d",
- path, buf, len, NULLSTR(directory), format);
+ VIR_DEBUG("path=%s, canonPath=%s, dir=%s, buf=%p, len=%zu, format=%d",
+ path, canonPath, directory, buf, len, format);
if (VIR_ALLOC(meta) < 0)
return NULL;
meta->backingStoreIsFile = true;
meta->backingStoreRaw = meta->backingStore;
meta->backingStore = NULL;
- if (virFindBackingFile(directory ? directory : path,
- !!directory, backing,
+ if (virFindBackingFile(directory, backing,
&meta->directory,
&meta->backingStore) < 0) {
/* the backing file is (currently) unavailable, treat this
size_t len,
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. */
static virStorageFileMetadataPtr
virStorageFileGetMetadataFromFDInternal(const char *path,
- int fd,
+ const char *canonPath,
const char *directory,
+ int fd,
int format)
{
char *buf = NULL;
goto cleanup;
}
- ret = virStorageFileGetMetadataInternal(path, buf, len, directory, format);
+ ret = virStorageFileGetMetadataInternal(path, canonPath, directory,
+ buf, len, format);
cleanup:
VIR_FREE(buf);
return ret;
int fd,
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;
}
return NULL;
}
- ret = virStorageFileGetMetadataFromFDInternal(path, fd, directory, format);
+ ret = virStorageFileGetMetadataFromFDInternal(path, canonPath, directory,
+ fd, format);
if (VIR_CLOSE(fd) < 0)
VIR_WARN("could not close file %s", path);
virHashTablePtr cycle = virHashCreate(5, NULL);
virStorageFileMetadataPtr ret = NULL;
- char *canonPath;
+ char *canonPath = NULL;
+ char *directory = NULL;
if (!cycle)
return NULL;
virReportSystemError(errno, _("unable to resolve '%s'"), path);
goto cleanup;
}
+ if (!(directory = mdir_name(path))) {
+ virReportOOMError();
+ goto cleanup;
+ }
if (format <= VIR_STORAGE_FILE_NONE)
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);
cleanup:
VIR_FREE(canonPath);
+ VIR_FREE(directory);
virHashFree(cycle);
return ret;
}
break;
} else if (owner->backingStoreIsFile) {
char *absName = NULL;
- if (virFindBackingFile(owner->directory, true, name,
+ if (virFindBackingFile(owner->directory, name,
NULL, &absName) < 0)
goto error;
if (absName && STREQ(absName, owner->backingStore)) {