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