diff options
| author | Laurent Bercot <ska-skaware@skarnet.org> | 2025-11-28 20:04:18 +0000 |
|---|---|---|
| committer | Laurent Bercot <ska-skaware@skarnet.org> | 2025-11-28 20:04:18 +0000 |
| commit | ba12e68e0561fe2e00ff2a8da73c809e5e4c6e2d (patch) | |
| tree | c615772818768939c82973a1a433e78f67b21747 /src | |
| parent | d203fe67af73ef0a52a248b8b85839359682823b (diff) | |
| download | s6-linux-utils-ba12e68e0561fe2e00ff2a8da73c809e5e4c6e2d.tar.gz | |
Add fstab2s6rc (untested), prepare for 2.6.4.0
Diffstat (limited to 'src')
| -rw-r--r-- | src/s6-linux-utils/deps-exe/fstab2s6rc | 1 | ||||
| -rw-r--r-- | src/s6-linux-utils/fstab2s6rc.c | 647 | ||||
| -rw-r--r-- | src/s6-linux-utils/s6-mount.c | 18 | ||||
| -rw-r--r-- | src/s6-linux-utils/s6-swapoff.c | 22 | ||||
| -rw-r--r-- | src/s6-linux-utils/s6-swapon.c | 23 | ||||
| -rw-r--r-- | src/s6-linux-utils/s6-umount.c | 23 |
6 files changed, 705 insertions, 29 deletions
diff --git a/src/s6-linux-utils/deps-exe/fstab2s6rc b/src/s6-linux-utils/deps-exe/fstab2s6rc new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/s6-linux-utils/deps-exe/fstab2s6rc @@ -0,0 +1 @@ +-lskarnet diff --git a/src/s6-linux-utils/fstab2s6rc.c b/src/s6-linux-utils/fstab2s6rc.c new file mode 100644 index 0000000..e7fa3b8 --- /dev/null +++ b/src/s6-linux-utils/fstab2s6rc.c @@ -0,0 +1,647 @@ +/* ISC license. */ + +#include <skalibs/nonposix.h> + +#include <string.h> +#include <errno.h> +#include <mntent.h> +#include <unistd.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> + +#include <skalibs/types.h> +#include <skalibs/bytestr.h> +#include <skalibs/envexec.h> +#include <skalibs/stat.h> +#include <skalibs/buffer.h> +#include <skalibs/stralloc.h> +#include <skalibs/genalloc.h> +#include <skalibs/djbunix.h> +#include <skalibs/skamisc.h> + +#include <execline/config.h> + +#include <s6-linux-utils/config.h> + +#define USAGE "fstab2s6rc [ -A | -a ] [ -U | -u ] [ -E | -e ] [ -F fstab ] [ -m mode ] [ -B bundle ] [ -d basedep ] dir" +#define dieusage() strerr_dieusage(100, USAGE) +#define dienomem() do { strerr_warnfu1sys("stralloc_catb") ; return 111 ; } while (0) + +enum fstab_golb_e +{ + FSTAB_GOLB_SKIPNOAUTO = 0x01, + FSTAB_GOLB_UUID = 0x02, + FSTAB_GOLB_NOESSENTIAL = 0x04, +} ; + +enum fstab_gola_e +{ + FSTAB_GOLA_FSTAB, + FSTAB_GOLA_MODE, + FSTAB_GOLA_BUNDLE, + FSTAB_GOLA_BASEDEP, + FSTAB_GOLA_N +} ; + +enum fstab_flags_e +{ + FSTAB_FLAG_NOFAIL = 0x01, + FSTAB_FLAG_NOAUTO = 0x02, + FSTAB_FLAG_ISUUID = 0x04, + FSTAB_FLAG_ISLABEL = 0x08, +} ; + +typedef struct fstabent_s fstabent, *fstabent_ref ; +struct fstabent_s +{ + size_t device ; + size_t mountpoint ; + size_t qmountpoint ; + size_t type ; + size_t opts ; + size_t servicename ; + uint32_t flags ; + genalloc sublist ; /* fstabent */ +} ; +#define FSTABENT_ZERO { .submounts = GENALLOC_ZERO } + +typedef struct swapent_s swapent, *swapent_ref ; +struct swapent_s +{ + size_t device ; + size_t opts ; + size_t servicename ; + uint32_t flags ; +} ; + + +static int process_device (stralloc *sa, char const *dev, uint32_t *flags) +{ + if (str_start(dev, "UUID=")) + { + if (!stralloc_cats(sa, dev + 5) || !stralloc_0(sa)) dienomem() ; + *flags |= FSTAB_FLAG_ISUUID ; + } + else if (str_start(dev, "LABEL=")) + { + if (!string_quotes(sa, dev + 6) || !stralloc_0(sa)) dienomem() ; + *flags |= FSTAB_FLAG_ISLABEL ; + } + else if (!string_quotes(sa, dev) || !stralloc_0(sa)) dienomem() ; + return 0 ; +} + +static int process_opts (stralloc *sa, char *opts, uint32_t *flags) +{ + static char const *const ignore[] = + { + "comment", + "defaults", + "owner", + "user", + } ; + size_t sabase = sa->len ; + size_t len = strlen(opts) ; + size_t pos = 0 ; + while (pos < len) + { + size_t i = str_chr(opts + pos, ',') ; + opts[pos + i] = 0 ; + if (!strncmp(opts + pos, "x-", 2)) ; + else if (!strcmp(opts + pos, "nofail")) *flags |= FSTAB_FLAG_NOFAIL ; + else if (!strcmp(opts + pos, "noauto")) *flags |= FSTAB_FLAG_NOAUTO ; + else if (bsearch(opts + pos, ignore, sizeof(ignore)/sizeof(char const *), sizeof(char const *), &str_bcmp)) ; + else + if (!stralloc_cats(sa, opts + pos) || !stralloc_catb(sa, ",", 1)) dienomem() ; + pos += i+1 ; + } + if (sa->len > sabase) sa->s[sa->len - 1] = 0 ; + return 0 ; +} + +static int process_servicename (stralloc *sa, char const *name, int isswap) +{ + size_t len = strlen(name) + 1 ; + size_t i = name[0] == '/' ? 1 : 0 ; + if (!stralloc_cats(sa, isswap ? "swap-" : "mount-")) dienomem() ; + while (i < len) + if (!stralloc_catb(sa, name[i] == '/' ? ":" : name + i, 1)) dienomem() ; + return 0 ; +} + +static inline int add_swap (struct mntent *mnt, genalloc *ga, stralloc *sa, uint64_t options) +{ + swapent f = { .flags = 0 } ; + int e ; + f.device = sa->len ; + if (options & FSTAB_GOLB_UUID) + { + e = process_device(sa, mnt->mnt_fsname, &f.flags) ; + if (e) return e ; + } + else + if (!string_quotes(sa, mnt->mnt_fsname) || !stralloc_0(sa)) dienomem() ; + f.opts = sa->len ; + e = process_opts(sa, mnt->mnt_opts, &f.flags) ; + if (e) return e ; + f.servicename = sa->len ; + e = process_servicename(sa, mnt->mnt_fsname, 1) ; + if (e) return e ; + if (genalloc_catb(swapent, ga, &f, 1)) dienomem() ; + return 0 ; +} + +static genalloc *findpoint (char const *dir, genalloc *ga, char const *s) +{ + size_t n = genalloc_len(fstabent, ga) ; + fstabent *t = genalloc_s(fstabent, ga) ; + for (unsigned int i = 0 ; i < n ; i++) + { + size_t fslen = strlen(s + t[i].mountpoint) ; + if (!strncmp(dir, s + t[i].mountpoint, fslen)) + { + if (!dir[fslen]) + { + strerr_warnfu2x("duplicate mount point: ", dir) ; + return 0 ; + } + if (dir[fslen] == '/') + return findpoint(dir, &t[i].sublist, s) ; + } + } + return ga ; +} + +static inline int add_fs (struct mntent *mnt, genalloc *ga, stralloc *sa, uint64_t options) +{ + fstabent f = { .flags = 0 } ; + int e ; + ga = findpoint(mnt->mnt_dir, ga, sa->s) ; + if (!ga) return 1 ; + + f.device = sa->len ; + if (options & FSTAB_GOLB_UUID) + { + e = process_device(sa, mnt->mnt_fsname, &f.flags) ; + if (e) return e ; + } + else + if (!string_quotes(sa, mnt->mnt_fsname) || !stralloc_0(sa)) dienomem() ; + f.mountpoint = sa->len ; + if (!stralloc_cats(sa, mnt->mnt_dir) || !stralloc_0(sa)) dienomem() ; + f.qmountpoint = sa->len ; + if (!string_quotes(sa, mnt->mnt_dir) || !stralloc_0(sa)) dienomem() ; + f.type = sa->len ; + if (!stralloc_cats(sa, mnt->mnt_type) || !stralloc_0(sa)) dienomem() ; + f.opts = sa->len ; + e = process_opts(sa, mnt->mnt_opts, &f.flags) ; + if (e) return e ; + f.servicename = sa->len ; + e = process_servicename(sa, mnt->mnt_dir, 0) ; + if (e) return e ; + if (!genalloc_catb(fstabent, ga, &f, 1)) dienomem() ; + return 0 ; +} + +static int write_dependencies (char const *dir, char const *myname, fstabent const *tab, size_t n, char const *s) +{ + size_t dirlen = strlen(dir) ; + size_t mylen = myname ? strlen(myname) : 0 ; + int e ; + + for (size_t i = 0 ; i < n ; i++) + { + if (myname) + { + size_t slen = strlen(s + tab[i].servicename) ; + char fn[dirlen + 18 + slen + mylen] ; + memcpy(fn, dir, dirlen) ; + fn[dirlen] = '/' ; + memcpy(fn + dirlen + 1, s + tab[i].servicename, slen) ; + memcpy(fn + dirlen + 1 + slen, "/dependencies.d/", 16) ; + memcpy(fn + dirlen + slen + 17, myname, mylen + 1) ; + if (!openwritenclose_unsafe5(fn, "", 0, 0, 0)) { strerr_warnfu2sys("touch ", fn) ; return 111 ; } + } + e = write_dependencies(dir, s + tab[i].servicename, genalloc_s(fstabent, &tab[i].sublist), genalloc_len(fstabent, &tab[i].sublist), s) ; + if (e) return e ; + } + return 0 ; +} + +static inline int write_fses (char const *dir, fstabent const *tab, size_t n, char const *s, uint64_t options, char const *bundle, char const *basedep) +{ + char buf[4096] ; + buffer b ; + int fd ; + size_t dirlen = strlen(dir) ; + for (size_t i = 0 ; i < n ; i++) + { + mode_t m = umask(0) ; + size_t slen = strlen(s + tab[i].servicename) ; + char fn[dirlen + slen + 19] ; + memcpy(fn, dir, dirlen) ; + fn[dirlen] = '/' ; + memcpy(fn + dirlen + 1, s + tab[i].servicename, slen + 1) ; + if (mkdir(fn, 0755) == -1) { strerr_warnfu2sys("mkdir ", fn) ; return 111 ; } + memcpy(fn + dirlen + 1 + slen, "/dependencies.d", 16) ; + if (mkdir(fn, 0755) == -1) { strerr_warnfu2sys("mkdir ", fn) ; return 111 ; } + umask(m) ; + + memcpy(fn + dirlen + 2 + slen, "type", 5) ; + if (!openwritenclose_unsafe5(fn, "oneshot\n", 8, 0, 0)) goto err1n ; + + if (!(tab[i].flags & FSTAB_FLAG_NOAUTO)) + { + memcpy(fn + dirlen + 2 + slen, "flag-", 5) ; + memcpy(fn + dirlen + 7 + slen, options & FSTAB_GOLB_NOESSENTIAL ? "essential" : "recommended", options & FSTAB_GOLB_NOESSENTIAL ? 10 : 12) ; + if (!openwritenclose_unsafe5(fn, "", 0, 0, 0)) goto err1n ; + } + + memcpy(fn + dirlen + 2 + slen, "down", 5) ; + if (tab[i].flags & FSTAB_FLAG_NOAUTO || options & FSTAB_GOLB_NOESSENTIAL) + { + fd = open_create(fn) ; + if (fd == -1) { strerr_warnfu3sys("open ", fn, " for writing") ; return 111 ; } + buffer_init(&b, &buffer_write, fd, buf, 4096) ; + if (buffer_puts(&b, EXECLINE_EXTBINPREFIX "foreground { ") < 0) goto err1 ; + if (options & FSTAB_GOLB_UUID) + { + if (buffer_puts(&b, "umount -l -- ") < 0) goto err1 ; + } + else + { + if (buffer_puts(&b, S6_LINUX_UTILS_BINPREFIX "s6-umount -- ") < 0) goto err1 ; + } + if (buffer_puts(&b, s + tab[i].qmountpoint) < 0 + || buffer_puts(&b, " }\n" EXECLINE_EXTBINPREFIX "exit 0") < 0 + || buffer_putflush(&b, "\n", 1) < 0) goto err1 ; + fd_close(fd) ; + goto ok1 ; + err1: + fd_close(fd) ; + err1n: + strerr_warnfu2sys("write to ", fn) ; + return 111 ; + ok1: + } + else if (!openwritenclose_unsafe5(fn, "", 0, 0, 0)) goto err2n ; + + memcpy(fn + dirlen + 2 + slen, "up", 3) ; + fd = open_create(fn) ; + if (fd == -1) { strerr_warnfu3sys("open ", fn, " for writing") ; return 111 ; } + buffer_init(&b, &buffer_write, fd, buf, 4096) ; + if (tab[i].flags & FSTAB_FLAG_NOFAIL) + if (buffer_puts(&b, EXECLINE_EXTBINPREFIX "foreground { ") < 0) goto err2 ; + if (options & FSTAB_GOLB_UUID) + { + if (buffer_puts(&b, "mount") < 0) goto err2 ; + if (tab[i].flags & FSTAB_FLAG_ISUUID) + { + if (buffer_puts(&b, " -U ") < 0 + || buffer_puts(&b, s + tab[i].device) < 0) goto err2 ; + } + else if (tab[i].flags & FSTAB_FLAG_ISLABEL) + { + if (buffer_puts(&b, " -L ") < 0 + || buffer_puts(&b, s + tab[i].device) < 0) goto err2 ; + } + } + else + { + if (buffer_puts(&b, S6_LINUX_UTILS_BINPREFIX "s6-mount") < 0) goto err2 ; + } + if (buffer_puts(&b, " -t ") < 0 + || buffer_puts(&b, s + tab[i].type) < 0) goto err2 ; + if (s[tab[i].opts]) + { + if (buffer_puts(&b, " -o ") < 0 + || buffer_puts(&b, s + tab[i].opts) < 0) goto err2 ; + } + if (buffer_put(&b, " -- ", 1) < 0) goto err2 ; + if (!(options & FSTAB_GOLB_UUID && (tab[i].flags & (FSTAB_FLAG_ISUUID | FSTAB_FLAG_ISLABEL)))) + { + if (buffer_puts(&b, s + tab[i].device) < 0 + || buffer_put(&b, " ", 1) < 0) goto err2 ; + } + if (buffer_puts(&b, s + tab[i].qmountpoint) < 0) goto err2 ; + if (tab[i].flags & FSTAB_FLAG_NOFAIL) + if (buffer_puts(&b, " }\n" EXECLINE_EXTBINPREFIX "exit 0") < 0) goto err2 ; + if (buffer_putflush(&b, "\n", 1) < 0) goto err2 ; + fd_close(fd) ; + goto ok2 ; + err2: + fd_close(fd) ; + err2n: + strerr_warnfu2sys("write to ", fn) ; + return 111 ; + ok2: + } + + if (bundle) + { + mode_t m = umask(0) ; + size_t blen = strlen(bundle) ; + char bdir[dirlen + blen + 20] ; + memcpy(bdir, dir, dirlen) ; + memcpy(bdir + dirlen, "-mounts", 7) ; + bdir[dirlen + 7] = '/' ; + memcpy(bdir + dirlen + 7, bundle, blen + 1) ; + if (mkdir(bdir, 0755) == -1) { strerr_warnfu2sys("mkdir ", bdir) ; return 111 ; } + memcpy(bdir + dirlen + blen + 8, "/type", 6) ; + if (!openwritenclose_unsafe5(bdir, "bundle\n", 7, 0, 0)) { strerr_warnfu2sys("write to ", bdir) ; return 111 ; } + memcpy(bdir + dirlen + blen + 8, "contents.d", 11) ; + if (mkdir(bdir, 0755) == -1) { strerr_warnfu2sys("mkdir ", bdir) ; return 111 ; } + umask(m) ; + bdir[dirlen + blen + 19] = '/' ; + for (size_t i = 0 ; i < n ; i++) if (!(tab[i].flags & FSTAB_FLAG_NOAUTO)) + { + size_t slen = strlen(s + tab[i].servicename) ; + char sfn[dirlen + blen + 21 + slen] ; + memcpy(sfn, bdir, dirlen + blen + 20) ; + memcpy(sfn + dirlen + blen + 20, s + tab[i].servicename, slen + 1) ; + if (!openwritenclose_unsafe5(sfn, "", 0, 0, 0)) { strerr_warnfu2sys("touch ", sfn) ; return 111 ; } + } + } + + return write_dependencies(dir, basedep, tab, n, s) ; +} + +static inline int write_swaps (char const *dir, swapent const *tab, size_t n, char const *s, uint64_t options, char const *bundle, char const *basedep) +{ + char buf[4096] ; + buffer b ; + int fd ; + size_t dirlen = strlen(dir) ; + size_t bdlen = basedep ? strlen(basedep) : 0 ; + for (size_t i = 0 ; i < n ; i++) + { + mode_t m = umask(0) ; + size_t slen = strlen(s + tab[i].servicename) ; + char fn[dirlen + slen + 19 + bdlen] ; + memcpy(fn, dir, dirlen) ; + fn[dirlen] = '/' ; + memcpy(fn + dirlen + 1, s + tab[i].servicename, slen + 1) ; + if (mkdir(fn, 0755) == -1) { strerr_warnfu2sys("mkdir ", fn) ; return 111 ; } + memcpy(fn + dirlen + 1 + slen, "/dependencies.d", 16) ; + if (mkdir(fn, 0755) == -1) { strerr_warnfu2sys("mkdir ", fn) ; return 111 ; } + umask(m) ; + + if (basedep) + { + fn[dirlen + slen + 16] = '/' ; + memcpy(fn + dirlen + slen + 17, basedep, bdlen + 1) ; + if (!openwritenclose_unsafe5(fn, "", 0, 0, 0)) goto err1n ; + } + + memcpy(fn + dirlen + 2 + slen, "type", 5) ; + if (!openwritenclose_unsafe5(fn, "oneshot\n", 8, 0, 0)) goto err1n ; + + if (!(tab[i].flags & FSTAB_FLAG_NOAUTO)) + { + memcpy(fn + dirlen + 2 + slen, "flag-", 5) ; + memcpy(fn + dirlen + 7 + slen, options & FSTAB_GOLB_NOESSENTIAL ? "essential" : "recommended", options & FSTAB_GOLB_NOESSENTIAL ? 10 : 12) ; + if (!openwritenclose_unsafe5(fn, "", 0, 0, 0)) goto err1n ; + } + + memcpy(fn + dirlen + 2 + slen, "down", 5) ; + if (tab[i].flags & FSTAB_FLAG_NOAUTO || options & FSTAB_GOLB_NOESSENTIAL) + { + fd = open_create(fn) ; + if (fd == -1) { strerr_warnfu3sys("open ", fn, " for writing") ; return 111 ; } + buffer_init(&b, &buffer_write, fd, buf, 4096) ; + if (buffer_puts(&b, EXECLINE_EXTBINPREFIX "foreground { ") < 0) goto err1 ; + if (options & FSTAB_GOLB_UUID) + { + if (buffer_puts(&b, "swapoff ") < 0) goto err1 ; + if (tab[i].flags & FSTAB_FLAG_ISUUID) + { + if (buffer_puts(&b, "-U ") < 0) goto err1 ; + } + else if (tab[i].flags & FSTAB_FLAG_ISLABEL) + { + if (buffer_puts(&b, "-L ") < 0) goto err1 ; + } + } + else + { + if (buffer_puts(&b, S6_LINUX_UTILS_BINPREFIX "s6-swapoff -- ") < 0) goto err1 ; + } + if (buffer_puts(&b, s + tab[i].device) < 0 + || buffer_puts(&b, " }\n" EXECLINE_EXTBINPREFIX "exit 0") < 0 + || buffer_putflush(&b, "\n", 1) < 0) goto err1 ; + fd_close(fd) ; + goto ok1 ; + err1: + fd_close(fd) ; + err1n: + strerr_warnfu2sys("write to ", fn) ; + return 111 ; + ok1: + } + else if (!openwritenclose_unsafe5(fn, "", 0, 0, 0)) goto err2n ; + + memcpy(fn + dirlen + 2 + slen, "up", 3) ; + fd = open_create(fn) ; + if (fd == -1) { strerr_warnfu3sys("open ", fn, " for writing") ; return 111 ; } + buffer_init(&b, &buffer_write, fd, buf, 4096) ; + if (tab[i].flags & FSTAB_FLAG_NOFAIL) + if (buffer_puts(&b, EXECLINE_EXTBINPREFIX "foreground { ") < 0) goto err2 ; + if (options & FSTAB_GOLB_UUID) + { + if (buffer_puts(&b, "swapon") < 0) goto err2 ; + if (tab[i].flags & FSTAB_FLAG_ISUUID) + { + if (buffer_puts(&b, " -U ") < 0 + || buffer_puts(&b, s + tab[i].device) < 0) goto err2 ; + } + else if (tab[i].flags & FSTAB_FLAG_ISLABEL) + { + if (buffer_puts(&b, " -L ") < 0 + || buffer_puts(&b, s + tab[i].device) < 0) goto err2 ; + } + if (s[tab[i].opts]) + { + if (buffer_puts(&b, " -o ") < 0 + || buffer_puts(&b, s + tab[i].opts) < 0) goto err2 ; + } + } + else + { + if (buffer_puts(&b, S6_LINUX_UTILS_BINPREFIX "s6-swapon --") < 0) goto err2 ; + } + if (buffer_put(&b, " ", 1) < 0 + || buffer_puts(&b, s + tab[i].device) < 0) goto err2 ; + if (tab[i].flags & FSTAB_FLAG_NOFAIL) + if (buffer_puts(&b, " }\n" EXECLINE_EXTBINPREFIX "exit 0") < 0) goto err2 ; + if (buffer_putflush(&b, "\n", 1) < 0) goto err2 ; + fd_close(fd) ; + goto ok2 ; + err2: + fd_close(fd) ; + err2n: + strerr_warnfu2sys("write to ", fn) ; + return 111 ; + ok2: + } + + if (bundle) + { + size_t blen = strlen(bundle) ; + char bdir[dirlen + blen + 19] ; + memcpy(bdir, dir, dirlen) ; + memcpy(bdir + dirlen, "-swaps", 6) ; + bdir[dirlen + 6] = '/' ; + memcpy(bdir + dirlen + 7, bundle, blen + 1) ; + if (mkdir(bdir, 0755) == -1) { strerr_warnfu2sys("mkdir ", bdir) ; return 111 ; } + memcpy(bdir + dirlen + blen + 7, "/type", 6) ; + if (!openwritenclose_unsafe5(bdir, "bundle\n", 7, 0, 0)) { strerr_warnfu2sys("write to ", bdir) ; return 111 ; } + memcpy(bdir + dirlen + blen + 7, "contents.d", 11) ; + if (mkdir(bdir, 0755) == -1) { strerr_warnfu2sys("mkdir ", bdir) ; return 111 ; } + bdir[dirlen + blen + 18] = '/' ; + for (size_t i = 0 ; i < n ; i++) if (!(tab[i].flags & FSTAB_FLAG_NOAUTO)) + { + size_t slen = strlen(s + tab[i].servicename) ; + char sfn[dirlen + blen + 20 + slen] ; + memcpy(sfn, bdir, dirlen + blen + 19) ; + memcpy(sfn + dirlen + blen + 19, s + tab[i].servicename, slen + 1) ; + if (!openwritenclose_unsafe5(sfn, "", 0, 0, 0)) { strerr_warnfu2sys("touch ", sfn) ; return 111 ; } + } + } + return 0 ; +} + +static inline int write_bundle (char const *dir, char const *bundle) +{ + mode_t m = umask(0) ; + size_t dirlen = strlen(dir) ; + size_t blen = strlen(bundle) ; + char bdir[dirlen + 22 + 2 * blen] ; + memcpy(bdir, dir, dirlen) ; + bdir[dirlen] = '/' ; + memcpy(bdir + dirlen + 1, bundle, blen + 1) ; + if (mkdir(bdir, 0755) == -1) { strerr_warnfu2sys("mkdir ", bdir) ; return 111 ; } + memcpy(bdir + dirlen + blen + 1, "/type", 6) ; + if (!openwritenclose_unsafe5(bdir, "bundle\n", 7, 0, 0)) { strerr_warnfu2sys("write to ", bdir) ; return 111 ; } + memcpy(bdir + dirlen + blen + 2, "contents.d", 11) ; + if (mkdir(bdir, 0755) == -1) { strerr_warnfu2sys("mkdir ", bdir) ; return 111 ; } + umask(m) ; + bdir[dirlen + blen + 13] = '/' ; + memcpy(bdir + dirlen + blen + 14, bundle, blen) ; + memcpy(bdir + dirlen + 14 + 2 * blen, "-swaps", 7) ; + if (!openwritenclose_unsafe5(bdir, "", 0, 0, 0)) { strerr_warnfu2sys("touch ", bdir) ; return 111 ; } + memcpy(bdir + dirlen + 15 + 2 * blen, "mounts", 7) ; + if (!openwritenclose_unsafe5(bdir, "", 0, 0, 0)) { strerr_warnfu2sys("touch ", bdir) ; return 111 ; } + return 0 ; +} + +static inline int doit (char const *fstab, char const *dir, uint64_t options, char const *bundle, char const *basedep, stralloc *sa) +{ + genalloc fses = GENALLOC_ZERO ; /* fstabent */ + genalloc swaps = GENALLOC_ZERO ; /* swapent */ + int e ; + + FILE *in = setmntent(fstab, "re") ; + for (;;) + { + struct mntent *mnt ; + errno = 0 ; + mnt = getmntent(in) ; + if (!mnt) break ; + if (options & FSTAB_GOLB_SKIPNOAUTO && hasmntopt(mnt, "noauto")) continue ; + if (strcmp(mnt->mnt_type, "swap")) + e = add_fs(mnt, &fses, sa, options) ; + else + e = add_swap(mnt, &swaps, sa, options) ; + if (e) + { + endmntent(in) ; + return e ; + } + } + if (errno) + { + strerr_warnfu2sys("getmntent ", fstab) ; + endmntent(in) ; + return e ; + } + endmntent(in) ; + + e = write_fses(dir, genalloc_s(fstabent, &fses), genalloc_len(fstabent, &fses), sa->s, options, bundle, basedep) ; + if (e) return e ; + e = write_swaps(dir, genalloc_s(swapent, &swaps), genalloc_len(swapent, &swaps), sa->s, options, bundle, basedep) ; + if (e) return e ; + if (bundle) + { + e = write_bundle(dir, bundle) ; + if (e) return e ; + } + + return 0 ; +} + +int main (int argc, char const *const *argv) +{ + static gol_bool const rgolb[] = + { + { .so = 'A', .lo = "include-noauto", .clear = FSTAB_GOLB_SKIPNOAUTO, .set = 0 }, + { .so = 'a', .lo = "exclude-noauto", .clear = 0, .set = FSTAB_GOLB_SKIPNOAUTO }, + { .so = 'U', .lo = "without-uuid", .clear = FSTAB_GOLB_UUID, .set = 0 }, + { .so = 'u', .lo = "with-uuid", .clear = 0, .set = FSTAB_GOLB_UUID }, + { .so = 'E', .lo = "essential", .clear = FSTAB_GOLB_NOESSENTIAL, .set = 0 }, + { .so = 'e', .lo = "not-essential", .clear = 0, .set = FSTAB_GOLB_NOESSENTIAL }, + } ; + static gol_arg const rgola[] = + { + { .so = 'F', .lo = "fstab", .i = FSTAB_GOLA_FSTAB }, + { .so = 'm', .lo = "mode", .i = FSTAB_GOLA_MODE }, + { .so = 'B', .lo = "bundle", .i = FSTAB_GOLA_BUNDLE }, + { .so = 'd', .lo = "base-dependency", .i = FSTAB_GOLA_BASEDEP }, + } ; + stralloc storage = STRALLOC_ZERO ; + uint64_t wgolb = 0 ; + unsigned int mode = 0755 ; + unsigned int golc ; + char const *wgola[FSTAB_GOLA_N] = { 0 } ; + + PROG = "fstab2s6rc" ; + wgola[FSTAB_GOLA_FSTAB] = "/etc/fstab" ; + golc = GOL_main(argc, argv, rgolb, rgola, &wgolb, wgola) ; + argc -= golc ; argv += golc ; + if (!argc) dieusage() ; + if (wgola[FSTAB_GOLA_MODE] && !uint0_oscan(wgola[FSTAB_GOLA_MODE], &mode)) dieusage() ; + + if (access(argv[0], F_OK) == -1) + { + if (errno != ENOENT) strerr_diefu2sys(111, "access ", argv[0]) ; + } + else strerr_dief2x(111, argv[0], "already exists") ; + + { + mode_t m = umask(0) ; + int e ; + size_t dirlen = strlen(argv[0]) ; + char dir[dirlen + 8] ; + memcpy(dir, argv[0], dirlen) ; + memcpy(dir + dirlen, ":XXXXXX", 8) ; + if (!mkdtemp(dir)) strerr_diefu2sys(111, "mkdtemp ", dir) ; + umask(m) ; + e = doit(wgola[FSTAB_GOLA_FSTAB], dir, wgolb, wgola[FSTAB_GOLA_BUNDLE], wgola[FSTAB_GOLA_BASEDEP], &storage) ; + if (e) + { + rm_rf(dir) ; + _exit(e) ; + } + if (chmod(dir, mode) == -1) + { + rm_rf(dir) ; + strerr_diefu2sys(111, "chmod ", dir) ; + } + if (rename(dir, argv[0]) == -1) + { + rm_rf(dir) ; + strerr_diefu4sys(111, "rename ", dir, " to ", argv[0]) ; + } + } + return 0 ; +} diff --git a/src/s6-linux-utils/s6-mount.c b/src/s6-linux-utils/s6-mount.c index 997ef33..4d20424 100644 --- a/src/s6-linux-utils/s6-mount.c +++ b/src/s6-linux-utils/s6-mount.c @@ -15,7 +15,7 @@ #include "mount-constants.h" -#define USAGE "s6-mount -a [ -z fstab ] | s6-mount [ -n ] [ -t type ] [ -o option[,option...] ]... device mountpoint" +#define USAGE "s6-mount [ -a ] [ -z fstab ] | s6-mount [ -n ] [ -t type ] [ -o option[,option...] ]... device mountpoint" #define dienomem() strerr_diefu1sys(111, "stralloc_catb") struct mount_flag_modif_s @@ -100,25 +100,29 @@ static void mount_scanopt (stralloc *data, unsigned long *flags, char const *s) static int mountall (char const *fstab) { - struct mntent *d ; int e = 0 ; + stralloc data = STRALLOC_ZERO ; FILE *yuck = setmntent(fstab, "r") ; if (!yuck) strerr_diefu2sys(111, "open ", fstab) ; - while ((d = getmntent(yuck))) + for (;;) { unsigned long flags = 0 ; - stralloc data = STRALLOC_ZERO ; + struct mntent *d ; + errno = 0 ; + d = getmntent(yuck) ; + if (!d) break ; mount_scanopt(&data, &flags, d->mnt_opts) ; - if (!stralloc_0(&data)) - strerr_diefu1sys(111, "build data string") ; + if (!stralloc_0(&data)) strerr_diefu1sys(111, "build data string") ; 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) ; + data.len = 0 ; } + if (errno) strerr_diefu2sys(111, "getmntent on ", fstab) ; endmntent(yuck) ; + // stralloc_free(&data) ; return e ; } diff --git a/src/s6-linux-utils/s6-swapoff.c b/src/s6-linux-utils/s6-swapoff.c index 13a2530..905d9e8 100644 --- a/src/s6-linux-utils/s6-swapoff.c +++ b/src/s6-linux-utils/s6-swapoff.c @@ -5,14 +5,15 @@ #include <sys/swap.h> #include <errno.h> +#include <skalibs/uint64.h> #include <skalibs/bytestr.h> #include <skalibs/buffer.h> -#include <skalibs/strerr.h> +#include <skalibs/envexec.h> #include <skalibs/stralloc.h> #include <skalibs/djbunix.h> #include <skalibs/skamisc.h> -#define USAGE "s6-swapoff device <or> s6-swapoff -a" +#define USAGE "s6-swapoff [ -a ] [ device ]" static int swapoffall (void) { @@ -44,10 +45,17 @@ static int swapoffall (void) int main (int argc, char const *const *argv) { + static gol_bool const rgolb[] = + { + { .so = 'a', .lo = "all", .clear = 0, .set = 1 }, + } ; + uint64_t wgolb = 0 ; + unsigned int golc ; PROG = "s6-swapoff" ; - if (argc < 2) strerr_dieusage(100, USAGE) ; - if ((argv[1][0] == '-') && (argv[1][1] == 'a') && !argv[1][2]) - return swapoffall() ; - if (swapoff(argv[1]) == -1) strerr_diefu2sys(111, "swapoff ", argv[1]) ; - return 0 ; + golc = gol_main(argc, argv, rgolb, 1, 0, 0, &wgolb, 0) ; + argc -= golc ; argv += golc ; + if (wgolb & 1) _exit(swapoffall()) ; + if (!argc) strerr_dieusage(100, USAGE) ; + if (swapoff(argv[0]) == -1) strerr_diefu2sys(111, "swapoff ", argv[0]) ; + _exit(0) ; } diff --git a/src/s6-linux-utils/s6-swapon.c b/src/s6-linux-utils/s6-swapon.c index d9166a7..f55f1ce 100644 --- a/src/s6-linux-utils/s6-swapon.c +++ b/src/s6-linux-utils/s6-swapon.c @@ -6,9 +6,10 @@ #include <stdio.h> #include <mntent.h> -#include <skalibs/strerr.h> +#include <skalibs/uint64.h> +#include <skalibs/envexec.h> -#define USAGE "s6-swapon device <or> s6-swapon -a" +#define USAGE "s6-swapon [ -a ] [ device ]" static int swaponall (void) { @@ -28,11 +29,17 @@ static int swaponall (void) int main (int argc, char const *const *argv) { + static gol_bool const rgolb[] = + { + { .so = 'a', .lo = "all", .clear = 0, .set = 1 }, + } ; + uint64_t wgolb = 0 ; + unsigned int golc ; PROG = "s6-swapon" ; - if (argc < 2) strerr_dieusage(100, USAGE) ; - if ((argv[1][0] == '-') && (argv[1][1] == 'a') && !argv[1][2]) - return swaponall() ; - if (swapon(argv[1], 0) == -1) - strerr_diefu2sys(111, "swapon ", argv[1]) ; - return 0 ; + golc = gol_main(argc, argv, rgolb, 1, 0, 0, &wgolb, 0) ; + argc -= golc ; argv += golc ; + if (wgolb & 1) _exit(swaponall()) ; + if (!argc) strerr_dieusage(100, USAGE) ; + if (swapon(argv[0], 0) == -1) strerr_diefu2sys(111, "swapon ", argv[0]) ; + _exit(0) ; } diff --git a/src/s6-linux-utils/s6-umount.c b/src/s6-linux-utils/s6-umount.c index 8a9b918..256ab00 100644 --- a/src/s6-linux-utils/s6-umount.c +++ b/src/s6-linux-utils/s6-umount.c @@ -2,15 +2,17 @@ #include <string.h> #include <sys/mount.h> +#include <unistd.h> +#include <skalibs/uint64.h> #include <skalibs/bytestr.h> #include <skalibs/buffer.h> -#include <skalibs/strerr.h> +#include <skalibs/envexec.h> #include <skalibs/stralloc.h> #include <skalibs/djbunix.h> #include <skalibs/skamisc.h> -#define USAGE "s6-umount mountpoint <or> s6-umount -a" +#define USAGE "s6-umount [ -a ] [ mountpoint ]" #define UMOUNTALL_MAXLINES 512 @@ -58,10 +60,17 @@ static int umountall (void) int main (int argc, char const *const *argv) { + static gol_bool const rgolb[] = + { + { .so = 'a', .lo = "all", .clear = 0, .set = 1 }, + } ; + uint64_t wgolb = 0 ; + unsigned int golc ; PROG = "s6-umount" ; - if (argc < 2) strerr_dieusage(100, USAGE) ; - if ((argv[1][0] == '-') && (argv[1][1] == 'a') && !argv[1][2]) - return umountall() ; - if (umount(argv[1]) == -1) strerr_diefu2sys(111, "umount ", argv[1]) ; - return 0 ; + golc = gol_main(argc, argv, rgolb, 1, 0, 0, &wgolb, 0) ; + argc -= golc ; argv += golc ; + if (wgolb & 1) _exit(umountall()) ; + if (!argc) strerr_dieusage(100, USAGE) ; + if (umount(argv[0]) == -1) strerr_diefu2sys(111, "unmount ", argv[0]) ; + _exit(0) ; } |
