diff options
-rw-r--r-- | package/deps.mak | 4 | ||||
-rw-r--r-- | src/s6-rc/deps-exe/s6-rc-update | 1 | ||||
-rw-r--r-- | src/s6-rc/s6-rc-db.c | 18 | ||||
-rw-r--r-- | src/s6-rc/s6-rc-update.c | 402 | ||||
-rw-r--r-- | src/s6-rc/s6-rc.c | 55 |
5 files changed, 440 insertions, 40 deletions
diff --git a/package/deps.mak b/package/deps.mak index 520f9a3..a5d7b1d 100644 --- a/package/deps.mak +++ b/package/deps.mak @@ -14,7 +14,7 @@ src/s6-rc/s6-rc-compile.o src/s6-rc/s6-rc-compile.lo: src/s6-rc/s6-rc-compile.c 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/s6rc.h src/s6-rc/s6-rc-dryrun.o src/s6-rc/s6-rc-dryrun.lo: src/s6-rc/s6-rc-dryrun.c src/s6-rc/s6-rc-init.o src/s6-rc/s6-rc-init.lo: src/s6-rc/s6-rc-init.c src/include/s6-rc/s6rc.h -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/s6rc-constants.h +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: src/libs6rc/s6rc_db_check_depcycles.o src/libs6rc/s6rc_db_read.o src/libs6rc/s6rc_db_read_sizes.o src/libs6rc/s6rc_db_read_uint32.o src/libs6rc/s6rc_db_check_revdeps.o src/libs6rc/s6rc_graph_closure.o @@ -30,4 +30,4 @@ s6-rc-dryrun: src/s6-rc/s6-rc-dryrun.o -lskarnet s6-rc-init: private EXTRA_LIBS := ${TAINNOW_LIB} ${SOCKET_LIB} s6-rc-init: src/s6-rc/s6-rc-init.o ${LIBS6RC} -ls6 -lskarnet s6-rc-update: private EXTRA_LIBS := ${TAINNOW_LIB} -s6-rc-update: src/s6-rc/s6-rc-update.o ${LIBS6RC} -ls6 -lskarnet +s6-rc-update: src/s6-rc/s6-rc-update.o ${LIBS6RC} -ls6 -lexecline -lskarnet diff --git a/src/s6-rc/deps-exe/s6-rc-update b/src/s6-rc/deps-exe/s6-rc-update index b76070e..ba32165 100644 --- a/src/s6-rc/deps-exe/s6-rc-update +++ b/src/s6-rc/deps-exe/s6-rc-update @@ -1,4 +1,5 @@ ${LIBS6RC} -ls6 +-lexecline -lskarnet ${TAINNOW_LIB} diff --git a/src/s6-rc/s6-rc-db.c b/src/s6-rc/s6-rc-db.c index 5d0493c..aeaff76 100644 --- a/src/s6-rc/s6-rc-db.c +++ b/src/s6-rc/s6-rc-db.c @@ -38,7 +38,7 @@ static void print_bundle_contents (char const *name) strerr_diefu3sys(111, "cdb_init ", compiled, "/resolve.cdb") ; r = cdb_find(&c, name, str_len(name)) ; if (r < 0) strerr_diefu3sys(111, "read ", compiled, "/resolve.cdb") ; - if (!r) strerr_dief3x(1, name, " is not a valid identifier in ", compiled) ; + if (!r) strerr_dief3x(3, name, " is not a valid identifier in ", compiled) ; if (cdb_datalen(&c) == 4) { uint32 x ; @@ -49,7 +49,7 @@ static void print_bundle_contents (char const *name) if (x >= db->nshort + db->nlong) strerr_dief2x(4, "invalid database in ", compiled) ; if (!str_diff(name, db->string + db->services[x].name)) - strerr_dief5x(1, "in database ", compiled, ": identifier ", name, " represents an atomic service") ; + strerr_dief5x(5, "in database ", compiled, ": identifier ", name, " represents an atomic service") ; if (buffer_puts(buffer_1, db->string + db->services[x].name) < 0 || buffer_put(buffer_1, "\n", 1) < 0) strerr_diefu1sys(111, "write to stdout") ; @@ -144,7 +144,7 @@ static unsigned int resolve_service (char const *name) strerr_diefu3sys(111, "cdb_init ", compiled, "/resolve.cdb") ; r = cdb_find(&c, name, str_len(name)) ; if (r < 0) strerr_diefu3sys(111, "read ", compiled, "/resolve.cdb") ; - if (!r) strerr_dief3x(1, name, " is not a valid identifier in ", compiled) ; + if (!r) strerr_dief3x(3, name, " is not a valid identifier in ", compiled) ; if (cdb_datalen(&c) != 4) return db->nshort + db->nlong ; if (cdb_read(&c, pack, 4, cdb_datapos(&c)) < 0) strerr_diefu3sys(111, "cdb_read ", compiled, "/resolve.cdb") ; @@ -173,7 +173,7 @@ static void print_timeout (char const *name, int h) unsigned int len ; char fmt[UINT32_FMT] ; if (n >= db->nshort + db->nlong) - strerr_dief5x(1, "in database ", compiled, ": identifier ", name, " represents a bundle") ; + strerr_dief5x(5, "in database ", compiled, ": identifier ", name, " represents a bundle") ; len = uint32_fmt(fmt, db->services[n].timeout[h]) ; fmt[len++] = '\n' ; if (buffer_putflush(buffer_1, fmt, len) < 0) @@ -184,7 +184,7 @@ static void print_servicedir (char const *name) { unsigned int n = resolve_service(name) ; if (n >= db->nlong) - strerr_dief5x(1, "in database ", compiled, ": identifier ", name, " does not represent a longrun service") ; + strerr_dief5x(5, "in database ", compiled, ": identifier ", name, " does not represent a longrun service") ; if (buffer_puts(buffer_1, db->string + db->services[n].x.longrun.servicedir) < 0 || buffer_putflush(buffer_1, "\n", 1) < 0) strerr_diefu1sys(111, "write to stdout") ; @@ -196,9 +196,9 @@ static void print_script (char const *name, int h) char const *const *argv ; unsigned int n = resolve_service(name) ; if (n >= db->nshort + db->nlong) - strerr_dief5x(1, "in database ", compiled, ": identifier ", name, " represents a bundle") ; + strerr_dief5x(5, "in database ", compiled, ": identifier ", name, " represents a bundle") ; if (n < db->nlong) - strerr_dief5x(1, "in database ", compiled, ": identifier ", name, " represents a longrun service") ; + strerr_dief5x(5, "in database ", compiled, ": identifier ", name, " represents a longrun service") ; argv = db->argvs + db->services[n].x.oneshot.argv[h] ; argc = db->services[n].x.oneshot.argc[h] ; while (argc--) @@ -214,7 +214,7 @@ static inline void print_flags (char const *name) unsigned int n = resolve_service(name) ; char fmt[9] = "00000000\n" ; if (n >= db->nshort + db->nlong) - strerr_dief5x(1, "in database ", compiled, ": identifier ", name, " represents a bundle") ; + strerr_dief5x(5, "in database ", compiled, ": identifier ", name, " represents a bundle") ; uint320_xfmt(fmt, db->services[n].flags, 8) ; if (buffer_putflush(buffer_1, fmt, 9) < 0) strerr_diefu1sys(111, "write to stdout") ; @@ -234,7 +234,7 @@ static void print_union (char const *const *argv, int h, int isdeps, int doclosu { register int r = cdb_find(&c, *argv, str_len(*argv)) ; if (r < 0) strerr_diefu3sys(111, "read ", compiled, "/resolve.cdb") ; - if (!r) strerr_dief3x(1, *argv, " is not a valid identifier in ", compiled) ; + if (!r) strerr_dief3x(3, *argv, " is not a valid identifier in ", compiled) ; { unsigned int len = cdb_datalen(&c) >> 2 ; char pack[cdb_datalen(&c) + 1] ; diff --git a/src/s6-rc/s6-rc-update.c b/src/s6-rc/s6-rc-update.c index 7e9af38..059bc84 100644 --- a/src/s6-rc/s6-rc-update.c +++ b/src/s6-rc/s6-rc-update.c @@ -1,22 +1,32 @@ /* ISC license. */ +#include <sys/types.h> +#include <sys/wait.h> #include <unistd.h> #include <errno.h> #include <stdio.h> +#include <skalibs/uint32.h> +#include <skalibs/uint.h> #include <skalibs/bytestr.h> #include <skalibs/sgetopt.h> #include <skalibs/strerr2.h> +#include <skalibs/bitarray.h> +#include <skalibs/cdb.h> #include <skalibs/stralloc.h> #include <skalibs/djbunix.h> #include <skalibs/skamisc.h> +#include <skalibs/unix-transactional.h> +#include <execline/execline.h> #include <s6/s6-supervise.h> -#include <s6-rc/s6rc-constants.h> +#include <s6-rc/config.h> +#include <s6-rc/s6rc.h> -#define USAGE "s6-rc-update [ -l live ]" +#define USAGE "s6-rc-update [ -n ] [ -v verbosity ] [ -t timeout ] [ -l live ] newdb" #define dieusage() strerr_dieusage(100, USAGE) #define dienomem() strerr_diefu1sys(111, "build string") ; static char const *live = S6RC_LIVE_BASE ; +static unsigned int verbosity = 1 ; static int safe_servicedir_update (char const *dst, char const *src, int h) { @@ -115,8 +125,394 @@ static int servicedir_name_change (char const *live, char const *oldname, char c return 1 ; } -int main (int argc, char const *const *argv) +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 ; + unsigned int oldn = olddb->nshort + olddb->nlong ; + unsigned int max ; + register int r ; + if (!stralloc_readyplus(sa, slen)) dienomem() ; + sa->len += slen ; + r = el_parse_from_string(sa, s) ; + switch (r) + { + case -1 : dienomem() ; + case -2 : strerr_dief2x(100, "syntax error in conversion file: ", s) ; + case -3 : strerr_dief2x(100, "mismatched braces in conversion file: ", s) ; + default : break ; + } + max = sa->len ; + sa->len = base ; + if (r >= 2) + { + char pack[4] ; + uint32 x ; + unsigned int cur ; + int r = cdb_find(oldc, sa->s + base + slen, str_len(sa->s + base + slen)) ; + if (r < 0) strerr_diefu3sys(111, "read ", live, "/compiled/resolve.cdb") ; + if (!r) strerr_dief5x(3, "unknown identifier in ", live, "/compiled/resolve.cdb", ": ", sa->s + base + slen) ; + if (cdb_datalen(oldc) != 4) strerr_dief5x(5, "identifier ", sa->s + base + slen, " does not represent an atomic service in ", live, "/compiled") ; + if (cdb_read(oldc, pack, 4, cdb_datapos(oldc)) < 0) + strerr_diefu3sys(111, "read ", live, "/compiled/resolve.cdb") ; + uint32_unpack_big(pack, &x) ; + if (x >= oldn) strerr_dief3x(4, "invalid database in ", live, "/compiled") ; + cur = base + slen + str_len(sa->s + base + slen) ; + + } +} + +static inline void parse_conversion_file (stralloc *sa, unsigned int *newnames, unsigned char *oldstate, int fdoldc, s6rc_db_t const *olddb) +{ + unsigned int base = satmp.len ; + cdb_t oldc = CDB_ZERO ; + int oldfdres = open_readatb(fdoldc, "resolve.cdb") ; + if (oldfdres < 0) strerr_diefu3sys(111, "open ", live, "/compiled/resolve.cdb") ; + if (!cdb_init_map(&oldc, oldfdres, 1)) + strerr_diefu3sys(111, "cdb_init ", live, "/compiled/resolve.cdb") ; + + for (;;) + { + register int r = skagetln(buffer_0, &satmp, '\n') ; + if (!r) break ; + if (r < 0) + { + if (errno != EPIPE) strerr_diefu1sys(111, "read from stdin") ; + if (!stralloc_0(&satmp)) dienomem() ; + } + else satmp.s[satmp.len - 1] = 0 ; + parse_line(sa, satmp.s + base, satmp.len - base, newnames, oldstate, &oldc, olddb) ; + satmp.len = base ; + } + + satmp.len = base ; + 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, int fdnewc, char const *newfn, s6rc_db_t const *olddb, s6rc_db_t const *newdb) +{ + unsigned int newn = newdb->nshort + newdb->nlong ; + cdb_t newc = CDB_ZERO ; + int newfdres = open_readatb(fdnewc, "resolve.cdb") ; + unsigned int i = olddb->nshort + olddb->nlong ; + if (newfdres < 0) strerr_diefu3sys(111, "open ", newfn, "/resolve.cdb") ; + if (!cdb_init_map(&newc, newfdres, 1)) + strerr_diefu3sys(111, "cdb_init ", newfn, "/resolve.cdb") ; + + while (i--) + { + char const *newname = oldstate[i] & 16 ? namedata + nameindex[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") ; + if (!r) + { + oldstate[i] |= 2 ; /* disappeared -> want down */ + continue ; + } + if (cdb_datalen(&newc) & 3) + strerr_dief3x(4, "invalid resolve database in ", newfn, "/resolve.cdb") ; + len = cdb_datalen(&newc) >> 2 ; + if (len > newn) + strerr_dief3x(4, "invalid resolve database in ", newfn, "/resolve.cdb") ; + { + char pack[cdb_datalen(&newc) + 1] ; + 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 */ + while (len--) + { + uint32 x ; + uint32_unpack_big(p, &x) ; p += 4 ; + if (x >= newn) + strerr_dief3x(4, "invalid resolve database in ", newfn, "/resolve.cdb") ; + if (newstate[x] & 4) + 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) ; + } + } + } + + 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) +{ + 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 ; + } + } +} + +static void compute_transitions (unsigned char *oldstate, int fdoldc, s6rc_db_t const *olddb, unsigned char *newstate, int fdnewc, char const *newfn, s6rc_db_t const *newdb) +{ + unsigned int oldn = olddb->nshort + olddb->nlong ; + unsigned int newn = newdb->nshort + newdb->nlong ; + unsigned char conversion_table[oldn * bitarray_div8(newn)] ; + byte_zero(conversion_table, oldn * bitarray_div8(newn)) ; + { + stralloc namedata = STRALLOC_ZERO ; + unsigned int nameindex[oldn] ; + parse_conversion_file(&namedata, nameindex, oldstate, fdoldc, olddb) ; + fill_convtable_and_flags(conversion_table, oldstate, newstate, namedata.s, nameindex, fdnewc, newfn, olddb, newdb) ; + stralloc_free(&namedata) ; + } + adjust_newwantup(oldstate, oldn, newstate, newn, conversion_table) ; + s6rc_graph_closure(olddb, oldstate, 5, 0) ; + adjust_newalreadyup(oldstate, oldn, newstate, newn, conversion_table) ; +} + +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 ; +} + +static void fill_tfmt (char *tfmt, tain_t const *deadline) +{ + int t ; + tain_t tto ; + tain_sub(&tto, deadline, &STAMP) ; + t = tain_to_millisecs(&tto) ; + if (!t) t = 1 ; + else if (t < 0) t = 0 ; + tfmt[uint_fmt(tfmt, t)] = 0 ; +} + +int main (int argc, char const *const *argv, char const *const *envp) +{ + tain_t deadline ; + char const *live = S6RC_LIVE_BASE ; + unsigned int livelen ; + int dryrun = 0 ; PROG = "s6-rc-update" ; strerr_dief1x(100, "this utility has not been written yet.") ; + { + unsigned int t = 0 ; + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "v:t:nl:", &l) ; + if (opt == -1) break ; + switch (opt) + { + 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 ; break ; + default : dieusage() ; + } + } + argc -= l.ind ; argv += l.ind ; + if (t) tain_from_millisecs(&deadline, t) ; + else deadline = tain_infinite_relative ; + } + if (argc < 2) dieusage() ; + + livelen = str_len(live) ; + + { + int livelock ; + int fdoldc, fdnewc ; + s6rc_db_t olddb, newdb ; + unsigned int oldn, oldm, newn, newm ; + char dbfn[livelen + 10] ; + + if (!tain_now_g()) + strerr_warnwu1x("get correct TAI time. (Do you have a valid leap seconds file?)") ; + tain_add_g(&deadline, &deadline) ; + + + /* Take the live lock */ + + 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 (lock_ex(livelock) < 0) strerr_diefu2sys(111, "lock ", dbfn) ; + + + /* 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 */ + + { + pid_t pid ; + 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] ; + char newstringblob[newdb.stringlen] ; + unsigned char oldstate[oldn] ; + unsigned char newstate[newn] ; + register int r ; + + olddb.services = oldserviceblob ; + olddb.argvs = oldargvblob ; + olddb.deps = olddepsblob ; + olddb.string = oldstringblob ; + newdb.services = newserviceblob ; + newdb.argvs = newargvblob ; + newdb.deps = newdepsblob ; + newdb.string = newstringblob ; + + + /* Read the dbs */ + + r = s6rc_db_read(fdoldc, &olddb) ; + if (r < 0) strerr_diefu3sys(111, "read ", dbfn, "/db") ; + if (!r) strerr_dief3x(4, "invalid service database in ", dbfn, "/db") ; + r = s6rc_db_read(fdnewc, &newdb) ; + if (r < 0) strerr_diefu3sys(111, "read ", argv[0], "/db") ; + if (!r) strerr_dief3x(4, "invalid service database in ", argv[0], "/db") ; + + + /* Initial state */ + + 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 ; + } + } + + + /* Read the conversion file and compute what to do */ + + if (verbosity >= 2) strerr_warni1x("computing state adjustments") ; + compute_transitions(oldstate, fdoldc, &olddb, newstate, fdnewc, argv[0], &newdb) ; + tain_now_g() ; + if (!tain_future(&deadline)) strerr_dief1x(1, "timed out") ; + + + /* Down transition */ + + { + char const *newargv[12 + (dryrun * 5) + want_count(oldstate, oldn)] ; + unsigned int m = 0, i = oldn ; + int wstat ; + char vfmt[UINT_FMT] ; + char tfmt[UINT_FMT] ; + vfmt[uint_fmt(vfmt, verbosity)] = 0 ; + fill_tfmt(tfmt, &deadline) ; + if (dryrun) + { + newargv[m++] = S6RC_BINPREFIX "s6-rc-dryrun" ; + newargv[m++] = "-v" ; + newargv[m++] = vfmt ; + newargv[m++] = "-t0" ; + newargv[m++] = "--" ; + } + newargv[m++] = S6RC_BINPREFIX "s6-rc" ; + newargv[m++] = "-v" ; + newargv[m++] = vfmt ; + newargv[m++] = "-t" ; + newargv[m++] = tfmt ; + newargv[m++] = "-l" ; + newargv[m++] = live ; + newargv[m++] = "-X" ; + newargv[m++] = "-d" ; + newargv[m++] = "--" ; + newargv[m++] = "change" ; + while (i--) if (oldstate[i] & 2) + newargv[m++] = olddb.string + olddb.services[i].name ; + newargv[m++] = 0 ; + if (verbosity >= 2) + strerr_warni1x("stopping services in the old database") ; + 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") ; + if (WIFSIGNALED(wstat) || WEXITSTATUS(wstat)) + strerr_diefu1sys(wait_estatus(wstat), "first s6-rc invocation failed") ; + } + + + /* Service directory and state switch */ + + if (verbosity >= 2) + strerr_warni1x("updating state and service directories") ; + + + /* Up transition */ + + if (!tain_future(&deadline)) strerr_dief1x(1, "timed out") ; + + { + char const *newargv[12 + (dryrun * 5) + want_count(newstate, newn)] ; + unsigned int m = 0, i = newn ; + char vfmt[UINT_FMT] ; + char tfmt[UINT_FMT] ; + vfmt[uint_fmt(vfmt, verbosity)] = 0 ; + fill_tfmt(tfmt, &deadline) ; + if (dryrun) + { + newargv[m++] = S6RC_BINPREFIX "s6-rc-dryrun" ; + newargv[m++] = "-v" ; + newargv[m++] = vfmt ; + newargv[m++] = "-t0" ; + newargv[m++] = "--" ; + } + newargv[m++] = S6RC_BINPREFIX "s6-rc" ; + newargv[m++] = "-v" ; + newargv[m++] = vfmt ; + newargv[m++] = "-t" ; + newargv[m++] = tfmt ; + newargv[m++] = "-l" ; + newargv[m++] = live ; + newargv[m++] = "-aX" ; + newargv[m++] = "-u" ; + newargv[m++] = "--" ; + newargv[m++] = "change" ; + while (i--) if (newstate[i] & 2) + newargv[m++] = newdb.string + newdb.services[i].name ; + newargv[m++] = 0 ; + if (verbosity >= 2) + strerr_warni1x("starting services in the new database") ; + pathexec_run(newargv[0], newargv, envp) ; + strerr_dieexec(111, newargv[0]) ; + } + } + } } diff --git a/src/s6-rc/s6-rc.c b/src/s6-rc/s6-rc.c index 1f1ab3f..2cb4caa 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 ; + int up = 1, prune = 0, selectlive = 0, takelock = 1 ; unsigned int what ; PROG = "s6-rc" ; { @@ -380,7 +380,7 @@ int main (int argc, char const *const *argv) subgetopt_t l = SUBGETOPT_ZERO ; for (;;) { - register int opt = subgetopt_r(argc, argv, "v:n:t:l:udpa", &l) ; + register int opt = subgetopt_r(argc, argv, "v:n:t:l:udpaX", &l) ; if (opt == -1) break ; switch (opt) { @@ -398,6 +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 ; default : dieusage() ; } } @@ -416,7 +417,6 @@ int main (int argc, char const *const *argv) livelen = str_len(live) ; { - int livelock ; int fdcompiled ; s6rc_db_t dbblob ; char dbfn[livelen + 10] ; @@ -425,18 +425,23 @@ int main (int argc, char const *const *argv) /* Take the live lock */ - 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) ; + if (takelock) + { + 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 */ + } /* Read the sizes of the compiled db */ - byte_copy(dbfn + livelen + 1, 9, "compiled") ; + byte_copy(dbfn + livelen, 10, "/compiled") ; fdcompiled = open_readb(dbfn) ; if (!s6rc_db_read_sizes(fdcompiled, &dbblob)) strerr_diefu3sys(111, "read ", dbfn, "/n") ; @@ -459,7 +464,19 @@ int main (int argc, char const *const *argv) dbblob.deps = depsblob ; dbblob.string = stringblob ; state = stateblob ; - byte_zero(state, n) ; + + + /* Read live state in bit 0 of state */ + + byte_copy(dbfn + livelen + 1, 6, "state") ; + { + r = openreadnclose(dbfn, (char *)state, n) ; + if (r != n) strerr_diefu2sys(111, "read ", dbfn) ; + { + register unsigned int i = n ; + while (i--) state[i] &= 1 ; + } + } /* Read the db from the file */ @@ -511,20 +528,6 @@ int main (int argc, char const *const *argv) close(fdcompiled) ; - /* Read live state in bit 0 of state */ - - byte_copy(dbfn + livelen + 1, 6, "state") ; - { - char tmpstate[n] ; - r = openreadnclose(dbfn, tmpstate, n) ; - if (r != n) strerr_diefu2sys(111, "read ", dbfn) ; - { - register unsigned int i = n ; - while (i--) if (tmpstate[i]) state[i] |= 1 ; - } - } - - /* Add live state to selection */ if (selectlive) |