summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/faq.html6
-rw-r--r--doc/index.html2
-rw-r--r--doc/overview.html10
-rw-r--r--doc/s6-rc-bundle.html132
-rw-r--r--package/deps.mak8
-rw-r--r--package/modes1
-rw-r--r--package/targets.mak3
-rw-r--r--src/include/s6-rc/s6rc-utils.h1
-rw-r--r--src/libs6rc/deps-lib/s6rc1
-rw-r--r--src/libs6rc/s6rc_lock.c48
-rw-r--r--src/s6-rc/deps-exe/s6-rc-bundle3
-rw-r--r--src/s6-rc/s6-rc-bundle.c364
-rw-r--r--src/s6-rc/s6-rc-compile.c3
-rw-r--r--src/s6-rc/s6-rc-db.c15
-rw-r--r--src/s6-rc/s6-rc-init.c39
-rw-r--r--src/s6-rc/s6-rc-update.c108
-rw-r--r--src/s6-rc/s6-rc.c28
17 files changed, 660 insertions, 112 deletions
diff --git a/doc/faq.html b/doc/faq.html
index 4776b00..2fe7acd 100644
--- a/doc/faq.html
+++ b/doc/faq.html
@@ -196,10 +196,14 @@ you don't want up anymore: <tt>s6-rc -p change runlevel-2</tt>.
<p>
Bundles are easy to use, they're flexible, and they're powerful.
They give you the same level of functionality as runlevels would, and more.
+You can even add bundles to compiled service databases - including the
+live one - or remove bundles from them without having to recompile them:
+that's what the <a href="s6-rc-bundle.html">s6-rc-bundle</a> utility is
+for.
</p>
<p>
- Use bundles.
+ When in doubt, use bundles.
</p>
</body>
diff --git a/doc/index.html b/doc/index.html
index 6c893c1..3e66a90 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -35,6 +35,7 @@ scripts are also run in a controlled environment.
<ul>
<li> <a href="why.html">Why</a> such a program&nbsp;? </li>
<li> A <a href="overview.html">high-level overview</a> of s6-rc </li>
+ <li> <a href="faq.html">FAQ</a> for s6-rc </li>
</ul>
<hr />
@@ -97,6 +98,7 @@ the previous versions of s6-rc and the current one. </li>
<ul>
<li> <a href="s6-rc-compile.html">The <tt>s6-rc-compile</tt> program</a> </li>
<li> <a href="s6-rc-db.html">The <tt>s6-rc-db</tt> program</a> </li>
+ <li> <a href="s6-rc-bundle.html">The <tt>s6-rc-bundle</tt> program</a> </li>
</ul>
<h4> Online tools: managing your live services </h4>
diff --git a/doc/overview.html b/doc/overview.html
index 2a90ee6..0d8dce0 100644
--- a/doc/overview.html
+++ b/doc/overview.html
@@ -217,5 +217,15 @@ provided in the packages, an invocation of
keep the live state up to date.
</p>
+<h2> Live bundle modifications </h2>
+
+<p>
+ It is possible to change bundle definitions in a compiled service
+database, including the live one, without recompiling everything by
+calling <a href="s6-rc-compile.html">s6-rc-compile</a>. The
+<a href="s6-rc-bundle.html">s6-rc-bundle</a> tool can edit compiled
+databases to add bundles to them, or delete bundles from them.
+</p>
+
</body>
</html>
diff --git a/doc/s6-rc-bundle.html b/doc/s6-rc-bundle.html
new file mode 100644
index 0000000..c77f890
--- /dev/null
+++ b/doc/s6-rc-bundle.html
@@ -0,0 +1,132 @@
+<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-rc: the s6-rc-bundle program</title>
+ <meta name="Description" content="s6-rc: the s6-rc-bundle program" />
+ <meta name="Keywords" content="s6-rc offline database dump command rc init dependency state management services" />
+ <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> -->
+ </head>
+<body>
+
+<p>
+<a href="index.html">s6-rc-bundle</a><br />
+<a href="http://skarnet.org/software/">Software</a><br />
+<a href="http://skarnet.org/">skarnet.org</a>
+</p>
+
+<h1> The s6-rc-bundle program </h1>
+
+<p>
+ s6-rc-bundle is a tool to add or delete bundles from a compiled
+service database without having to recompile it from source.
+</p>
+
+<p>
+ It is an <em>offline tool</em>, i.e. you can run it on any
+compiled service database without actually having a live set
+of services managed by s6-rc. However, if you do have a live
+set, you can still run s6-rc-bundle on the current database (and
+it is the default); it won't interfere with your normal service
+operation.
+</p>
+
+<h2> Interface </h2>
+
+<pre>
+ s6-rc-bundle help
+ s6-rc-bundle [ -f ] [ -l <em>live</em> ] [ -c <em>compiled</em> ] add <em>bundlename</em> <em>contents...</em>
+ s6-rc-bundle [ -f ] [ -l <em>live</em> ] [ -c <em>compiled</em> ] delete <em>bundlenames...</em>
+ s6-rc-bundle [ -f ] [ -l <em>live</em> ] [ -c <em>compiled</em> ] multiple <em>args...</em>
+</pre>
+
+<ul>
+ <li> s6-rc-bundle expects to find a <em>compiled service database</em>
+in <em>compiled</em>; by default it uses the service database
+used by the live state in <em>live</em>. </li>
+ <li> Depending on the arguments, it adds a bundle definition to this database, or
+deletes a bundle definition from it, or performs multiple additions/deletions. </li>
+</ul>
+
+<h2> Options </h2>
+
+<ul>
+ <li> <tt>-c&nbsp;<em>compiled</em></tt>&nbsp;: operate on a
+compiled service database in <em>compiled</em> instead of
+the current live one. </li>
+ <li> <tt>-l&nbsp;<em>live</em></tt>&nbsp;: assume the live
+state is in <em>live</em>. This option is ignored if the
+<tt>-c</tt> option has been given. Default is
+<tt>/run/s6-rc</tt>. The default can be changed at package
+compilation time, by giving the <tt>--livedir=<em>live</em></tt>
+option to <tt>./configure</tt>. </li>
+ <li> <tt>-f</tt>&nbsp;: force. s6-rc-bundle will not complain
+when given a nonexisting name to delete (it will do nothing), or
+when given an existing name to add (it will replace the definition).
+By default, s6-rc-bundle will exit when asked to delete a
+nonexistent name or to add an existing name. </li>
+</ul>
+
+<h2> Exit codes </h2>
+
+<ul>
+ <li> 0: success </li>
+ <li> 1: identifier already exists in service database </li>
+ <li> 3: identifier not found in service database </li>
+ <li> 4: invalid or corrupted service database </li>
+ <li> 5: wrong identifier type for the given command </li>
+ <li> 100: wrong usage </li>
+ <li> 111: system call failed </li>
+</ul>
+
+<h2> Subcommands </h2>
+
+<h3> s6-rc-bundle help </h3>
+
+<p>
+ Prints a help message on stdout.
+</p>
+
+<h3> s6-rc-bundle add <em>bundlename</em> <em>contents...</em> </h3>
+
+<p>
+ Adds a bundle named <em>bundlename</em> to the database, representing
+the services listed in <em>contents</em>. The arguments in <em>contents...</em>
+are resolved <em>before</em> the database is modified by the
+s6-rc-bundle invocation.
+</p>
+
+<h3> s6-rc-bundle delete <em>bundlenames...</em> </h3>
+
+<p>
+ Deletes bundles listed in <em>bundlenames...</em>.
+</p>
+
+<h3> s6-rc-bundle multiple <em>args...</em> </h3>
+
+<p>
+ Performs multiple bundle deletions and additions. This subcommand is best
+used in an <a href="http://skarnet.org/software/execline/">execline</a>
+script, because it uses
+<a href="http://skarnet.org/software/execline/el_semicolon.html">blocks</a>.
+</p>
+
+<p>
+<em>args...</em> is composed of:
+</p>
+
+<ul>
+ <li> One block listing bundle names that will be
+deleted from the database. </li>
+ <li> Zero or more addition definitions, each of them composed of:
+ <ul>
+ <li> One argument that is the name of the bundle to add </li>
+ <li> One block listing the services contained in the
+new bundle. The names in the block are resolved before any addition
+is made to the database. </li>
+ </ul> </li>
+</ul>
+
+</body>
+</html>
diff --git a/package/deps.mak b/package/deps.mak
index 73db48e..7d388fb 100644
--- a/package/deps.mak
+++ b/package/deps.mak
@@ -11,6 +11,7 @@ src/libs6rc/s6rc_db_read.o src/libs6rc/s6rc_db_read.lo: src/libs6rc/s6rc_db_read
src/libs6rc/s6rc_db_read_sizes.o src/libs6rc/s6rc_db_read_sizes.lo: src/libs6rc/s6rc_db_read_sizes.c src/include/s6-rc/s6rc-db.h
src/libs6rc/s6rc_db_read_uint32.o src/libs6rc/s6rc_db_read_uint32.lo: src/libs6rc/s6rc_db_read_uint32.c src/include/s6-rc/s6rc-db.h
src/libs6rc/s6rc_graph_closure.o src/libs6rc/s6rc_graph_closure.lo: src/libs6rc/s6rc_graph_closure.c src/include/s6-rc/s6rc-db.h src/include/s6-rc/s6rc-utils.h
+src/libs6rc/s6rc_lock.o src/libs6rc/s6rc_lock.lo: src/libs6rc/s6rc_lock.c src/include/s6-rc/s6rc-utils.h
src/libs6rc/s6rc_read_uint.o src/libs6rc/s6rc_read_uint.lo: src/libs6rc/s6rc_read_uint.c
src/libs6rc/s6rc_sanitize_dir.o src/libs6rc/s6rc_sanitize_dir.lo: src/libs6rc/s6rc_sanitize_dir.c src/include/s6-rc/s6rc-utils.h
src/libs6rc/s6rc_servicedir_block.o src/libs6rc/s6rc_servicedir_block.lo: src/libs6rc/s6rc_servicedir_block.c src/include/s6-rc/s6rc-servicedir.h
@@ -18,6 +19,7 @@ src/libs6rc/s6rc_servicedir_copy_offline.o src/libs6rc/s6rc_servicedir_copy_offl
src/libs6rc/s6rc_servicedir_copy_online.o src/libs6rc/s6rc_servicedir_copy_online.lo: src/libs6rc/s6rc_servicedir_copy_online.c src/include/s6-rc/s6rc-servicedir.h src/include/s6-rc/s6rc-utils.h src/libs6rc/s6rc-servicedir-internal.h
src/libs6rc/s6rc_servicedir_internal.o src/libs6rc/s6rc_servicedir_internal.lo: src/libs6rc/s6rc_servicedir_internal.c src/include/s6-rc/s6rc-utils.h src/libs6rc/s6rc-servicedir-internal.h
src/libs6rc/s6rc_servicedir_unblock.o src/libs6rc/s6rc_servicedir_unblock.lo: src/libs6rc/s6rc_servicedir_unblock.c src/include/s6-rc/s6rc-servicedir.h
+src/s6-rc/s6-rc-bundle.o src/s6-rc/s6-rc-bundle.lo: src/s6-rc/s6-rc-bundle.c src/include/s6-rc/config.h src/include/s6-rc/s6rc.h
src/s6-rc/s6-rc-compile.o src/s6-rc/s6-rc-compile.lo: src/s6-rc/s6-rc-compile.c src/include/s6-rc/config.h src/include/s6-rc/s6rc.h
src/s6-rc/s6-rc-db.o src/s6-rc/s6-rc-db.lo: src/s6-rc/s6-rc-db.c src/include/s6-rc/config.h src/include/s6-rc/s6rc.h
src/s6-rc/s6-rc-dryrun.o src/s6-rc/s6-rc-dryrun.lo: src/s6-rc/s6-rc-dryrun.c
@@ -26,11 +28,13 @@ src/s6-rc/s6-rc-init.o src/s6-rc/s6-rc-init.lo: src/s6-rc/s6-rc-init.c src/inclu
src/s6-rc/s6-rc-update.o src/s6-rc/s6-rc-update.lo: src/s6-rc/s6-rc-update.c src/include/s6-rc/config.h src/include/s6-rc/s6rc.h
src/s6-rc/s6-rc.o src/s6-rc/s6-rc.lo: src/s6-rc/s6-rc.c src/include/s6-rc/config.h src/include/s6-rc/s6rc.h
-libs6rc.a.xyzzy: src/libs6rc/s6rc_db_check_depcycles.o src/libs6rc/s6rc_db_check_pipelines.o src/libs6rc/s6rc_db_check_revdeps.o src/libs6rc/s6rc_db_read.o src/libs6rc/s6rc_db_read_sizes.o src/libs6rc/s6rc_db_read_uint32.o src/libs6rc/s6rc_graph_closure.o src/libs6rc/s6rc_read_uint.o src/libs6rc/s6rc_sanitize_dir.o src/libs6rc/s6rc_servicedir_internal.o src/libs6rc/s6rc_servicedir_block.o src/libs6rc/s6rc_servicedir_unblock.o src/libs6rc/s6rc_servicedir_copy_offline.o src/libs6rc/s6rc_servicedir_copy_online.o
+libs6rc.a.xyzzy: src/libs6rc/s6rc_db_check_depcycles.o src/libs6rc/s6rc_db_check_pipelines.o src/libs6rc/s6rc_db_check_revdeps.o src/libs6rc/s6rc_db_read.o src/libs6rc/s6rc_db_read_sizes.o src/libs6rc/s6rc_db_read_uint32.o src/libs6rc/s6rc_graph_closure.o src/libs6rc/s6rc_lock.o src/libs6rc/s6rc_read_uint.o src/libs6rc/s6rc_sanitize_dir.o src/libs6rc/s6rc_servicedir_internal.o src/libs6rc/s6rc_servicedir_block.o src/libs6rc/s6rc_servicedir_unblock.o src/libs6rc/s6rc_servicedir_copy_offline.o src/libs6rc/s6rc_servicedir_copy_online.o
libs6rc.so.xyzzy: private EXTRA_LIBS := -ls6 -lskarnet
-libs6rc.so.xyzzy: src/libs6rc/s6rc_db_check_depcycles.lo src/libs6rc/s6rc_db_check_pipelines.lo src/libs6rc/s6rc_db_check_revdeps.lo src/libs6rc/s6rc_db_read.lo src/libs6rc/s6rc_db_read_sizes.lo src/libs6rc/s6rc_db_read_uint32.lo src/libs6rc/s6rc_graph_closure.lo src/libs6rc/s6rc_read_uint.lo src/libs6rc/s6rc_sanitize_dir.lo src/libs6rc/s6rc_servicedir_internal.lo src/libs6rc/s6rc_servicedir_block.lo src/libs6rc/s6rc_servicedir_unblock.lo src/libs6rc/s6rc_servicedir_copy_offline.lo src/libs6rc/s6rc_servicedir_copy_online.lo
+libs6rc.so.xyzzy: src/libs6rc/s6rc_db_check_depcycles.lo src/libs6rc/s6rc_db_check_pipelines.lo src/libs6rc/s6rc_db_check_revdeps.lo src/libs6rc/s6rc_db_read.lo src/libs6rc/s6rc_db_read_sizes.lo src/libs6rc/s6rc_db_read_uint32.lo src/libs6rc/s6rc_graph_closure.lo src/libs6rc/s6rc_lock.lo src/libs6rc/s6rc_read_uint.lo src/libs6rc/s6rc_sanitize_dir.lo src/libs6rc/s6rc_servicedir_internal.lo src/libs6rc/s6rc_servicedir_block.lo src/libs6rc/s6rc_servicedir_unblock.lo src/libs6rc/s6rc_servicedir_copy_offline.lo src/libs6rc/s6rc_servicedir_copy_online.lo
s6-rc: private EXTRA_LIBS := ${TAINNOW_LIB}
s6-rc: src/s6-rc/s6-rc.o ${LIBS6RC} -lskarnet
+s6-rc-bundle: private EXTRA_LIBS :=
+s6-rc-bundle: src/s6-rc/s6-rc-bundle.o ${LIBS6RC} -lexecline -lskarnet
s6-rc-compile: private EXTRA_LIBS :=
s6-rc-compile: src/s6-rc/s6-rc-compile.o ${LIBS6RC} -lexecline -lskarnet
s6-rc-db: private EXTRA_LIBS :=
diff --git a/package/modes b/package/modes
index d6bd849..967fa37 100644
--- a/package/modes
+++ b/package/modes
@@ -1,6 +1,7 @@
s6-rc-compile 0755
s6-rc-db 0755
s6-rc-dryrun 0755
+s6-rc-bundle 0755
s6-rc-init 0755
s6-rc 0755
s6-rc-update 0755
diff --git a/package/targets.mak b/package/targets.mak
index 0f4d396..1dcce9e 100644
--- a/package/targets.mak
+++ b/package/targets.mak
@@ -1,7 +1,8 @@
BIN_TARGETS := \
s6-rc-compile \
s6-rc-dryrun \
-s6-rc-db
+s6-rc-db \
+s6-rc-bundle
SBIN_TARGETS := \
s6-rc-init \
diff --git a/src/include/s6-rc/s6rc-utils.h b/src/include/s6-rc/s6rc-utils.h
index c382b85..e7a6d0c 100644
--- a/src/include/s6-rc/s6rc-utils.h
+++ b/src/include/s6-rc/s6rc-utils.h
@@ -7,6 +7,7 @@
#include <s6-rc/s6rc-db.h>
extern void s6rc_graph_closure (s6rc_db_t const *, unsigned char *, unsigned int, int) ;
+extern int s6rc_lock (char const *, int, int *, char const *, int, int *) ;
extern int s6rc_read_uint (char const *, unsigned int *) ;
extern int s6rc_sanitize_dir (stralloc *, char const *, unsigned int *) ;
diff --git a/src/libs6rc/deps-lib/s6rc b/src/libs6rc/deps-lib/s6rc
index 1ee4dfb..00c3aab 100644
--- a/src/libs6rc/deps-lib/s6rc
+++ b/src/libs6rc/deps-lib/s6rc
@@ -5,6 +5,7 @@ s6rc_db_read.o
s6rc_db_read_sizes.o
s6rc_db_read_uint32.o
s6rc_graph_closure.o
+s6rc_lock.o
s6rc_read_uint.o
s6rc_sanitize_dir.o
s6rc_servicedir_internal.o
diff --git a/src/libs6rc/s6rc_lock.c b/src/libs6rc/s6rc_lock.c
new file mode 100644
index 0000000..69ec75b
--- /dev/null
+++ b/src/libs6rc/s6rc_lock.c
@@ -0,0 +1,48 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/bytestr.h>
+#include <skalibs/diuint.h>
+#include <skalibs/djbunix.h>
+#include <s6-rc/s6rc-utils.h>
+
+int s6rc_lock (char const *live, int lwhat, int *llfd, char const *compiled, int cwhat, int *ccfd)
+{
+ int e ;
+ int lfd = -1, cfd = -1 ;
+
+ if (lwhat)
+ {
+ unsigned int llen = str_len(live) ;
+ char lfn[llen + 6] ;
+ byte_copy(lfn, llen, live) ;
+ byte_copy(lfn + llen, 6, "/lock") ;
+ lfd = open_create(lfn) ;
+ if (lfd < 0) return 0 ;
+ if ((lwhat > 1 ? lock_ex(lfd) : lock_sh(lfd)) < 0) { e = errno ; goto lerr ; }
+ }
+
+ if (cwhat)
+ {
+ unsigned int clen = str_len(compiled) ;
+ char cfn[clen + 6] ;
+ byte_copy(cfn, clen, compiled) ;
+ byte_copy(cfn + clen, 6, "/lock") ;
+ cfd = open_create(cfn) ;
+ if (cfd < 0)
+ if (cwhat == 1 || errno != EROFS) { e = errno ; goto lerr ; }
+ else cfd = -errno ;
+ else if ((cwhat > 1 ? lock_ex(cfd) : lock_sh(cfd)) < 0) { e = errno ; goto cerr ; }
+ }
+
+ if (lwhat) *llfd = lfd ;
+ if (cwhat) *ccfd = cfd ;
+ return 1 ;
+
+ cerr:
+ fd_close(cfd) ;
+ lerr:
+ if (lwhat) fd_close(lfd) ;
+ errno = e ;
+ return 0 ;
+}
diff --git a/src/s6-rc/deps-exe/s6-rc-bundle b/src/s6-rc/deps-exe/s6-rc-bundle
new file mode 100644
index 0000000..9dbd823
--- /dev/null
+++ b/src/s6-rc/deps-exe/s6-rc-bundle
@@ -0,0 +1,3 @@
+${LIBS6RC}
+-lexecline
+-lskarnet
diff --git a/src/s6-rc/s6-rc-bundle.c b/src/s6-rc/s6-rc-bundle.c
new file mode 100644
index 0000000..e4caf00
--- /dev/null
+++ b/src/s6-rc/s6-rc-bundle.c
@@ -0,0 +1,364 @@
+/* ISC license. */
+
+#include <unistd.h>
+#include <errno.h>
+#include <stdio.h>
+#include <skalibs/uint32.h>
+#include <skalibs/bytestr.h>
+#include <skalibs/buffer.h>
+#include <skalibs/strerr2.h>
+#include <skalibs/sgetopt.h>
+#include <skalibs/bitarray.h>
+#include <skalibs/djbunix.h>
+#include <skalibs/cdb.h>
+#include <skalibs/cdb_make.h>
+#include <skalibs/unix-transactional.h>
+#include <execline/execline.h>
+#include <s6-rc/config.h>
+#include <s6-rc/s6rc.h>
+
+#define USAGE "s6-rc-bundle [ -l live ] [ -c compiled ] command... (use s6-rc-bundle help for more information)"
+#define dieusage() strerr_dieusage(100, USAGE)
+
+static void cleanup (char const *compiled)
+{
+ int e = errno ;
+ unsigned int len = str_len(compiled) ;
+ char fn[len + sizeof("/resolve.cdb.new")] ;
+ byte_copy(fn, len, compiled) ;
+ byte_copy(fn + len, sizeof("/resolve.cdb.new"), "/resolve.cdb.new") ;
+ unlink(fn) ;
+ errno = e ;
+}
+
+
+ /* switch to renameat when it's more portable */
+
+static inline int renameit (char const *compiled, char const *src, char const *dst)
+{
+ unsigned int clen = str_len(compiled) ;
+ unsigned int srclen = str_len(src) ;
+ unsigned int dstlen = str_len(dst) ;
+ char srcfn[clen + srclen + 2] ;
+ char dstfn[clen + dstlen + 2] ;
+ byte_copy(srcfn, clen, compiled) ;
+ srcfn[clen] = '/' ;
+ byte_copy(srcfn + clen + 1, srclen + 1, src) ;
+ byte_copy(dstfn, clen, compiled) ;
+ dstfn[clen] = '/' ;
+ byte_copy(dstfn + clen + 1, dstlen + 1, dst) ;
+ return rename(srcfn, dstfn) ;
+}
+
+static void check (cdb_t *cr, s6rc_db_t *db, char const *name, int h, int force, char const *compiled)
+{
+ unsigned int namelen = str_len(name) ;
+ register int r = cdb_find(cr, name, namelen) ;
+ if (r < 0) strerr_diefu3sys(111, "cdb_find in ", compiled, "/resolve.cdb") ;
+ if (!r)
+ {
+ if (!h && !force)
+ strerr_dief4x(3, "identifier ", name, "does not exist in database ", compiled) ;
+ return ;
+ }
+ if (h && !force)
+ strerr_dief4x(1, "identifier ", name, " exists in database ", compiled) ;
+ if (cdb_datalen(cr) == 4)
+ {
+ uint32 x ;
+ char pack[4] ;
+ if (cdb_read(cr, pack, 4, cdb_datapos(cr)) < 0)
+ strerr_diefu3sys(111, "cdb_read ", compiled, "/resolve.cdb") ;
+ uint32_unpack_big(pack, &x) ;
+ if (x >= db->nshort + db->nlong)
+ strerr_dief2x(4, "invalid database in ", compiled) ;
+ if (!str_diff(name, db->string + db->services[x].name))
+ strerr_dief4x(5, "identifier ", name, " does not represent a bundle for database ", compiled) ;
+ }
+}
+
+static void modify_resolve (int fdcompiled, s6rc_db_t *db, char const *const *todel, unsigned int todeln, char const *const *toadd, char const *const *const *toadd_contents, unsigned int toaddn, int force, char const *compiled)
+{
+ cdb_t cr = CDB_ZERO ;
+ struct cdb_make cw = CDB_MAKE_ZERO ;
+ uint32 kpos ;
+ unsigned int i = toaddn ;
+ int fdw ;
+ int fdr = open_readatb(fdcompiled, "resolve.cdb") ;
+ unsigned int n = db->nlong + db->nshort ;
+ unsigned char bits[bitarray_div8(n)] ;
+ if (fdr < 0) strerr_diefu3sys(111, "open ", compiled, "/resolve.cdb") ;
+ if (cdb_init_map(&cr, fdr, 1))
+ strerr_diefu3sys(111, "cdb_init ", compiled, "/resolve.cdb") ;
+ while (i--) check(&cr, db, toadd[i], 1, force, compiled) ;
+ i = todeln ;
+ while (i--) check(&cr, db, todel[i], 0, force, compiled) ;
+ fdw = open_truncatb(fdcompiled, "resolve.cdb.new") ;
+ if (fdw < 0) strerr_diefu3sys(111, "open ", compiled, "/resolve.cdb.new") ;
+ if (cdb_make_start(&cw, fdw) < 0)
+ {
+ cleanup(compiled) ;
+ strerr_diefu1sys(111, "cdb_make_start") ;
+ }
+ cdb_traverse_init(&cr, &kpos) ;
+ for (;;)
+ {
+ register int r = cdb_nextkey(&cr, &kpos) ;
+ if (r < 0)
+ {
+ cleanup(compiled) ;
+ strerr_diefu3sys(111, "cdb_nextkey in ", compiled, "/resolve.cdb") ;
+ }
+ if (!r) break ;
+ {
+ unsigned int klen = cdb_keylen(&cr) ;
+ char ktmp[klen + 1] ;
+ if (cdb_read(&cr, ktmp, klen, cdb_keypos(&cr)) < 0)
+ {
+ cleanup(compiled) ;
+ strerr_diefu3sys(111, "cdb_read ", compiled, "/resolve.cdb") ;
+ }
+ for (i = 0 ; i < todeln ; i++) if (!str_diffn(todel[i], ktmp, klen)) break ;
+ if (i >= todeln)
+ {
+ unsigned int dlen = cdb_datalen(&cr) ;
+ char dtmp[dlen + 1] ;
+ if (cdb_read(&cr, dtmp, dlen, cdb_datapos(&cr)) < 0)
+ {
+ cleanup(compiled) ;
+ strerr_diefu3sys(111, "cdb_read ", compiled, "/resolve.cdb") ;
+ }
+ if (cdb_make_add(&cw, ktmp, klen, dtmp, dlen) < 0)
+ {
+ cleanup(compiled) ;
+ strerr_diefu1sys(111, "cdb_make_add") ;
+ }
+ }
+ }
+ }
+ i = toaddn ;
+ while (i--)
+ {
+ char const *const *p = toadd_contents[i] ;
+ unsigned int total = 0 ;
+ byte_zero(bits, bitarray_div8(n)) ;
+ for (; *p ; p++)
+ {
+ register int r = cdb_find(&cr, *p, str_len(*p)) ;
+ if (r < 0) strerr_diefu3sys(111, "cdb_find in ", compiled, "/resolve.cdb") ;
+ if (!r) strerr_dief4x(3, "identifier ", *p, "does not exist in database ", compiled) ;
+ {
+ unsigned int j = cdb_datalen(&cr) ;
+ char pack[j + 1] ;
+ if (cdb_read(&cr, pack, j, cdb_datapos(&cr)) < 0)
+ {
+ cleanup(compiled) ;
+ strerr_diefu3sys(111, "cdb_read ", compiled, "/resolve.cdb") ;
+ }
+ j >>= 2 ;
+ while (j--)
+ {
+ uint32 x ;
+ uint32_unpack_big(pack + (j << 2), &x) ;
+ if (x >= db->nshort + db->nlong)
+ strerr_dief2x(4, "invalid database in ", compiled) ;
+ if (!bitarray_testandset(bits, x)) total++ ;
+ }
+ }
+ }
+ {
+ char pack[(total << 2) + 1] ;
+ char *s = pack ;
+ uint32 j = n ;
+ while (j--) if (bitarray_peek(bits, j))
+ {
+ uint32_pack_big(s, j) ;
+ s += 4 ;
+ }
+ if (cdb_make_add(&cw, toadd[i], str_len(toadd[i]), pack, total << 2) < 0)
+ {
+ cleanup(compiled) ;
+ strerr_diefu1sys(111, "cdb_make_add") ;
+ }
+ }
+ }
+ cdb_free(&cr) ;
+ close(fdr) ;
+ if (cdb_make_finish(&cw) < 0 || fsync(fdw) < 0)
+ {
+ cleanup(compiled) ;
+ strerr_diefu3sys(111, "write to ", compiled, "/resolve.cdb.new") ;
+ }
+ close(fdw) ;
+ if (renameit(compiled, "resolve.cdb.new", "resolve.cdb") < 0)
+ {
+ cleanup(compiled) ;
+ strerr_diefu2sys(111, "rename resolve.cdb.new to resolve.cdb in ", compiled) ;
+ }
+}
+
+static inline void parse_multiple (int argc, char const **argv, unsigned int *todeln, unsigned int *toaddn, char const **toadd, char const *const **toadd_contents)
+{
+ unsigned int m = 0 ;
+ int argc1 = el_semicolon(argv) ;
+ if (argc1 >= argc) strerr_dief1x(100, "unterminated block") ;
+ *todeln = argc1 ;
+ argv += argc1 + 1 ; argc -= argc1 + 1 ;
+ while (argc)
+ {
+ toadd[m] = *argv++ ;
+ if (!--argc) strerr_dief1x(100, "missing bundle contents block") ;
+ argc1 = el_semicolon(argv) ;
+ if (argc1 >= argc) strerr_dief1x(100, "unterminated block") ;
+ argv[argc1] = 0 ;
+ toadd_contents[m++] = argv ;
+ argv += argc1 + 1 ; argc -= argc1 + 1 ;
+ }
+ *toaddn = m ;
+}
+
+static inline void print_help (void)
+{
+ static char const *help =
+"s6-rc-bundle help\n"
+"s6-rc-bundle add bundlename contents...\n"
+"s6-rc-bundle delete bundlenames...\n"
+"s6-rc-bundle multiple { to-delete } to-add { contents... } ... (execlineb syntax)\n" ;
+ if (buffer_putsflush(buffer_1, help) < 0)
+ strerr_diefu1sys(111, "write to stdout") ;
+}
+
+static inline unsigned int lookup (char const *const *table, char const *command)
+{
+ register unsigned int i = 0 ;
+ for (; table[i] ; i++) if (!str_diff(command, table[i])) break ;
+ return i ;
+}
+
+static inline unsigned int parse_command (char const *command)
+{
+ static char const *const command_table[5] =
+ {
+ "help",
+ "add",
+ "delete",
+ "multiple",
+ 0
+ } ;
+ register unsigned int i = lookup(command_table, command) ;
+ if (!command_table[i]) dieusage() ;
+ return i ;
+}
+
+int main (int argc, char const **argv)
+{
+ char const *live = S6RC_LIVE_BASE ;
+ char const *compiled = 0 ;
+ unsigned int what ;
+ int force = 0 ;
+ PROG = "s6-rc-bundle" ;
+ {
+ subgetopt_t l = SUBGETOPT_ZERO ;
+ for (;;)
+ {
+ register int opt = subgetopt_r(argc, argv, "fl:c:", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'f' : force = 1 ; break ;
+ case 'l' : live = l.arg ; break ;
+ case 'c' : compiled = l.arg ; break ;
+ default : dieusage() ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
+ }
+
+ if (!argc) dieusage() ;
+ what = parse_command(*argv++) ;
+ if (!what)
+ {
+ print_help() ;
+ return 0 ;
+ }
+ if (!--argc) dieusage() ;
+ if (what != 2 && argc < 2) dieusage() ;
+
+ {
+ unsigned int livelen = str_len(live) ;
+ int fdcompiled = -1 ;
+ int compiledlock ;
+ s6rc_db_t dbblob ;
+ char compiledblob[compiled ? str_len(compiled) : livelen + 10] ;
+
+ if (!compiled)
+ {
+ byte_copy(compiledblob, livelen, live) ;
+ byte_copy(compiledblob + livelen, 10, "/compiled") ;
+ compiled = compiledblob ;
+ }
+
+ if (!s6rc_lock(0, 0, 0, compiled, 2, &compiledlock))
+ strerr_diefu2sys(111, "take lock on ", compiled) ;
+ fdcompiled = open_readb(compiled) ;
+ if (fdcompiled < 0)
+ strerr_diefu2sys(111, "open ", compiled) ;
+
+
+ /* Read the sizes of the compiled db */
+
+ fdcompiled = open_readb(compiled) ;
+ if (!s6rc_db_read_sizes(fdcompiled, &dbblob))
+ strerr_diefu3sys(111, "read ", compiled, "/n") ;
+
+
+ /* Allocate enough stack for the db */
+
+ {
+ unsigned int n = dbblob.nshort + dbblob.nlong ;
+ s6rc_service_t serviceblob[n] ;
+ char const *argvblob[dbblob.nargvs] ;
+ uint32 depsblob[dbblob.ndeps << 1] ;
+ char stringblob[dbblob.stringlen] ;
+ register int r ;
+
+ dbblob.services = serviceblob ;
+ dbblob.argvs = argvblob ;
+ dbblob.deps = depsblob ;
+ dbblob.string = stringblob ;
+
+
+ /* Read the db from the file */
+
+ r = s6rc_db_read(fdcompiled, &dbblob) ;
+ if (r < 0) strerr_diefu3sys(111, "read ", compiled, "/db") ;
+ if (!r) strerr_dief3x(4, "invalid service database in ", compiled, "/db") ;
+
+
+ /* Perform the action */
+
+ switch (what)
+ {
+ case 1 : /* add */
+ {
+ char const *const *contents = argv + 1 ;
+ modify_resolve(fdcompiled, &dbblob, 0, 0, argv, &contents, 1, force, compiled) ;
+ break ;
+ }
+ case 2 : /* delete */
+ modify_resolve(fdcompiled, &dbblob, argv, argc, 0, 0, 0, force, compiled) ;
+ break ;
+ case 3 : /* multiple */
+ {
+ unsigned int toaddn, todeln ;
+ char const *toadd[argc - 1] ;
+ char const *const *toadd_contents[argc - 1] ;
+ parse_multiple(argc, argv, &todeln, &toaddn, toadd, toadd_contents) ;
+ modify_resolve(fdcompiled, &dbblob, argv, todeln, toadd, toadd_contents, toaddn, force, compiled) ;
+ break ;
+ }
+ }
+ }
+ }
+ return 0 ;
+}
diff --git a/src/s6-rc/s6-rc-compile.c b/src/s6-rc/s6-rc-compile.c
index f4ba147..33e53fc 100644
--- a/src/s6-rc/s6-rc-compile.c
+++ b/src/s6-rc/s6-rc-compile.c
@@ -880,8 +880,11 @@ static void auto_rights (char const *compiled, char const *file, mode_t mode)
static inline void init_compiled (char const *compiled)
{
+ int compiledlock ;
if (mkdir(compiled, 0755) < 0)
strerr_diefu2sys(111, "mkdir ", compiled) ;
+ if (!s6rc_lock(0, 0, 0, compiled, 2, &compiledlock))
+ strerr_diefu2sys(111, "take lock on ", compiled) ;
auto_dir(compiled, "servicedirs") ;
}
diff --git a/src/s6-rc/s6-rc-db.c b/src/s6-rc/s6-rc-db.c
index 5fe43f1..0d8df53 100644
--- a/src/s6-rc/s6-rc-db.c
+++ b/src/s6-rc/s6-rc-db.c
@@ -1,24 +1,14 @@
/* ISC license. */
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
#include <unistd.h>
-#include <errno.h>
-#include <signal.h>
#include <skalibs/uint32.h>
-#include <skalibs/uint.h>
-#include <skalibs/allreadwrite.h>
#include <skalibs/bytestr.h>
-#include <skalibs/cdb.h>
#include <skalibs/sgetopt.h>
#include <skalibs/buffer.h>
#include <skalibs/strerr2.h>
-#include <skalibs/environ.h>
-#include <skalibs/direntry.h>
#include <skalibs/djbunix.h>
+#include <skalibs/cdb.h>
#include <skalibs/unix-transactional.h>
-#include <s6/config.h>
#include <s6-rc/config.h>
#include <s6-rc/s6rc.h>
@@ -384,6 +374,7 @@ int main (int argc, char const *const *argv)
{
unsigned int livelen = str_len(live) ;
+ int compiledlock ;
s6rc_db_t dbblob ;
char compiledblob[compiled ? str_len(compiled) : livelen + 10] ;
db = &dbblob ;
@@ -395,6 +386,8 @@ int main (int argc, char const *const *argv)
compiled = compiledblob ;
}
+ if (!s6rc_lock(0, 0, 0, compiled, 1, &compiledlock))
+ strerr_diefu2sys(111, "take lock on ", compiled) ;
fdcompiled = open_readb(compiled) ;
if (fdcompiled < 0)
strerr_diefu2sys(111, "open ", compiled) ;
diff --git a/src/s6-rc/s6-rc-init.c b/src/s6-rc/s6-rc-init.c
index a6afad5..750875d 100644
--- a/src/s6-rc/s6-rc-init.c
+++ b/src/s6-rc/s6-rc-init.c
@@ -30,7 +30,7 @@ static void cleanup (void)
int e = errno ;
satmp.s[llen] = 0 ;
unlink(satmp.s) ;
- satmp.s[llen] = ' ' ;
+ satmp.s[llen] = '.' ;
rm_rf_in_tmp(&satmp, 0) ;
stralloc_free(&satmp) ;
errno = e ;
@@ -88,29 +88,21 @@ int main (int argc, char const *const *argv)
char cfn[llen + 23] ;
- /* Create the real dir and the symlink */
+ /* Create the real dir, lock it, symlink */
if (mkdir(satmp.s, 0755) < 0) strerr_diefu2sys(111, "mkdir ", satmp.s) ;
- byte_copy(lfn, llen, live) ; lfn[llen] = 0 ;
- if (symlink(satmp.s + dirlen, lfn) < 0)
- strerr_diefu4sys(111, "symlink ", satmp.s + dirlen, " to ", lfn) ;
-
-
- /* lock */
-
- byte_copy(lfn + llen, 6, "/lock") ;
- fdlock = open_trunc(lfn) ;
- if (fdlock < 0)
+ if (!s6rc_lock(satmp.s, 2, &fdlock, 0, 0, 0))
{
cleanup() ;
- strerr_diefu2sys(111, "open ", lfn) ;
+ strerr_diefu2sys(111, "take lock on ", satmp.s) ;
}
- if (lock_ex(fdlock) < 0)
+ byte_copy(lfn, llen, live) ; lfn[llen] = 0 ;
+ if (symlink(satmp.s + dirlen, lfn) < 0)
{
cleanup() ;
- strerr_diefu2sys(111, "lock ", lfn) ;
+ strerr_diefu4sys(111, "symlink ", satmp.s + dirlen, " to ", lfn) ;
}
-
+
/* compiled */
@@ -237,24 +229,17 @@ int main (int argc, char const *const *argv)
thislen = str_len(d->d_name) ;
byte_copy(srcfn + llen + 13, thislen, d->d_name) ;
byte_copy(srcfn + llen + 13 + thislen, 6, "/down") ;
- r = open_trunc(srcfn) ;
- if (r < 0)
+ if (!touch(srcfn))
{
cleanup() ;
strerr_diefu2sys(111, "touch ", srcfn) ;
}
- close(r) ;
byte_copy(srcfn + llen + 14 + thislen, 9, "log/down") ;
- r = open_trunc(srcfn) ;
- if (r < 0)
+ if (!touch(srcfn))
{
- if (errno != ENOENT)
- {
- cleanup() ;
- strerr_diefu2sys(111, "touch ", srcfn) ;
- }
+ cleanup() ;
+ strerr_diefu2sys(111, "touch ", srcfn) ;
}
- else close(r) ;
byte_copy(srcfn + llen + 14 + thislen, 6, "event") ;
if (!ftrigw_fifodir_make(srcfn, gid, 0))
{
diff --git a/src/s6-rc/s6-rc-update.c b/src/s6-rc/s6-rc-update.c
index 242a9e0..b45d99e 100644
--- a/src/s6-rc/s6-rc-update.c
+++ b/src/s6-rc/s6-rc-update.c
@@ -135,7 +135,7 @@ static inline void parse_conversion_file (char const *convfile, stralloc *sa, un
close(fd) ;
}
-static inline void stuff_with_oldc (unsigned char *oldstate, int fdoldc, s6rc_db_t const *olddb, char const *convfile, unsigned int *nameindex, stralloc *namedata)
+static inline void stuff_with_oldc (unsigned char *oldstate, int fdoldc, s6rc_db_t const *olddb, char const *convfile, unsigned int *oldindex, stralloc *namedata)
{
cdb_t oldc = CDB_ZERO ;
int oldfdres = open_readatb(fdoldc, "resolve.cdb") ;
@@ -143,20 +143,20 @@ static inline void stuff_with_oldc (unsigned char *oldstate, int fdoldc, s6rc_db
if (!cdb_init_map(&oldc, oldfdres, 1))
strerr_diefu3sys(111, "cdb_init ", live, "/compiled/resolve.cdb") ;
- parse_conversion_file(convfile, namedata, nameindex, oldstate, &oldc, olddb) ;
+ parse_conversion_file(convfile, namedata, oldindex, oldstate, &oldc, olddb) ;
cdb_free(&oldc) ;
close(oldfdres) ;
}
-static inline void fill_convtable_and_flags (unsigned char *conversion_table, unsigned char *oldstate, unsigned char *newstate, char const *namedata, unsigned int const *nameindex, cdb_t *newc, char const *newfn, s6rc_db_t const *olddb, s6rc_db_t const *newdb)
+static inline void fill_convtable_and_flags (unsigned char *conversion_table, unsigned char *oldstate, unsigned char *newstate, char const *namedata, unsigned int const *oldindex, unsigned int *oldlong, unsigned int *newlong, cdb_t *newc, char const *newfn, s6rc_db_t const *olddb, s6rc_db_t const *newdb)
{
unsigned int newn = newdb->nshort + newdb->nlong ;
unsigned int i = olddb->nshort + olddb->nlong ;
while (i--)
{
- char const *newname = oldstate[i] & 16 ? namedata + nameindex[i] : olddb->string + olddb->services[i].name ;
+ char const *newname = oldstate[i] & 16 ? namedata + oldindex[i] : olddb->string + olddb->services[i].name ;
unsigned int len ;
int r = cdb_find(newc, newname, str_len(newname)) ;
if (r < 0) strerr_diefu3sys(111, "read ", newfn, "/resolve.cdb") ;
@@ -186,13 +186,19 @@ static inline void fill_convtable_and_flags (unsigned char *conversion_table, un
strerr_dief4x(1, "bad conversion file: new service ", newdb->string + newdb->services[x].name, " is a target for more than one conversion, including old service ", olddb->string + olddb->services[i].name) ;
newstate[x] |= 4 ;
bitarray_set(conversion_table + i * bitarray_div8(newn), x) ;
+ if (oldstate[i] & 8)
+ {
+ if (i < olddb->nlong) oldlong[i] = x ;
+ if (x < newdb->nlong) newlong[x] = i ;
+ if ((i < olddb->nlong) != (x < newdb->nlong)) oldstate[i] |= 4 ;
+ }
}
}
+ if (oldstate[i] & 1 && (oldstate[i] & 4 || !(oldstate[i] & 8))) oldstate[i] |= 34 ;
}
-
}
-static inline void stuff_with_newc (int fdnewc, char const *newfn, unsigned char *conversion_table, unsigned char *oldstate, unsigned char *newstate, char const *namedata, unsigned int const *nameindex, s6rc_db_t const *olddb, s6rc_db_t const *newdb)
+static inline void stuff_with_newc (int fdnewc, char const *newfn, unsigned char *conversion_table, unsigned char *oldstate, unsigned char *newstate, char const *namedata, unsigned int const *oldindex, unsigned int *oldlong, unsigned int *newlong, s6rc_db_t const *olddb, s6rc_db_t const *newdb)
{
cdb_t newc = CDB_ZERO ;
int newfdres = open_readatb(fdnewc, "resolve.cdb") ;
@@ -200,50 +206,36 @@ static inline void stuff_with_newc (int fdnewc, char const *newfn, unsigned char
if (!cdb_init_map(&newc, newfdres, 1))
strerr_diefu3sys(111, "cdb_init ", newfn, "/compiled/resolve.cdb") ;
- fill_convtable_and_flags(conversion_table, oldstate, newstate, namedata, nameindex, &newc, newfn, olddb, newdb) ;
+ fill_convtable_and_flags(conversion_table, oldstate, newstate, namedata, oldindex, oldlong, newlong, &newc, newfn, olddb, newdb) ;
cdb_free(&newc) ;
close(newfdres) ;
}
-static inline void adjust_newwantup (unsigned char *oldstate, unsigned int oldn, unsigned char *newstate, unsigned int newn, unsigned char const *conversion_table)
+static inline void adjust_newup (unsigned char const *oldstate, unsigned int oldn, unsigned char *newstate, unsigned int newn, unsigned char const *conversion_table)
{
unsigned int i = oldn ;
while (i--) if (oldstate[i] & 1)
{
register unsigned int j = newn ;
- if (!(oldstate[i] & 8) || (oldstate[i] & 4)) oldstate[i] |= 34 ;
- while (j--) if (bitarray_peek(conversion_table + i * bitarray_div8(newn), j)) newstate[j] |= 3 ;
- }
-}
-
-static inline void adjust_newalreadyup (unsigned char const *oldstate, unsigned int oldn, unsigned char *newstate, unsigned int newn, unsigned char const *conversion_table)
-{
- unsigned int i = oldn ;
- while (i--) if (oldstate[i] & 32)
- {
- register unsigned int j = newn ;
while (j--) if (bitarray_peek(conversion_table + i * bitarray_div8(newn), j))
- {
- newstate[j] &= 254 ;
- newstate[j] |= 2 ;
- }
+ newstate[j] |= (oldstate[i] & 32) ? 2 : 1 ;
}
}
-static void compute_transitions (char const *convfile, unsigned char *oldstate, int fdoldc, s6rc_db_t const *olddb, unsigned char *newstate, int fdnewc, char const *newfn, s6rc_db_t const *newdb, stralloc *sa)
+static void compute_transitions (char const *convfile, unsigned char *oldstate, unsigned int *oldlong, int fdoldc, s6rc_db_t const *olddb, unsigned char *newstate, unsigned int *newlong, int fdnewc, char const *newfn, s6rc_db_t const *newdb, stralloc *sa)
{
unsigned int oldn = olddb->nshort + olddb->nlong ;
unsigned int newn = newdb->nshort + newdb->nlong ;
+ unsigned int oldindex[oldn] ;
+ unsigned int sabase = sa->len ;
unsigned char conversion_table[oldn * bitarray_div8(newn)] ;
- unsigned int nameindex[oldn] ;
byte_zero(conversion_table, oldn * bitarray_div8(newn)) ;
- stuff_with_oldc(oldstate, fdoldc, olddb, convfile, nameindex, sa) ;
- stuff_with_newc(fdnewc, newfn, conversion_table, oldstate, newstate, sa->s, nameindex, olddb, newdb) ;
- sa->len = 0 ;
- adjust_newwantup(oldstate, oldn, newstate, newn, conversion_table) ;
+ stuff_with_oldc(oldstate, fdoldc, olddb, convfile, oldindex, sa) ;
+ stuff_with_newc(fdnewc, newfn, conversion_table, oldstate, newstate, sa->s + sabase, oldindex, oldlong, newlong, olddb, newdb) ;
+ sa->len = sabase ;
s6rc_graph_closure(olddb, oldstate, 5, 0) ;
- adjust_newalreadyup(oldstate, oldn, newstate, newn, conversion_table) ;
+ adjust_newup(oldstate, oldn, newstate, newn, conversion_table) ;
}
@@ -257,6 +249,7 @@ static void compute_transitions (char const *convfile, unsigned char *oldstate,
static inline void make_new_live (unsigned char const *newstate, unsigned int newn, char const *newcompiled, stralloc *sa)
{
+ unsigned int sabase = sa->len ;
unsigned int dirlen, llen, newlen ;
if (!s6rc_sanitize_dir(sa, live, &dirlen)) dienomem() ;
llen = sa->len ;
@@ -264,27 +257,30 @@ static inline void make_new_live (unsigned char const *newstate, unsigned int ne
|| !stralloc_0(sa))
dienomem() ;
newlen = sa->len - 1 ;
- rm_rf(sa->s) ;
- if (mkdir(sa->s, 0755) < 0) strerr_diefu2sys(111, "mkdir ", sa->s) ;
- strerr_diefu2sys(111, "mkdir ", sa->s) ;
+ rm_rf(sa->s + sabase) ;
+ if (mkdir(sa->s + sabase, 0755) < 0) strerr_diefu2sys(111, "mkdir ", sa->s + sabase) ;
+ strerr_diefu2sys(111, "mkdir ", sa->s + sabase) ;
sa->len = newlen ;
if (!stralloc_cats(sa, "/state") || !stralloc_0(sa)) goto err ;
{
char tmpstate[newn] ;
unsigned int i = newn ;
while (i--) tmpstate[i] = newstate[i] & 1 ;
- if (!openwritenclose_unsafe(sa->s, tmpstate, newn)) goto err ;
+ if (!openwritenclose_unsafe(sa->s + sabase, tmpstate, newn)) goto err ;
}
sa->len = newlen ;
if (!stralloc_cats(sa, "/compiled") || !stralloc_0(sa)) goto err ;
- if (symlink(newcompiled, sa->s) < 0) goto err ;
+ if (symlink(newcompiled, sa->s + sabase) < 0) goto err ;
+
+ sa->len = sabase ;
+ return ;
err:
{
int e = errno ;
sa->len = newlen ;
sa->s[sa->len++] = 0 ;
- rm_rf(sa->s) ;
+ rm_rf(sa->s + sabase) ;
errno = e ;
strerr_diefu2sys(111, "make new live directory in ", sa->s) ;
}
@@ -443,10 +439,10 @@ int main (int argc, char const *const *argv, char const *const *envp)
strerr_dief2x(100, argv[0], " is not an absolute directory") ;
{
- int livelock ;
+ int livelock, oldlock, newlock ;
int fdoldc, fdnewc ;
s6rc_db_t olddb, newdb ;
- unsigned int oldn, oldm, newn, newm ;
+ unsigned int oldn, newn ;
unsigned int livelen = str_len(live) ;
char dbfn[livelen + 10] ;
@@ -455,28 +451,26 @@ int main (int argc, char const *const *argv, char const *const *envp)
tain_add_g(&deadline, &deadline) ;
- /* Take the live lock */
+ /* Take the live, old and new locks */
byte_copy(dbfn, livelen, live) ;
- byte_copy(dbfn + livelen, 6, "/lock") ;
- livelock = open_write(dbfn) ;
- if (livelock < 0) strerr_diefu2sys(111, "open ", dbfn) ;
- if (lock_ex(livelock) < 0) strerr_diefu2sys(111, "lock ", dbfn) ;
+ byte_copy(dbfn + livelen, 10, "/compiled") ;
+ if (!s6rc_lock(live, 2, &livelock, dbfn, 1, &oldlock))
+ strerr_diefu4sys(111, "take lock on ", live, " and ", dbfn) ;
+ if (!s6rc_lock(0, 0, 0, argv[0], 1, &newlock))
+ strerr_diefu2sys(111, "take lock on ", argv[0]) ;
/* Read the sizes of the compiled dbs */
- byte_copy(dbfn + livelen + 1, 9, "compiled") ;
fdoldc = open_readb(dbfn) ;
if (!s6rc_db_read_sizes(fdoldc, &olddb))
strerr_diefu3sys(111, "read ", dbfn, "/n") ;
oldn = olddb.nshort + olddb.nlong ;
- oldm = bitarray_div8(oldn) ;
fdnewc = open_readb(argv[0]) ;
if (!s6rc_db_read_sizes(fdnewc, &newdb))
strerr_diefu3sys(111, "read ", argv[0], "/n") ;
newn = newdb.nshort + newdb.nlong ;
- newm = bitarray_div8(newn) ;
/* Allocate enough stack for the dbs */
@@ -487,10 +481,12 @@ int main (int argc, char const *const *argv, char const *const *envp)
s6rc_service_t oldserviceblob[oldn] ;
char const *oldargvblob[olddb.nargvs] ;
uint32 olddepsblob[olddb.ndeps << 1] ;
- char oldstringblob[olddb.stringlen] ;
s6rc_service_t newserviceblob[newn] ;
char const *newargvblob[newdb.nargvs] ;
uint32 newdepsblob[newdb.ndeps << 1] ;
+ unsigned int oldlong[olddb.nlong] ;
+ unsigned int newlong[newdb.nlong] ;
+ char oldstringblob[olddb.stringlen] ;
char newstringblob[newdb.stringlen] ;
unsigned char oldstate[oldn] ;
unsigned char newstate[newn] ;
@@ -520,20 +516,20 @@ int main (int argc, char const *const *argv, char const *const *envp)
byte_zero(newstate, newn) ;
byte_copy(dbfn + livelen + 1, 6, "state") ;
- {
- r = openreadnclose(dbfn, (char *)oldstate, oldn) ;
- if (r != oldn) strerr_diefu2sys(111, "read ", dbfn) ;
- {
- register unsigned int i = oldn ;
- while (i--) oldstate[i] &= 1 ;
- }
- }
+ r = openreadnclose(dbfn, (char *)oldstate, oldn) ;
+ if (r != oldn) strerr_diefu2sys(111, "read ", dbfn) ;
+ r = oldn ;
+ while (r--) oldstate[r] &= 1 ;
+ r = olddb.nlong ;
+ while (r--) oldlong[r] = newdb.nlong + newdb.nshort ;
+ r = newdb.nlong ;
+ while (r--) newlong[r] = olddb.nlong + olddb.nshort ;
/* Read the conversion file and compute what to do */
if (verbosity >= 2) strerr_warni1x("computing state adjustments") ;
- compute_transitions(convfile, oldstate, fdoldc, &olddb, newstate, fdnewc, argv[0], &newdb, &sa) ;
+ compute_transitions(convfile, oldstate, oldlong, fdoldc, &olddb, newstate, newlong, fdnewc, argv[0], &newdb, &sa) ;
tain_now_g() ;
if (!tain_future(&deadline)) strerr_dief1x(1, "timed out") ;
diff --git a/src/s6-rc/s6-rc.c b/src/s6-rc/s6-rc.c
index 698b52e..ca504e2 100644
--- a/src/s6-rc/s6-rc.c
+++ b/src/s6-rc/s6-rc.c
@@ -372,7 +372,7 @@ static inline void print_help (void)
int main (int argc, char const *const *argv)
{
- int up = 1, prune = 0, selectlive = 0, takelock = 1 ;
+ int up = 1, prune = 0, selectlive = 0, takelocks = 1 ;
unsigned int what ;
PROG = "s6-rc" ;
{
@@ -398,7 +398,7 @@ int main (int argc, char const *const *argv)
case 'd' : up = 0 ; break ;
case 'p' : prune = 1 ; break ;
case 'a' : selectlive = 1 ; break ;
- case 'X' : takelock = 0 ; break ;
+ case 'X' : takelocks = 0 ; break ;
default : dieusage() ;
}
}
@@ -421,27 +421,27 @@ int main (int argc, char const *const *argv)
s6rc_db_t dbblob ;
char dbfn[livelen + 10] ;
db = &dbblob ;
+ byte_copy(dbfn, livelen, live) ;
+ byte_copy(dbfn + livelen, 10, "/compiled") ;
- /* Take the live lock */
+ /* Take the locks on live and compiled */
- if (takelock)
+ if (takelocks)
{
- int livelock ;
- byte_copy(dbfn, livelen, live) ;
- byte_copy(dbfn + livelen, 6, "/lock") ;
- livelock = open_write(dbfn) ;
- if (livelock < 0) strerr_diefu2sys(111, "open ", dbfn) ;
- if (coe(livelock) < 0) strerr_diefu2sys(111, "coe ", dbfn) ;
- if ((what < 3 ? lock_sh(livelock) : lock_ex(livelock)) < 0)
- strerr_diefu2sys(111, "lock ", dbfn) ;
- /* livelock leaks, but we don't care */
+ int livelock, compiledlock ;
+ if (!s6rc_lock(live, 1 + (what >= 3), &livelock, dbfn, 1, &compiledlock))
+ strerr_diefu1sys(111, "take locks") ;
+ if (coe(livelock) < 0)
+ strerr_diefu3sys(111, "coe ", live, "/lock") ;
+ if (compiledlock >= 0 && coe(compiledlock) < 0)
+ strerr_diefu4sys(111, "coe ", live, "/compiled", "/lock") ;
+ /* locks leak, but we don't care */
}
/* Read the sizes of the compiled db */
- byte_copy(dbfn + livelen, 10, "/compiled") ;
fdcompiled = open_readb(dbfn) ;
if (!s6rc_db_read_sizes(fdcompiled, &dbblob))
strerr_diefu3sys(111, "read ", dbfn, "/n") ;