diff options
author | Laurent Bercot <ska-skaware@skarnet.org> | 2015-08-27 20:15:21 +0000 |
---|---|---|
committer | Laurent Bercot <ska-skaware@skarnet.org> | 2015-08-27 20:15:21 +0000 |
commit | 381b64487199a9edd46e84f7ff134722c3c3bcfc (patch) | |
tree | c7b08bd79c25cb1153b300d4d0cb5743ab1d1454 | |
parent | 8d9bb38022b9282128e5ddbfa8f62f9023a8698b (diff) | |
download | s6-rc-381b64487199a9edd46e84f7ff134722c3c3bcfc.tar.xz |
More work on s6-rc-update
-rw-r--r-- | INSTALL | 4 | ||||
-rw-r--r-- | doc/index.html | 4 | ||||
-rw-r--r-- | package/deps.mak | 5 | ||||
-rw-r--r-- | src/include/s6-rc/s6rc-constants.h | 3 | ||||
-rw-r--r-- | src/include/s6-rc/s6rc-utils.h | 2 | ||||
-rw-r--r-- | src/libs6rc/deps-lib/s6rc | 1 | ||||
-rw-r--r-- | src/libs6rc/s6rc_sanitize_dir.c | 26 | ||||
-rw-r--r-- | src/s6-rc/s6-rc-init.c | 13 | ||||
-rw-r--r-- | src/s6-rc/s6-rc-update.c | 316 |
9 files changed, 214 insertions, 160 deletions
@@ -6,9 +6,9 @@ Build Instructions - A POSIX-compliant C development environment - GNU make version 4.0 or later - - skalibs version 2.3.6.1 or later: http://skarnet.org/software/skalibs/ + - skalibs version 2.3.7.0 or later: http://skarnet.org/software/skalibs/ - execline version 2.1.4.0 or later: http://skarnet.org/software/execline/ - - s6 version 2.2.0.1 or later: http://skarnet.org/software/s6/ + - s6 version 2.2.1.0 or later: http://skarnet.org/software/s6/ This software will run on any operating system that implements POSIX.1-2008, available at: diff --git a/doc/index.html b/doc/index.html index 4a749ad..6c893c1 100644 --- a/doc/index.html +++ b/doc/index.html @@ -47,11 +47,11 @@ scripts are also run in a controlled environment. <li> A POSIX-compliant system with a standard C development environment </li> <li> GNU make, version 4.0 or later </li> <li> <a href="http://skarnet.org/software/skalibs/">skalibs</a> version -2.3.6.1 or later </li> +2.3.7.0 or later </li> <li> <a href="http://skarnet.org/software/execline/">execline</a> version 2.1.4.0 or later </li> <li> <a href="http://skarnet.org/software/s6/">s6</a> version -2.2.0.1 or later </li> +2.2.1.0 or later </li> </ul> <h3> Licensing </h3> diff --git a/package/deps.mak b/package/deps.mak index a094a7a..73db48e 100644 --- a/package/deps.mak +++ b/package/deps.mak @@ -12,6 +12,7 @@ src/libs6rc/s6rc_db_read_sizes.o src/libs6rc/s6rc_db_read_sizes.lo: src/libs6rc/ 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_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 src/libs6rc/s6rc_servicedir_copy_offline.o src/libs6rc/s6rc_servicedir_copy_offline.lo: src/libs6rc/s6rc_servicedir_copy_offline.c src/include/s6-rc/s6rc-servicedir.h src/libs6rc/s6rc-servicedir-internal.h 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 @@ -25,9 +26,9 @@ 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_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_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_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_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-compile: private EXTRA_LIBS := diff --git a/src/include/s6-rc/s6rc-constants.h b/src/include/s6-rc/s6rc-constants.h index 168dac8..05e2ff1 100644 --- a/src/include/s6-rc/s6rc-constants.h +++ b/src/include/s6-rc/s6rc-constants.h @@ -3,6 +3,9 @@ #ifndef S6RC_CONSTANTS_H #define S6RC_CONSTANTS_H +#define S6RC_LIVE_REAL_SUFFIX ".real" +#define S6RC_LIVE_NEW_SUFFIX ".new" + #define S6RC_COMPILED_BASE "/etc/s6-rc/compiled" #define S6RC_ONESHOT_RUNNER "s6rc-oneshot-runner" diff --git a/src/include/s6-rc/s6rc-utils.h b/src/include/s6-rc/s6rc-utils.h index c51c940..c382b85 100644 --- a/src/include/s6-rc/s6rc-utils.h +++ b/src/include/s6-rc/s6rc-utils.h @@ -3,9 +3,11 @@ #ifndef S6RC_UTILS_H #define S6RC_UTILS_H +#include <skalibs/stralloc.h> #include <s6-rc/s6rc-db.h> extern void s6rc_graph_closure (s6rc_db_t const *, unsigned char *, unsigned int, int) ; extern int s6rc_read_uint (char const *, unsigned int *) ; +extern int s6rc_sanitize_dir (stralloc *, char const *, unsigned int *) ; #endif diff --git a/src/libs6rc/deps-lib/s6rc b/src/libs6rc/deps-lib/s6rc index cedae10..1ee4dfb 100644 --- a/src/libs6rc/deps-lib/s6rc +++ b/src/libs6rc/deps-lib/s6rc @@ -6,6 +6,7 @@ s6rc_db_read_sizes.o s6rc_db_read_uint32.o s6rc_graph_closure.o s6rc_read_uint.o +s6rc_sanitize_dir.o s6rc_servicedir_internal.o s6rc_servicedir_block.o s6rc_servicedir_unblock.o diff --git a/src/libs6rc/s6rc_sanitize_dir.c b/src/libs6rc/s6rc_sanitize_dir.c new file mode 100644 index 0000000..69c4d13 --- /dev/null +++ b/src/libs6rc/s6rc_sanitize_dir.c @@ -0,0 +1,26 @@ +/* ISC license. */ + +#include <skalibs/bytestr.h> +#include <skalibs/stralloc.h> +#include <skalibs/djbunix.h> +#include <s6-rc/s6rc-utils.h> + +int s6rc_sanitize_dir (stralloc *sa, char const *fn, unsigned int *dirlen) +{ + int wasnull = !sa->s ; + unsigned int base = sa->len ; + unsigned int fnlen = str_len(fn) ; + unsigned int ddirlen ; + if (!sadirname(sa, fn, fnlen)) return 0 ; + if (sa->len != base + 1 || sa->s[base] != '/') + if (!stralloc_catb(sa, "/", 1)) goto err ; + ddirlen = sa->len ; + if (!sabasename(sa, fn, fnlen)) goto err ; + *dirlen = ddirlen ; + return 1 ; + + err: + if (wasnull) stralloc_free(sa) ; + else sa->len = base ; + return 0 ; +} diff --git a/src/s6-rc/s6-rc-init.c b/src/s6-rc/s6-rc-init.c index 49e7d17..a6afad5 100644 --- a/src/s6-rc/s6-rc-init.c +++ b/src/s6-rc/s6-rc-init.c @@ -21,8 +21,7 @@ #define USAGE "s6-rc-init [ -c compiled ] [ -l live ] [ -t timeout ] scandir" #define dieusage() strerr_dieusage(100, USAGE) - -#define INITIAL_MAGIC "(s6-rc-init initial live directory)" +#define dienomem() strerr_diefu1sys(111, "stralloc_catb") static unsigned int llen ; @@ -72,15 +71,9 @@ int main (int argc, char const *const *argv) if (argv[0][0] != '/') strerr_dief2x(100, "scandir", " must be an absolute path") ; - llen = str_len(live) ; - if (!sadirname(&satmp, live, llen) - || !stralloc_catb(&satmp, "/", 1)) - strerr_diefu1sys(111, "stralloc_catb") ; - dirlen = satmp.len ; - if (!sabasename(&satmp, live, llen)) - strerr_diefu1sys(111, "stralloc_catb") ; + if (!s6rc_sanitize_dir(&satmp, live, &dirlen)) dienomem() ; llen = satmp.len ; - if (!stralloc_catb(&satmp, " " INITIAL_MAGIC, 1 + sizeof(INITIAL_MAGIC))) + if (!stralloc_catb(&satmp, S6RC_LIVE_REAL_SUFFIX, sizeof(S6RC_LIVE_REAL_SUFFIX))) strerr_diefu1sys(111, "stralloc_catb") ; { diff --git a/src/s6-rc/s6-rc-update.c b/src/s6-rc/s6-rc-update.c index d7d0e4e..242a9e0 100644 --- a/src/s6-rc/s6-rc-update.c +++ b/src/s6-rc/s6-rc-update.c @@ -15,11 +15,15 @@ #include <skalibs/bitarray.h> #include <skalibs/cdb.h> #include <skalibs/stralloc.h> +#include <skalibs/tai.h> #include <skalibs/djbunix.h> #include <skalibs/skamisc.h> +#include <skalibs/webipc.h> #include <skalibs/unix-transactional.h> #include <execline/execline.h> +#include <s6/config.h> #include <s6/s6-supervise.h> +#include <s6/s6-fdholder.h> #include <s6-rc/config.h> #include <s6-rc/s6rc.h> @@ -36,6 +40,21 @@ static unsigned int verbosity = 1 ; /* Conversions and transitions */ + /* oldstate flags: + 1 -> is up + 2 -> wanted down + 4 -> restart + 8 -> converts to atomic or singleton + 16 -> has a new name + 32 -> wanted down after closure + 64 -> appears in convfile + + newstate flags: + 1 -> is up (converted from old up) + 2 -> wanted up + 4 -> is a conversion target + */ + static inline void parse_line (stralloc *sa, char const *s, unsigned int slen, unsigned int *newnames, unsigned char *oldstate, cdb_t *oldc, s6rc_db_t const *olddb) { unsigned int base = sa->len ; @@ -143,7 +162,7 @@ static inline void fill_convtable_and_flags (unsigned char *conversion_table, un if (r < 0) strerr_diefu3sys(111, "read ", newfn, "/resolve.cdb") ; if (!r) { - oldstate[i] |= 2 ; /* disappeared -> want down */ + oldstate[i] |= 34 ; /* disappeared */ continue ; } if (cdb_datalen(newc) & 3) @@ -156,7 +175,7 @@ static inline void fill_convtable_and_flags (unsigned char *conversion_table, un char const *p = pack ; if (cdb_read(newc, pack, cdb_datalen(newc), cdb_datapos(newc)) < 0) strerr_diefu3sys(111, "read ", newfn, "/resolve.cdb") ; - if (len == 1) oldstate[i] |= 8 ; /* atomic or singleton bundle */ + if (len == 1) oldstate[i] |= 8 ; while (len--) { uint32 x ; @@ -212,22 +231,16 @@ static inline void adjust_newalreadyup (unsigned char const *oldstate, unsigned } } -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) +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) { unsigned int oldn = olddb->nshort + olddb->nlong ; unsigned int newn = newdb->nshort + newdb->nlong ; unsigned char conversion_table[oldn * bitarray_div8(newn)] ; - unsigned int oldpairings[olddb->nlong] ; - unsigned int newpairings[newdb->nlong] ; + unsigned int nameindex[oldn] ; byte_zero(conversion_table, oldn * bitarray_div8(newn)) ; - { - stralloc namedata = STRALLOC_ZERO ; - unsigned int nameindex[oldn] ; - - stuff_with_oldc(oldstate, fdoldc, olddb, convfile, nameindex, &namedata) ; - stuff_with_newc(fdnewc, newfn, conversion_table, oldstate, newstate, namedata.s, nameindex, olddb, newdb) ; - stralloc_free(&namedata) ; - } + 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) ; s6rc_graph_closure(olddb, oldstate, 5, 0) ; adjust_newalreadyup(oldstate, oldn, newstate, newn, conversion_table) ; @@ -238,142 +251,100 @@ static void compute_transitions (char const *convfile, unsigned char *oldstate, /* Service directory replacement */ -static int safe_servicedir_update (char const *dst, char const *src, int h) + + /* The update itself. */ + + +static inline void make_new_live (unsigned char const *newstate, unsigned int newn, char const *newcompiled, stralloc *sa) { - unsigned int dstlen = str_len(dst) ; - unsigned int srclen = str_len(src) ; - int fd ; - int hasdata = 1, hasenv = 1, ok = 1 ; - char dstfn[dstlen + 15 + sizeof(S6_SUPERVISE_CTLDIR)] ; - char srcfn[srclen + 17] ; - char tmpfn[dstlen + 21] ; - byte_copy(dstfn, dstlen, dst) ; - byte_copy(srcfn, srclen, src) ; - - byte_copy(dstfn + dstlen, 6, "/down") ; - fd = open_trunc(dstfn) ; - if (fd < 0) strerr_warnwu2sys("touch ", dstfn) ; - else close(fd) ; - byte_copy(dstfn + dstlen + 1, 5, "data") ; - byte_copy(tmpfn, dstlen + 5, dstfn) ; - byte_copy(tmpfn + dstlen + 5, 5, ".old") ; - if (rename(dstfn, tmpfn) < 0) - { - if (errno == ENOENT) hasdata = 0 ; - else goto err ; - } - byte_copy(dstfn + dstlen + 1, 4, "env") ; - byte_copy(tmpfn + dstlen + 1, 8, "env.old") ; - if (rename(dstfn, tmpfn) < 0) - { - if (errno == ENOENT) hasenv = 0 ; - else goto err ; - } - byte_copy(dstfn + dstlen + 1, 9, "nosetsid") ; - if (unlink(dstfn) < 0 && errno != ENOENT) goto err ; - byte_copy(dstfn + dstlen + 3, 14, "tification-fd") ; - if (unlink(dstfn) < 0 && errno != ENOENT) goto err ; - - byte_copy(srcfn + srclen, 17, "/notification-fd") ; - hiercopy(srcfn, dstfn) ; - byte_copy(srcfn + srclen + 3, 7, "setsid") ; - byte_copy(dstfn + dstlen + 3, 7, "setsid") ; - hiercopy(srcfn, dstfn) ; - byte_copy(srcfn + srclen + 1, 5, "data") ; - byte_copy(dstfn + dstlen + 1, 5, "data") ; - hiercopy(srcfn, dstfn) ; - byte_copy(srcfn + srclen + 1, 4, "env") ; - byte_copy(dstfn + dstlen + 1, 4, "env") ; - hiercopy(srcfn, dstfn) ; - byte_copy(srcfn + srclen + 1, 4, "run") ; - byte_copy(dstfn + dstlen + 1, 4, "run") ; - if (!hiercopy(srcfn, dstfn)) goto err ; - byte_copy(srcfn + srclen + 1, 4, "run") ; - byte_copy(dstfn + dstlen + 1, 7, "finish") ; - byte_copy(tmpfn + dstlen + 1, 11, "finish.new") ; - if (hiercopy(srcfn, tmpfn) && rename(tmpfn, dstfn) < 0) goto err ; - if (h) + unsigned int dirlen, llen, newlen ; + if (!s6rc_sanitize_dir(sa, live, &dirlen)) dienomem() ; + llen = sa->len ; + if (!stralloc_cats(sa, S6RC_LIVE_REAL_SUFFIX S6RC_LIVE_NEW_SUFFIX) + || !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) ; + sa->len = newlen ; + if (!stralloc_cats(sa, "/state") || !stralloc_0(sa)) goto err ; { - byte_copy(dstfn + dstlen + 1, 5, "down") ; - if (unlink(dstfn) < 0) - { - strerr_warnwu2sys("unlink ", dstfn) ; - ok = 0 ; - } - byte_copy(dstfn + dstlen + 1, 8 + sizeof(S6_SUPERVISE_CTLDIR), S6_SUPERVISE_CTLDIR "/control") ; - s6_svc_write(dstfn, "u", 1) ; + char tmpstate[newn] ; + unsigned int i = newn ; + while (i--) tmpstate[i] = newstate[i] & 1 ; + if (!openwritenclose_unsafe(sa->s, tmpstate, newn)) goto err ; } - byte_copy(dstfn + dstlen + 1, 9, "data.old") ; - if (rm_rf(dstfn) < 0) strerr_warnwu2sys("remove ", dstfn) ; - byte_copy(dstfn + dstlen + 1, 8, "env.old") ; - if (rm_rf(dstfn) < 0) strerr_warnwu2sys("remove ", dstfn) ; - return 1 ; + sa->len = newlen ; + if (!stralloc_cats(sa, "/compiled") || !stralloc_0(sa)) goto err ; + if (symlink(newcompiled, sa->s) < 0) goto err ; err: - if (h) { int e = errno ; - byte_copy(dstfn + dstlen + 1, 5, "down") ; - unlink(dstfn) ; + sa->len = newlen ; + sa->s[sa->len++] = 0 ; + rm_rf(sa->s) ; errno = e ; + strerr_diefu2sys(111, "make new live directory in ", sa->s) ; } - return 0 ; } -static int servicedir_name_change (char const *live, char const *oldname, char const *newname) -{ - unsigned int livelen = str_len(live) ; - unsigned int oldlen = str_len(oldname) ; - unsigned int newlen = str_len(oldname) ; - char oldfn[livelen + oldlen + 2] ; - char newfn[livelen + newlen + 2] ; - byte_copy(oldfn, livelen, live) ; - oldfn[livelen] = '/' ; - byte_copy(oldfn + livelen + 1, oldlen + 1, oldname) ; - byte_copy(newfn, livelen + 1, oldfn) ; - byte_copy(newfn + livelen + 1, newlen + 1, newname) ; - if (rename(oldfn, newfn) < 0) return 0 ; - return 1 ; -} - -static inline void update_servicedirs (unsigned char const *oldstate, unsigned int oldn, unsigned char const *newstate, unsigned int newn) -{ -} + /* Pipe updates */ - /* The update itself. */ - - -static inline void update_state_and_compiled (unsigned char const *newstate, unsigned int newn, char const *newcompiled) +static inline int delete_old_pipes (s6_fdholder_t *a, s6rc_db_t const *olddb, unsigned char const *oldstate, tain_t const *deadline) { - char fn[livelen + 14] ; - byte_copy(fn, livelen, live) ; - byte_copy(fn + livelen, 7, "/state") ; - { - char tmpstate[newn] ; - unsigned int i = newn ; - while (i--) tmpstate[i] = newstate[i] & 1 ; - if (!openwritenclose_suffix(fn, tmpstate, newn, ".new")) - strerr_diefu2sys(112, "write ", fn) ; - } - byte_copy(fn + livelen + 1, 13, "compiled.new") ; - if (symlink(newcompiled, fn) < 0) - strerr_diefu4sys(112, "symlink ", newcompiled, " to ", fn) ; - { - char realfn[livelen + 10] ; - byte_copy(realfn, livelen + 9, fn) ; - realfn[livelen + 9] - 0 ; - if (rename(fn, realfn) < 0) - strerr_diefu4sys(112, "rename ", fn, " to ", realfn) ; - } + unsigned int i = olddb->nlong ; + while (i--) + if (!(oldstate[i] & 32) && oldstate[i] & 16 + && olddb->services[i].x.longrun.pipeline[0] < olddb->nlong) + { + unsigned int len = str_len(olddb->string + olddb->services[i].name) ; + char pipename[len + 13] ; + byte_copy(pipename, 12, "pipe:s6rc-w-") ; + byte_copy(pipename + 12, len + 1, olddb->string + olddb->services[i].name) ; + if (!s6_fdholder_delete_g(a, pipename, deadline)) return 0 ; + pipename[10] = 'r' ; + if (!s6_fdholder_delete_g(a, pipename, deadline)) return 0 ; + } + return 1 ; } -static unsigned int want_count (unsigned char const *state, unsigned int n) +static inline int create_new_pipes (s6_fdholder_t *a, s6rc_db_t const *newdb, unsigned char const *newstate, tain_t const *deadline) { - unsigned int count = 0, i = n ; - while (i--) if (state[i] & 2) count++ ; - return count ; + tain_t nano1 = { .sec = TAI_ZERO, .nano = 1 } ; + tain_t limit ; + tain_add_g(&limit, &tain_infinite_relative) ; + unsigned int i = newdb->nlong ; + while (i--) + if (newstate[i] & 4 && newdb->services[i].x.longrun.pipeline[0] < newdb->nlong) + { + int p[2] ; + unsigned int len = str_len(newdb->string + newdb->services[i].name) ; + char pipename[len + 13] ; + byte_copy(pipename, 12, "pipe:s6rc-w-") ; + byte_copy(pipename + 12, len + 1, newdb->string + newdb->services[i].name) ; + if (pipe(p) < 0) return 0 ; + tain_add(&limit, &limit, &nano1) ; + if (!s6_fdholder_store_g(a, p[1], pipename, &limit, deadline)) + { + close(p[1]) ; + close(p[0]) ; + return 0 ; + } + close(p[1]) ; + pipename[10] = 'r' ; + tain_add(&limit, &limit, &nano1) ; + if (!s6_fdholder_store_g(a, p[0], pipename, &limit, deadline)) + { + close(p[0]) ; + return 0 ; + } + close(p[0]) ; + } + return 1 ; } static void fill_tfmt (char *tfmt, tain_t const *deadline) @@ -387,13 +358,65 @@ static void fill_tfmt (char *tfmt, tain_t const *deadline) tfmt[uint_fmt(tfmt, t)] = 0 ; } +static void update_fdholder (s6rc_db_t const *olddb, unsigned char const *oldstate, s6rc_db_t const *newdb, unsigned char const *newstate, char const *const *envp, tain_t const *deadline) +{ + int fdsocket ; + s6_fdholder_t a = S6_FDHOLDER_ZERO ; + char fnsocket[livelen + sizeof("/servicedirs/" S6RC_FDHOLDER "/s")] ; + if (!(newstate[1] & 1)) return ; + byte_copy(fnsocket, livelen, live) ; + byte_copy(fnsocket + livelen, sizeof("/servicedirs/" S6RC_FDHOLDER "/s"), "/servicedirs" S6RC_FDHOLDER "/s") ; + fdsocket = ipc_stream_nb() ; + if (fdsocket < 0) goto hammer ; + if (!ipc_timed_connect_g(fdsocket, fnsocket, deadline)) goto closehammer ; + s6_fdholder_init(&a, fdsocket) ; + if (!delete_old_pipes(&a, olddb, oldstate, deadline)) goto freehammer ; + if (!create_new_pipes(&a, newdb, newstate, deadline)) goto freehammer ; + s6_fdholder_free(&a) ; + close(fdsocket) ; + return ; + + freehammer: + s6_fdholder_free(&a) ; + closehammer: + close(fdsocket) ; + hammer: + if (verbosity) strerr_warnwu1x("live update s6rc-fdholder - restarting it") ; + { + pid_t pid ; + int wstat ; + char tfmt[UINT_FMT] ; + char const *newargv[7] = { S6_EXTBINPREFIX "s6-svc", "-T", tfmt, "-twR", "--", fnsocket, 0 } ; + fill_tfmt(tfmt, deadline) ; + fnsocket[livelen + sizeof("/servicedirs/" S6RC_FDHOLDER) - 1] = 0 ; + pid = child_spawn0(newargv[0], newargv, envp) ; + if (!pid) strerr_diefu2sys(111, "spawn ", newargv[0]) ; + if (wait_pid(pid, &wstat) < 0) strerr_diefu1sys(111, "waitpid") ; + tain_now_g() ; + if (WIFSIGNALED(wstat) || WEXITSTATUS(wstat)) + if (verbosity) strerr_warnw1x("restart s6rc-fdholder") ; + } +} + + + + /* Main */ + + +static unsigned int want_count (unsigned char const *state, unsigned int n) +{ + unsigned int count = 0, i = n ; + while (i--) if (state[i] & 2) count++ ; + return count ; +} + int main (int argc, char const *const *argv, char const *const *envp) { char const *convfile = "/dev/null" ; tain_t deadline ; int dryrun = 0 ; PROG = "s6-rc-update" ; - strerr_dief1x(100, "will you please stop trying to run this? It's not ready!") ; + strerr_dief1x(100, "nope, not quite yet.") ; { unsigned int t = 0 ; subgetopt_t l = SUBGETOPT_ZERO ; @@ -406,7 +429,7 @@ int main (int argc, char const *const *argv, char const *const *envp) case 'v' : if (!uint0_scan(l.arg, &verbosity)) dieusage() ; break ; case 't' : if (!uint0_scan(l.arg, &t)) dieusage() ; break ; case 'n' : dryrun = 1 ; break ; - case 'l' : live = l.arg ; livelen = str_len(live) ; break ; + case 'l' : live = l.arg ; break ; case 'f' : convfile = l.arg ; break ; default : dieusage() ; } @@ -424,6 +447,7 @@ int main (int argc, char const *const *argv, char const *const *envp) int fdoldc, fdnewc ; s6rc_db_t olddb, newdb ; unsigned int oldn, oldm, newn, newm ; + unsigned int livelen = str_len(live) ; char dbfn[livelen + 10] ; if (!tain_now_g()) @@ -437,7 +461,6 @@ int main (int argc, char const *const *argv, char const *const *envp) 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 (lock_ex(livelock) < 0) strerr_diefu2sys(111, "lock ", dbfn) ; @@ -460,6 +483,7 @@ int main (int argc, char const *const *argv, char const *const *envp) { pid_t pid ; + stralloc sa = STRALLOC_ZERO ; s6rc_service_t oldserviceblob[oldn] ; char const *oldargvblob[olddb.nargvs] ; uint32 olddepsblob[olddb.ndeps << 1] ; @@ -509,7 +533,7 @@ int main (int argc, char const *const *argv, char const *const *envp) /* 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) ; + compute_transitions(convfile, oldstate, fdoldc, &olddb, newstate, fdnewc, argv[0], &newdb, &sa) ; tain_now_g() ; if (!tain_future(&deadline)) strerr_dief1x(1, "timed out") ; @@ -517,7 +541,7 @@ int main (int argc, char const *const *argv, char const *const *envp) /* Down transition */ { - char const *newargv[12 + (dryrun * 5) + want_count(oldstate, oldn)] ; + char const *newargv[11 + (dryrun * 5) + want_count(oldstate, oldn)] ; unsigned int m = 0, i = oldn ; int wstat ; char vfmt[UINT_FMT] ; @@ -539,8 +563,7 @@ int main (int argc, char const *const *argv, char const *const *envp) newargv[m++] = tfmt ; newargv[m++] = "-l" ; newargv[m++] = live ; - newargv[m++] = "-X" ; - newargv[m++] = "-d" ; + newargv[m++] = "-Xd" ; newargv[m++] = "--" ; newargv[m++] = "change" ; while (i--) if (oldstate[i] & 2) @@ -551,8 +574,9 @@ int main (int argc, char const *const *argv, char const *const *envp) pid = child_spawn0(newargv[0], newargv, envp) ; if (!pid) strerr_diefu2sys(111, "spawn ", newargv[0]) ; if (wait_pid(pid, &wstat) < 0) strerr_diefu1sys(111, "waitpid") ; + tain_now_g() ; if (WIFSIGNALED(wstat) || WEXITSTATUS(wstat)) - strerr_diefu1sys(wait_estatus(wstat), "first s6-rc invocation failed") ; + strerr_dief1x(wait_estatus(wstat), "first s6-rc invocation failed") ; } @@ -561,8 +585,13 @@ int main (int argc, char const *const *argv, char const *const *envp) if (verbosity >= 2) strerr_warni1x("updating state and service directories") ; - update_servicedirs(oldstate, oldn, newstate, newn) ; - update_state_and_compiled(newstate, newn, argv[0]) ; + + /* Pipelines */ + + if (verbosity >= 2) + strerr_warni1x("updating s6rc-fdholder pipe storage") ; + + update_fdholder(&olddb, oldstate, &newdb, newstate, envp, &deadline) ; /* Up transition */ @@ -570,7 +599,7 @@ int main (int argc, char const *const *argv, char const *const *envp) if (!tain_future(&deadline)) strerr_dief1x(1, "timed out") ; { - char const *newargv[12 + (dryrun * 5) + want_count(newstate, newn)] ; + char const *newargv[11 + (dryrun * 5) + want_count(newstate, newn)] ; unsigned int m = 0, i = newn ; char vfmt[UINT_FMT] ; char tfmt[UINT_FMT] ; @@ -591,8 +620,7 @@ int main (int argc, char const *const *argv, char const *const *envp) newargv[m++] = tfmt ; newargv[m++] = "-l" ; newargv[m++] = live ; - newargv[m++] = "-aX" ; - newargv[m++] = "-u" ; + newargv[m++] = "-Xua" ; newargv[m++] = "--" ; newargv[m++] = "change" ; while (i--) if (newstate[i] & 2) |