From ba12e68e0561fe2e00ff2a8da73c809e5e4c6e2d Mon Sep 17 00:00:00 2001
From: Laurent Bercot
Date: Fri, 28 Nov 2025 20:04:18 +0000
Subject: Add fstab2s6rc (untested), prepare for 2.6.4.0
---
.gitignore | 1 +
NEWS | 3 +-
doc/fstab2s6rc.html | 136 +++++++
doc/index.html | 7 +-
doc/upgrade.html | 5 +-
package/deps-build | 5 +-
package/deps.mak | 4 +
package/info | 2 +-
package/modes | 1 +
src/s6-linux-utils/deps-exe/fstab2s6rc | 1 +
src/s6-linux-utils/fstab2s6rc.c | 647 +++++++++++++++++++++++++++++++++
src/s6-linux-utils/s6-mount.c | 18 +-
src/s6-linux-utils/s6-swapoff.c | 22 +-
src/s6-linux-utils/s6-swapon.c | 23 +-
src/s6-linux-utils/s6-umount.c | 23 +-
tools/gen-multicall.sh | 12 +-
16 files changed, 865 insertions(+), 45 deletions(-)
create mode 100644 doc/fstab2s6rc.html
create mode 100644 src/s6-linux-utils/deps-exe/fstab2s6rc
create mode 100644 src/s6-linux-utils/fstab2s6rc.c
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 @@
+
+
+
+
+
+ s6-linux-utils: the fstab2s6rc program
+
+
+
+
+
+
+
+s6-linux-utils
+Software
+skarnet.org
+
+
+ The fstab2s6rc program
+
+
+ fstab2s6rc reads the /etc/fstab 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 s6-rc-compile, having the
+effect of mounting these partitions when run by s6-rc.
+
+
+
+ This method has several advantages over the classic mount -a:
+
+
+
+ - Parallelization. Dependencies between the mount points are respected: if /var
+and /var/log are mount points in /etc/fstab, s6-rc will not attempt to
+mount /var/log before /var is successfully mounted. But apart from this
+necessary serialization, s6-rc will performs in parallel as much as it can.
+ - Granularity. mount -a 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.
+
+
+
+ fstab2s6rc is an offline tool. It does not perform mounts or unmounts itself;
+it just converts the data in /etc/fstab, which is in a format usable by mount,
+into a format usable — after compilation — by s6-rc.
+
+
+ Interface
+
+
+ fstab2s6rc [ -A | -a ] [ -U | -u ] [ -E | -e ] [ -F fstab ] [ -m mode ] [ -B bundle ] [ -d basedep ] dir
+
+
+
+ - fstab2s6rc creates a directory dir in the filesystem to host all the service definition it will create.
+dir/em> must not previously exist.
+ - fstab2s6rc reads the /etc/fstab file. For every mount defined
+in the file, it creates a subdirectory of dir that is a suitable definition
+directory for an s6-rc service performing that mount.
+ - The service is named after the mount point: the service mounting /var/log
+will be called mount-var:log (slashes being replaced with colons, first slash
+omitted).
+ - For swap partitions, the partition named is used: the service activating swap on
+/dev/sda2 will be called swap-dev:sda2.
+
+
+ Options
+
+
+ - -F fstab, --fstab=fstab
+ - Read mount point information from file fstab instead of /etc/fstab.
+
+ - -m mode, --mode=mode
+ - Create dir with permissions mode. mode is interpreted in octal.
+
+ - -B bundle, --bundle=bundle
+ - Create a bundle named bundle containing all the created services.
+The mount point services will also be grouped under a bundle named bundle-mounts
+and the swap services will be grouped under a bundle named bundle-swaps.
+Services marked noauto will not be included in these bundles.
+
+ - -d dep, --base-dependency=dep
+ - Add a dependency to a service named dep 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.
+
+ - -A, --include-noauto
+ - Include mount points and swaps marked noauto 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.
+
+ - -a, --exclude-noauto
+ - Exclude mount points and swaps marked noauto. No service will be created
+for these fstab entries.
+
+ - -U, --without-uuid
+ - The created services will use s6-linux-utils commands such as
+s6-mount and s6-swapon.
+This makes the created services only depend on s6-linux-utils, but the fstab
+entries must not contain util-linux-specific syntax such as UUID= or
+LABEL= in place of device names. This is the default.
+
+ - -u, --with-uuid
+ - The created services will use util-linux commands such as
+mount and
+swapon. Running
+the services will depend on having such commands installed, but syntax
+for labels and uuids will be understood.
+
+ - -E, --essential
+ - Mark the services as essential, and do not create down 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. (noauto entries will not be marked as
+essential.) This is the default.
+
+ - -e, --not-essential
+ - Mark the services as recommended rather than essential; create down
+scripts to unmount the filesystem. This makes services suitable for being called
+later 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.
+noauto entries will not be marked as recommended.
+
+
+ Exit codes
+
+
+ - 0
- Success.
+ - 1
- Invalid fstab file.
+ - 100
- Incorrect usage.
+ - 111
- system call failed
+
+
+
+
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.
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.
+
execline version
+2.9.8.0 or later. It's a build-time requirement.
Licensing
@@ -63,8 +65,8 @@ library.
- The current released version of s6-linux-utils is
-2.6.3.1.
-You can access its checksum here.
+2.6.4.0.
+You can access its checksum here.
- Alternatively, you can checkout a copy of the
s6-linux-utils
git repository:
@@ -107,6 +109,7 @@ the previous versions of s6-linux-utils and the current one.
(Miscellaneous tools)
+- The fstab2s6rc program
- The rngseed program
- The s6-chroot program
- The s6-freeramdisk program
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 @@
What has changed in s6-linux-utils
- in 2.6.3.1
+ in 2.6.4.0
- skalibs
dependency bumped to 2.14.5.0.
+ - execline
+dependency (to 2.9.8.0) introduced.
- Shared libraries are now supported on MacOS.
+ - New binary: fstab2s6rc.
in 2.6.3.0
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
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include
+
+#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
#include
+#include
#include
#include
-#include
+#include
#include
#include
#include
-#define USAGE "s6-swapoff device 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
#include
-#include
+#include
+#include
-#define USAGE "s6-swapon device 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
#include
+#include
+#include
#include
#include
-#include
+#include
#include
#include
#include
-#define USAGE "s6-umount mountpoint 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 '
echo
-{ echo '#include ' ; echo '#include ' ; cat src/$P/*.c | grep '^#include <' | grep -vF '' ; echo '#include ' ; cat src/$P/*.c | grep '^#include <' | grep -vF -e '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
--
cgit v1.3.1