aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2025-11-28 20:04:18 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2025-11-28 20:04:18 +0000
commitba12e68e0561fe2e00ff2a8da73c809e5e4c6e2d (patch)
treec615772818768939c82973a1a433e78f67b21747
parentd203fe67af73ef0a52a248b8b85839359682823b (diff)
downloads6-linux-utils-ba12e68e0561fe2e00ff2a8da73c809e5e4c6e2d.tar.gz
Add fstab2s6rc (untested), prepare for 2.6.4.0
-rw-r--r--.gitignore1
-rw-r--r--NEWS3
-rw-r--r--doc/fstab2s6rc.html136
-rw-r--r--doc/index.html7
-rw-r--r--doc/upgrade.html5
-rw-r--r--package/deps-build5
-rw-r--r--package/deps.mak4
-rw-r--r--package/info2
-rw-r--r--package/modes1
-rw-r--r--src/s6-linux-utils/deps-exe/fstab2s6rc1
-rw-r--r--src/s6-linux-utils/fstab2s6rc.c647
-rw-r--r--src/s6-linux-utils/s6-mount.c18
-rw-r--r--src/s6-linux-utils/s6-swapoff.c22
-rw-r--r--src/s6-linux-utils/s6-swapon.c23
-rw-r--r--src/s6-linux-utils/s6-umount.c23
-rwxr-xr-xtools/gen-multicall.sh12
16 files changed, 865 insertions, 45 deletions
diff --git a/.gitignore b/.gitignore
index c6e68cd..5bb120b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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
diff --git a/NEWS b/NEWS
index dde0bf3..7d8db99 100644
--- a/NEWS
+++ b/NEWS
@@ -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 &mdash; after compilation &mdash; 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