| /* |
| * by rmk |
| * |
| * Decode mount options. |
| */ |
| #include <sys/mount.h> |
| #include <stdlib.h> |
| #include <string.h> |
| |
| #include "mount_opts.h" |
| |
| #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) |
| |
| static const struct mount_opts options[] = { |
| /* name mask set noset */ |
| {"async", MS_SYNCHRONOUS, 0, MS_SYNCHRONOUS}, |
| {"atime", MS_NOATIME, 0, MS_NOATIME}, |
| {"bind", MS_TYPE, MS_BIND, 0,}, |
| {"dev", MS_NODEV, 0, MS_NODEV}, |
| {"diratime", MS_NODIRATIME, 0, MS_NODIRATIME}, |
| {"dirsync", MS_DIRSYNC, MS_DIRSYNC, 0}, |
| {"exec", MS_NOEXEC, 0, MS_NOEXEC}, |
| {"move", MS_TYPE, MS_MOVE, 0}, |
| {"nodev", MS_NODEV, MS_NODEV, 0}, |
| {"noexec", MS_NOEXEC, MS_NOEXEC, 0}, |
| {"nosuid", MS_NOSUID, MS_NOSUID, 0}, |
| {"recurse", MS_REC, MS_REC, 0}, |
| {"remount", MS_TYPE, MS_REMOUNT, 0}, |
| {"ro", MS_RDONLY, MS_RDONLY, 0}, |
| {"rw", MS_RDONLY, 0, MS_RDONLY}, |
| {"suid", MS_NOSUID, 0, MS_NOSUID}, |
| {"sync", MS_SYNCHRONOUS, MS_SYNCHRONOUS, 0}, |
| {"verbose", MS_VERBOSE, MS_VERBOSE, 0}, |
| }; |
| |
| static void add_extra_option(struct extra_opts *extra, char *s) |
| { |
| int len = strlen(s); |
| int newlen = extra->used_size + len; |
| |
| if (extra->str) |
| len++; /* +1 for ',' */ |
| |
| if (newlen >= extra->alloc_size) { |
| char *new; |
| |
| new = realloc(extra->str, newlen + 1); /* +1 for NUL */ |
| if (!new) |
| return; |
| |
| extra->str = new; |
| extra->end = extra->str + extra->used_size; |
| extra->alloc_size = newlen; |
| } |
| |
| if (extra->used_size) { |
| *extra->end = ','; |
| extra->end++; |
| } |
| strcpy(extra->end, s); |
| extra->used_size += len; |
| |
| } |
| |
| unsigned long |
| parse_mount_options(char *arg, unsigned long rwflag, struct extra_opts *extra) |
| { |
| char *s; |
| |
| while ((s = strsep(&arg, ",")) != NULL) { |
| char *opt = s; |
| unsigned int i; |
| int res, no = s[0] == 'n' && s[1] == 'o'; |
| |
| if (no) |
| s += 2; |
| |
| for (i = 0, res = 1; i < ARRAY_SIZE(options); i++) { |
| res = strcmp(s, options[i].str); |
| |
| if (res == 0) { |
| rwflag &= ~options[i].rwmask; |
| if (no) |
| rwflag |= options[i].rwnoset; |
| else |
| rwflag |= options[i].rwset; |
| } |
| if (res <= 0) |
| break; |
| } |
| |
| if (res != 0 && s[0]) |
| add_extra_option(extra, opt); |
| } |
| |
| return rwflag; |
| } |