]> xenbits.xensource.com Git - libvirt.git/commitdiff
util: Introduce virFileComparePaths
authorErik Skultety <eskultet@redhat.com>
Tue, 7 Feb 2017 09:19:06 +0000 (10:19 +0100)
committerErik Skultety <eskultet@redhat.com>
Fri, 10 Feb 2017 16:01:12 +0000 (17:01 +0100)
So rather than comparing 2 paths (strings) as they are, which can very
easily lead to unnecessary errors (e.g. in storage driver) that the paths
are not the same when in fact they'd be e.g. just symlinks to the same
location, we should put our best effort into resolving any symlinks and
canonicalizing the path and only then compare the 2 paths for equality.

Signed-off-by: Erik Skultety <eskultet@redhat.com>
src/libvirt_private.syms
src/util/virfile.c
src/util/virfile.h

index 0a7de9a8ee173d5764142f0959c16b0ac48e2cc5..6bbb36b4e6ff99f56955524b6a07a11278194c2a 100644 (file)
@@ -1575,6 +1575,7 @@ virFileActivateDirOverride;
 virFileBindMountDevice;
 virFileBuildPath;
 virFileClose;
+virFileComparePaths;
 virFileCopyACLs;
 virFileDeleteTree;
 virFileDirectFdFlag;
index 49ea1d1f00d75658e0ceaf345dc578d5bcb0309f..6ba67bfbd36009c5c4f8eefd85f92c969a8940a7 100644 (file)
@@ -3749,3 +3749,47 @@ virFileCopyACLs(const char *src,
     virFileFreeACLs(&acl);
     return ret;
 }
+
+/*
+ * virFileComparePaths:
+ * @p1: source path 1
+ * @p2: source path 2
+ *
+ * Compares two paths for equality. To do so, it first canonicalizes both paths
+ * to resolve all symlinks and discard relative path components. If symlinks
+ * resolution or path canonicalization fails, plain string equality of @p1
+ * and @p2 is performed.
+ *
+ * Returns:
+ *  1 : Equal
+ *  0 : Non-Equal
+ * -1 : Error
+ */
+int
+virFileComparePaths(const char *p1, const char *p2)
+{
+    int ret = -1;
+    char *res1, *res2;
+
+    res1 = res2 = NULL;
+
+    /* Assume p1 and p2 are symlinks, so try to resolve and canonicalize them.
+     * Canonicalization fails for example on file systems names like 'proc' or
+     * 'sysfs', since they're no real paths so fallback to plain string
+     * comparison.
+     */
+    ignore_value(virFileResolveLink(p1, &res1));
+    if (!res1 && VIR_STRDUP(res1, p1) < 0)
+        goto cleanup;
+
+    ignore_value(virFileResolveLink(p2, &res2));
+    if (!res2 && VIR_STRDUP(res2, p2) < 0)
+        goto cleanup;
+
+    ret = STREQ_NULLABLE(res1, res2);
+
+ cleanup:
+    VIR_FREE(res1);
+    VIR_FREE(res2);
+    return ret;
+}
index 232c1d66e115ce01bf95bbb7e7f5ede6e532e520..f2a3faa158d36022711141419c452d57f234337c 100644 (file)
@@ -334,4 +334,6 @@ void virFileFreeACLs(void **acl);
 
 int virFileCopyACLs(const char *src,
                     const char *dst);
+
+int virFileComparePaths(const char *p1, const char *p2);
 #endif /* __VIR_FILE_H */