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 | |
| parent | d203fe67af73ef0a52a248b8b85839359682823b (diff) | |
| download | s6-linux-utils-ba12e68e0561fe2e00ff2a8da73c809e5e4c6e2d.tar.gz | |
Add fstab2s6rc (untested), prepare for 2.6.4.0
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | NEWS | 3 | ||||
| -rw-r--r-- | doc/fstab2s6rc.html | 136 | ||||
| -rw-r--r-- | doc/index.html | 7 | ||||
| -rw-r--r-- | doc/upgrade.html | 5 | ||||
| -rw-r--r-- | package/deps-build | 5 | ||||
| -rw-r--r-- | package/deps.mak | 4 | ||||
| -rw-r--r-- | package/info | 2 | ||||
| -rw-r--r-- | package/modes | 1 | ||||
| -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 | ||||
| -rwxr-xr-x | tools/gen-multicall.sh | 12 |
16 files changed, 865 insertions, 45 deletions
@@ -7,6 +7,7 @@ /src/include/s6-linux-utils/config.h /src/multicall/s6-linux-utils.c /s6-linux-utils +/fstab2s6rc /rngseed /s6-chroot /s6-freeramdisk @@ -1,10 +1,11 @@ Changelog for s6-linux-utils. -In 2.6.3.1 +In 2.6.4.0 ---------- - Bugfixes. - Support of shared libraries on MacOS. + - New binary: fstab2s6rc. In 2.6.3.0 diff --git a/doc/fstab2s6rc.html b/doc/fstab2s6rc.html new file mode 100644 index 0000000..388258a --- /dev/null +++ b/doc/fstab2s6rc.html @@ -0,0 +1,136 @@ +<html> + <head> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-linux-utils: the fstab2s6rc program</title> + <meta name="Description" content="s6-linux-utils: the fstab2s6rc program" /> + <meta name="Keywords" content="s6-rc fstab mount umount swapon swapoff swap filesystem boot offline conversion utility" /> + <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6-linux-utils</a><br /> +<a href="//skarnet.org/software/">Software</a><br /> +<a href="//skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>fstab2s6rc</tt> program </h1> + +<p> + fstab2s6rc reads the <tt>/etc/fstab</tt> file, listing the filesystems and swap partitions +to mount at boot time, and builds a set of service definition directories from it, meant to +be fed to <a href="//skarnet.org/s6-rc/s6-rc-compile.html">s6-rc-compile</a>, having the +effect of mounting these partitions when run by <a href="//skarnet.org/s6-rc/s6-rc.html">s6-rc</a>. +</p> + +<p> + This method has several advantages over the classic <tt>mount -a</tt>: +</p> + +<ul> + <li> Parallelization. Dependencies between the mount points are respected: if <tt>/var</tt> +and <tt>/var/log</tt> are mount points in <tt>/etc/fstab</tt>, s6-rc will not attempt to +mount <tt>/var/log</tt> before <tt>/var</tt> is successfully mounted. But apart from this +necessary serialization, s6-rc will performs in parallel as much as it can. </li> + <li> Granularity. <tt>mount -a</tt> in the boot sequence treats all the mounts as one +unit; and although the output of fstab2s6rc can provide a bundle listing all the mounts, +each mount is available as a separate service. </li> +</ul> + +<p> + fstab2s6rc is an <em>offline tool</em>. It does not perform mounts or unmounts itself; +it just converts the data in <tt>/etc/fstab</tt>, which is in a format usable by <tt>mount</tt>, +into a format usable — after compilation — by <a href="//skarnet.org/s6-rc/s6-rc.html">s6-rc</a>. +</p> + +<h2> Interface </h2> + +<pre> + fstab2s6rc [ -A | -a ] [ -U | -u ] [ -E | -e ] [ -F <em>fstab</em> ] [ -m <em>mode</em> ] [ -B <em>bundle</em> ] [ -d <em>basedep</em> ] <em>dir</em> +</pre> + +<ul> + <li> fstab2s6rc creates a directory <em>dir</em> in the filesystem to host all the service definition it will create. +<em>dir/em> must not previously exist. </li> + <li> fstab2s6rc reads the <tt>/etc/fstab</tt> file. For every mount defined +in the file, it creates a subdirectory of <em>dir</em> that is a suitable definition +directory for an s6-rc service performing that mount. </li> + <li> The service is named after the mount point: the service mounting <tt>/var/log</tt> +will be called <tt>mount-var:log</tt> (slashes being replaced with colons, first slash +omitted). </li> + <li> For swap partitions, the partition named is used: the service activating swap on +<tt>/dev/sda2</tt> will be called <tt>swap-dev:sda2</tt>. </li> +</ul> + +<h2> Options </h2> + +<dl> + <dt> -F <em>fstab</em>, --fstab=<em>fstab</em> </dt> + <dd> Read mount point information from file <em>fstab</em> instead of <tt>/etc/fstab</tt>. </dd> + + <dt> -m <em>mode</em>, --mode=<em>mode</em> </dt> + <dd> Create <em>dir</em> with permissions <em>mode</em>. <em>mode</em> is interpreted in octal. </dd> + + <dt> -B <em>bundle</em>, --bundle=<em>bundle</em> </dt> + <dd> Create a bundle named <em>bundle</em> containing all the created services. +The mount point services will also be grouped under a bundle named <tt><em>bundle</em>-mounts</tt> +and the swap services will be grouped under a bundle named <tt><em>bundle</em>-swaps</tt>. +Services marked <tt>noauto</tt> will not be included in these bundles. </dd> + + <dt> -d <em>dep</em>, --base-dependency=<em>dep</em> </dt> + <dd> Add a dependency to a service named <em>dep</em> to all the created services. +This is useful e.g. in a boot sequence to ensure that the mounts will not start before +a certain point. </dd> + + <dt> -A, --include-noauto </dt> + <dd> Include mount points and swaps marked <tt>noauto</tt> in the output. These +services will not be marked as essential or recommended, and they will not be included +in any bundle, but they will be there. This is the default. </dd> + + <dt> -a, --exclude-noauto </dt> + <dd> Exclude mount points and swaps marked <tt>noauto</tt>. No service will be created +for these fstab entries. </dd> + + <dt> -U, --without-uuid </dt> + <dd> The created services will use s6-linux-utils commands such as +<a href="s6-mount.html">s6-mount</a> and <a href="s6-swapon.html">s6-swapon</a>. +This makes the created services only depend on s6-linux-utils, but the fstab +entries must not contain util-linux-specific syntax such as <tt>UUID=</tt> or +<tt>LABEL=</tt> in place of device names. This is the default. </dd> + + <dt> -u, --with-uuid </dt> + <dd> The created services will use util-linux commands such as +<a href="https://man7.org/linux/man-pages/man8/mount.8.html">mount</a> and +<a href="https://man7.org/linux/man-pages/man8/swapon.8.html">swapon</a>. Running +the services will depend on having such commands installed, but syntax +for labels and uuids will be understood. </dd> + + <dt> -E, --essential </dt> + <dd> Mark the services as essential, and do not create <tt>down</tt> scripts +for them. This makes services suitable to be part of a base init sequence where +all the listed filesystems are mounted early, and never unmounted until right +before the machine reboots. (<tt>noauto</tt> entries will not be marked as +essential.) This is the default. </dd> + + <dt> -e, --not-essential </dt> + <dd> Mark the services as recommended rather than essential; create <tt>down</tt> +scripts to unmount the filesystem. This makes services suitable for being called +<em>later</em> than the base init sequence, as an optional part of a system's +functionality. Stopping the services will unmount the +corresponding filesystems and turn off the corresponding swap devices. +<tt>noauto</tt> entries will not be marked as recommended. </dd> +</dl> + +<h2> Exit codes </h2> + +<dl> + <dt> 0 </dt> <dd> Success. </dd> + <dt> 1 </dt> <dd> Invalid fstab file. </dd> + <dt> 100 </dt> <dd> Incorrect usage. </dd> + <dt> 111 </dt> <dd> system call failed </dd> +</ul> + +</body> +</html> diff --git a/doc/index.html b/doc/index.html index 52c02ce..67fcb58 100644 --- a/doc/index.html +++ b/doc/index.html @@ -50,6 +50,8 @@ The Linux kernel must be 3.5 or later. </li> 2.14.5.0 or later. It's a build-time requirement. It's also a run-time requirement if you link against the shared version of the skalibs library. </li> + <li> <a href="//skarnet.org/software/execline/">execline</a> version +2.9.8.0 or later. It's a build-time requirement. </li> </ul> <h3> Licensing </h3> @@ -63,8 +65,8 @@ library. </li> <ul> <li> The current released version of s6-linux-utils is -<a href="s6-linux-utils-2.6.3.1.tar.gz">2.6.3.1</a>. -You can access its checksum <a href="s6-linux-utils-2.6.3.1.tar.gz.sha256">here</a>. </li> +<a href="s6-linux-utils-2.6.4.0.tar.gz">2.6.4.0</a>. +You can access its checksum <a href="s6-linux-utils-2.6.4.0.tar.gz.sha256">here</a>. </li> <li> Alternatively, you can checkout a copy of the <a href="//git.skarnet.org/cgi-bin/cgit.cgi/s6-linux-utils/">s6-linux-utils git repository</a>: @@ -107,6 +109,7 @@ the previous versions of s6-linux-utils and the current one. </li> (Miscellaneous tools) </p> <ul> +<li><a href="fstab2s6rc.html">The <tt>fstab2s6rc</tt> program</a></li> <li><a href="rngseed.html">The <tt>rngseed</tt> program</a></li> <li><a href="s6-chroot.html">The <tt>s6-chroot</tt> program</a></li> <li><a href="s6-freeramdisk.html">The <tt>s6-freeramdisk</tt> program</a></li> diff --git a/doc/upgrade.html b/doc/upgrade.html index 2747b1c..b373afe 100644 --- a/doc/upgrade.html +++ b/doc/upgrade.html @@ -18,12 +18,15 @@ <h1> What has changed in s6-linux-utils </h1> -<h2> in 2.6.3.1 </h2> +<h2> in 2.6.4.0 </h2> <ul> <li> <a href="//skarnet.org/software/skalibs/">skalibs</a> dependency bumped to 2.14.5.0. </li> + <li> <a href="//skarnet.org/software/execline/">execline</a> +dependency (to 2.9.8.0) introduced. </li> <li> Shared libraries are now supported on MacOS. </li> + <li> New binary: <a href="fstab2s6rc.html">fstab2s6rc</a>. </li> </ul> <h2> in 2.6.3.0 </h2> diff --git a/package/deps-build b/package/deps-build index fb4d1da..32de94b 100644 --- a/package/deps-build +++ b/package/deps-build @@ -1,2 +1,3 @@ -true true /package/prog/skalibs 2.14.4.0 libskarnet -$usensss false /package/admin/nsss 0.2.1.0 libnsss +true true /package/prog/skalibs 2.14.5.0 libskarnet +$usensss false /package/admin/nsss 0.2.1.1 libnsss +true true /package/admin/execline 2.9.8.0 diff --git a/package/deps.mak b/package/deps.mak index 7ce090c..6440245 100644 --- a/package/deps.mak +++ b/package/deps.mak @@ -10,6 +10,8 @@ src/libs6ps/s6ps_pwcache.o src/libs6ps/s6ps_pwcache.lo: src/libs6ps/s6ps_pwcache src/libs6ps/s6ps_statparse.o src/libs6ps/s6ps_statparse.lo: src/libs6ps/s6ps_statparse.c src/include-local/s6ps.h src/libs6ps/s6ps_ttycache.o src/libs6ps/s6ps_ttycache.lo: src/libs6ps/s6ps_ttycache.c src/libs6ps/s6ps-internal.h src/include-local/s6ps.h src/libs6ps/s6ps_wchan.o src/libs6ps/s6ps_wchan.lo: src/libs6ps/s6ps_wchan.c src/include-local/s6ps.h +src/multicall/s6-linux-utils.o src/multicall/s6-linux-utils.lo: src/multicall/s6-linux-utils.c src/include/s6-linux-utils/config.h src/include-local/s6ps.h +src/s6-linux-utils/fstab2s6rc.o src/s6-linux-utils/fstab2s6rc.lo: src/s6-linux-utils/fstab2s6rc.c src/include/s6-linux-utils/config.h src/s6-linux-utils/rngseed.o src/s6-linux-utils/rngseed.lo: src/s6-linux-utils/rngseed.c src/include/s6-linux-utils/config.h src/s6-linux-utils/s6-chroot.o src/s6-linux-utils/s6-chroot.lo: src/s6-linux-utils/s6-chroot.c src/s6-linux-utils/s6-freeramdisk.o src/s6-linux-utils/s6-freeramdisk.lo: src/s6-linux-utils/s6-freeramdisk.c @@ -29,6 +31,8 @@ libs6ps.a.xyzzy:src/libs6ps/s6ps_cache.lo src/libs6ps/s6ps_grcache.lo src/libs6p endif s6-linux-utils: EXTRA_LIBS := ${SYSCLOCK_LIB} ${MAYBEPTHREAD_LIB} s6-linux-utils: src/multicall/s6-linux-utils.o libs6ps.a.xyzzy ${LIBNSSS} -lskarnet +fstab2s6rc: EXTRA_LIBS := +fstab2s6rc: src/s6-linux-utils/fstab2s6rc.o -lskarnet rngseed: EXTRA_LIBS := ${SYSCLOCK_LIB} rngseed: src/s6-linux-utils/rngseed.o -lskarnet s6-chroot: EXTRA_LIBS := diff --git a/package/info b/package/info index 2b1c106..f129083 100644 --- a/package/info +++ b/package/info @@ -1,4 +1,4 @@ package=s6-linux-utils -version=2.6.3.1 +version=2.6.4.0 category=admin package_macro_name=S6_LINUX_UTILS diff --git a/package/modes b/package/modes index aad1e20..13c1ca4 100644 --- a/package/modes +++ b/package/modes @@ -1,3 +1,4 @@ +fstab2s6rc 0755 rngseed 0744 s6-chroot 0744 s6-freeramdisk 0744 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) ; } diff --git a/tools/gen-multicall.sh b/tools/gen-multicall.sh index 130f5b0..bac28d7 100755 --- a/tools/gen-multicall.sh +++ b/tools/gen-multicall.sh @@ -9,7 +9,7 @@ echo '/* ISC license. */' echo echo '#include <skalibs/nonposix.h>' echo -{ echo '#include <string.h>' ; echo '#include <stdlib.h>' ; cat src/$P/*.c | grep '^#include <' | grep -vF '<skalibs/' | grep -vF '<linux/' | grep -vF "<$P/" ; } | sort -u +{ echo '#include <string.h>' ; echo '#include <stdlib.h>' ; cat src/$P/*.c | grep '^#include <' | grep -vF -e '<skalibs/' -e '<linux/' -e "<$P/" ; } | sort -u cat <<EOF @@ -30,12 +30,6 @@ struct multicall_app_s emain_func_ref mainf ; } ; -static int multicall_app_cmp (void const *a, void const *b) -{ - char const *name = a ; - multicall_app const *p = b ; - return strcmp(name, p->name) ; -} EOF for i in `ls -1 src/$P/deps-exe` ; do @@ -72,7 +66,7 @@ static int ${p}_main (int argc, char const *const *argv, char const *const *envp multicall_app const *p ; PROG = "$P" ; if (argc < 2) dieusage() ; - p = bsearch(argv[1], multicall_apps, sizeof(multicall_apps) / sizeof(multicall_app), sizeof(multicall_app), &multicall_app_cmp) ; + p = bsearch(argv[1], multicall_apps, sizeof(multicall_apps) / sizeof(multicall_app), sizeof(multicall_app), &str_bcmp) ; if (!p) strerr_dief2x(100, "unknown subcommand: ", argv[1]) ; return (*(p->mainf))(argc-1, argv+1, envp) ; } @@ -82,7 +76,7 @@ int main (int argc, char const *const *argv, char const *const *envp) multicall_app const *p ; char const *name = strrchr(argv[0], '/') ; if (name) name++ ; else name = argv[0] ; - p = bsearch(name, multicall_apps, sizeof(multicall_apps) / sizeof(multicall_app), sizeof(multicall_app), &multicall_app_cmp) ; + p = bsearch(name, multicall_apps, sizeof(multicall_apps) / sizeof(multicall_app), sizeof(multicall_app), &str_bcmp) ; return p ? (*(p->mainf))(argc, argv, envp) : ${p}_main(argc, argv, envp) ; } EOF |
