c401cc
From cc6955130dfd090c2f24f787b9aacfd444f5ed45 Mon Sep 17 00:00:00 2001
c401cc
Message-Id: <cc6955130dfd090c2f24f787b9aacfd444f5ed45.1386348946.git.jdenemar@redhat.com>
c401cc
From: "Daniel P. Berrange" <berrange@redhat.com>
c401cc
Date: Mon, 2 Dec 2013 13:39:10 +0000
c401cc
Subject: [PATCH] Add virFileIsMountPoint function
c401cc
c401cc
For
c401cc
c401cc
  https://bugzilla.redhat.com/show_bug.cgi?id=1035403
c401cc
c401cc
Add a function for efficiently checking if a path is a filesystem
c401cc
mount point.
c401cc
c401cc
NB will not work for bind mounts, only true filesystem mounts.
c401cc
c401cc
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
c401cc
(cherry picked from commit ccacd4fe3b7c9de7a4b6bb10220193fc4ba41221)
c401cc
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
c401cc
---
c401cc
 src/libvirt_private.syms |  1 +
c401cc
 src/util/virfile.c       | 52 ++++++++++++++++++++++++++++++++++++++++++++++++
c401cc
 src/util/virfile.h       |  2 ++
c401cc
 3 files changed, 55 insertions(+)
c401cc
c401cc
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
c401cc
index 6821352..fa36b31 100644
c401cc
--- a/src/libvirt_private.syms
c401cc
+++ b/src/libvirt_private.syms
c401cc
@@ -1385,6 +1385,7 @@ virFileIsAbsPath;
c401cc
 virFileIsDir;
c401cc
 virFileIsExecutable;
c401cc
 virFileIsLink;
c401cc
+virFileIsMountPoint;
c401cc
 virFileLinkPointsTo;
c401cc
 virFileLock;
c401cc
 virFileLoopDeviceAssociate;
c401cc
diff --git a/src/util/virfile.c b/src/util/virfile.c
c401cc
index 33a8a6d..b396b16 100644
c401cc
--- a/src/util/virfile.c
c401cc
+++ b/src/util/virfile.c
c401cc
@@ -1440,6 +1440,58 @@ virFileIsExecutable(const char *file)
c401cc
     return false;
c401cc
 }
c401cc
 
c401cc
+
c401cc
+/*
c401cc
+ * Check that a file refers to a mount point. Trick is that for
c401cc
+ * a mount point, the st_dev field will differ from the parent
c401cc
+ * directory.
c401cc
+ *
c401cc
+ * Note that this will not detect bind mounts of dirs/files,
c401cc
+ * only true filesystem mounts.
c401cc
+ */
c401cc
+int virFileIsMountPoint(const char *file)
c401cc
+{
c401cc
+    char *parent = NULL;
c401cc
+    int ret = -1;
c401cc
+    struct stat sb1, sb2;
c401cc
+
c401cc
+    if (!(parent = mdir_name(file))) {
c401cc
+        virReportOOMError();
c401cc
+        goto cleanup;
c401cc
+    }
c401cc
+
c401cc
+    VIR_DEBUG("Comparing '%s' to '%s'", file, parent);
c401cc
+
c401cc
+    if (stat(file, &sb1) < 0) {
c401cc
+        if (errno == ENOENT)
c401cc
+            ret = 0;
c401cc
+        else
c401cc
+            virReportSystemError(errno,
c401cc
+                                 _("Cannot stat '%s'"),
c401cc
+                                 file);
c401cc
+        goto cleanup;
c401cc
+    }
c401cc
+
c401cc
+    if (stat(parent, &sb2) < 0) {
c401cc
+        virReportSystemError(errno,
c401cc
+                             _("Cannot stat '%s'"),
c401cc
+                             parent);
c401cc
+        goto cleanup;
c401cc
+    }
c401cc
+
c401cc
+    if (!S_ISDIR(sb1.st_mode)) {
c401cc
+        ret = 0;
c401cc
+        goto cleanup;
c401cc
+    }
c401cc
+
c401cc
+    ret = sb1.st_dev != sb2.st_dev;
c401cc
+    VIR_DEBUG("Is mount %d", ret);
c401cc
+
c401cc
+ cleanup:
c401cc
+    VIR_FREE(parent);
c401cc
+    return ret;
c401cc
+}
c401cc
+
c401cc
 #ifndef WIN32
c401cc
 /* Check that a file is accessible under certain
c401cc
  * user & gid.
c401cc
diff --git a/src/util/virfile.h b/src/util/virfile.h
c401cc
index 72d35ce..ff84719 100644
c401cc
--- a/src/util/virfile.h
c401cc
+++ b/src/util/virfile.h
c401cc
@@ -156,6 +156,8 @@ bool virFileIsDir (const char *file) ATTRIBUTE_NONNULL(1);
c401cc
 bool virFileExists(const char *file) ATTRIBUTE_NONNULL(1);
c401cc
 bool virFileIsExecutable(const char *file) ATTRIBUTE_NONNULL(1);
c401cc
 
c401cc
+int virFileIsMountPoint(const char *file) ATTRIBUTE_NONNULL(1);
c401cc
+
c401cc
 char *virFileSanitizePath(const char *path);
c401cc
 
c401cc
 enum {
c401cc
-- 
c401cc
1.8.4.5
c401cc