]> err.no Git - util-linux/commitdiff
libmount: add fstab/mtab/mountinfo lookup routines
authorKarel Zak <kzak@redhat.com>
Mon, 1 Mar 2010 21:29:38 +0000 (22:29 +0100)
committerKarel Zak <kzak@redhat.com>
Thu, 3 Jun 2010 13:20:11 +0000 (15:20 +0200)
Signed-off-by: Karel Zak <kzak@redhat.com>
shlibs/mount/src/cache.c
shlibs/mount/src/fs.c
shlibs/mount/src/mount.h.in
shlibs/mount/src/mountP.h
shlibs/mount/src/tab.c

index 18cf9fad21a627a100ef56585b9f412dfca8dc28..b9d89f4385784968000269d3fca019bde9fdb357 100644 (file)
@@ -408,7 +408,8 @@ error:
  * @spec: path or tag
  * @cache: paths cache
  *
- * Returns canonicalized path or NULL.
+ * Returns canonicalized path or NULL. The result has to be
+ * deallocated by free() if @cache is NULL.
  */
 char *mnt_resolve_spec(const char *spec, mnt_cache *cache)
 {
index 0e12052d5f3a5f6ca7eed41c32ff2d369606c0eb..01c2d02775b1d5cb8dd2989bc4f0aab62553697e 100644 (file)
@@ -11,6 +11,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <ctype.h>
+#include <errno.h>
 #include <blkid/blkid.h>
 
 #include "nls.h"
@@ -415,6 +416,154 @@ int mnt_fs_get_option(mnt_fs *fs, const char *name,
 }
 
 
+/**
+ * mnt_fs_match_target:
+ * @fs: filesystem
+ * @target: mountpoint path
+ * @cache: tags/paths cache or NULL
+ *
+ * Possible are three attempts:
+ *     1) compare @target with @fs->target
+ *     2) realpath(@target) with @fs->target
+ *     3) realpath(@target) with realpath(@fs->target).
+ *
+ * The 2nd and 3rd attempts are not performed when @cache is NULL.
+ *
+ * Returns 1 if @fs target is equal to @target else 0.
+ */
+int mnt_fs_match_target(mnt_fs *fs, const char *target, mnt_cache *cache)
+{
+       int rc = 0;
+
+       if (!fs || !target || !fs->target)
+               return 0;
+
+       /* 1) native paths */
+       rc = !strcmp(target, fs->target);
+
+       if (!rc && cache) {
+               /* 2) - canonicalized and non-canonicalized */
+               char *cn = mnt_resolve_path(target, cache);
+               rc = (cn && strcmp(cn, fs->target) == 0);
+
+               /* 3) - canonicalized and canonicalized */
+               if (!rc && cn) {
+                       char *tcn = mnt_resolve_path(fs->target, cache);
+                       rc = (tcn && strcmp(cn, tcn) == 0);
+               }
+       }
+
+       return rc;
+}
+
+/**
+ * mnt_fs_match_source:
+ * @fs: filesystem
+ * @source: tag or path (device or so)
+ * @cache: tags/paths cache or NULL
+ *
+ * Possible are four attempts:
+ *     1) compare @source with @fs->source
+ *     2) compare realpath(@source) with @fs->source
+ *     3) compare realpath(@source) with realpath(@fs->source)
+ *     4) compare realpath(@source) with evaluated tag from @fs->source
+ *
+ * The 2nd, 3rd and 4th attempts are not performed when @cache is NULL. The
+ * 2nd and 3rd attempts are not performed if @fs->source is tag.
+ *
+ * Returns 1 if @fs source is equal to @source else 0.
+ */
+int mnt_fs_match_source(mnt_fs *fs, const char *source, mnt_cache *cache)
+{
+       int rc = 0;
+       char *cn;
+       const char *src, *t, *v;
+
+       if (!fs || !source || !fs->source)
+               return 0;
+
+       /* 1) native paths/tags */
+       rc = !strcmp(source, fs->source);
+       if (rc || !cache)
+               return rc;
+
+       if (fs->flags & (MNT_FS_NET | MNT_FS_PSEUDO))
+               return 0;
+
+       cn = mnt_resolve_spec(source, cache);
+       if (!cn)
+               return 0;
+
+       /* 2) canonicalized and native */
+       src = mnt_fs_get_srcpath(fs);
+       if (src)
+               rc = !strcmp(cn, src);
+
+       /* 3) canonicalized and canonicalized */
+       if (src && !rc) {
+               src = mnt_resolve_path(src, cache);
+               rc = !strcmp(cn, src);
+       }
+       if (src && !rc)
+               /* fs->source is path and does not match with @source */
+               return 0;
+
+       if (mnt_fs_get_tag(fs, &t, &v))
+               return 0;
+
+       /* read @source's tags to the cache */
+       if (mnt_cache_read_tags(cache, cn) < 1) {
+               if (errno == EACCES) {
+                       /* we don't have permissions to read TAGs from
+                        * @source, but can translate @fs tag to devname.
+                        *
+                        * (because libblkid uses udev symlinks and this is
+                        * accessible for non-root uses)
+                        */
+                       char *x = mnt_resolve_tag(t, v, cache);
+                       if (x && !strcmp(x, cn))
+                               return 1;
+               }
+               return 0;
+       }
+
+       /* 4) has the @source a tag that matches with tag from @fs ? */
+       if (!mnt_cache_device_has_tag(cache, cn, t, v))
+               return 0;
+
+       return 1;
+}
+
+/**
+ * mnt_fs_match_fstype:
+ * @fs: filesystem
+ * @types: filesystem name or comma delimited list of filesystems
+ *
+ * For more details see mnt_match_fstype().
+ *
+ * Returns 1 if @fs type is matching to @types else 0. The function returns
+ * 0 when types is NULL.
+ */
+int mnt_fs_match_fstype(mnt_fs *fs, const char *types)
+{
+       return mnt_match_fstype(fs->fstype, types);
+}
+
+/**
+ * mnt_fs_match_options:
+ * @fs: filesystem
+ * @options: comma delimited list of options (and nooptions)
+ *
+ * For more details see mnt_match_options().
+ *
+ * Returns 1 if @fs type is matching to @options else 0. The function returns
+ * 0 when types is NULL.
+ */
+int mnt_fs_match_options(mnt_fs *fs, const char *options)
+{
+       return mnt_match_options(fs->optstr, options);
+}
+
 /* Unfortunately the classical Unix /etc/mtab and /etc/fstab
    do not handle directory names containing spaces.
    Here we mangle them, replacing a space by \040.
index 6bea2a174b2db0bedb3a35d3477b9fa127d0129a..04bbee96308e4a83e073cf40651da99390c74355 100644 (file)
@@ -230,6 +230,11 @@ extern int mnt_fs_set_passno(mnt_fs *ent, int passno);
 extern int mnt_fs_get_option(mnt_fs *ent, const char *name,
                                char **value, size_t *valsz);
 
+extern int mnt_fs_match_target(mnt_fs *fs, const char *target, mnt_cache *cache);
+extern int mnt_fs_match_source(mnt_fs *fs, const char *source, mnt_cache *cache);
+extern int mnt_fs_match_fstype(mnt_fs *fs, const char *types);
+extern int mnt_fs_match_options(mnt_fs *fs, const char *options);
+
 /* mtab/fstab line */
 #define MNT_MFILE_PRINTFMT     "%s %s %s %s %d %d\n"
 
@@ -269,8 +274,11 @@ extern mnt_fs *mnt_tab_find_srcpath(mnt_tab *tb, const char *path, int direction
 extern mnt_fs *mnt_tab_find_tag(mnt_tab *tb, const char *tag,
                                const char *val, int direction);
 extern mnt_fs *mnt_tab_find_source(mnt_tab *tb, const char *source, int direction);
-extern mnt_fs *mnt_tab_find_pair(mnt_tab *tb, const char *srcpath,
-                               const char *target, int direction);
+
+extern int mnt_tab_find_next_fs(mnt_tab *tb, mnt_iter *itr,
+                       int (*match_func)(mnt_fs *, void *), void *userdata,
+                       mnt_fs **fs);
+
 extern int mnt_tab_fprintf(mnt_tab *tb, FILE *f, const char *fmt);
 extern int mnt_tab_update_file(mnt_tab *tb);
 
index f08f435a401c0ff87bc8faceaf320c5faf3ba81a..3ba3205f6b4c699fda092c845b3af224181026f4 100644 (file)
@@ -152,7 +152,7 @@ struct _mnt_fs {
        int             freq;           /* fstab[5]:  dump frequency in days */
        int             passno;         /* fstab[6]: pass number on parallel fsck */
 
-       int             flags;          /* MNT_ENTRY_* flags */
+       int             flags;          /* MNT_FS_* flags */
        int             lineno;         /* line number in the parental file */
 };
 
index fd9293136c50634894d3f20bac45b7d2427d8675..bfd3a6e127673098285a2d142cdb8e7d0d27ac2e 100644 (file)
@@ -31,6 +31,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <ctype.h>
+#include <errno.h>
 #include <limits.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -232,6 +233,8 @@ int mnt_tab_remove_fs(mnt_tab *tb, mnt_fs *fs)
  */
 int mnt_tab_next_fs(mnt_tab *tb, mnt_iter *itr, mnt_fs **fs)
 {
+       int rc;
+
        assert(tb);
        assert(itr);
        assert(fs);
@@ -239,17 +242,54 @@ int mnt_tab_next_fs(mnt_tab *tb, mnt_iter *itr, mnt_fs **fs)
        if (!tb || !itr || !fs)
                return -1;
 again:
+       rc = 1;
        if (!itr->head)
                MNT_ITER_INIT(itr, &tb->ents);
        if (itr->p != itr->head) {
                MNT_ITER_ITERATE(itr, *fs, struct _mnt_fs, ents);
-               return 0;
+               rc = 0;
        }
 
        /* ignore broken entries */
        if (*fs && ((*fs)->flags & MNT_FS_ERROR))
                goto again;
 
+       return rc;
+}
+
+/**
+ * mnt_tab_find_next_fs:
+ * @tb: table
+ * @itr: iterator
+ * @match_func: function returns 1 or 0
+ * @fs: returns pointer to the next matching table entry
+ *
+ * This function allows search in @tb.
+ *
+ * Returns -1 in case of error, 1 at end of table or 0 o success.
+ */
+int mnt_tab_find_next_fs(mnt_tab *tb, mnt_iter *itr,
+               int (*match_func)(mnt_fs *, void *), void *userdata,
+               mnt_fs **fs)
+{
+       if (!tb || !itr || !fs || !match_func)
+               return -1;
+
+       if (!itr->head)
+               MNT_ITER_INIT(itr, &tb->ents);
+
+       do {
+               if (itr->p != itr->head)
+                       MNT_ITER_ITERATE(itr, *fs, struct _mnt_fs, ents);
+               else
+                       break;                  /* end */
+
+               if ((*fs)->flags & MNT_FS_ERROR)
+                       continue;
+               if (match_func(*fs, userdata))
+                       return 0;
+       } while(1);
+
        return 1;
 }
 
@@ -386,16 +426,32 @@ mnt_fs *mnt_tab_find_srcpath(mnt_tab *tb, const char *path, int direction)
        }
 
        /* evaluated tag */
-       if (ntags && mnt_cache_read_tags(tb->cache, cn) > 0) {
+       if (ntags) {
                mnt_reset_iter(&itr, direction);
-               while(mnt_tab_next_fs(tb, &itr, &fs) == 0) {
-                       const char *t, *v;
 
-                       if (mnt_fs_get_tag(fs, &t, &v))
-                               continue;
+               if (mnt_cache_read_tags(tb->cache, cn) > 0) {
+                       /* @path's TAGs are in the cache */
+                       while(mnt_tab_next_fs(tb, &itr, &fs) == 0) {
+                               const char *t, *v;
 
-                       if (mnt_cache_device_has_tag(tb->cache, cn, t, v))
-                               return fs;
+                               if (mnt_fs_get_tag(fs, &t, &v))
+                                       continue;
+
+                               if (mnt_cache_device_has_tag(tb->cache, cn, t, v))
+                                       return fs;
+                       }
+               } else if (errno == EACCES) {
+                       /* @path is unaccessible, try evaluate all TAGs in @tb
+                        * by udev symlinks -- this could be expensive on systems
+                        * with huge fstab/mtab */
+                        while(mnt_tab_next_fs(tb, &itr, &fs) == 0) {
+                                const char *t, *v, *x;
+                                if (mnt_fs_get_tag(fs, &t, &v))
+                                        continue;
+                                x = mnt_resolve_tag(t, v, tb->cache);
+                                if (x && !strcmp(x, cn))
+                                        return fs;
+                        }
                }
        }
 
@@ -503,87 +559,6 @@ mnt_fs *mnt_tab_find_source(mnt_tab *tb, const char *source, int direction)
        return fs;
 }
 
-/**
- * mnt_tab_find_pair:
- * @tb: tab pointer
- * @srcpath: canonicalized source path (devname or dirname)
- * @target: canonicalized mountpoint
- * @direction: MNT_ITER_{FORWARD,BACKWARD}
- *
- * Returns a tab entry or NULL.
- */
-mnt_fs *mnt_tab_find_pair(mnt_tab *tb, const char *srcpath,
-                       const char *target, int direction)
-{
-       mnt_iter itr;
-       mnt_fs *fs;
-       int has_tags = -1;
-       const char *p;
-
-       assert(tb);
-       assert(srcpath);
-       assert(target);
-
-       DBG(DEBUG_TAB, fprintf(stderr,
-               "libmount: %s: lookup pair: srcpath(%s) target(%s)\n",
-               tb->filename, srcpath, target));
-
-       /* native paths */
-       mnt_reset_iter(&itr, direction);
-       while(mnt_tab_next_fs(tb, &itr, &fs) == 0) {
-               if (!fs->target || strcmp(fs->target, target))
-                       continue;
-               p = mnt_fs_get_srcpath(fs);
-               if (p && strcmp(p, srcpath) == 0)
-                       return fs;
-       }
-
-       if (!tb->cache)
-               return NULL;
-
-       mnt_reset_iter(&itr, direction);
-       while(mnt_tab_next_fs(tb, &itr, &fs) == 0) {
-               const char *src;
-
-               if (!fs->target)
-                       continue;
-
-               /* canonicalized or non-canonicalied target */
-               if (strcmp(fs->target, target)) {
-                       p = mnt_resolve_path(fs->target, tb->cache);
-                       if (!p || strcmp(p, target))
-                               continue;
-               }
-
-               src = mnt_fs_get_srcpath(fs);
-               if (src) {
-                       /* canonicalized or non-canonicalied srcpath */
-                       if (strcmp(src, srcpath)) {
-                               p = mnt_resolve_path(src, tb->cache);
-                               if (!p || strcmp(p, srcpath))
-                                       continue;
-                       }
-               } else if (has_tags != 0) {
-                       /* entry source is tag */
-                       const char *t, *v;
-
-                       if (mnt_fs_get_tag(fs, &t, &v))
-                               continue;
-                       if (has_tags == -1 &&
-                           mnt_cache_read_tags(tb->cache, srcpath)) {
-                               has_tags = 0;
-                               continue;
-                       }
-                       has_tags = 1;
-                       if (!mnt_cache_device_has_tag(tb->cache, srcpath, t, v))
-                               continue;
-               } else
-                       continue;
-
-               return fs;
-       }
-       return NULL;
-}
 
 /**
  * mnt_tab_fprintf: