* @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
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)
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
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[])
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;
{ "--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);