From 3661b841289fb36c5690272441737d5d0b34bf88 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Fri, 9 Jul 2010 16:39:50 +0200 Subject: [PATCH] libmount: add mnt_split_optstr() Signed-off-by: Karel Zak --- shlibs/mount/src/fs.c | 40 +++++++++--- shlibs/mount/src/mount.h.in | 3 + shlibs/mount/src/mount.sym | 2 + shlibs/mount/src/optmap.c | 7 +- shlibs/mount/src/optstr.c | 126 ++++++++++++++++++++++++++++++++---- 5 files changed, 152 insertions(+), 26 deletions(-) diff --git a/shlibs/mount/src/fs.c b/shlibs/mount/src/fs.c index c8677c70..8e51fd73 100644 --- a/shlibs/mount/src/fs.c +++ b/shlibs/mount/src/fs.c @@ -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 diff --git a/shlibs/mount/src/mount.h.in b/shlibs/mount/src/mount.h.in index d42ab1d6..402d8fc7 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 8a0fc3a8..e5c1fcf9 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 6eef332c..0163776a 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 19efbf3f..fe9ee9be 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) @@ -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, " [] (un)set value" }, { "--get", test_get, " search name in optstr" }, { "--remove", test_remove, " remove name in optstr" }, + { "--split", test_split, " split into FS, VFS and userspace" }, { NULL } }; return mnt_run_test(tss, argc, argv); -- 2.39.5