]> err.no Git - util-linux/commitdiff
libmount: better work with mtab options
authorKarel Zak <kzak@redhat.com>
Wed, 22 Dec 2010 12:15:04 +0000 (13:15 +0100)
committerKarel Zak <kzak@redhat.com>
Mon, 3 Jan 2011 11:28:48 +0000 (12:28 +0100)
Signed-off-by: Karel Zak <kzak@redhat.com>
shlibs/mount/src/fs.c
shlibs/mount/src/mount.h.in
shlibs/mount/src/mount.sym
shlibs/mount/src/mountP.h
shlibs/mount/src/optmap.c
shlibs/mount/src/optstr.c
shlibs/mount/src/tab_parse.c
shlibs/mount/src/tab_update.c
shlibs/mount/src/utils.c

index 94c35355801816f990f8f9636b091ded9a4eb366..21e02f3dfbd77952869e2121b7dd3822d57fb7f2 100644 (file)
@@ -145,6 +145,60 @@ err:
        return NULL;
 }
 
+/**
+ * mnt_copy_mtab_fs:
+ * @fs: filesystem
+ *
+ * This function copies all @fs description except information that does not
+ * belong to /etc/mtab (e.g. VFS and userspace mount options with MNT_NOMTAB
+ * mask).
+ *
+ * Returns: copy of @fs.
+ */
+mnt_fs *mnt_copy_mtab_fs(const mnt_fs *fs)
+{
+       mnt_fs *n = mnt_new_fs();
+
+       if (!n)
+               return NULL;
+
+       if (cpy_str_at_offset(n, fs, offsetof(struct _mnt_fs, source)))
+               goto err;
+       if (cpy_str_at_offset(n, fs, offsetof(struct _mnt_fs, target)))
+               goto err;
+       if (cpy_str_at_offset(n, fs, offsetof(struct _mnt_fs, fstype)))
+               goto err;
+
+       if (fs->vfs_optstr) {
+               char *p = NULL;
+               mnt_optstr_get_options(fs->vfs_optstr, &p,
+                               mnt_get_builtin_optmap(MNT_LINUX_MAP),
+                               MNT_NOMTAB);
+               n->vfs_optstr = p;
+       }
+
+       if (fs->user_optstr) {
+               char *p = NULL;
+               mnt_optstr_get_options(fs->user_optstr, &p,
+                               mnt_get_builtin_optmap(MNT_USERSPACE_MAP),
+                               MNT_NOMTAB);
+               n->user_optstr = p;
+       }
+
+       if (cpy_str_at_offset(n, fs, offsetof(struct _mnt_fs, fs_optstr)))
+               goto err;
+
+       n->freq       = fs->freq;
+       n->passno     = fs->passno;
+       n->flags      = fs->flags;
+
+       return n;
+err:
+       mnt_free_fs(n);
+       return NULL;
+
+}
+
 /**
  * mnt_fs_get_userdata:
  * @fs: mnt_file instance
index e0212fa51f9c293a124eea805ee61b326bd5d8b8..76d66aaad75376723a9c6c92f25c0dfd5933ec76 100644 (file)
@@ -65,7 +65,7 @@ struct mnt_optmap
 {
        const char      *name;   /* option name[=%<type>] (e.g. "loop[=%s]") */
        int             id;      /* option ID or MS_* flags (e.g MS_RDONLY) */
