summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2015-08-29 20:25:40 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2015-08-29 20:25:40 +0000
commitee111aabf49128fe88968f658b0f4b683a3caa00 (patch)
tree4e62e9b5728eb711ff48d8ff017ab48aeb6f9775 /src
parent381b64487199a9edd46e84f7ff134722c3c3bcfc (diff)
downloads6-rc-ee111aabf49128fe88968f658b0f4b683a3caa00.tar.xz
- some work on s6-rc-update
- add s6-rc-bundle and relevant doc
Diffstat (limited to 'src')
-rw-r--r--src/include/s6-rc/s6rc-utils.h1
-rw-r--r--src/libs6rc/deps-lib/s6rc1
-rw-r--r--src/libs6rc/s6rc_lock.c48
-rw-r--r--src/s6-rc/deps-exe/s6-rc-bundle3
-rw-r--r--src/s6-rc/s6-rc-bundle.c364
-rw-r--r--src/s6-rc/s6-rc-compile.c3
-rw-r--r--src/s6-rc/s6-rc-db.c15
-rw-r--r--src/s6-rc/s6-rc-init.c39
-rw-r--r--src/s6-rc/s6-rc-update.c108
-rw-r--r--src/s6-rc/s6-rc.c28
10 files changed, 502 insertions, 108 deletions
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") ;