summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2021-06-29 00:16:10 +0000
committerLaurent Bercot <ska@appnovation.com>2021-06-29 00:16:10 +0000
commit4c1d58b509c83ff788fe1ad6b5bdd1073977622c (patch)
tree2788fa5a734ec40a0a3690846189090ff629ecba
parent4b057ce275a2761656b62a3fa1e57ebf934c3af8 (diff)
downloads6-rc-4c1d58b509c83ff788fe1ad6b5bdd1073977622c.tar.xz
Some work on the db representation
Signed-off-by: Laurent Bercot <ska@appnovation.com>
-rw-r--r--src/include-local/db.h (renamed from src/include/s6-rc/db.h)26
-rw-r--r--src/libs6rcd/s6rc_db_free.c18
-rw-r--r--src/libs6rcd/s6rc_db_read.c131
-rw-r--r--src/libs6rcd/s6rc_db_read_hash.c15
-rw-r--r--src/libs6rcd/s6rc_service_common.c19
-rw-r--r--src/libs6rcd/s6rc_service_resolve.c33
-rw-r--r--src/server/db.h13
-rw-r--r--src/server/s6-rcd.h1
-rw-r--r--src/server/state.c20
-rw-r--r--src/server/state.h3
10 files changed, 252 insertions, 27 deletions
diff --git a/src/include/s6-rc/db.h b/src/include-local/db.h
index 8953a49..a937e7a 100644
--- a/src/include/s6-rc/db.h
+++ b/src/include-local/db.h
@@ -1,13 +1,16 @@
/* ISC license. */
-#ifndef S6RC_SERVICE_H
-#define S6RC_SERVICE_H
+#ifndef S6RCD_SERVICE_H
+#define S6RCD_SERVICE_H
#include <stdint.h>
/* Service types and db representation in memory */
+#define S6RC_INSTANCES_MAX 0xffffffU
+#define S6RC_INSTANCEPARAM_MAXLEN 0xffffffU
+
typedef enum s6rc_stype_e s6rc_stype_t, *s6rc_stype_t_ref ;
enum s6rc_stype_e
{
@@ -19,14 +22,21 @@ enum s6rc_stype_e
S6RC_STYPE_PHAIL
} ;
-typedef struct s6rc_sid_s s6rc_sid_t, *s6rc_sid_t_ref ;
-struct s6rc_sid_s
+
+typedef struct s6rc_baseid_s s6rc_baseid_t, *s6rc_baseid_t_ref ;
+struct s6rc_baseid_s
{
uint32_t i ;
- char const *param ;
s6rc_stype_t stype ;
} ;
+typedef struct s6rc_id_s s6rc_id_t, *s6rc_id_t_ref ;
+struct s6rc_id_s
+{
+ char const *param ;
+ s6rc_baseid_t baseid ;
+} ;
+
typedef struct s6rc_common_s s6rc_common_t, *s6rc_common_t_ref ;
struct s6rc_common_s
{
@@ -86,17 +96,15 @@ struct s6rc_deptype_s
typedef struct s6rc_db_s s6rc_db_t, *s6rc_db_t_ref ;
struct s6rc_db_s
{
- uint32_t ntotal ;
uint32_t n[STYPE_PHAIL << 1] ;
- uint32_t storagelen ;
s6rc_longrun_t *longruns ;
s6rc_oneshot_t *oneshots ;
s6rc_external_t *externals ;
s6rc_bundle_t *bundles ;
s6rc_bundle_t *virtuals ;
- s6rc_sid_t *deps[2] ;
+ s6rc_baseid_t *deps[2] ;
s6rc_deptype_t *deptypes[2] ;
- s6rc_sid_t *producers ;
+ s6rc_baseid_t *producers ;
char const **argvs ;
char *storage ;
} ;
diff --git a/src/libs6rcd/s6rc_db_free.c b/src/libs6rcd/s6rc_db_free.c
new file mode 100644
index 0000000..b8eb54e
--- /dev/null
+++ b/src/libs6rcd/s6rc_db_free.c
@@ -0,0 +1,18 @@
+/* ISC license. */
+
+#include <skalibs/alloc.h>
+
+#include "db.h"
+
+void s6rc_db_free (s6rc_db_t *db)
+{
+ alloc_free(db->storage) ;
+ alloc_free(db->argvs) ;
+ alloc_free(db->producers) ;
+ alloc_free(db->deptypes[0]) ;
+ alloc_free(db->deps[0]) ;
+ alloc_free(db->bundles) ;
+ alloc_free(db->externals) ;
+ alloc_free(db->oneshots) ;
+ alloc_free(db->longruns) ;
+}
diff --git a/src/libs6rcd/s6rc_db_read.c b/src/libs6rcd/s6rc_db_read.c
new file mode 100644
index 0000000..9b60184
--- /dev/null
+++ b/src/libs6rcd/s6rc_db_read.c
@@ -0,0 +1,131 @@
+/* ISC license. */
+
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+
+#include <skalibs/alloc.h>
+#include <skalibs/buffer.h>
+#include <skalibs/djbunix.h>
+#include <skalibs/sha256.h>
+
+#include "db.h"
+
+#include <skalibs/posixishard.h>
+
+static int geth (buffer *b, SHA256Schedule *ctx, char *s, size_t len)
+{
+ if (buffer_get(b, s, len) < len) return 0 ;
+ sha256_update(ctx, s, len) ;
+ return 1 ;
+}
+
+static int readu32 (buffer *b, SHA256Schedule *ctx, uint32_t *x)
+{
+ char pack[4] ;
+ if (!geth(b, ctx, pack, 4)) return 0 ;
+ uint32_unpack_big(pack, x) ;
+ return 1 ;
+}
+
+static int readdeps (buffer *b, SHA256Schedule *ctx, s6rc_baseid_t *deps, uint32_t ndeps, uint32_t const *dbn)
+{
+ for (uint32_t i = 0 ; i < (ndeps << 1) ; i++)
+ {
+ char pack[5] ;
+ if (!geth(b, ctx, pack, 5)) return 0 ;
+ if ((unsigned char)pack[0] >= S6RC_STYPE_PHAIL) return (errno = EPROTO, 0) ;
+ deps[i].stype = pack[0] ;
+ uint32_unpack_big(pack + 1, &deps[i].i) ;
+ }
+ return 1 ;
+}
+
+int s6rc_db_read_main (char const *dir, s6rc_db_t const *db, char *dbhash)
+{
+ SHA256Schedule ctx = SHA256_INIT() ;
+ int fd ;
+ buffer b ;
+ size_t len = strlen(dir) ;
+ uint32_t ndeps, nproducers, nargvs, storagelen ;
+ char buf[1024] ;
+ char fn[len + 4] ;
+ memcpy(fn, dir, len) ;
+ memcpy(fn + len, "/db", 4) ;
+ fd = openc_read(fn) ;
+ if (fd == -1) return 0 ;
+ buffer_init(&b, &buffer_read, fd, buf, 1024) ;
+
+ {
+ char banner[S6RC_DB_BANNER_START_LEN] ;
+ if (!geth(&b, &ctx, banner, S6RC_DB_BANNER_START_LEN)) goto err0 ;
+ if (memcmp(banner, S6RC_DB_BANNER_START, S6RC_DB_BANNER_START_LEN)) { errno = EPROTO ; goto err0 ; }
+ }
+
+ {
+ uint32_t ntotal ;
+ uint32_t nacc = 0 ;
+ if (!readu32(&b, &ctx, &ntotal)) goto err0 ;
+ for (s6rc_stype_t type = 0 ; (type < S6RC_STYPE_PHAIL << 1) ; type++)
+ {
+ if (!readu32(&b, &ctx, db->n + type)) goto err0 ;
+ nacc += db->n[type] ;
+ }
+ if (ntotal != nacc) { errno = EPROTO ; goto err0 ; }
+ }
+ if (!readu32(&b, &ctx, &ndeps)) goto err0 ;
+ if (!readu32(&b, &ctx, &nproducers)) goto err0 ;
+ if (!readu32(&b, &ctx, &nargvs)) goto err0 ;
+ if (!readu32(&b, &ctx, &storagelen)) goto err0 ;
+
+ db->longruns = alloc(sizeof(s6rc_longrun_t) * (db->n[S6RC_STYPE_LONGRUN] + db->n[S6RC_STYPE_PHAIL + S6RC_STYPE_LONGRUN])) ;
+ if (!db->longruns) goto err0 ;
+ db->oneshots = alloc(sizeof(s6rc_oneshot_t) * (db->n[S6RC_STYPE_ONESHOT] + db->n[S6RC_STYPE_PHAIL + S6RC_STYPE_ONESHOT])) ;
+ if (!db->oneshots) goto err1 ;
+ db->externals = alloc(sizeof(s6rc_external_t) * (db->n[S6RC_STYPE_EXTERNAL] + db->n[S6RC_STYPE_PHAIL + S6RC_STYPE_EXTERNAL])) ;
+ if (!db->externals) goto err2 ;
+ db->bundles = alloc(sizeof(s6rc_bundle_t) * (db->n[S6RC_STYPE_BUNDLE] + db->n[S6RC_STYPE_PHAIL + S6RC_STYPE_BUNDLE] + db->n[S6RC_STYPE_VIRTUAL] + db->n[S6RC_STYPE_PHAIL + S6RC_TYPE_VIRTUAL])) ;
+ if (!db->bundles) goto err3 ;
+ db->virtuals = db->bundles + db->n[S6RC_STYPE_BUNDLE] + db->n[S6RC_STYPE_PHAIL + S6RC_STYPE_BUNDLE])) ;
+ db->deps[0] = alloc(sizeof(s6rc_baseid_t) * (ndeps << 1)) ;
+ if (!db->deps[0]) goto err4 ;
+ db->deps[1] = db->deps[0] + ndeps ;
+ db->deptypes[0] = alloc(sizeof(s6rc_deptype_t) * (ndeps << 1)) ;
+ if (!db->deptypes[0]) goto err5 ;
+ db->deptypes[1] = db->deptypes[0] + ndeps ;
+ db->producers = alloc(sizeof(s6rc_baseid_t) * nproducers) ;
+ if (!db->producers) goto err6 ;
+ db->argvs = alloc(sizeof(char const *) * nargvs) ;
+ if (!db->longruns) goto err7 ;
+ db->storage = alloc(storagelen) ;
+ if (!db->storage) goto err8 ;
+
+ if (!geth(&b, &ctx, db->storage, storagelen)) goto err ;
+ if (!geth(&b, &ctx, db->deptypes[0], sizeof(s6rc_deptype_t) * (ndeps << 1))) goto err ;
+ if (!readdeps(&b, &ctx, db->deps[0], ndeps, db->n)) goto err ;
+
+ sha256_final(&ctx, dbhash) ;
+ return 1 ;
+
+ err:
+ alloc_free(db->storage) ;
+ err8:
+ alloc_free(db->argvs) ;
+ err7:
+ alloc_free(db->producers) ;
+ err6:
+ alloc_free(db->deptypes[0]) ;
+ err5:
+ alloc_free(db->deps[0]) ;
+ err4:
+ alloc_free(db->bundles) ;
+ err3:
+ alloc_free(db->externals) ;
+ err2:
+ alloc_free(db->oneshots) ;
+ err1:
+ alloc_free(db->longruns) ;
+ err0:
+ fd_close(fd) ;
+ return 0 ;
+}
diff --git a/src/libs6rcd/s6rc_db_read_hash.c b/src/libs6rcd/s6rc_db_read_hash.c
new file mode 100644
index 0000000..f33e657
--- /dev/null
+++ b/src/libs6rcd/s6rc_db_read_hash.c
@@ -0,0 +1,15 @@
+/* ISC license. */
+
+#include <string.h>
+#include <skalibs/djbunix.h>
+
+#include "db.h"
+
+int s6rc_db_read_hash (char const *dir, char *dbhash)
+{
+ size_t len = strlen(dir) ;
+ char fn[len + 6] ;
+ memcpy(fn, dir, len) ;
+ memcpy(fn + len, "/hash", 6) ;
+ return openreadnclose(fn, dbhash, 32) == 32 ;
+}
diff --git a/src/libs6rcd/s6rc_service_common.c b/src/libs6rcd/s6rc_service_common.c
new file mode 100644
index 0000000..93c6ee3
--- /dev/null
+++ b/src/libs6rcd/s6rc_service_common.c
@@ -0,0 +1,19 @@
+/* ISC license. */
+
+#include <stdint.h>
+
+#include "db.h"
+
+s6rc_common_t const *s6rc_service_common (s6rc_db_t const *db, s6rc_sid_t const *id)
+{
+ uint32_t i = id->i + (id->param ? db->n[id->stype] : 0) ;
+ switch (id->stype)
+ {
+ case STYPE_LONGRUN : return &db->longruns[i].common ;
+ case STYPE_ONESHOT : return &db->oneshots[i].common ;
+ case STYPE_EXTERNAL : return &db->externals[i].common ;
+ case STYPE_BUNDLE : return &db->bundles[i].common ;
+ case STYPE_VIRTUAL : return &db->virtuals[i].common ;
+ default : return 0 ;
+ }
+}
diff --git a/src/libs6rcd/s6rc_service_resolve.c b/src/libs6rcd/s6rc_service_resolve.c
new file mode 100644
index 0000000..a786542
--- /dev/null
+++ b/src/libs6rcd/s6rc_service_resolve.c
@@ -0,0 +1,33 @@
+/* ISC license. */
+
+#include <string.h>
+#include <errno.h>
+
+#include <skalibs/uint32.h>
+#include <skalibs/bytestr.h>
+#include <skalibs/cdb.h>
+
+#include "db.h"
+
+int s6rc_service_resolve (cdb_t *c, s6rc_sid_t *id, char const *s)
+{
+ size_t len = strlen(s) ;
+ char const *param = 0 ;
+ char pack[5] ;
+ int r = cdb_find(c, s, len) ;
+ if (r < 0) return r ;
+ if (!r)
+ {
+ size_t at = byte_chr(s, len, '@') ;
+ if (at == len) return 0 ;
+ if (at == len - 1) return (errno = EINVAL, -1) ;
+ r = cdb_find(c, s, at + 1) ;
+ if (r <= 0) return r ;
+ param = s + at + 1 ;
+ }
+ if (cdb_read(c, pack, 5, cdb_datapos(c)) < 0) return -1 ;
+ id->stype = pack[0] ;
+ uint32_unpack_big(pack + 1, &id->i) ;
+ id->param = param ;
+ return 1 ;
+}
diff --git a/src/server/db.h b/src/server/db.h
deleted file mode 100644
index 2c960bc..0000000
--- a/src/server/db.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/* ISC license. */
-
-#ifndef S6RCD_DB_H
-#define S6RCD_DB_H
-
-#include <s6-rc/db.h>
-
- /* Service database */
-
-extern int db_load (s6rc_db_t *, char const *) ;
-extern int db_read_sizes (s6rc_db_sizes_t *, char const *) ;
-
-#endif
diff --git a/src/server/s6-rcd.h b/src/server/s6-rcd.h
index ca0867a..ce47e0b 100644
--- a/src/server/s6-rcd.h
+++ b/src/server/s6-rcd.h
@@ -6,7 +6,6 @@
#include "client.h"
#include "clientrules.h"
#include "command.h"
-#include "db.h"
#include "dynstorage.h"
#include "ep.h"
#include "ev.h"
diff --git a/src/server/state.c b/src/server/state.c
index c6fb2d0..29d1548 100644
--- a/src/server/state.c
+++ b/src/server/state.c
@@ -4,16 +4,19 @@
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
+#include <errno.h>
#include <skalibs/alloc.h>
#include <skalibs/genalloc.h>
#include <skalibs/buffer.h>
#include <skalibs/djbunix.h>
-#include <s6-rc/db.h>
+#include "db.h"
#include "dynstorage.h"
#include "state.h"
+#include <skalibs/posixishard.h>
+
static stateatom_t const stateatom_zero = STATEATOM_ZERO ;
void instance_free (instance_t *ins)
@@ -154,6 +157,7 @@ int state_read (char const *file, state_t *st, uint32_t const *dbn)
char pack[4] ;
if (buffer_get(&b, pack, 4) < 4) goto err ;
uint32_unpack_big(pack, &n) ;
+ if (n > S6RC_INSTANCES_MAX) goto eproto ;
if (!genalloc_ready(instance_t, st->dyn[type] + i, n)) goto err ;
for (uint32_t j = 0 ; i < n ; j++)
{
@@ -162,10 +166,11 @@ int state_read (char const *file, state_t *st, uint32_t const *dbn)
if (!atom_read(&b, &ins->state)) goto err ;
if (buffer_get(&b, pack, 4) < 4) goto err ;
uint32_unpack_big(pack, &len) ;
+ if (len > S6RC_INSTANCE_MAXLEN) goto eproto ;
{
char param[len + 1] ;
if (buffer_get(&b, param, len + 1) < len + 1) goto err ;
- if (param[len]) { errno = EINVAL ; goto err ; }
+ if (param[len]) goto eproto ;
ins->param = dynstorage_add(param) ;
if (!ins_param) goto err ;
}
@@ -173,9 +178,20 @@ int state_read (char const *file, state_t *st, uint32_t const *dbn)
genalloc_setlen(instance_t, st->dyn[type] + i, n) ;
}
+ {
+ char c ;
+ switch (buffer_get(&b, &c, 1))
+ {
+ case -1 : goto err ;
+ case 1 : goto eproto ;
+ }
+ }
+
fd_close(fd) ;
return 1 ;
+ eproto:
+ errno = EPROTO ;
err:
fd_close(fd) ;
err0:
diff --git a/src/server/state.h b/src/server/state.h
index f49ffb4..2690f45 100644
--- a/src/server/state.h
+++ b/src/server/state.h
@@ -5,8 +5,7 @@
#include <skalibs/genalloc.h>
-#include <s6-rc/db.h>
-
+#include "db.h"
/* Service states, instances, machine state */