-       int             mask;    /* MNT_{MFLAG,MDATA,INVMASK,...} mask */
+       int             mask;    /* MNT_{NOMTAB,INVERT,...} mask */
 };
 
 /*
@@ -167,6 +167,9 @@ extern int mnt_split_optstr(const char *optstr,
                            char **user, char **vfs, char **fs,
                            int ifnore_user, int ignore_vfs);
 
+extern int mnt_optstr_get_options(const char *optstr, char **subset,
+                            const struct mnt_optmap *map, int ignore);
+
 extern int mnt_optstr_get_flags(const char *optstr, unsigned long *flags,
                                const struct mnt_optmap *map);
 extern int mnt_optstr_apply_flags(char **optstr, unsigned long flags,
@@ -204,6 +207,7 @@ extern int mnt_lock_file(mnt_lock *ml);
 extern mnt_fs *mnt_new_fs(void);
 extern void mnt_free_fs(mnt_fs *ent);
 extern mnt_fs *mnt_copy_fs(const mnt_fs *fs);
+extern mnt_fs *mnt_copy_mtab_fs(const mnt_fs *fs);
 extern void *mnt_fs_get_userdata(mnt_fs *fs);
 extern int mnt_fs_set_userdata(mnt_fs *fs, void *data);
 extern const char *mnt_fs_get_source(mnt_fs *ent);
@@ -314,6 +318,7 @@ extern int mnt_update_tab(mnt_update *upd, mnt_lock *lc);
 extern unsigned long mnt_update_get_mountflags(mnt_update *upd);
 extern int mnt_update_force_rdonly(mnt_update *upd, int rdonly);
 extern const char *mnt_update_get_filename(mnt_update *upd);
+extern mnt_fs *mnt_update_get_fs(mnt_update *upd);
 
 /* context.c */
 
index 7890a1403d061fed35afb321d1f7ac230cce2c80..3d2475ba175e264438a69767854c421d1b121c7f 100644 (file)
@@ -136,7 +136,7 @@ global:
        mnt_update_get_mountflags;
        mnt_update_force_rdonly;
        mnt_update_get_filename;
-
+       mnt_update_get_fs;
 local:
        *;
 };
index 3403ab70582a5a1b078c8d424aab0d4f4537d6c6..fe6ea56984d82972347fd86c7a7390db70029028 100644 (file)
@@ -84,8 +84,8 @@ mnt_debug_h(void *handler, const char *mesg, ...)
 }
 
 #else /* !CONFIG_LIBMOUNT_DEBUG */
-# define DBG(m,x)
-# define DBG_FLUSH
+# define DBG(m,x) do { ; } while(0)
+# define DBG_FLUSH do { ; } while(0)
 #endif
 
 /* extension for files in the /etc/fstab.d directory */
index d5f641096a6619ce79df95069bcacec96dd56a3b..38256b09df3e413fc77564df76b957cc3608db06 100644 (file)
@@ -99,7 +99,7 @@ static const struct mnt_optmap linux_flags_map[] =
    { "async",    MS_SYNCHRONOUS, MNT_INVERT },/* asynchronous I/O */
 
    { "dirsync",  MS_DIRSYNC },                /* synchronous directory modifications */
-   { "remount",  MS_REMOUNT },                /* Alter flags of mounted FS */
+   { "remount",  MS_REMOUNT, MNT_NOMTAB },    /* alter flags of mounted FS */
    { "bind",     MS_BIND },                   /* Remount part of tree elsewhere */
    { "rbind",    MS_BIND | MS_REC },          /* Idem, plus mounted subtrees */
 #ifdef MS_NOSUB
index 62c5701dd2ef4b07b154dbaf7fe3572526f17353..7c41f685773dc22b688daafa9023d624a67930df 100644 (file)
@@ -147,7 +147,6 @@ static int mnt_optstr_locate_option(char *optstr, const char *name,
                }
        } while(1);
 
-       DBG(OPTIONS, mnt_debug("can't found '%s' option", name));
        return rc;
 }
 
@@ -513,6 +512,59 @@ int mnt_split_optstr(const char *optstr, char **user, char **vfs, char **fs,
        return 0;
 }
 
