diff options
-rw-r--r-- | doc/faq.html | 6 | ||||
-rw-r--r-- | doc/index.html | 2 | ||||
-rw-r--r-- | doc/overview.html | 10 | ||||
-rw-r--r-- | doc/s6-rc-bundle.html | 132 | ||||
-rw-r--r-- | package/deps.mak | 8 | ||||
-rw-r--r-- | package/modes | 1 | ||||
-rw-r--r-- | package/targets.mak | 3 | ||||
-rw-r--r-- | src/include/s6-rc/s6rc-utils.h | 1 | ||||
-rw-r--r-- | src/libs6rc/deps-lib/s6rc | 1 | ||||
-rw-r--r-- | src/libs6rc/s6rc_lock.c | 48 | ||||
-rw-r--r-- | src/s6-rc/deps-exe/s6-rc-bundle | 3 | ||||
-rw-r--r-- | src/s6-rc/s6-rc-bundle.c | 364 | ||||
-rw-r--r-- | src/s6-rc/s6-rc-compile.c | 3 | ||||
-rw-r--r-- | src/s6-rc/s6-rc-db.c | 15 | ||||
-rw-r--r-- | src/s6-rc/s6-rc-init.c | 39 | ||||
-rw-r--r-- | src/s6-rc/s6-rc-update.c | 108 | ||||
-rw-r--r-- | src/s6-rc/s6-rc.c | 28 |
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 ? </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 <em>compiled</em></tt> : operate on a +compiled service database in <em>compiled</em> instead of +the current live one. </li> + <li> <tt>-l <em>live</em></tt> : 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> : 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") ; |