summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2015-08-12 20:00:17 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2015-08-12 20:00:17 +0000
commit9473830ad612dcb674f6048a9a17e372ff9d9ec3 (patch)
tree6cf045657b34be4b6fd685c68993b13bf7e55f26 /src
parentabfd58b78188c3408599b98fcce611349bfa8b9c (diff)
downloads6-rc-9473830ad612dcb674f6048a9a17e372ff9d9ec3.tar.xz
Intermediary commit; working on source dir format change. Should work, but untested as for now.
Diffstat (limited to 'src')
-rw-r--r--src/include/s6-rc/s6rc-constants.h3
-rw-r--r--src/include/s6-rc/s6rc-db.h6
-rw-r--r--src/libs6rc/deps-lib/s6rc4
-rw-r--r--src/libs6rc/s6rc_db_check_depcycles.c26
-rw-r--r--src/libs6rc/s6rc_db_check_revdeps.c5
-rw-r--r--src/libs6rc/s6rc_db_read.c5
-rw-r--r--src/s6-rc/s6-rc-compile.c660
-rw-r--r--src/s6-rc/s6-rc-db.c58
-rw-r--r--src/s6-rc/s6-rc-update.c101
-rw-r--r--src/s6-rc/s6-rc.c8
10 files changed, 617 insertions, 259 deletions
diff --git a/src/include/s6-rc/s6rc-constants.h b/src/include/s6-rc/s6rc-constants.h
index 92af2a9..87e7053 100644
--- a/src/include/s6-rc/s6rc-constants.h
+++ b/src/include/s6-rc/s6rc-constants.h
@@ -11,4 +11,7 @@
#define S6RC_ONESHOT_RUNNER "s6rc-oneshot-runner"
#define S6RC_ONESHOT_RUNNER_LEN (sizeof S6RC_ONESHOT_RUNNER - 1)
+#define S6RC_FDHOLDER "s6rc-fdholder"
+#define S6RC_FDHOLDER_LEN (sizeof S6RC_FDHOLDER - 1)
+
#endif
diff --git a/src/include/s6-rc/s6rc-db.h b/src/include/s6-rc/s6rc-db.h
index bc516b2..0053af9 100644
--- a/src/include/s6-rc/s6rc-db.h
+++ b/src/include/s6-rc/s6rc-db.h
@@ -4,6 +4,7 @@
#define S6RC_DB_H
#include <skalibs/uint32.h>
+#include <skalibs/diuint32.h>
#include <skalibs/buffer.h>
#define S6RC_DB_BANNER_START "s6rc-db: start\n"
@@ -22,7 +23,7 @@ struct s6rc_oneshot_s
typedef struct s6rc_longrun_s s6rc_longrun_t, *s6rc_longrun_t_ref ;
struct s6rc_longrun_s
{
- uint32 servicedir ;
+ uint32 pipeline[2] ;
} ;
typedef union s6rc_longshot_u s6rc_longshot_t, *s6rc_longshot_t_ref ;
@@ -62,7 +63,8 @@ extern int s6rc_db_read_uint32 (buffer *, uint32 *) ;
extern int s6rc_db_read_sizes (int, s6rc_db_t *) ;
extern int s6rc_db_read (int, s6rc_db_t *) ;
-extern unsigned int s6rc_db_check_depcycles (s6rc_db_t const *, int, unsigned int *) ;
+extern int s6rc_db_check_pipelines (s6rc_db_t const *, diuint32 *) ;
+extern int s6rc_db_check_depcycles (s6rc_db_t const *, int, diuint32 *) ;
extern int s6rc_db_check_revdeps (s6rc_db_t const *) ;
#endif
diff --git a/src/libs6rc/deps-lib/s6rc b/src/libs6rc/deps-lib/s6rc
index 65b562e..194ea43 100644
--- a/src/libs6rc/deps-lib/s6rc
+++ b/src/libs6rc/deps-lib/s6rc
@@ -1,6 +1,8 @@
s6rc_db_check_depcycles.o
+s6rc_db_check_pipelines.o
+s6rc_db_check_revdeps.o
s6rc_db_read.o
s6rc_db_read_sizes.o
s6rc_db_read_uint32.o
-s6rc_db_check_revdeps.o
s6rc_graph_closure.o
+-lskarnet
diff --git a/src/libs6rc/s6rc_db_check_depcycles.c b/src/libs6rc/s6rc_db_check_depcycles.c
index 13dcf7b..db6ed6e 100644
--- a/src/libs6rc/s6rc_db_check_depcycles.c
+++ b/src/libs6rc/s6rc_db_check_depcycles.c
@@ -1,6 +1,7 @@
/* ISC license. */
#include <skalibs/uint32.h>
+#include <skalibs/diuint32.h>
#include <skalibs/bitarray.h>
#include <skalibs/bytestr.h>
#include <s6-rc/s6rc-db.h>
@@ -9,22 +10,22 @@ typedef struct recinfo_s recinfo_t, *recinfo_t_ref ;
struct recinfo_s
{
s6rc_db_t const *db ;
- unsigned int n ;
+ uint32 n ;
unsigned char *gray ;
unsigned char *black ;
unsigned char h : 1 ;
} ;
-static unsigned int s6rc_db_checknocycle_rec (recinfo_t *recinfo, unsigned int i)
+static uint32 s6rc_db_checknocycle_rec (recinfo_t *recinfo, uint32 i)
{
if (!bitarray_peek(recinfo->black, i))
{
- unsigned int j = recinfo->db->services[i].ndeps[recinfo->h] ;
+ uint32 j = recinfo->db->services[i].ndeps[recinfo->h] ;
if (bitarray_peek(recinfo->gray, i)) return i ;
bitarray_set(recinfo->gray, i) ;
while (j--)
{
- register unsigned int r = s6rc_db_checknocycle_rec(recinfo, recinfo->db->deps[recinfo->h * recinfo->db->ndeps + recinfo->db->services[i].deps[recinfo->h] + j]) ;
+ register uint32 r = s6rc_db_checknocycle_rec(recinfo, recinfo->db->deps[recinfo->h * recinfo->db->ndeps + recinfo->db->services[i].deps[recinfo->h] + j]) ;
if (r < recinfo->n) return r ;
}
bitarray_set(recinfo->black, i) ;
@@ -32,19 +33,24 @@ static unsigned int s6rc_db_checknocycle_rec (recinfo_t *recinfo, unsigned int i
return recinfo->n ;
}
-unsigned int s6rc_db_check_depcycles (s6rc_db_t const *db, int h, unsigned int *problem)
+int s6rc_db_check_depcycles (s6rc_db_t const *db, int h, diuint32 *problem)
{
- unsigned int n = db->nshort + db->nlong ;
+ uint32 n = db->nshort + db->nlong ;
+ uint32 i = n ;
unsigned char gray[bitarray_div8(n)] ;
unsigned char black[bitarray_div8(n)] ;
recinfo_t info = { .db = db, .n = n, .gray = gray, .black = black, .h = !!h } ;
- unsigned int i = n ;
byte_zero(gray, bitarray_div8(n)) ;
byte_zero(black, bitarray_div8(n)) ;
while (i--)
{
- register unsigned int r = s6rc_db_checknocycle_rec(&info, i) ;
- if (r < n) return (*problem = r, i) ;
+ register uint32 r = s6rc_db_checknocycle_rec(&info, i) ;
+ if (r < n)
+ {
+ problem->left = i ;
+ problem->right = r ;
+ return 1 ;
+ }
}
- return n ;
+ return 0 ;
}
diff --git a/src/libs6rc/s6rc_db_check_revdeps.c b/src/libs6rc/s6rc_db_check_revdeps.c
index 0cb2845..a4342b1 100644
--- a/src/libs6rc/s6rc_db_check_revdeps.c
+++ b/src/libs6rc/s6rc_db_check_revdeps.c
@@ -1,6 +1,5 @@
/* ISC license. */
-#include <skalibs/uint32.h>
#include <skalibs/bytestr.h>
#include <skalibs/bitarray.h>
#include <s6-rc/s6rc-db.h>
@@ -25,6 +24,6 @@ int s6rc_db_check_revdeps (s6rc_db_t const *db)
while (j--) bitarray_not(matrix + m * db->deps[db->services[i].deps[0] + j], i, 1) ;
}
i = n * m ;
- while (i--) if (*p++) return 0 ;
- return 1 ;
+ while (i--) if (*p++) return 1 ;
+ return 0 ;
}
diff --git a/src/libs6rc/s6rc_db_read.c b/src/libs6rc/s6rc_db_read.c
index 7a38797..50e1f78 100644
--- a/src/libs6rc/s6rc_db_read.c
+++ b/src/libs6rc/s6rc_db_read.c
@@ -90,9 +90,8 @@ static inline int s6rc_db_read_services (buffer *b, s6rc_db_t *db)
#endif
if (i < db->nlong)
{
- if (!s6rc_db_read_uint32(b, &sv->x.longrun.servicedir)) return -1 ;
- DBG(" longrun - servicedir is %u: %s", sv->x.longrun.servicedir, db->string + sv->x.longrun.servicedir) ;
- if (!s6rc_db_check_valid_string(db->string, db->stringlen, sv->x.longrun.servicedir)) return 0 ;
+ if (!s6rc_db_read_uint32(b, &sv->x.longrun.pipeline[0])) return -1 ;
+ if (!s6rc_db_read_uint32(b, &sv->x.longrun.pipeline[1])) return -1 ;
}
else
{
diff --git a/src/s6-rc/s6-rc-compile.c b/src/s6-rc/s6-rc-compile.c
index 1126967..a1ffdee 100644
--- a/src/s6-rc/s6-rc-compile.c
+++ b/src/s6-rc/s6-rc-compile.c
@@ -27,10 +27,12 @@
#include <s6/config.h>
#include <s6-rc/s6rc.h>
-#define USAGE "s6-rc-compile [ -v verbosity ] [ -u okuid,okuid... ] [ -g okgid,okgid... ] destdir sources..."
+#define USAGE "s6-rc-compile [ -v verbosity ] [ -u okuid,okuid... ] [ -g okgid,okgid... ] [ -h fdholder_user ] destdir sources..."
#define dieusage() strerr_dieusage(100, USAGE)
#define dienomem() strerr_dief1x(111, "out of memory") ;
+#define S6RC_INTERNALS "s6-rc-compile internals"
+
#define S6RC_ONESHOT_RUNNER_RUNSCRIPT \
"#!" EXECLINE_SHEBANGPREFIX "execlineb -P\n" \
EXECLINE_EXTBINPREFIX "fdmove -c 2 1\n" \
@@ -40,8 +42,6 @@ S6_EXTBINPREFIX "s6-ipcserverd -1 --\n" \
S6_EXTBINPREFIX "s6-ipcserver-access -v0 -E -l0 -i data/rules --\n" \
S6_EXTBINPREFIX "s6-sudod -t 2000 --\n"
-#define BASE_RULES "servicedirs/" S6RC_ONESHOT_RUNNER "/data/rules/gid"
-
static unsigned int verbosity = 1 ;
static stralloc keep = STRALLOC_ZERO ;
static stralloc data = STRALLOC_ZERO ;
@@ -91,7 +91,6 @@ static avltree names_map = AVLTREE_INIT(8, 3, 8, &names_dtok, &names_cmp, &namei
typedef struct common_s common_t, *common_t_ref ;
struct common_s
{
- unsigned int name ; /* pos in data */
unsigned int kname ; /* pos in keep */
unsigned int ndeps ;
unsigned int depindex ; /* pos in indices */
@@ -103,7 +102,7 @@ typedef struct oneshot_s oneshot_t, *oneshot_t_ref ;
struct oneshot_s
{
common_t common ;
- unsigned int argvindex[2] ; /* pos in data */
+ unsigned int argvindex[2] ; /* pos in keep */
unsigned int argc[2] ;
} ;
@@ -112,9 +111,8 @@ struct longrun_s
{
common_t common ;
char const *srcdir ;
- unsigned int servicedirname ;
- unsigned int logrelated ;
- unsigned char logtype ;
+ unsigned int pipeline[2] ; /* pos in data */
+ unsigned int pipelinename ; /* pos in data */
} ;
typedef struct bundle_s bundle_t, *bundle_t_ref ;
@@ -128,19 +126,19 @@ struct bundle_s
typedef struct before_s before_t, *before_t_ref ;
struct before_s
{
- genalloc indices ; /* uint32 */
+ genalloc indices ; /* unsigned int */
genalloc oneshots ; /* oneshot_t */
genalloc longruns ; /* longrun_t */
genalloc bundles ; /* bundle_t */
unsigned int nargvs ;
- unsigned int maxnamelen ;
+ uint32 specialdeps[2] ;
} ;
-#define BEFORE_ZERO { .indices = GENALLOC_ZERO, .oneshots = GENALLOC_ZERO, .longruns = GENALLOC_ZERO, .bundles = GENALLOC_ZERO, .nargvs = 0 } ;
+#define BEFORE_ZERO { .indices = GENALLOC_ZERO, .oneshots = GENALLOC_ZERO, .longruns = GENALLOC_ZERO, .bundles = GENALLOC_ZERO, .nargvs = 0, .specialdeps = { 0, 0 } } ;
- /* Read all the sources, populate the map and string data */
+ /* Read all the sources, populate the name map */
static char const *typestr (servicetype_t type)
@@ -151,7 +149,7 @@ static char const *typestr (servicetype_t type)
"unknown" ;
}
-static int add_name (before_t *be, char const *srcdir, char const *name, servicetype_t type, unsigned int *pos, unsigned int *kpos)
+static int add_name_nocheck (before_t *be, char const *srcdir, char const *name, servicetype_t type, unsigned int *pos, unsigned int *kpos)
{
unsigned int id ;
@@ -214,20 +212,32 @@ static int add_name (before_t *be, char const *srcdir, char const *name, service
} ;
unsigned int namelen = str_len(name) ;
unsigned int i = genalloc_len(nameinfo_t, &nameinfo) ;
- if (!stralloc_catb(&data, name, namelen + 1)) dienomem() ;
if (type == SVTYPE_ONESHOT || type == SVTYPE_LONGRUN)
if (!stralloc_catb(&keep, name, namelen + 1)) dienomem() ;
+ if (!stralloc_catb(&data, name, namelen + 1)) dienomem() ;
if (!genalloc_append(nameinfo_t, &nameinfo, &info)) dienomem() ;
if (!avltree_insert(&names_map, i)) dienomem() ;
*pos = info.pos ;
*kpos = info.kpos ;
- if (namelen > be->maxnamelen) be->maxnamelen = namelen ;
return 0 ;
}
}
-static inline void add_specials (before_t *be)
+static void check_identifier (char const *srcdir, char const *s)
+{
+ if (!byte_diff(s, 5, "s6rc-") && !byte_diff(s, 6, "s6-rc-"))
+ strerr_dief5x(1, "in ", srcdir, ": identifier ", s, " starts with reserved prefix") ;
+}
+
+static int add_name (before_t *be, char const *srcdir, char const *name, servicetype_t type, unsigned int *pos, unsigned int *kpos)
+{
+ check_identifier(srcdir, name) ;
+ return add_name_nocheck(be, srcdir, name, type, pos, kpos) ;
+}
+
+static unsigned int add_internal_longrun (before_t *be, char const *name)
{
+ unsigned int pos ;
longrun_t service =
{
.common =
@@ -238,14 +248,86 @@ static inline void add_specials (before_t *be)
.timeout = { 0, 0 }
},
.srcdir = 0,
- .servicedirname = keep.len,
- .logrelated = 0,
- .logtype = 0
+ .pipeline = { 0, 0 }
} ;
- add_name(be, "(s6-rc-compile internals)", S6RC_ONESHOT_RUNNER, SVTYPE_LONGRUN, &service.common.name, &service.common.kname) ;
- if (!stralloc_cats(&keep, data.s + service.common.name)
- || !stralloc_0(&keep)) dienomem() ;
+ add_name_nocheck(be, S6RC_INTERNALS, name, SVTYPE_LONGRUN, &pos, &service.common.kname) ;
if (!genalloc_append(longrun_t, &be->longruns, &service)) dienomem() ;
+ return pos ;
+}
+
+static unsigned int add_internal_oneshot (before_t *be, char const *name, char const *ups, unsigned int upn, char const *downs, unsigned int downn)
+{
+ unsigned int pos ;
+ oneshot_t service =
+ {
+ .common =
+ {
+ .ndeps = 2,
+ .depindex = genalloc_len(unsigned int, &be->indices),
+ .annotation_flags = 0,
+ .timeout = { 0, 0 }
+ },
+ .argvindex = { keep.len, keep.len + downn }
+ } ;
+ service.argc[0] = byte_count(downs, downn, '\0') ;
+ service.argc[1] = byte_count(ups, upn, '\0') ;
+ if (!genalloc_catb(unsigned int, &be->indices, be->specialdeps, 2)
+ || !stralloc_catb(&keep, downs, downn)
+ || !stralloc_catb(&keep, ups, upn)) dienomem() ;
+ add_name_nocheck(be, S6RC_INTERNALS, name, SVTYPE_ONESHOT, &pos, &service.common.kname) ;
+ if (!genalloc_append(oneshot_t, &be->oneshots, &service)) dienomem() ;
+ return pos ;
+}
+
+static void add_word (char const *word)
+{
+ if (!stralloc_cats(&satmp, word) || !stralloc_0(&satmp)) dienomem() ;
+}
+
+static unsigned int add_storepipe (before_t *be, char const *name)
+{
+ unsigned int pos, sep, base = satmp.len ;
+ unsigned int namelen = str_len(name) ;
+ char svname[16 + namelen] ;
+ byte_copy(svname, 15, "s6rc-storepipe-") ;
+ byte_copy(svname + 15, namelen + 1, name) ;
+
+ add_word(EXECLINE_EXTBINPREFIX "piperw") ;
+ add_word("0") ;
+ add_word("1") ;
+ add_word(EXECLINE_EXTBINPREFIX "if") ;
+ add_word(" " S6_EXTBINPREFIX "s6-fdholder-store") ;
+ add_word(" ../s6rc-fdholder/s") ;
+ add_word(" pipe:s6rc-r-") ; satmp.len-- ; add_word(name) ;
+ add_word("") ;
+ add_word(EXECLINE_EXTBINPREFIX "if") ;
+ add_word("-nt") ;
+ add_word(" " S6_EXTBINPREFIX "s6-fdholder-store") ;
+ add_word(" -d1") ;
+ add_word(" ./s6rc-fdholder/s") ;
+ add_word(" pipe:s6rc-w-") ; satmp.len-- ; add_word(name) ;
+ add_word("") ;
+ add_word(EXECLINE_EXTBINPREFIX "exit") ;
+ add_word("1") ;
+
+ sep = satmp.len ;
+
+ add_word(EXECLINE_EXTBINPREFIX "foreground") ;
+ add_word(" " S6_EXTBINPREFIX "s6-fdholder-delete") ;
+ add_word(" ../s6rc-fdholder/s") ;
+ add_word(" pipe:s6rc-w-") ; satmp.len-- ; add_word(name) ;
+ add_word("") ;
+ add_word(EXECLINE_EXTBINPREFIX "foreground") ;
+ add_word(" " S6_EXTBINPREFIX "s6-fdholder-delete") ;
+ add_word(" ../s6rc-fdholder/s") ;
+ add_word(" pipe:s6rc-r-") ; satmp.len-- ; add_word(name) ;
+ add_word("") ;
+ add_word(EXECLINE_EXTBINPREFIX "exit") ;
+ add_word("0") ;
+
+ pos = add_internal_oneshot(be, svname, satmp.s + base, sep - base, satmp.s + sep, satmp.len - sep) ;
+ satmp.len = base ;
+ return pos ;
}
static int uint_uniq (unsigned int const *list, unsigned int n, unsigned int pos)
@@ -348,8 +430,9 @@ static uint32 read_timeout (int dirfd, char const *srcdir, char const *name, cha
static void add_common (before_t *be, int dirfd, char const *srcdir, char const *name, common_t *common, servicetype_t svtype)
{
+ unsigned int dummy ;
common->annotation_flags = 0 ;
- add_name(be, srcdir, name, svtype, &common->name, &common->kname) ;
+ add_name(be, srcdir, name, svtype, &dummy, &common->kname) ;
if (!add_namelist(be, dirfd, srcdir, name, "dependencies", &common->depindex, &common->ndeps))
{
if (errno != ENOENT)
@@ -363,19 +446,13 @@ static void add_common (before_t *be, int dirfd, char const *srcdir, char const
static inline void add_oneshot (before_t *be, int dirfd, char const *srcdir, char const *name)
{
- static unsigned int const special_dep = 0 ;
oneshot_t service ;
if (verbosity >= 3) strerr_warni3x(name, " has type ", "oneshot") ;
add_common(be, dirfd, srcdir, name, &service.common, SVTYPE_ONESHOT) ;
read_script(be, dirfd, srcdir, name, "up", &service.argvindex[1], &service.argc[1], 1) ;
read_script(be, dirfd, srcdir, name, "down", &service.argvindex[0], &service.argc[0], 0) ;
- if (uint_uniq(genalloc_s(unsigned int, &be->indices) + service.common.depindex, service.common.ndeps, 0))
- {
- if (!genalloc_append(unsigned int, &be->indices, &special_dep)) dienomem() ;
- service.common.ndeps++ ;
- }
- else if (verbosity)
- strerr_warnw6x(srcdir, "/", name, "/dependencies", " explicitly lists ", S6RC_ONESHOT_RUNNER) ;
+ if (!genalloc_append(unsigned int, &be->indices, &be->specialdeps[0])) dienomem() ;
+ service.common.ndeps++ ;
if (verbosity >= 4)
{
unsigned int i = service.common.ndeps ;
@@ -387,16 +464,15 @@ static inline void add_oneshot (before_t *be, int dirfd, char const *srcdir, cha
strerr_warnt7x("dependency from ", name, " to ", data.s + *p, " (", fmt, ")") ;
p++ ;
}
-
}
if (!genalloc_append(oneshot_t, &be->oneshots, &service)) dienomem() ;
}
static inline void add_longrun (before_t *be, int dirfd, char const *srcdir, char const *name)
{
- longrun_t service = { .srcdir = srcdir } ;
+ longrun_t service = { .srcdir = srcdir, .pipeline = { 0, 0 }, .pipelinename = 0 } ;
+ unsigned int relatedindex, n ;
int fd ;
- unsigned int logindex, n ;
if (verbosity >= 3) strerr_warni3x(name, " has type ", "longrun") ;
add_common(be, dirfd, srcdir, name, &service.common, SVTYPE_LONGRUN) ;
fd = open_readat(dirfd, "run") ;
@@ -415,40 +491,48 @@ static inline void add_longrun (before_t *be, int dirfd, char const *srcdir, cha
strerr_dief4x(1, srcdir, "/", name, "/run is not a regular file") ;
}
close(fd) ;
- if (add_namelist(be, dirfd, srcdir, name, "logger", &logindex, &n))
+ fd = 0 ;
+ if (add_namelist(be, dirfd, srcdir, name, "producer-for", &relatedindex, &n))
{
- register unsigned int const *deps = genalloc_s(unsigned int, &be->indices) + service.common.depindex ;
- register unsigned int i = 0 ;
if (n != 1)
- strerr_dief5x(1, srcdir, "/", name, "/logger", " should only contain one service name") ;
- service.logtype = 1 ;
- service.logrelated = genalloc_s(unsigned int, &be->indices)[logindex] ;
- service.servicedirname = service.common.kname ;
- for (; i < service.common.ndeps ; i++) if (service.logrelated == deps[i]) break ;
- if (i < service.common.ndeps)
- genalloc_setlen(unsigned int, &be->indices, logindex) ;
- else service.common.ndeps++ ;
+ strerr_dief5x(1, srcdir, "/", name, "/producer-for", " should only contain one service name") ;
+ service.pipeline[1] = genalloc_s(unsigned int, &be->indices)[relatedindex] ;
+ {
+ unsigned int dummy ;
+ unsigned int namelen = str_len(data.s + service.pipeline[1]) ;
+ char svname[16 + namelen] ;
+ byte_copy(svname, 15, "s6rc-storepipe-") ;
+ byte_copy(svname + 15, namelen + 1, data.s + service.pipeline[1]) ;
+ add_name_nocheck(be, srcdir, svname, SVTYPE_UNDEFINED, &n, &dummy) ;
+ if (!genalloc_append(unsigned int, &be->indices, &n)) dienomem() ;
+ service.common.ndeps += 2 ;
+ }
if (verbosity >= 3)
- strerr_warni3x(name, " is a producer for ", data.s + service.logrelated) ;
+ strerr_warni3x(name, " is a producer for ", data.s + service.pipeline[1]) ;
+ fd = 1 ;
}
- else if (add_namelist(be, dirfd, srcdir, name, "producer", &logindex, &n))
+ if (add_namelist(be, dirfd, srcdir, name, "consumer-for", &relatedindex, &n))
{
+ unsigned int namelen = str_len(name) ;
+ char svname[16 + namelen] ;
if (n != 1)
- strerr_dief5x(1, srcdir, "/", name, "/producer", " should only contain one service name") ;
- service.logtype = 2 ;
- service.logrelated = genalloc_s(unsigned int, &be->indices)[logindex] ;
- genalloc_setlen(unsigned int, &be->indices, logindex) ;
- service.servicedirname = keep.len ;
- if (!stralloc_cats(&keep, data.s + service.logrelated)
- || !stralloc_catb(&keep, "/log", 5)) dienomem() ;
+ strerr_dief5x(1, srcdir, "/", name, "/consumer-for", " should only contain one service name") ;
+ service.pipeline[0] = genalloc_s(unsigned int, &be->indices)[relatedindex] ;
+ byte_copy(svname, 15, "s6rc-storepipe-") ;
+ byte_copy(svname + 15, namelen + 1, name) ;
if (verbosity >= 3)
- strerr_warni3x(name, " is a logger for ", data.s + service.logrelated) ;
+ strerr_warni3x(name, " is a consumer for ", data.s + service.pipeline[0]) ;
+ n = add_storepipe(be, svname) ;
+ genalloc_s(unsigned int, &be->indices)[relatedindex] = n ;
+ service.common.ndeps++ ;
+ fd = 0 ;
}
- else
+ if (fd && add_namelist(be, dirfd, srcdir, name, "pipeline-name", &relatedindex, &n))
{
- service.logtype = 0 ;
- service.servicedirname = service.common.kname ;
- if (verbosity >= 3) strerr_warni2x(name, " has no logger or producer") ;
+ if (n != 1)
+ strerr_dief5x(1, srcdir, "/", name, "/pipeline-name", " should only contain one name") ;
+ service.pipelinename = genalloc_s(unsigned int, &be->indices)[relatedindex] ;
+ genalloc_setlen(unsigned int, &be->indices, relatedindex) ;
}
if (!genalloc_append(longrun_t, &be->longruns, &service)) dienomem() ;
}
@@ -501,7 +585,8 @@ static inline void add_sources (before_t *be, char const *srcdir)
if (!d) break ;
if (d->d_name[0] == '.') continue ;
if (d->d_name[str_chr(d->d_name, '\n')])
- strerr_dief3x(2, "subdirectory of ", srcdir, " contains a newline character") ;
+ strerr_dief3x(1, "subdirectory of ", srcdir, " contains a newline character") ;
+ check_identifier(srcdir, d->d_name) ;
satmp.len = cur ;
if (!stralloc_catb(&satmp, d->d_name, str_len(d->d_name) + 1)) dienomem() ;
if (stat(satmp.s + start, &st) < 0)
@@ -517,6 +602,48 @@ static inline void add_sources (before_t *be, char const *srcdir)
satmp.len = start ;
}
+static inline void add_pipeline_bundles (before_t *be)
+{
+ longrun_t const *longruns = genalloc_s(longrun_t, &be->longruns) ;
+ unsigned int n = genalloc_len(longrun_t, &be->longruns) ;
+ unsigned int i = n ;
+ while (i--) if (longruns[i].pipelinename)
+ {
+ bundle_t bundle = { .listindex = genalloc_len(unsigned int, &be->indices), .n = 1 } ;
+ unsigned int id ;
+ nameinfo_t const *info ;
+ unsigned int j = i ;
+ if (verbosity >= 3) strerr_warni2x("creating bundle for pipeline ", data.s + longruns[i].pipelinename) ;
+ add_name(be, S6RC_INTERNALS, data.s + longruns[i].pipelinename, SVTYPE_BUNDLE, &bundle.name, &id) ;
+ avltree_search(&names_map, keep.s + longruns[i].common.kname, &id) ;
+ info = genalloc_s(nameinfo_t, &nameinfo) + id ;
+ if (!genalloc_append(unsigned int, &be->indices, &info->pos)) dienomem() ;
+
+ while (longruns[j].pipeline[1])
+ {
+ if (bundle.n >= n)
+ strerr_dief4x(1, "pipeline ", data.s + longruns[i].pipelinename, " is too long: possible loop involving ", keep.s + longruns[j].common.kname) ;
+ avltree_search(&names_map, data.s + longruns[j].pipeline[1], &id) ;
+ info = genalloc_s(nameinfo_t, &nameinfo) + id ;
+ if (info->type != SVTYPE_LONGRUN)
+ strerr_dief5x(1, "longrun service ", keep.s + longruns[j].common.kname, " declares a consumer ", data.s + longruns[j].pipeline[1], " that is not a longrun service") ;
+ if (!genalloc_append(unsigned int, &be->indices, &info->pos)) dienomem() ;
+ j = info->i ;
+ {
+ unsigned int namelen = str_len(data.s + info->pos) ;
+ char svname[16 + namelen] ;
+ byte_copy(svname, 15, "s6rc-storepipe-") ;
+ byte_copy(svname + 15, namelen + 1, data.s + info->pos) ;
+ avltree_search(&names_map, svname, &id) ;
+ info = genalloc_s(nameinfo_t, &nameinfo) + id ;
+ if (!genalloc_append(unsigned int, &be->indices, &info->pos)) dienomem() ;
+ }
+ bundle.n += 2 ;
+ }
+ if (!genalloc_append(bundle_t, &be->bundles, &bundle)) dienomem() ;
+ }
+}
+
/* Resolve all names and dependencies */
@@ -530,7 +657,7 @@ struct bundle_recinfo_s
unsigned int n ;
unsigned int nlong ;
unsigned int nbits ;
- uint32 const *indices ;
+ unsigned int const *indices ;
unsigned char *barray ;
unsigned char *mark ;
unsigned int source ;
@@ -541,7 +668,7 @@ static void resolve_bundle_rec (bundle_recinfo_t *recinfo, unsigned int i)
if (!(recinfo->mark[i] & 2))
{
bundle_t const *me = recinfo->oldb + i ;
- uint32 const *listindex = recinfo->indices + me->listindex ;
+ unsigned int const *listindex = recinfo->indices + me->listindex ;
unsigned int j = 0 ;
if (recinfo->mark[i] & 1)
strerr_dief4x(1, "cyclic bundle definition: resolution of ", data.s + recinfo->oldb[recinfo->source].name, " encountered a cycle involving ", data.s + me->name) ;
@@ -572,7 +699,7 @@ static void resolve_bundle_rec (bundle_recinfo_t *recinfo, unsigned int i)
}
}
-static inline unsigned int resolve_bundles (bundle_t const *oldb, bundle_t *newb, unsigned int nshort, unsigned int nlong, unsigned int nbundles, uint32 const *indices, unsigned char *barray)
+static inline unsigned int resolve_bundles (bundle_t const *oldb, bundle_t *newb, unsigned int nshort, unsigned int nlong, unsigned int nbundles, unsigned int const *indices, unsigned char *barray)
{
unsigned int total = 0, i = 0 ;
unsigned char mark[nbundles] ;
@@ -609,7 +736,7 @@ static inline void flatlist_bundles (bundle_t *bundles, unsigned int nbundles, u
}
}
-static void resolve_deps (common_t const *me, unsigned int nlong, unsigned int n, unsigned int nbits, uint32 const *indices, unsigned char *sarray, unsigned char const *barray)
+static void resolve_deps (common_t const *me, unsigned int nlong, unsigned int n, unsigned int nbits, unsigned int const *indices, unsigned char *sarray, unsigned char const *barray)
{
unsigned int j = 0 ;
for (; j < me->ndeps ; j++)
@@ -626,7 +753,7 @@ static void resolve_deps (common_t const *me, unsigned int nlong, unsigned int n
{
char fmt[UINT_FMT] ;
fmt[uint_fmt(fmt, nlong + p->i)] = 0 ;
- strerr_warnt7x("atomic ", data.s + me->name, " depends on oneshot ", data.s + p->pos, " (", fmt, ")") ;
+ strerr_warnt7x("atomic ", keep.s + me->kname, " depends on oneshot ", data.s + p->pos, " (", fmt, ")") ;
}
break ;
case SVTYPE_LONGRUN :
@@ -635,7 +762,7 @@ static void resolve_deps (common_t const *me, unsigned int nlong, unsigned int n
{
char fmt[UINT_FMT] ;
fmt[uint_fmt(fmt, p->i)] = 0 ;
- strerr_warnt7x("atomic ", data.s + me->name, " depends on longrun ", data.s + p->pos, " (", fmt, ")") ;
+ strerr_warnt7x("atomic ", keep.s + me->kname, " depends on longrun ", data.s + p->pos, " (", fmt, ")") ;
}
break ;
case SVTYPE_BUNDLE :
@@ -644,21 +771,21 @@ static void resolve_deps (common_t const *me, unsigned int nlong, unsigned int n
{
char fmt[UINT_FMT] ;
fmt[uint_fmt(fmt, nlong + p->i)] = 0 ;
- strerr_warnt4x("atomic ", data.s + me->name, " depends on bundle ", data.s + p->pos) ;
+ strerr_warnt4x("atomic ", keep.s + me->kname, " depends on bundle ", data.s + p->pos) ;
}
break ;
default :
- strerr_dief4x(1, "during dependency resolution for service ", data.s + me->name, ": undefined service name ", data.s + p->pos) ;
+ strerr_dief4x(1, "during dependency resolution for service ", keep.s + me->kname, ": undefined service name ", data.s + p->pos) ;
}
}
}
-static inline void check_logger (longrun_t const *longruns, unsigned int i)
+static uint32 resolve_prodcons (longrun_t const *longruns, unsigned int i, int h, uint32 nlong)
{
unsigned int j ;
register nameinfo_t const *p ;
- if (!longruns[i].logtype) return ;
- avltree_search(&names_map, data.s + longruns[i].logrelated, &j) ;
+ if (!longruns[i].pipeline[h]) return nlong ;
+ avltree_search(&names_map, data.s + longruns[i].pipeline[h], &j) ;
p = genalloc_s(nameinfo_t, &nameinfo) + j ;
switch (p->type)
{
@@ -666,21 +793,21 @@ static inline void check_logger (longrun_t const *longruns, unsigned int i)
{
unsigned int k ;
register nameinfo_t const *q ;
- if (longruns[p->i].logtype != 3 - longruns[i].logtype) goto err ;
- avltree_search(&names_map, data.s + longruns[p->i].logrelated, &k) ;
+ avltree_search(&names_map, data.s + longruns[p->i].pipeline[!h], &k) ;
q = genalloc_s(nameinfo_t, &nameinfo) + k ;
if (q->type != SVTYPE_LONGRUN) goto err ;
if (q->i != i) goto err ;
break ;
- err:
- strerr_dief7x(1, "longrun service ", data.s + longruns[i].common.name, " declares a ", longruns[i].logtype == 2 ? "producer" : "logger", " named ", data.s + p->pos, " that does not declare it back ") ;
+ err:
+ strerr_dief7x(1, "longrun service ", keep.s + longruns[i].common.kname, " declares being a ", h ? "producer" : "consumer", " for a service named ", data.s + p->pos, " that does not declare it back ") ;
}
case SVTYPE_ONESHOT :
case SVTYPE_BUNDLE :
- strerr_dief8x(1, "longrun service ", data.s + longruns[i].common.name, " declares a ", longruns[i].logtype == 2 ? "producer" : "logger", " named ", data.s + p->pos, " of type ", p->type == SVTYPE_BUNDLE ? "bundle" : "oneshot") ;
+ strerr_dief8x(1, "longrun service ", keep.s + longruns[i].common.kname, " declares being a ", h ? "producer" : "consumer", " for a service named ", data.s + p->pos, " of type ", p->type == SVTYPE_BUNDLE ? "bundle" : "oneshot") ;
default :
- strerr_dief7x(1, "longrun service ", data.s + longruns[i].common.name, " declares a ", longruns[i].logtype == 2 ? "producer" : "logger", " named ", data.s + p->pos, " that is not defined") ;
+ strerr_dief6x(1, "longrun service ", keep.s + longruns[i].common.kname, " declares being a ", h ? "producer" : "consumer", " for an undefined service: ", data.s + p->pos) ;
}
+ return p->i ;
}
static inline unsigned int ugly_bitarray_vertical_countones (unsigned char const *sarray, unsigned int n, unsigned int i)
@@ -695,7 +822,7 @@ static inline unsigned int resolve_services (s6rc_db_t *db, before_t const *be,
{
oneshot_t const *oneshots = genalloc_s(oneshot_t const, &be->oneshots) ;
longrun_t const *longruns = genalloc_s(longrun_t const, &be->longruns) ;
- uint32 const *indices = genalloc_s(uint32 const, &be->indices) ;
+ unsigned int const *indices = genalloc_s(unsigned int const, &be->indices) ;
unsigned int n = db->nshort + db->nlong ;
unsigned int nbits = bitarray_div8(n) ;
unsigned int total[2] = { 0, 0 } ;
@@ -704,14 +831,14 @@ static inline unsigned int resolve_services (s6rc_db_t *db, before_t const *be,
byte_zero(sarray, nbits * n) ;
for (; i < db->nlong ; i++)
{
+ srcdirs[i] = longruns[i].srcdir ;
db->services[i].name = longruns[i].common.kname ;
db->services[i].flags = longruns[i].common.annotation_flags ;
db->services[i].timeout[0] = longruns[i].common.timeout[0] ;
db->services[i].timeout[1] = longruns[i].common.timeout[1] ;
- db->services[i].x.longrun.servicedir = longruns[i].servicedirname ;
- srcdirs[i] = longruns[i].srcdir ;
+ db->services[i].x.longrun.pipeline[0] = resolve_prodcons(longruns, i, 0, db->nlong) ;
+ db->services[i].x.longrun.pipeline[1] = resolve_prodcons(longruns, i, 1, db->nlong) ;
resolve_deps(&longruns[i].common, db->nlong, n, nbits, indices, sarray + i * nbits, barray) ;
- check_logger(longruns, i) ;
}
for (i = 0 ; i < db->nshort ; i++)
{
@@ -742,7 +869,9 @@ static inline void flatlist_services (s6rc_db_t *db, unsigned char const *sarray
{
unsigned int n = db->nshort + db->nlong ;
unsigned int nbits = bitarray_div8(n) ;
+ diuint32 problem ;
unsigned int i = 0 ;
+ register int r ;
if (verbosity >= 3) strerr_warni1x("converting service dependency array") ;
for (; i < n ; i++)
{
@@ -755,10 +884,18 @@ static inline void flatlist_services (s6rc_db_t *db, unsigned char const *sarray
for (; k < db->services[i].ndeps[1] ; j++)
if (bitarray_peek(sarray + i * nbits, j)) mydeps[k++] = j ;
}
- if (verbosity >= 3) strerr_warni1x("checking for dependency cycles") ;
- nbits = s6rc_db_check_depcycles(db, 1, &i) ;
- if (nbits < n)
- strerr_dief4x(1, "cyclic service definition: resolution of ", db->string + db->services[nbits].name, " encountered a cycle involving ", db->string + db->services[i].name) ;
+
+ if (verbosity >= 3) strerr_warni1x("checking database correctness") ;
+ if (s6rc_db_check_depcycles(db, 1, &problem))
+ strerr_dief4x(1, "cyclic service dependency involving", db->string + db->services[problem.left].name, " and ", db->string + db->services[problem.right].name) ;
+ r = s6rc_db_check_pipelines(db, &problem) ;
+ if (r)
+ {
+ if (r == 1)
+ strerr_dief4x(1, "cyclic longrun pipeline involving", db->string + db->services[problem.left].name, " and ", db->string + db->services[problem.right].name) ;
+ else
+ strerr_dief4x(1, "longrun pipeline collision involving", db->string + db->services[problem.left].name, " and ", db->string + db->services[problem.right].name) ;
+ }
}
@@ -803,6 +940,21 @@ static void auto_file (char const *compiled, char const *file, char const *s, un
}
}
+static void auto_symlink (char const *compiled, char const *name, char const *target)
+{
+ unsigned int clen = str_len(compiled) ;
+ unsigned int flen = str_len(name) ;
+ char fn[clen + flen + 2] ;
+ byte_copy(fn, clen, compiled) ;
+ fn[clen] = '/' ;
+ byte_copy(fn + clen + 1, flen + 1, name) ;
+ if (symlink(target, fn) < 0)
+ {
+ cleanup(compiled) ;
+ strerr_diefu4sys(111, "symlink ", target, " to ", fn) ;
+ }
+}
+
static void auto_rights (char const *compiled, char const *file, mode_t mode)
{
unsigned int clen = str_len(compiled) ;
@@ -837,40 +989,120 @@ static inline void write_sizes (char const *compiled, s6rc_db_t const *db)
auto_file(compiled, "n", pack, 20) ;
}
-static inline void write_specials (char const *compiled, uint64 const *uids, unsigned int uidn, gid_t const *gids, unsigned int gidn)
+static void make_skel (char const *compiled, char const *name, uint64 const *uids, unsigned int uidn, gid_t const *gids, unsigned int gidn)
{
+ unsigned int namelen = str_len(name) ;
unsigned int i = uidn ;
- char fn[sizeof(BASE_RULES) + UINT64_FMT + 6] = BASE_RULES ;
- auto_dir(compiled, "servicedirs/" S6RC_ONESHOT_RUNNER) ;
- auto_file(compiled, "servicedirs/" S6RC_ONESHOT_RUNNER "/notification-fd", "3\n", 2) ;
- auto_file(compiled, "servicedirs/" S6RC_ONESHOT_RUNNER "/run", S6RC_ONESHOT_RUNNER_RUNSCRIPT, sizeof(S6RC_ONESHOT_RUNNER_RUNSCRIPT) - 1) ;
- auto_rights(compiled, "servicedirs/" S6RC_ONESHOT_RUNNER "/run", 0755) ;
- auto_dir(compiled, "servicedirs/" S6RC_ONESHOT_RUNNER "/data") ;
- auto_dir(compiled, "servicedirs/" S6RC_ONESHOT_RUNNER "/data/rules") ;
- if (gidn) auto_dir(compiled, fn) ;
- fn[sizeof(BASE_RULES) - 4] = 'u' ;
+ char fn[UINT64_FMT + namelen + 35] ;
+ byte_copy(fn, 12, "servicedirs/") ;
+ byte_copy(fn + 12, namelen + 1, name) ;
+ auto_dir(compiled, fn) ;
+ byte_copy(fn + 12 + namelen, 17, "/notification-fd") ;
+ auto_file(compiled, fn, "3\n", 2) ;
+ byte_copy(fn + 13 + namelen, 5, "data") ;
+ auto_dir(compiled, fn) ;
+ byte_copy(fn + 17 + namelen, 7, "/rules") ;
+ auto_dir(compiled, fn) ;
+ if (gidn)
+ {
+ byte_copy(fn + 23 + namelen, 5, "/gid") ;
+ auto_dir(compiled, fn) ;
+ }
+ byte_copy(fn + 23 + namelen, 5, "/uid") ;
auto_dir(compiled, fn) ;
- fn[sizeof(BASE_RULES) - 1] = '/' ;
+ fn[27 + namelen] = '/' ;
while (i--)
{
- unsigned int len = uint64_fmt(fn + sizeof(BASE_RULES), uids[i]) ;
- fn[sizeof(BASE_RULES) + len] = 0 ;
+ unsigned int len = uint64_fmt(fn + 28 + namelen, uids[i]) ;
+ fn[28 + namelen + len] = 0 ;
auto_dir(compiled, fn) ;
- byte_copy(fn + sizeof(BASE_RULES) + len, 7, "/allow") ;
+ byte_copy(fn + 28 + namelen + len, 7, "/allow") ;
auto_file(compiled, fn, "", 0) ;
}
- fn[sizeof(BASE_RULES) - 4] = 'g' ;
i = gidn ;
while (i--)
{
- unsigned int len = gid_fmt(fn + sizeof(BASE_RULES), gids[i]) ;
- fn[sizeof(BASE_RULES) + len] = 0 ;
+ unsigned int len = gid_fmt(fn + 28 + namelen, gids[i]) ;
+ fn[28 + namelen + len] = 0 ;
auto_dir(compiled, fn) ;
- byte_copy(fn + sizeof(BASE_RULES) + len, 7, "/allow") ;
+ byte_copy(fn + 28 + namelen + len, 7, "/allow") ;
auto_file(compiled, fn, "", 0) ;
}
}
+static inline void write_oneshot_runner (char const *compiled, uint64 const *uids, unsigned int uidn, gid_t const *gids, unsigned int gidn)
+{
+ make_skel(compiled, S6RC_ONESHOT_RUNNER, uids, uidn, gids, gidn) ;
+ auto_file(compiled, "servicedirs/" S6RC_ONESHOT_RUNNER "/run", S6RC_ONESHOT_RUNNER_RUNSCRIPT, sizeof(S6RC_ONESHOT_RUNNER_RUNSCRIPT) - 1) ;
+ auto_rights(compiled, "servicedirs/" S6RC_ONESHOT_RUNNER "/run", 0755) ;
+}
+
+static inline void write_fdholder (char const *compiled, uint64 const *uids, unsigned int uidn, gid_t const *gids, unsigned int gidn, char const *fdhuser)
+{
+ unsigned int base = satmp.len ;
+ make_skel(compiled, S6RC_FDHOLDER, uids, uidn, gids, gidn) ;
+ {
+ char fn[62 + S6RC_FDHOLDER_LEN + UINT64_FMT] = "servicedirs/" S6RC_FDHOLDER "/data/rules/uid/" ;
+ char fmt[7 + UINT64_FMT] = "../uid/" ;
+ unsigned int i = uint64_fmt(fmt + 7, uids[0]) ;
+ fmt[7 + i] = 0 ;
+ byte_copy(fn + 28 + S6RC_FDHOLDER_LEN, i, fmt + 7) ;
+ byte_copy(fn + 28 + S6RC_FDHOLDER_LEN + i, 5, "/env") ;
+ auto_dir(compiled, fn) ;
+ byte_copy(fn + 32 + S6RC_FDHOLDER_LEN + i, 18, "/S6_FDHOLDER_LIST") ;
+ auto_file(compiled, fn, "\n", 1) ;
+ byte_copy(fn + 45 + S6RC_FDHOLDER_LEN + i, 12, "STORE_REGEX") ;
+ auto_file(compiled, fn, "^pipe:s6rc-\n", 12) ;
+ byte_copy(fn + 45 + S6RC_FDHOLDER_LEN + i, 15, "RETRIEVE_REGEX") ;
+ auto_symlink(compiled, fn, "S6_FDHOLDER_STORE_REGEX") ;
+ byte_copy(fn + 45 + S6RC_FDHOLDER_LEN + i, 8, "SETDUMP") ;
+ auto_file(compiled, fn, "\n", 1) ;
+ fn[45 + S6RC_FDHOLDER_LEN + i] = 'G' ;
+ auto_file(compiled, fn, "\n", 1) ;
+
+ for (i = 1 ; i < uidn ; i++)
+ {
+ unsigned int len = uint64_fmt(fn + 28 + S6RC_FDHOLDER_LEN, uids[i]) ;
+ fn[28 + S6RC_FDHOLDER_LEN + len] = 0 ;
+ auto_symlink(compiled, fn, fmt + 7) ;
+ }
+ fn[24 + S6RC_FDHOLDER_LEN] = 'g' ;
+ i = gidn ;
+ while (i--)
+ {
+ unsigned int len = gid_fmt(fn + 28 + S6RC_FDHOLDER_LEN, gids[i]) ;
+ fn[28 + S6RC_FDHOLDER_LEN + len] = 0 ;
+ auto_symlink(compiled, fn, fmt) ;
+ }
+ }
+
+ if (!stralloc_cats(&satmp,
+ "#!" EXECLINE_SHEBANGPREFIX "execlineb -P\n" \
+ EXECLINE_EXTBINPREFIX "fdmove -c 2 1\n" \
+ EXECLINE_EXTBINPREFIX "fdmove 1 3\n")) dienomem() ;
+ if (fdhuser)
+ {
+ if (!stralloc_cats(&satmp, S6_EXTBINPREFIX "s6-envuidgid -i -- ")
+ || !string_quote(&satmp, fdhuser, str_len(fdhuser))
+ || !stralloc_catb(&satmp, "\n", 1)) dienomem() ;
+ }
+ if (!stralloc_cats(&satmp, S6_EXTBINPREFIX "s6-fdholder-daemon -1 ")) dienomem() ;
+ if (fdhuser)
+ {
+ if (!stralloc_cats(&satmp, "-U ")) dienomem() ;
+ }
+ if (!stralloc_cats(&satmp, "-i data/rules -- s\n")) dienomem() ;
+ auto_file(compiled, "servicedirs/" S6RC_FDHOLDER "/run", satmp.s + base, satmp.len - base) ;
+ satmp.len = base ;
+ auto_rights(compiled, "servicedirs/" S6RC_FDHOLDER "/run", 0755) ;
+}
+
+static inline void write_specials (char const *compiled, uint64 const *uids, unsigned int uidn, gid_t const *gids, unsigned int gidn, char const *fdhuser)
+{
+ write_oneshot_runner(compiled, uids, uidn, gids, gidn) ;
+ write_fdholder(compiled, uids, uidn, gids, gidn, fdhuser) ;
+}
+
static inline void write_resolve (char const *compiled, s6rc_db_t const *db, bundle_t const *bundles, unsigned int nbundles, uint32 const *bdeps)
{
unsigned int clen = str_len(compiled) ;
@@ -975,95 +1207,138 @@ static void dircopy (char const *compiled, char const *srcfn, char const *dstfn)
}
}
-static void write_servicedir (char const *compiled, char const *srcdir, char const *src, char const *dst)
+static int read_uint (char const *file, unsigned int *fd)
{
- unsigned int clen = str_len(compiled) ;
- unsigned int srcdirlen = str_len(srcdir) ;
- unsigned int srclen = str_len(src) ;
- unsigned int dstlen = str_len(dst) ;
- struct stat st ;
- char dstfn[clen + 30 + dstlen] ;
- char srcfn[srcdirlen + srclen + 18] ;
- byte_copy(dstfn, clen, compiled) ;
- byte_copy(dstfn + clen, 13, "/servicedirs/") ;
- byte_copy(dstfn + clen + 13, dstlen + 1, dst) ;
- if (mkdir(dstfn, 0755) < 0)
+ char buf[UINT_FMT + 1] ;
+ register int r = openreadnclose(file, buf, UINT_FMT) ;
+ if (r < 0) return (errno == ENOENT) ? 0 : -1 ;
+ buf[byte_chr(buf, r, '\n')] = 0 ;
+ if (!uint0_scan(buf, fd)) return (errno = EINVAL, -1) ;
+ return 1 ;
+}
+
+static inline void write_run_wrapper (char const *compiled, char const *fn, s6rc_db_t const *db, unsigned int i, unsigned int fd)
+{
+ unsigned int base = satmp.len ;
+ if (!stralloc_cats(&satmp, "#!" EXECLINE_SHEBANGPREFIX "execlineb -P\n")) dienomem() ;
+ if (db->services[i].x.longrun.pipeline[0] < db->nlong)
{
- cleanup(compiled) ;
- strerr_diefu2sys(111, "mkdir ", dstfn) ;
+ if (!stralloc_cats(&satmp, EXECLINE_EXTBINPREFIX "s6-fdholder-retrieve ../s6rc-fdholder/s \"pipe:s6rc-r-")
+ || !string_quote_nodelim(&satmp, db->string + db->services[i].name, str_len(db->string + db->services[i].name))
+ || !stralloc_cats(&satmp, "\"\n")) dienomem() ;
}
- byte_copy(dstfn + clen + 13 + dstlen, 5, "/run") ;
- byte_copy(srcfn, srcdirlen, srcdir) ;
- srcfn[srcdirlen] = '/' ;
- byte_copy(srcfn + srcdirlen + 1, srclen, src) ;
- byte_copy(srcfn + srcdirlen + srclen + 1, 5, "/run") ;
- if (!filecopy(srcfn, dstfn, 0755))
+ if (db->services[i].x.longrun.pipeline[1] < db->nlong)
{
- cleanup(compiled) ;
- strerr_diefu4sys(111, "copy ", srcfn, " to ", dstfn) ;
+ char const *consumername = db->string + db->services[db->services[i].x.longrun.pipeline[1]].name ;
+ if (!stralloc_cats(&satmp, EXECLINE_EXTBINPREFIX "fdmove ")
+ || !stralloc_cats(&satmp, fd == 3 ? "4" : "3")
+ || !stralloc_cats(&satmp, " 0\n"
+ EXECLINE_EXTBINPREFIX "s6-fdholder-retrieve ../s6rc-fdholder/s \"pipe:s6rc-w-")
+ || !string_quote_nodelim(&satmp, consumername, str_len(consumername))
+ || !stralloc_cats(&satmp, "\"\n"
+ EXECLINE_EXTBINPREFIX "fdmove 1 0\n"
+ EXECLINE_EXTBINPREFIX "fdmove 0 ")
+ || !stralloc_cats(&satmp, fd == 3 ? "4" : "3")
+ || !stralloc_cats(&satmp, "\n")) dienomem() ;
}
- byte_copy(dstfn + clen + 14 + dstlen, 7, "finish") ;
- byte_copy(srcfn + srcdirlen + srclen + 2, 7, "finish") ;
- filecopy(srcfn, dstfn, 0755) ;
- byte_copy(dstfn + clen + 14 + dstlen, 15, "timeout-finish") ;
- byte_copy(srcfn + srcdirlen + srclen + 2, 15, "timeout-finish") ;
- filecopy(srcfn, dstfn, 0644) ;
- byte_copy(dstfn + clen + 14 + dstlen, 16, "notification-fd") ;
- byte_copy(srcfn + srcdirlen + srclen + 2, 16, "notification-fd") ;
- filecopy(srcfn, dstfn, 0644) ;
-
- byte_copy(srcfn + srcdirlen + srclen + 4, 7, "setsid") ;
- if (stat(srcfn, &st) < 0)
+ if (!stralloc_cats(&satmp, "./run.user\n")) dienomem() ;
+ auto_file(compiled, fn, satmp.s + base, satmp.len - base) ;
+ satmp.len = base ;
+ auto_rights(compiled, fn, 0755) ;
+}
+
+static inline void write_servicedirs (char const *compiled, s6rc_db_t const *db, char const *const *srcdirs)
+{
+ unsigned int clen = str_len(compiled) ;
+ unsigned int i = 2 ;
+ if (verbosity >= 3) strerr_warni3x("writing ", compiled, "/servicedirs") ;
+ for (; i < db->nlong ; i++)
{
- if (errno != ENOENT)
+ struct stat st ;
+ unsigned int srcdirlen = str_len(srcdirs[i]) ;
+ unsigned int len = str_len(db->string + db->services[i].name) ;
+ unsigned int fd = 0 ;
+ register int r ;
+ char srcfn[srcdirlen + len + 18] ;
+ char dstfn[clen + len + 30] ;
+ byte_copy(dstfn, clen, compiled) ;
+ byte_copy(dstfn + clen, 13, "/servicedirs/") ;
+ byte_copy(dstfn + clen + 13, len + 1, db->string + db->services[i].name) ;
+ if (mkdir(dstfn, 0755) < 0)
{
cleanup(compiled) ;
- strerr_diefu2sys(111, "stat ", srcfn) ;
+ strerr_diefu2sys(111, "mkdir ", dstfn) ;
}
- }
- else
- {
- int fd ;
- byte_copy(dstfn + clen + 16 + dstlen, 7, "setsid") ;
- fd = open_trunc(dstfn) ;
- if (fd < 0)
+ byte_copy(srcfn, srcdirlen, srcdirs[i]) ;
+ srcfn[srcdirlen] = '/' ;
+ byte_copy(srcfn + srcdirlen + 1, len, db->string + db->services[i].name) ;
+ byte_copy(srcfn + srcdirlen + 1 + len, 17, "/notification-fd") ;
+ r = read_uint(srcfn, &fd) ;
+ if (r < 0)
{
cleanup(compiled) ;
- strerr_diefu2sys(111, "touch ", dstfn) ;
+ strerr_diefu2sys(111, "read ", srcfn) ;
+ }
+ if (r)
+ {
+ char fmt[UINT_FMT] ;
+ unsigned int fmtlen = uint_fmt(fmt, fd) ;
+ fmt[fmtlen++] = '\n' ;
+ byte_copy(dstfn + clen + 13 + len, 17, "/notification-fd") ;
+ if (!openwritenclose_unsafe(dstfn, fmt, fmtlen))
+ {
+ cleanup(compiled) ;
+ strerr_diefu2sys(111, "write to ", dstfn) ;
+ }
}
- close(fd) ;
- }
-
- byte_copy(dstfn + clen + 14 + dstlen, 5, "data") ;
- byte_copy(srcfn + srcdirlen + srclen + 2, 5, "data") ;
- dircopy(compiled, srcfn, dstfn) ;
- byte_copy(dstfn + clen + 14 + dstlen, 4, "env") ;
- byte_copy(srcfn + srcdirlen + srclen + 2, 4, "env") ;
- dircopy(compiled, srcfn, dstfn) ;
-}
-static inline void write_servicedirs (char const *compiled, s6rc_db_t const *db, char const *const *srcdirs, unsigned int maxnamelen)
-{
- unsigned int clen = str_len(compiled) ;
- unsigned int i = 1 ;
- char fn[clen + 23 + maxnamelen] ;
- char islogger[db->nlong] ;
- if (verbosity >= 3) strerr_warni3x("writing ", compiled, "/servicedirs") ;
- byte_copy(fn, clen, compiled) ;
- byte_copy(fn + clen, 12, "/servicedirs") ;
- fn[clen+12] = '/' ;
- byte_zero(islogger, db->nlong) ;
- for (; i < db->nlong ; i++)
- {
- char const *servicedirname = db->string + db->services[i].x.longrun.servicedir ;
- islogger[i] = servicedirname[str_chr(servicedirname, '/')] ;
- if (!islogger[i])
- write_servicedir(compiled, srcdirs[i], db->string + db->services[i].name, servicedirname) ;
- }
- for (i = 1 ; i < db->nlong ; i++)
- {
- if (islogger[i])
- write_servicedir(compiled, srcdirs[i], db->string + db->services[i].name, db->string + db->services[i].x.longrun.servicedir) ;
+ byte_copy(dstfn + clen + 13 + len, 5, "/run") ;
+ if (db->services[i].x.longrun.pipeline[0] < db->nlong || db->services[i].x.longrun.pipeline[1] < db->nlong)
+ {
+ write_run_wrapper(compiled, dstfn + clen + 1, db, i, fd) ;
+ byte_copy(dstfn + clen + 17 + len, 6, ".user") ;
+ }
+ byte_copy(srcfn + srcdirlen + 1 + len, 5, "/run") ;
+ if (!filecopy(srcfn, dstfn, 0755))
+ {
+ cleanup(compiled) ;
+ strerr_diefu4sys(111, "copy ", srcfn, " to ", dstfn) ;
+ }
+ byte_copy(dstfn + clen + 14 + len, 7, "finish") ;
+ byte_copy(srcfn + srcdirlen + len + 2, 7, "finish") ;
+ filecopy(srcfn, dstfn, 0755) ;
+ byte_copy(dstfn + clen + 14 + len, 15, "timeout-finish") ;
+ byte_copy(srcfn + srcdirlen + len + 2, 15, "timeout-finish") ;
+ filecopy(srcfn, dstfn, 0644) ;
+
+ byte_copy(srcfn + srcdirlen + len + 4, 7, "setsid") ;
+ if (stat(srcfn, &st) < 0)
+ {
+ if (errno != ENOENT)
+ {
+ cleanup(compiled) ;
+ strerr_diefu2sys(111, "stat ", srcfn) ;
+ }
+ }
+ else
+ {
+ int fd ;
+ byte_copy(dstfn + clen + 16 + len, 7, "setsid") ;
+ fd = open_trunc(dstfn) ;
+ if (fd < 0)
+ {
+ cleanup(compiled) ;
+ strerr_diefu2sys(111, "touch ", dstfn) ;
+ }
+ close(fd) ;
+ }
+
+ byte_copy(dstfn + clen + 14 + len, 5, "data") ;
+ byte_copy(srcfn + srcdirlen + len + 2, 5, "data") ;
+ dircopy(compiled, srcfn, dstfn) ;
+ byte_copy(dstfn + clen + 14 + len, 4, "env") ;
+ byte_copy(srcfn + srcdirlen + len + 2, 4, "env") ;
+ dircopy(compiled, srcfn, dstfn) ;
}
}
@@ -1081,8 +1356,9 @@ static inline int write_service (buffer *b, s6rc_service_t const *sv, int type)
uint32_pack_big(pack + 28, sv->deps[1]) ;
if (type)
{
- uint32_pack_big(pack + 32, sv->x.longrun.servicedir) ;
- m = 36 ;
+ uint32_pack_big(pack + 32, sv->x.longrun.pipeline[0]) ;
+ uint32_pack_big(pack + 36, sv->x.longrun.pipeline[1]) ;
+ m = 40 ;
}
else
{
@@ -1154,21 +1430,23 @@ static inline void write_db (char const *compiled, s6rc_db_t const *db)
strerr_diefu2sys(111, "write to ", dbfn) ;
}
-static inline void write_compiled (char const *compiled, s6rc_db_t const *db, char const *const *srcdirs, bundle_t const *bundles, unsigned int nbundles, uint32 const *bdeps, unsigned int maxnamelen, uint64 const *uids, unsigned int uidn, gid_t const *gids, unsigned int gidn)
+static inline void write_compiled (char const *compiled, s6rc_db_t const *db, char const *const *srcdirs, bundle_t const *bundles, unsigned int nbundles, uint32 const *bdeps, uint64 const *uids, unsigned int uidn, gid_t const *gids, unsigned int gidn, char const *fdhuser)
{
if (verbosity >= 2) strerr_warni2x("writing compiled information to ", compiled) ;
init_compiled(compiled) ;
write_sizes(compiled, db) ;
write_resolve(compiled, db, bundles, nbundles, bdeps) ;
+ stralloc_free(&data) ;
write_db(compiled, db) ;
- write_specials(compiled, uids, uidn, gids, gidn) ;
- write_servicedirs(compiled, db, srcdirs, maxnamelen) ;
+ write_specials(compiled, uids, uidn, gids, gidn, fdhuser) ;
+ write_servicedirs(compiled, db, srcdirs) ;
}
int main (int argc, char const *const *argv)
{
before_t before = BEFORE_ZERO ;
char const *compiled ;
+ char const *fdhuser = 0 ;
unsigned int uidn = 0, gidn = 0 ;
uint64 uids[256] ;
gid_t gids[256] ;
@@ -1177,13 +1455,14 @@ int main (int argc, char const *const *argv)
subgetopt_t l = SUBGETOPT_ZERO ;
for (;;)
{
- register int opt = subgetopt_r(argc, argv, "v:u:g:", &l) ;
+ register int opt = subgetopt_r(argc, argv, "v:u:g:h:", &l) ;
if (opt == -1) break ;
switch (opt)
{
case 'v' : if (!uint0_scan(l.arg, &verbosity)) dieusage() ; break ;
case 'u' : if (!uint64_scanlist(uids, 255, l.arg, &uidn)) dieusage() ; break ;
case 'g' : if (!gid_scanlist(gids, 255, l.arg, &gidn)) dieusage() ; break ;
+ case 'h' : fdhuser = l.arg ; break ;
default : dieusage() ;
}
}
@@ -1192,14 +1471,15 @@ int main (int argc, char const *const *argv)
if (argc < 2) dieusage() ;
if (!uidn && !gidn) uids[uidn++] = 0 ;
compiled = *argv++ ;
- add_specials(&before) ;
+ before.specialdeps[0] = add_internal_longrun(&before, S6RC_ONESHOT_RUNNER) ;
+ before.specialdeps[1] = add_internal_longrun(&before, S6RC_FDHOLDER) ;
for (; *argv ; argv++) add_sources(&before, *argv) ;
+ add_pipeline_bundles(&before) ;
{
unsigned int n = genalloc_len(oneshot_t, &before.oneshots) + genalloc_len(longrun_t, &before.longruns) ;
unsigned int nbits = bitarray_div8(n) ;
unsigned int nbundles = genalloc_len(bundle_t, &before.bundles) ;
- unsigned int maxnamelen = before.maxnamelen ;
s6rc_service_t servicesblob[n] ;
s6rc_db_t db =
{
@@ -1214,13 +1494,13 @@ int main (int argc, char const *const *argv)
unsigned char sarray[nbits * n] ;
bundle_t bundles[nbundles] ;
unsigned char barray[nbits * nbundles] ;
- unsigned int nbdeps = resolve_bundles(genalloc_s(bundle_t, &before.bundles), bundles, db.nshort, db.nlong, nbundles, genalloc_s(uint32, &before.indices), barray) ;
+ unsigned int nbdeps = resolve_bundles(genalloc_s(bundle_t, &before.bundles), bundles, db.nshort, db.nlong, nbundles, genalloc_s(unsigned int, &before.indices), barray) ;
uint32 bdeps[nbdeps] ;
genalloc_free(bundle_t, &before.bundles) ;
flatlist_bundles(bundles, nbundles, nbits, barray, bdeps) ;
db.ndeps = resolve_services(&db, &before, srcdirs, sarray, barray) ;
- genalloc_free(uint32, &before.indices) ;
+ genalloc_free(unsigned int, &before.indices) ;
genalloc_free(oneshot_t, &before.oneshots) ;
genalloc_free(longrun_t, &before.longruns) ;
genalloc_free(nameinfo_t, &nameinfo) ;
@@ -1229,7 +1509,7 @@ int main (int argc, char const *const *argv)
uint32 deps[db.ndeps << 1] ;
db.deps = deps ;
flatlist_services(&db, sarray) ;
- write_compiled(compiled, &db, srcdirs, bundles, nbundles, bdeps, maxnamelen, uids, uidn, gids, gidn) ;
+ write_compiled(compiled, &db, srcdirs, bundles, nbundles, bdeps, uids, uidn, gids, gidn, fdhuser) ;
}
}
diff --git a/src/s6-rc/s6-rc-db.c b/src/s6-rc/s6-rc-db.c
index aeaff76..8621b6c 100644
--- a/src/s6-rc/s6-rc-db.c
+++ b/src/s6-rc/s6-rc-db.c
@@ -180,16 +180,6 @@ static void print_timeout (char const *name, int h)
strerr_diefu1sys(111, "write to stdout") ;
}
-static void print_servicedir (char const *name)
-{
- unsigned int n = resolve_service(name) ;
- if (n >= db->nlong)
- 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") ;
-}
-
static void print_script (char const *name, int h)
{
unsigned int argc ;
@@ -209,6 +199,30 @@ static void print_script (char const *name, int h)
strerr_diefu1sys(111, "write to stdout") ;
}
+static inline void print_pipeline (char const *name)
+{
+ unsigned int n = resolve_service(name) ;
+ if (n >= db->nlong)
+ strerr_dief5x(5, "in database ", compiled, ": identifier ", name, " does not represent a longrun") ;
+ for (;;)
+ {
+ register unsigned int j = db->services[n].x.longrun.pipeline[0] ;
+ if (j >= db->nlong) break ;
+ n = j ;
+ }
+ for (;;)
+ {
+ register unsigned int j = db->services[n].x.longrun.pipeline[1] ;
+ if (buffer_puts(buffer_1, db->string + db->services[n].name) < 0
+ || buffer_put(buffer_1, "\n", 1) < 0)
+ strerr_diefu1sys(111, "write to stdout") ;
+ if (j >= db->nlong) break ;
+ n = j ;
+ }
+ if (buffer_flush(buffer_1))
+ strerr_diefu1sys(111, "write to stdout") ;
+}
+
static inline void print_flags (char const *name)
{
unsigned int n = resolve_service(name) ;
@@ -278,7 +292,7 @@ static inline void print_help (void)
"s6-rc-db [ -u | -d ] timeout atomicname\n"
"s6-rc-db contents bundlename\n"
"s6-rc-db [ -u | -d ] dependencies servicename...\n"
-"s6-rc-db servicedir longrunname\n"
+"s6-rc-db pipeline longrunname\n"
"s6-rc-db [ -u | -d ] script oneshotname\n"
"s6-rc-db flags atomicname\n"
"s6-rc-db atomics servicename...\n"
@@ -305,7 +319,7 @@ static inline unsigned int parse_command (char const *command)
"timeout",
"contents",
"dependencies",
- "servicedir",
+ "pipeline",
"script",
"flags",
"atomics",
@@ -421,11 +435,19 @@ int main (int argc, char const *const *argv)
{
case 1 : /* check */
{
- unsigned int problem, w ;
- if (!s6rc_db_check_revdeps(&dbblob))
+ diuint32 problem ;
+ if (s6rc_db_check_revdeps(&dbblob))
strerr_dief3x(4, "invalid service database in ", compiled, ": direct and reverse dependencies are mismatched") ;
- w = s6rc_db_check_depcycles(&dbblob, 1, &problem) ;
- if (w < n) strerr_dief6x(4, "invalid service database in ", compiled, ": service ", stringblob + serviceblob[w].name, " has a dependency cycle involving ", stringblob + serviceblob[problem].name) ;
+ if (s6rc_db_check_depcycles(&dbblob, 1, &problem))
+ strerr_dief8x(4, "invalid service database in ", compiled, ": dependency ", "cycle", " involving ", stringblob + serviceblob[problem.left].name, " and ", stringblob + serviceblob[problem.right].name) ;
+ r = s6rc_db_check_pipelines(&dbblob, &problem) ;
+ if (r)
+ {
+ if (r == 1)
+ strerr_dief8x(4, "invalid service database in ", compiled, ": pipeline ", "cycle", " involving ", stringblob + serviceblob[problem.left].name, " and ", stringblob + serviceblob[problem.right].name) ;
+ else
+ strerr_dief8x(4, "invalid service database in ", compiled, ": pipeline ", "collision", " involving ", stringblob + serviceblob[problem.left].name, " and ", stringblob + serviceblob[problem.right].name) ;
+ }
break ;
}
case 2 : /* list */
@@ -450,8 +472,8 @@ int main (int argc, char const *const *argv)
case 6 : /* dependencies */
print_union(argv + 1, up, 1, 0) ;
break ;
- case 7 : /* servicedir */
- print_servicedir(argv[1]) ;
+ case 7 : /* pipeline */
+ print_pipeline(argv[1]) ;
break ;
case 8 : /* script */
print_script(argv[1], up) ;
diff --git a/src/s6-rc/s6-rc-update.c b/src/s6-rc/s6-rc-update.c
index 42a84e8..08f719f 100644
--- a/src/s6-rc/s6-rc-update.c
+++ b/src/s6-rc/s6-rc-update.c
@@ -8,8 +8,10 @@
#include <skalibs/uint32.h>
#include <skalibs/uint.h>
#include <skalibs/bytestr.h>
-#include <skalibs/sgetopt.h>
+#include <skalibs/allreadwrite.h>
+#include <skalibs/buffer.h>
#include <skalibs/strerr2.h>
+#include <skalibs/sgetopt.h>
#include <skalibs/bitarray.h>
#include <skalibs/cdb.h>
#include <skalibs/stralloc.h>
@@ -21,7 +23,7 @@
#include <s6-rc/config.h>
#include <s6-rc/s6rc.h>
-#define USAGE "s6-rc-update [ -n ] [ -v verbosity ] [ -t timeout ] [ -l live ] newdb"
+#define USAGE "s6-rc-update [ -n ] [ -v verbosity ] [ -t timeout ] [ -l live ] [ -f conversion_file ] newdb"
#define dieusage() strerr_dieusage(100, USAGE)
#define dienomem() strerr_diefu1sys(111, "build string") ;
@@ -29,6 +31,11 @@ static char const *live = S6RC_LIVE_BASE ;
static unsigned int livelen = sizeof(S6RC_LIVE_BASE) - 1 ;
static unsigned int verbosity = 1 ;
+
+
+ /* Conversions and transitions */
+
+
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 ;
@@ -60,6 +67,9 @@ static inline void parse_line (stralloc *sa, char const *s, unsigned int slen, u
strerr_diefu3sys(111, "read ", live, "/compiled/resolve.cdb") ;
uint32_unpack_big(pack, &x) ;
if (x >= oldn) strerr_dief3x(4, "invalid database in ", live, "/compiled") ;
+ if (oldstate[x] & 64)
+ strerr_dief3x(6, "service ", olddb->string + olddb->services[x].name, " appears more than once in conversion file") ;
+ oldstate[x] |= 64 ;
cur = base + slen + str_len(sa->s + base + slen) + 1 ;
if (n >= 2 && !str_diff(sa->s + cur, "->"))
{
@@ -80,18 +90,17 @@ static inline void parse_line (stralloc *sa, char const *s, unsigned int slen, u
}
}
-static inline void parse_conversion_file (stralloc *sa, unsigned int *newnames, unsigned char *oldstate, int fdoldc, s6rc_db_t const *olddb)
+static inline void parse_conversion_file (char const *convfile, stralloc *sa, unsigned int *newnames, unsigned char *oldstate, cdb_t *oldc, s6rc_db_t const *olddb)
{
+ int fd = open_readb(convfile) ;
+ char buf[4096] ;
+ buffer b = BUFFER_INIT(&fd_readsv, fd, buf, 4096) ;
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") ;
+ if (fd < 0) strerr_diefu2sys(111, "open ", convfile) ;
for (;;)
{
- register int r = skagetln(buffer_0, &satmp, '\n') ;
+ register int r = skagetln(&b, &satmp, '\n') ;
if (!r) break ;
if (r < 0)
{
@@ -99,45 +108,53 @@ static inline void parse_conversion_file (stralloc *sa, unsigned int *newnames,
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) ;
+ parse_line(sa, satmp.s + base, satmp.len - base, newnames, oldstate, oldc, olddb) ;
satmp.len = base ;
}
satmp.len = base ;
+ 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)
+{
+ 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") ;
+
+ parse_conversion_file(convfile, namedata, nameindex, 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, int fdnewc, 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 *nameindex, cdb_t *newc, 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)) ;
+ 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)
+ if (cdb_datalen(newc) & 3)
strerr_dief3x(4, "invalid resolve database in ", newfn, "/resolve.cdb") ;
- len = cdb_datalen(&newc) >> 2 ;
+ 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 pack[cdb_datalen(newc) + 1] ;
char const *p = pack ;
- if (cdb_read(&newc, pack, cdb_datalen(&newc), cdb_datapos(&newc)) < 0)
+ 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--)
@@ -154,6 +171,18 @@ static inline void fill_convtable_and_flags (unsigned char *conversion_table, un
}
}
+}
+
+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)
+{
+ cdb_t newc = CDB_ZERO ;
+ int newfdres = open_readatb(fdnewc, "resolve.cdb") ;
+ if (newfdres < 0) strerr_diefu3sys(111, "open ", newfn, "/compiled/resolve.cdb") ;
+ 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) ;
+
cdb_free(&newc) ;
close(newfdres) ;
}
@@ -183,17 +212,20 @@ static inline void adjust_newalreadyup (unsigned char const *oldstate, unsigned
}
}
-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)
+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)
{
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] ;
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) ;
+
+ 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) ;
}
adjust_newwantup(oldstate, oldn, newstate, newn, conversion_table) ;
@@ -201,6 +233,11 @@ static void compute_transitions (unsigned char *oldstate, int fdoldc, s6rc_db_t
adjust_newalreadyup(oldstate, oldn, newstate, newn, conversion_table) ;
}
+
+
+ /* Service directory replacement */
+
+
static int safe_servicedir_update (char const *dst, char const *src, int h)
{
unsigned int dstlen = str_len(dst) ;
@@ -252,8 +289,9 @@ static int safe_servicedir_update (char const *dst, char const *src, int h)
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, 4, "finish") ;
- hiercopy(srcfn, dstfn) ;
+ 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)
{
byte_copy(dstfn + dstlen + 1, 5, "down") ;
@@ -302,6 +340,11 @@ static inline void update_servicedirs (unsigned char const *oldstate, unsigned i
{
}
+
+
+ /* The update itself. */
+
+
static inline void update_state_and_compiled (unsigned char const *newstate, unsigned int newn, char const *newcompiled)
{
char fn[livelen + 14] ;
@@ -346,6 +389,7 @@ static void fill_tfmt (char *tfmt, tain_t const *deadline)
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" ;
@@ -355,7 +399,7 @@ int main (int argc, char const *const *argv, char const *const *envp)
subgetopt_t l = SUBGETOPT_ZERO ;
for (;;)
{
- register int opt = subgetopt_r(argc, argv, "v:t:nl:", &l) ;
+ register int opt = subgetopt_r(argc, argv, "v:t:nl:f:", &l) ;
if (opt == -1) break ;
switch (opt)
{
@@ -363,6 +407,7 @@ int main (int argc, char const *const *argv, char const *const *envp)
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 'f' : convfile = l.arg ; break ;
default : dieusage() ;
}
}
@@ -464,7 +509,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(oldstate, fdoldc, &olddb, newstate, fdnewc, argv[0], &newdb) ;
+ compute_transitions(convfile, oldstate, fdoldc, &olddb, newstate, fdnewc, argv[0], &newdb) ;
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 2cb4caa..db30690 100644
--- a/src/s6-rc/s6-rc.c
+++ b/src/s6-rc/s6-rc.c
@@ -121,7 +121,7 @@ static pid_t start_oneshot (unsigned int i, int h)
static pid_t start_longrun (unsigned int i, int h)
{
- unsigned int svdlen = str_len(db->string + db->services[i].x.longrun.servicedir) ;
+ unsigned int svdlen = str_len(db->string + db->services[i].name) ;
unsigned int m = 0 ;
char fmt[UINT32_FMT] ;
char vfmt[UINT_FMT] ;
@@ -129,7 +129,7 @@ static pid_t start_longrun (unsigned int i, int h)
char const *newargv[7 + !!dryrun[0] * 6] ;
byte_copy(servicefn, livelen, live) ;
byte_copy(servicefn + livelen, 9, "/scandir/") ;
- byte_copy(servicefn + livelen + 9, svdlen, db->string + db->services[i].x.longrun.servicedir) ;
+ byte_copy(servicefn + livelen + 9, svdlen, db->string + db->services[i].name) ;
if (h)
{
byte_copy(servicefn + livelen + 9 + svdlen, 17, "/notification-fd") ;
@@ -166,11 +166,11 @@ static void success_longrun (unsigned int i, int h)
{
if (!dryrun[0])
{
- unsigned int svdlen = str_len(db->string + db->services[i].x.longrun.servicedir) ;
+ unsigned int svdlen = str_len(db->string + db->services[i].name) ;
char fn[livelen + svdlen + 15] ;
byte_copy(fn, livelen, live) ;
byte_copy(fn + livelen, 9, "/scandir/") ;
- byte_copy(fn + livelen + 9, svdlen, db->string + db->services[i].x.longrun.servicedir) ;
+ byte_copy(fn + livelen + 9, svdlen, db->string + db->services[i].name) ;
byte_copy(fn + livelen + 9 + svdlen, 6, "/down") ;
if (h)
{