+/**
+ * mnt_optstr_get_options
+ * @optstr: string with comma separated list of options
+ * @subset: returns newly allocated string with options
+ * @map: options map
+ * @ignore: mask of the options that should be ignored
+ *
+ * Extracts options from @optstr that belongs to the @map, for example:
+ *
+ *      mnt_split_optstr_by_map(optstr, &p,
+ *                     mnt_get_builtin_optmap(MNT_LINUX_MAP),
+ *                     MNT_NOMTAB);
+ *
+ * returns all VFS options, the options that does not belong to mtab
+ * are ignored.
+ *
+ * Returns: 0 on success, or negative number in case of error.
+ */
+int mnt_optstr_get_options(const char *optstr, char **subset,
+                           const struct mnt_optmap *map, int ignore)
+{
+       struct mnt_optmap const *maps[1];
+       char *name, *val, *str = (char *) optstr;
+       size_t namesz, valsz;
+
+       if (!optstr || !subset)
+               return -EINVAL;
+
+       maps[0] = map;
+       *subset = NULL;
+
+       while(!mnt_optstr_next_option(&str, &name, &namesz, &val, &valsz)) {
+               int rc = 0;
+               const struct mnt_optmap *ent;
+
+               mnt_optmap_get_entry(maps, 1, name, namesz, &ent);
+
+               if (!ent || !ent->id)
+                       continue;       /* ignore undefined options (comments) */
+
+               if (ignore && (ent->mask & ignore))
+                       continue;
+               rc = __mnt_optstr_append_option(subset, name, namesz, val, valsz);
+               if (rc) {
+                       free(*subset);
+                       return rc;
+               }
+       }
+
+       return 0;
+}
+
+
 /**
  * mnt_optstr_get_flags:
  * @optstr: string with comma separated list of options
index a6c14ffff5d1818fae2952676a85676087803ef7..335f703aa904d65feb496ae547ffbc091ae6e83e 100644 (file)
@@ -469,7 +469,7 @@ mnt_tab *__mnt_new_tab_from_file(const char *filename, int fmt)
 
        if (!filename)
                return NULL;
-       if (stat(filename, &st) || st.st_size == 0)
+       if (stat(filename, &st))
                return NULL;
        tb = mnt_new_tab();
        if (tb) {
index 603b6689c789440e17b66b6c364e440f383fe0ab..986eff8e9d894f7e1d0ee49ed0dd867678cb1321 100644 (file)
@@ -201,9 +201,10 @@ int mnt_update_set_fs(mnt_update *upd, unsigned long mountflags,
                        if (rc)
                                return rc;
                } else {
-                       upd->fs = mnt_copy_fs(fs);
+                       upd->fs = mnt_copy_mtab_fs(fs);
                        if (!upd->fs)
                                return -ENOMEM;
+
                }
        }
 
@@ -214,7 +215,10 @@ int mnt_update_set_fs(mnt_update *upd, unsigned long mountflags,
 }
 
 /**
- * Returns update filesystem or NULL
+ * mnt_update_get_fs:
+ * @upd: update
+ *
+ * Returns: update filesystem entry or NULL
  */
 mnt_fs *mnt_update_get_fs(mnt_update *upd)
 {
@@ -283,6 +287,7 @@ static int utab_new_entry(mnt_fs *fs, unsigned long mountflags, mnt_fs **ent)
 {
        int rc = 0;
        const char *o = NULL, *a = NULL;
+       char *u = NULL;
 
        assert(fs);
        assert(ent);
@@ -297,8 +302,19 @@ static int utab_new_entry(mnt_fs *fs, unsigned long mountflags, mnt_fs **ent)
        o = mnt_fs_get_userspace_options(fs);
        a = mnt_fs_get_attributes(fs);
 
-       if (!o && !a)
-               return 1;       /* don't have mount options */
+       if (o) {
+               /* remove non-mtab options */
+               rc = mnt_optstr_get_options(o, &u,
+                               mnt_get_builtin_optmap(MNT_USERSPACE_MAP),
+                               MNT_NOMTAB);
+               if (rc)
+                       goto err;
+       }
+
+       if (!u && !a) {
+               DBG(UPDATE, mnt_debug("utab entry unnecessary (no options)"));
+               return 1;
+       }
 
        /* allocate the entry */
        *ent = mnt_copy_fs(fs);
@@ -307,7 +323,7 @@ static int utab_new_entry(mnt_fs *fs, unsigned long mountflags, mnt_fs **ent)
                goto err;
        }
 
-       rc = mnt_fs_set_userspace_options(*ent, o);
+       rc = mnt_fs_set_userspace_options(*ent, u);
        if (rc)
                goto err;
        rc = mnt_fs_set_attributes(*ent, a);
@@ -320,10 +336,12 @@ static int utab_new_entry(mnt_fs *fs, unsigned long mountflags, mnt_fs **ent)
                        goto err;
        }
 
