summaryrefslogtreecommitdiffstats
path: root/shlibs/mount
diff options
context:
space:
mode:
authorKarel Zak2010-07-09 16:39:50 +0200
committerKarel Zak2011-01-03 12:28:40 +0100
commit3661b841289fb36c5690272441737d5d0b34bf88 (patch)
tree6946577ab1a4f82264a56c852b089d4763068a11 /shlibs/mount
parentlibmount: don't return old data from optls iterator (diff)
downloadkernel-qcow2-util-linux-3661b841289fb36c5690272441737d5d0b34bf88.tar.gz
kernel-qcow2-util-linux-3661b841289fb36c5690272441737d5d0b34bf88.tar.xz
kernel-qcow2-util-linux-3661b841289fb36c5690272441737d5d0b34bf88.zip
libmount: add mnt_split_optstr()
Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'shlibs/mount')
-rw-r--r--shlibs/mount/src/fs.c40
-rw-r--r--shlibs/mount/src/mount.h.in3
-rw-r--r--shlibs/mount/src/mount.sym2
-rw-r--r--shlibs/mount/src/optmap.c7
-rw-r--r--shlibs/mount/src/optstr.c126
5 files changed, 152 insertions, 26 deletions
diff --git a/shlibs/mount/src/fs.c b/shlibs/mount/src/fs.c
index c8677c702..8e51fd73d 100644
--- a/shlibs/mount/src/fs.c
+++ b/shlibs/mount/src/fs.c
@@ -332,37 +332,59 @@ 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
*
diff --git a/shlibs/mount/src/mount.h.in b/shlibs/mount/src/mount.h.in
index d42ab1d62..402d8fc76 100644
--- a/shlibs/mount/src/mount.h.in
+++ b/shlibs/mount/src/mount.h.in
@@ -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);
diff --git a/shlibs/mount/src/mount.sym b/shlibs/mount/src/mount.sym
index 8a0fc3a81..e5c1fcf96 100644
--- a/shlibs/mount/src/mount.sym
+++ b/shlibs/mount/src/mount.sym
@@ -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;
diff --git a/shlibs/mount/src/optmap.c b/shlibs/mount/src/optmap.c
index 6eef332c7..0163776a7 100644
--- a/shlibs/mount/src/optmap.c
+++ b/shlibs/mount/src/optmap.c
@@ -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;
}
}
diff --git a/shlibs/mount/src/optstr.c b/shlibs/mount/src/optstr.c
index 19efbf3fb..fe9ee9bed 100644
--- a/shlibs/mount/src/optstr.c
+++ b/shlibs/mount/src/optstr.c
@@ -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)
@@ -199,6 +190,27 @@ int mnt_optstr_append_option(char **optstr, const char *name, const char *value)
}
/**
+ * 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
* @name: requested option name
@@ -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);