]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libmount: add mnt_split_optstr()
authorKarel Zak <kzak@redhat.com>
Fri, 9 Jul 2010 14:39:50 +0000 (16:39 +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/fs.c
shlibs/mount/src/mount.h.in
shlibs/mount/src/mount.sym
shlibs/mount/src/optmap.c
shlibs/mount/src/optstr.c

index c8677c702ddd9f84e1eac84c4c3dcad351713c70..8e51fd73d3c9e1a94fb577b7a5d3ad35313e9342 100644 (file)
@@ -332,36 +332,58 @@ const char *mnt_fs_get_optstr(mnt_fs *fs)
  * @fs: fstab/mtab/mountinfo entry
  * @optstr: options string
  *
- * This function creates a private copy (strdup()) of @optstr.
+ * This function creates a private copy of @optstr.
  *
  * Returns: 0 on success or -1 in case of error.
  */
 int mnt_fs_set_optstr(mnt_fs *fs, const char *optstr)
 {
-       char *p;
+       char *p, *v, *f;
 
        assert(fs);
 
        if (!fs || !optstr)
                return -1;
+       if (mnt_split_optstr((char *) optstr, NULL, &v, &f))
+               return -1;
+
        p = strdup(optstr);
-       if (!p)
+       if (!p) {
+               free(v);
+               free(f);
                return -1;
+       }
 
        free(fs->optstr);
        free(fs->fs_optstr);
        free(fs->vfs_optstr);
-       fs->fs_optstr = fs->vfs_optstr = NULL;
-
-       /* TODO: it would be possible to use built-in maps of options
-        * and differentiate between VFS and FS options, then we can
-        * set fs_optstr and vfs_optstr */
 
        fs->optstr = p;
-
+       fs->fs_optstr = f;
+       fs->vfs_optstr = v;
        return 0;
 }
 
+/**
+ * mnt_fs_append_optstr:
+ * @fs: fstab/mtab/mountinfo entry
+ * @optstr: options string (usually userspace specific options)
+ *
+ * This function appends @optstr to the current list of the mount options. The
+ * VFS and FS specific lists are not modified -- so then the
+ * mnt_fs_get_optstr() function returns VFS + FS + userspace mount options.
+ *
+ * Returns: 0 on success or -1 in case of error.
+ */
+int mnt_fs_append_optstr(mnt_fs *fs, const char *optstr)
+{
+       assert(fs);
+
+       if (!fs || !optstr)
+               return -1;
+       return mnt_optstr_append_option(&fs->optstr, optstr, NULL);
+}
+
 /**
  * mnt_fs_get_fs_optstr:
  * @fs: fstab/mtab/mountinfo entry pointer
index d42ab1d622ab771d1faf9632f2cab48470d13453..402d8fc7644187fb7a40d59f5fcdd3f19c4c02b6 100644 (file)
@@ -143,6 +143,8 @@ extern int mnt_optstr_set_option(char **optstr, const char *name,
                                const char *value);
 extern int mnt_optstr_remove_option(char **optstr, const char *name);
 
+extern int mnt_split_optstr(char *optstr, char **user, char **vfs, char **fs);
+
 /* iter.c */
 enum {
 
@@ -229,6 +231,7 @@ extern const char *mnt_fs_get_fstype(mnt_fs *ent);
 extern int mnt_fs_set_fstype(mnt_fs *ent, const char *fstype);
 extern const char *mnt_fs_get_optstr(mnt_fs *ent);
 extern int mnt_fs_set_optstr(mnt_fs *ent, const char *optstr);
+extern int mnt_fs_append_optstr(mnt_fs *fs, const char *optstr);
 extern const char *mnt_fs_get_vfs_optstr(mnt_fs *ent);
 extern const char *mnt_fs_get_fs_optstr(mnt_fs *ent);
 extern int mnt_fs_get_freq(mnt_fs *ent);
index 8a0fc3a81075add953a1fda6d73c65c82ddd2d01..e5c1fcf96f4bbd4cce260a9352a0d5b2ac9fcc3f 100644 (file)
@@ -17,6 +17,7 @@ global:
        mnt_free_lock;
        mnt_free_optls;
        mnt_free_tab;
+       mnt_fs_append_optstr;
        mnt_fs_fprintf;
        mnt_fs_get_devno;
        mnt_fs_get_freq;
@@ -109,6 +110,7 @@ global:
        mnt_resolve_path;
        mnt_resolve_spec;
        mnt_resolve_tag;
+       mnt_split_optstr;
        mnt_tab_add_fs;
        mnt_tab_find_next_fs;
        mnt_tab_find_source;
index 6eef332c7d333de7a45862001699971ffe509bee..0163776a7df9c35448e53598dfc5abc1baed645b 100644 (file)
@@ -210,9 +210,9 @@ const struct mnt_optmap *mnt_optmap_get_entry(
        assert(nmaps);
        assert(name);
        assert(namelen);
-       assert(mapent);
 
-       *mapent = NULL;
+       if (mapent)
+               *mapent = NULL;
 
        for (i = 0; i < nmaps; i++) {
                const struct mnt_optmap *map = maps[i];
@@ -224,7 +224,8 @@ const struct mnt_optmap *mnt_optmap_get_entry(
                                continue;
                        p = ent->name + namelen;
                        if (*p == '\0' || *p == '=' || *p == '[') {
-                               *mapent = ent;
+                               if (mapent)
+                                       *mapent = ent;
                                return map;
                        }
                }
index 19efbf3fba0a1803fdf79c5fea47d072347f2c56..fe9ee9bed3d37d0f6b6f0cc47203f759490b9c65 100644 (file)
@@ -149,25 +149,16 @@ int mnt_optstr_next_option(char **optstr, char **name, size_t *namesz,
        return mnt_optstr_parse_next(optstr, name, namesz, value, valuesz);
 }
 
-/**
- * mnt_optstr_append_option:
- * @optstr: option string or NULL
- * @name: value name
- * @value: value
- *
- * Returns: reallocated (or newly allocated) @optstr with ,name=value
- */
-int mnt_optstr_append_option(char **optstr, const char *name, const char *value)
+static int __mnt_optstr_append_option(char **optstr,
+                       const char *name, size_t nsz,
+                       const char *value, size_t vsz)
 {
        char *p;
-       size_t sz, vsz, osz, nsz;
+       size_t sz, osz;
 
-       if (!name)
-               return -1;
+       assert(name);
 
        osz = *optstr ? strlen(*optstr) : 0;
-       nsz = strlen(name);
-       vsz = value ? strlen(value) : 0;
 
        sz = osz + nsz + 1;             /* 1: '\0' */
        if (osz)
@@ -198,6 +189,27 @@ int mnt_optstr_append_option(char **optstr, const char *name, const char *value)
        return 0;
 }
 
+/**
+ * mnt_optstr_append_option:
+ * @optstr: option string or NULL
+ * @name: value name
+ * @value: value
+ *
+ * Returns: reallocated (or newly allocated) @optstr with ,name=value
+ */
+int mnt_optstr_append_option(char **optstr, const char *name, const char *value)
+{
+       size_t vsz, nsz;
+
+       if (!name)
+               return -1;
+
+       nsz = strlen(name);
+       vsz = value ? strlen(value) : 0;
+
+       return __mnt_optstr_append_option(optstr, name, nsz, value, vsz);
+}
+
 /**
  * mnt_optstr_get_option:
  * @optstr: string with comma separated list of options
@@ -318,6 +330,67 @@ int mnt_optstr_remove_option(char **optstr, const char *name)
        return 0;
 }
 
+/**
+ * mnt_split_optstr:
+ * @optstr: string with comma separated list of options
+ * @user: returns newly allocated string with userspace options
+ * @vfs: returns newly allocated string with VFS options
+ * @fs: returns newly allocated string with FS options
+ *
+ * Note that FS options are all options that are undefined in MNT_USERSPACE_MAP
+ * or MNT_LINUX_MAP.
+ *
+ * Returns: 0 on success, or -1 in case of error.
+ */
+int mnt_split_optstr(char *optstr, char **user, char **vfs, char **fs)
+{
+       char *name, *val;
+       size_t namesz, valsz;
+       struct mnt_optmap const *maps[2];
+
+       assert(optstr);
+
+       if (!optstr)
+               return -1;
+
+       maps[0] = mnt_get_builtin_optmap(MNT_LINUX_MAP);
+       maps[1] = mnt_get_builtin_optmap(MNT_USERSPACE_MAP);
+
+       if (vfs)
+               *vfs = NULL;
+       if (fs)
+               *fs = NULL;
+       if (user)
+               *user = NULL;
+
+       while(!mnt_optstr_next_option(&optstr, &name, &namesz, &val, &valsz)) {
+               int rc = 0;
+               const struct mnt_optmap *m =
+                        mnt_optmap_get_entry(maps, 2, name, namesz, NULL);
+
+               if (m && m == maps[0] && vfs)
+                       rc = __mnt_optstr_append_option(vfs, name, namesz,
+                                                               val, valsz);
+               else if (m && m == maps[1] && user)
+                       rc = __mnt_optstr_append_option(user, name, namesz,
+                                                               val, valsz);
+               else if (!m && fs)
+                       rc = __mnt_optstr_append_option(fs, name, namesz,
+                                                               val, valsz);
+               if (rc) {
+                       if (vfs)
+                               free(*vfs);
+                       if (fs)
+                               free(*fs);
+                       if (user)
+                               free(*user);
+                       return rc;
+               }
+       }
+
+       return 0;
+}
+
 #ifdef TEST_PROGRAM
 
 int test_append(struct mtest *ts, int argc, char *argv[])
@@ -341,6 +414,30 @@ done:
        return -1;
 }
 
+int test_split(struct mtest *ts, int argc, char *argv[])
+{
+       char *optstr, *user = NULL, *fs = NULL, *vfs = NULL;
+       int rc = -1;
+
+       if (argc < 2)
+               return -1;
+
+       optstr = strdup(argv[1]);
+
+       if (mnt_split_optstr(optstr, &user, &vfs, &fs) == 0) {
+               printf("user : %s\n", user);
+               printf("vfs  : %s\n", vfs);
+               printf("fs   : %s\n", fs);
+               rc = 0;
+       }
+
+       free(user);
+       free(vfs);
+       free(fs);
+       free(optstr);
+       return rc;
+}
+
 int test_set(struct mtest *ts, int argc, char *argv[])
 {
        const char *value = NULL, *name;
@@ -419,6 +516,7 @@ int main(int argc, char *argv[])
                { "--set",    test_set,    "<optstr> <name> [<value>]  (un)set value" },
                { "--get",    test_get,    "<optstr> <name>            search name in optstr" },
                { "--remove", test_remove, "<optstr> <name>            remove name in optstr" },
+               { "--split",  test_split,  "<optstr>                   split into FS, VFS and userspace" },
                { NULL }
        };
        return  mnt_run_test(tss, argc, argv);