diff options
author | Laurent Bercot <ska-skaware@skarnet.org> | 2014-09-19 15:01:58 +0000 |
---|---|---|
committer | Laurent Bercot <ska-skaware@skarnet.org> | 2014-09-19 15:01:58 +0000 |
commit | 54b6467013bfbdb3ee606961c02fbff1271ca582 (patch) | |
tree | e3969743e61542979f12fca01017e67c4480eca8 /src/minutils/s6-mount.c | |
download | s6-linux-utils-54b6467013bfbdb3ee606961c02fbff1271ca582.tar.xz |
initial commit
Diffstat (limited to 'src/minutils/s6-mount.c')
-rw-r--r-- | src/minutils/s6-mount.c | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/src/minutils/s6-mount.c b/src/minutils/s6-mount.c new file mode 100644 index 0000000..6970c05 --- /dev/null +++ b/src/minutils/s6-mount.c @@ -0,0 +1,126 @@ +/* ISC license. */ + +#include <sys/mount.h> +#include <mntent.h> +#include <stdio.h> +#include <skalibs/sgetopt.h> +#include <skalibs/bytestr.h> +#include <skalibs/strerr2.h> +#include <skalibs/stralloc.h> +#include <skalibs/djbunix.h> +#include "mount-constants.h" + +#define USAGE "s6-mount -a [ -z fstab ] | s6-mount [ -t type ] [ -o option[,option...] ]... device mountpoint" +#define BUFSIZE 4096 + +#define SWITCH(opt) do +#define HCTIWS(opt) while(0) ; +#define CASE(s) if (!str_diffn(opt, (s), str_len(s))) + +static void scanopt (stralloc *data, unsigned long *flags, char const *opt) +{ + for (;;) + { + register unsigned int n = str_chr(opt, ',') ; + + SWITCH(opt) + { + CASE("defaults") { *flags = MS_MGC_VAL ; break ; } + CASE("ro") { *flags |= MS_RDONLY ; break ; } + CASE("rw") { *flags &= ~MS_RDONLY ; break ; } + CASE("remount") { *flags |= MS_REMOUNT ; break ; } + CASE("sync") { *flags |= MS_SYNCHRONOUS ; break ; } + CASE("async") { *flags &= ~MS_SYNCHRONOUS ; break ; } + CASE("nodev") { *flags |= MS_NODEV ; break ; } + CASE("dev") { *flags &= ~MS_NODEV ; break ; } + CASE("noexec") { *flags |= MS_NOEXEC ; break ; } + CASE("exec") { *flags &= ~MS_NOEXEC ; break ; } + CASE("nosuid") { *flags |= MS_NOSUID ; break ; } + CASE("suid") { *flags &= ~MS_NOSUID ; break ; } + CASE("noatime") { *flags |= MS_NOATIME ; break ; } + CASE("atime") { *flags &= ~MS_NOATIME ; break ; } + CASE("nodiratime") { *flags |= MS_NODIRATIME ; break ; } + CASE("diratime") { *flags &= ~MS_NODIRATIME ; break ; } + CASE("bind") { *flags |= MS_BIND ; break ; } + CASE("nobind") { *flags &= ~MS_BIND ; break ; } + CASE("move") { *flags |= MS_MOVE ; break ; } + CASE("nomove") { *flags &= ~MS_MOVE ; break ; } + + if ((data->s && data->len && !stralloc_catb(data, ",", 1)) || !stralloc_catb(data, opt, n)) + strerr_diefu1sys(111, "build data string") ; + } + HCTIWS(opt) + + opt += n ; + if (!*opt) break ; + if (*opt != ',') strerr_dief1x(100, "unrecognized option") ; + opt++ ; + } +} + +static int mountall (char const *fstab) +{ + struct mntent *d ; + int e = 0 ; + FILE *yuck = setmntent(fstab, "r") ; + if (!yuck) strerr_diefu2sys(111, "open ", fstab) ; + while ((d = getmntent(yuck))) + { + unsigned long flags = MS_MGC_VAL ; + stralloc data = STRALLOC_ZERO ; + scanopt(&data, &flags, d->mnt_opts) ; + if (!stralloc_0(&data)) + strerr_diefu1sys(111, "build data string") ; +#ifdef DEBUG + strerr_warni4x("mounting ", d->mnt_fsname, " on ", d->mnt_dir) ; +#endif + if (mount(d->mnt_fsname, d->mnt_dir, d->mnt_type, flags, data.s) == -1) + { + e++ ; + strerr_warnwu4sys("mount ", d->mnt_fsname, " on ", d->mnt_dir) ; + } + stralloc_free(&data) ; + } + endmntent(yuck) ; + return e ; +} + +int main (int argc, char const *const *argv) +{ + stralloc data = STRALLOC_ZERO ; + unsigned long flags = MS_MGC_VAL ; + char const *fstype = "none" ; + char const *fstab = "/etc/fstab" ; + PROG = "s6-mount" ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "z:arwt:o:", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'z' : fstab = l.arg ; break ; + case 'a' : return mountall(fstab) ; + case 't' : fstype = l.arg ; break ; + case 'w' : scanopt(&data, &flags, "rw") ; break ; + case 'r' : scanopt(&data, &flags, "ro") ; break ; + case 'o' : scanopt(&data, &flags, l.arg) ; break ; + default : strerr_dieusage(100, USAGE) ; + } + } + argc -= l.ind ; argv += l.ind ; + } + if (!argc) + { + int fd = open_readb("/proc/mounts") ; + if (fd < 0) strerr_diefu2sys(111, "read ", "/proc/mounts") ; + if (fd_cat(fd, 1) < 0) strerr_diefu2sys(111, "fd_cat ", "/proc/mounts") ; + fd_close(fd) ; + } + else if (argc == 1) strerr_dieusage(100, USAGE) ; + else if (!stralloc_0(&data)) strerr_diefu1sys(111, "build data string") ; + else if (mount(argv[0], argv[1], fstype, flags, data.s) == -1) + strerr_diefu4sys(111, "mount ", argv[0], " on ", argv[1]) ; + return 0 ; +} |