]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
virfile: Take symlink into account in virFileIsSharedFixFUSE
authorMichal Privoznik <mprivozn@redhat.com>
Thu, 18 Oct 2018 12:57:19 +0000 (14:57 +0200)
committerMichal Privoznik <mprivozn@redhat.com>
Fri, 19 Oct 2018 11:15:54 +0000 (13:15 +0200)
https://bugzilla.redhat.com/show_bug.cgi?id=1640465

Weirdly enough, there can be symlinks in the path we are trying
to fix. If it is the case our clever algorithm that finds matches
against mount table won't work. Canonicalize path at the
beginning then.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Erik Skultety <eskultet@redhat.com>
cfg.mk
src/util/virfile.c
tests/virfilemock.c
tests/virfiletest.c

diff --git a/cfg.mk b/cfg.mk
index 4790d0b7e7ab8caa81231e87a6ce820d575a0b09..d0183c02ffc8b8f0cf4dcb2ee5406d86c3708a6c 100644 (file)
--- a/cfg.mk
+++ b/cfg.mk
@@ -1229,7 +1229,7 @@ exclude_file_name_regexp--sc_prohibit_select = \
        ^cfg\.mk$$
 
 exclude_file_name_regexp--sc_prohibit_canonicalize_file_name = \
-  ^cfg\.mk$$
+  ^(cfg\.mk|tests/virfilemock\.c)$$
 
 exclude_file_name_regexp--sc_prohibit_raw_allocation = \
   ^(docs/hacking\.html\.in|src/util/viralloc\.[ch]|examples/.*|tests/(securityselinuxhelper|(vircgroup|nss)mock|commandhelper)\.c|tools/wireshark/src/packet-libvirt\.c)$$
index f6f01ec1e12ab283328955af96a04378c2f05f80..f6f9e4ceda8e2b2187864ed2fbfde8a15ee08c62 100644 (file)
@@ -3473,9 +3473,19 @@ virFileIsSharedFixFUSE(const char *path,
     char mntbuf[1024];
     char *mntDir = NULL;
     char *mntType = NULL;
+    char *canonPath = NULL;
     size_t maxMatching = 0;
     int ret = -1;
 
+    if (!(canonPath = virFileCanonicalizePath(path))) {
+        virReportSystemError(errno,
+                             _("unable to canonicalize %s"),
+                             path);
+        return -1;
+    }
+
+    VIR_DEBUG("Path canonicalization: %s->%s", path, canonPath);
+
     if (!(f = setmntent(PROC_MOUNTS, "r"))) {
         virReportSystemError(errno,
                              _("Unable to open %s"),
@@ -3487,7 +3497,7 @@ virFileIsSharedFixFUSE(const char *path,
         const char *p;
         size_t len = strlen(mb.mnt_dir);
 
-        if (!(p = STRSKIP(path, mb.mnt_dir)))
+        if (!(p = STRSKIP(canonPath, mb.mnt_dir)))
             continue;
 
         if (*(p - 1) != '/' && *p != '/' && *p != '\0')
@@ -3505,12 +3515,13 @@ virFileIsSharedFixFUSE(const char *path,
 
     if (STREQ_NULLABLE(mntType, "fuse.glusterfs")) {
         VIR_DEBUG("Found gluster FUSE mountpoint=%s for path=%s. "
-                  "Fixing shared FS type", mntDir, path);
+                  "Fixing shared FS type", mntDir, canonPath);
         *f_type = GFS2_MAGIC;
     }
 
     ret = 0;
  cleanup:
+    VIR_FREE(canonPath);
     VIR_FREE(mntType);
     VIR_FREE(mntDir);
     endmntent(f);
index 822c75738023c60d664de3797ca7bb7784f3e927..ae5c8d025acafae34c3bc59db695eba5a65f839f 100644 (file)
 #endif
 
 #include "virmock.h"
+#include "virstring.h"
+#include "viralloc.h"
 
 #define VIR_FROM_THIS VIR_FROM_NONE
 
 static FILE *(*real_setmntent)(const char *filename, const char *type);
 static int (*real_statfs)(const char *path, struct statfs *buf);
+static char *(*real_canonicalize_file_name)(const char *path);
 
 
 static void
@@ -43,6 +46,7 @@ init_syms(void)
 
     VIR_MOCK_REAL_INIT(setmntent);
     VIR_MOCK_REAL_INIT(statfs);
+    VIR_MOCK_REAL_INIT(canonicalize_file_name);
 }
 
 
@@ -94,6 +98,7 @@ statfs_mock(const char *mtab,
     FILE *f;
     struct mntent mb;
     char mntbuf[1024];
+    char *canonPath = NULL;
     int ret = -1;
 
     if (!(f = real_setmntent(mtab, "r"))) {
@@ -101,10 +106,16 @@ statfs_mock(const char *mtab,
         return -1;
     }
 
+    /* We don't need to do this in callers because real statfs(2)
+     * does that for us. However, in mocked implementation we
+     * need to do this. */
+    if (!(canonPath = canonicalize_file_name(path)))
+        return -1;
+
     while (getmntent_r(f, &mb, mntbuf, sizeof(mntbuf))) {
         int ftype;
 
-        if (STRNEQ(mb.mnt_dir, path))
+        if (STRNEQ(mb.mnt_dir, canonPath))
             continue;
 
         if (STREQ(mb.mnt_type, "nfs") ||
@@ -136,6 +147,7 @@ statfs_mock(const char *mtab,
     }
 
     endmntent(f);
+    VIR_FREE(canonPath);
     return ret;
 }
 
@@ -152,3 +164,22 @@ statfs(const char *path, struct statfs *buf)
 
     return real_statfs(path, buf);
 }
+
+
+char *
+canonicalize_file_name(const char *path)
+{
+    if (getenv("LIBVIRT_MTAB")) {
+        const char *p;
+        char *ret;
+
+        if ((p = STRSKIP(path, "/some/symlink")))
+            ignore_value(virAsprintfQuiet(&ret, "/gluster%s", p));
+        else
+            ignore_value(VIR_STRDUP_QUIET(ret, path));
+
+        return ret;
+    }
+
+    return real_canonicalize_file_name(path);
+}
index 1f2be74c8dd62024182a5ec8c6748a969c765848..f7b263f2e928b1c5970b7b1a9d1c537ea3c0a313 100644 (file)
@@ -456,6 +456,7 @@ mymain(void)
     DO_TEST_FILE_IS_SHARED_FS_TYPE("mounts3.txt", "/nfs/blah", false);
     DO_TEST_FILE_IS_SHARED_FS_TYPE("mounts3.txt", "/gluster/file", true);
     DO_TEST_FILE_IS_SHARED_FS_TYPE("mounts3.txt", "/gluster/sshfs/file", false);
+    DO_TEST_FILE_IS_SHARED_FS_TYPE("mounts3.txt", "/some/symlink/file", true);
 
     return ret != 0 ? EXIT_FAILURE : EXIT_SUCCESS;
 }