+       free(u);
        DBG(UPDATE, mnt_debug("utab entry OK"));
        return 0;
 err:
        mnt_free_fs(*ent);
+       free(u);
        *ent = NULL;
        return rc;
 }
@@ -349,6 +367,8 @@ static int set_fs_root(mnt_fs *result, mnt_fs *fs, unsigned long mountflags)
                const char *src, *src_root;
                mnt_fs *src_fs;
 
+               DBG(UPDATE, mnt_debug("setting FS root: bind"));
+
                src = mnt_fs_get_srcpath(fs);
                if (src) {
                        rc = mnt_fs_set_bindsrc(result, src);
@@ -363,11 +383,15 @@ static int set_fs_root(mnt_fs *result, mnt_fs *fs, unsigned long mountflags)
                root = mnt_get_fs_root(src, mnt);
 
                tb = __mnt_new_tab_from_file(_PATH_PROC_MOUNTINFO, MNT_FMT_MOUNTINFO);
-               if (!tb)
+               if (!tb) {
+                       DBG(UPDATE, mnt_debug("failed to parse mountinfo -- using default"));
                        goto dflt;
+               }
                src_fs = mnt_tab_find_target(tb, mnt, MNT_ITER_BACKWARD);
-               if (!src_fs)
+               if (!src_fs)  {
+                       DBG(UPDATE, mnt_debug("not found '%s' in mountinfo -- using default", mnt));
                        goto dflt;
+               }
 
                /* set device name and fs */
                src = mnt_fs_get_srcpath(src_fs);
@@ -405,6 +429,8 @@ static int set_fs_root(mnt_fs *result, mnt_fs *fs, unsigned long mountflags)
                if (mnt_fs_get_option(fs, "subvol", &vol, &volsz))
                        goto dflt;
 
+               DBG(UPDATE, mnt_debug("setting FS root: btrfs subvol"));
+
                sz = volsz;
                if (*vol != '/')
                        sz++;
@@ -762,7 +788,9 @@ int mnt_update_tab(mnt_update *upd, mnt_lock *lc)
                return 0;
 
        DBG(UPDATE, mnt_debug_h(upd, "%s: update tab", upd->filename));
-       DBG(UPDATE, mnt_fs_print_debug(upd->fs, stderr));
+       if (upd->fs) {
+               DBG(UPDATE, mnt_fs_print_debug(upd->fs, stderr));
+       }
 
        if (!upd->fs && upd->target)
                rc = update_remove_entry(upd, lc);      /* umount */
index 96ce7ddb10fe84db49f7542575b40c9e835d5cf0..ff3c90cdb43bb05ad48b7ad5c95c68c0e5d57fd2 100644 (file)
@@ -722,7 +722,7 @@ char *mnt_get_mountpoint(const char *path)
 
        memcpy(mnt, "/", 2);
 done:
-       DBG(UTILS, mnt_debug("fs-root for %s is %s", path, mnt));
+       DBG(UTILS, mnt_debug("%s mountpoint is %s", path, mnt));
        return mnt;
 err:
        free(mnt);
@@ -731,7 +731,7 @@ err:
 
 char *mnt_get_fs_root(const char *path, const char *mnt)
 {
-       char *m = (char *) mnt;
+       char *m = (char *) mnt, *res;
        const char *p;
        size_t sz;
 
@@ -746,7 +746,9 @@ char *mnt_get_fs_root(const char *path, const char *mnt)
        if (m != mnt)
                free(m);
 
-       return *p ? strdup(p) : strdup("/");
+       res = *p ? strdup(p) : strdup("/");
+       DBG(UTILS, mnt_debug("%s fs-root is %s", path, res));
+       return res;
 }
 
 #ifdef TEST_PROGRAM