]> err.no Git - util-linux/commitdiff
libmount: add utils to get FS root/mountpoint
authorKarel Zak <kzak@redhat.com>
Mon, 26 Jul 2010 14:26:27 +0000 (16:26 +0200)
committerKarel Zak <kzak@redhat.com>
Mon, 3 Jan 2011 11:28:40 +0000 (12:28 +0100)
Signed-off-by: Karel Zak <kzak@redhat.com>
shlibs/mount/src/mountP.h
shlibs/mount/src/utils.c

index 04876a0bf15623ce7f9d3598b3587d016b6b2612..59ffb94e381f71e6f3a27fb88a99ef4c337ce46d 100644 (file)
@@ -73,6 +73,9 @@ extern int startswith(const char *s, const char *sx);
 extern char *mnt_get_username(const uid_t uid);
 extern int mnt_has_regular_mtab(void);
 
+extern char *mnt_get_mountpoint(const char *path);
+extern char *mnt_get_fs_root(const char *path);
+
 /*
  * Generic iterator
  */
index 372351acc2190d1e48df5456ae82887a0f04ef59..da2799b508aba10786b6b131bd8dfc5bea9512c8 100644 (file)
@@ -32,6 +32,7 @@
 #include "pathnames.h"
 #include "mountP.h"
 #include "mangle.h"
+#include "canonicalize.h"
 
 char *mnt_getenv_safe(const char *arg)
 {
@@ -358,6 +359,73 @@ const char *mnt_get_writable_mtab_path(void)
        return NULL;
 }
 
+
+/* returns basename and keeps dirname in the @path, if @path is "/" (root)
+ * then returns empty string */
+static char *stripoff_last_component(char *path)
+{
+       char *p = strrchr(path, '/');
+
+       if (!p)
+               return NULL;
+       *p = '\0';
+       return ++p;
+}
+
+char *mnt_get_mountpoint(const char *path)
+{
+       char *mnt = strdup(path);
+       struct stat st;
+       dev_t dir, base;
+
+       if (!mnt)
+               return NULL;
+       if (*mnt == '/' && *(mnt + 1) == '\0')
+               return mnt;                             /* root fs */
+
+       if (stat(mnt, &st))
+               goto err;
+       base = st.st_dev;
+
+       do {
+               char *p = stripoff_last_component(mnt);
+
+               if (!p)
+                       break;
+               if (stat(*mnt ? mnt : "/", &st))
+                       goto err;
+               dir = st.st_dev;
+               if (dir != base) {
+                       *(p - 1) = '/';
+                       return mnt;
+               }
+               base = dir;
+       } while (mnt && *(mnt + 1) != '\0');
+
+       memcpy(mnt, "/", 2);
+       return mnt;             /* root fs */
+err:
+       free(mnt);
+       return NULL;
+}
+
+char *mnt_get_fs_root(const char *path)
+{
+       char *mnt = mnt_get_mountpoint(path);
+       const char *p;
+       size_t sz;
+
+       if (!mnt)
+               return NULL;
+
+       sz = strlen(mnt);
+       p = sz > 1 ? path + sz : path;
+
+       free(mnt);
+
+       return *p ? strdup(p) : strdup("/");
+}
+
 #ifdef TEST_PROGRAM
 int test_match_fstype(struct mtest *ts, int argc, char *argv[])
 {
@@ -395,6 +463,27 @@ int test_endswith(struct mtest *ts, int argc, char *argv[])
        return 0;
 }
 
+int test_mountpoint(struct mtest *ts, int argc, char *argv[])
+{
+       char *path = canonicalize_path(argv[1]),
+            *mnt = path ? mnt_get_mountpoint(path) :  NULL;
+
+       printf("%s: %s\n", argv[1], mnt ? : "unknown");
+       free(mnt);
+       free(path);
+       return 0;
+}
+
+int test_fsroot(struct mtest *ts, int argc, char *argv[])
+{
+       char *path = canonicalize_path(argv[1]),
+            *mnt = path ? mnt_get_fs_root(path) : NULL;
+
+       printf("%s: %s\n", argv[1], mnt ? : "unknown");
+       free(mnt);
+       free(path);
+       return 0;
+}
 
 int main(int argc, char *argv[])
 {
@@ -403,6 +492,8 @@ int main(int argc, char *argv[])
        { "--match-options", test_match_options,   "<options> <pattern>  options matching" },
        { "--starts-with",   test_startswith,      "<string> <prefix>" },
        { "--ends-with",     test_endswith,        "<string> <prefix>" },
+       { "--mountpoint",    test_mountpoint,      "<path>" },
+       { "--fs-root",       test_fsroot,          "<path>" },
        { NULL }
        };