diff options
author | Laurent Bercot <ska-skaware@skarnet.org> | 2020-12-04 22:35:08 +0000 |
---|---|---|
committer | Laurent Bercot <ska-skaware@skarnet.org> | 2020-12-04 22:35:08 +0000 |
commit | ce6f2000cee65d8cf3875a746815b725d4597c62 (patch) | |
tree | 7ba8615aab45ba45b792be349d730c284b0d9aff /src | |
parent | df753171561929de4aa1a6383f01655464e459ae (diff) | |
download | s6-ce6f2000cee65d8cf3875a746815b725d4597c62.tar.xz |
Add s6_supervise_link and s6_supervise_unlink for future s6-rc change
Diffstat (limited to 'src')
-rw-r--r-- | src/include/s6/s6-supervise.h | 11 | ||||
-rw-r--r-- | src/libs6/deps-lib/s6 | 2 | ||||
-rw-r--r-- | src/libs6/s6_supervise_link.c | 124 | ||||
-rw-r--r-- | src/libs6/s6_supervise_unlink.c | 45 |
4 files changed, 176 insertions, 6 deletions
diff --git a/src/include/s6/s6-supervise.h b/src/include/s6/s6-supervise.h index 187bc20..77280e7 100644 --- a/src/include/s6/s6-supervise.h +++ b/src/include/s6/s6-supervise.h @@ -3,7 +3,9 @@ #ifndef S6_SUPERVISE_H #define S6_SUPERVISE_H +#include <stdint.h> #include <sys/types.h> + #include <skalibs/tai.h> #define S6_SUPERVISE_CTLDIR "supervise" @@ -19,9 +21,6 @@ extern int s6_svc_write (char const *, char const *, size_t) ; extern int s6_svc_writectl (char const *, char const *, char const *, size_t) ; extern int s6_svc_main (int, char const *const *, char const *, char const *, char const *) ; -extern int s6_svc_lock_take (char const *) ; -extern void s6_svc_lock_release(int) ; - typedef struct s6_svstatus_s s6_svstatus_t, *s6_svstatus_t_ref ; struct s6_svstatus_s { @@ -56,9 +55,9 @@ extern void s6_svstatus_unpack (char const *, s6_svstatus_t *) ; extern int s6_svstatus_read (char const *, s6_svstatus_t *) ; extern int s6_svstatus_write (char const *, s6_svstatus_t const *) ; -/* These functions leak a fd, that's intended */ -extern int s6_supervise_lock (char const *) ; -extern int s6_supervise_lock_mode (char const *, unsigned int, unsigned int) ; +extern int s6_supervise_link (char const *, char const *const *, size_t, char const *, uint32_t, tain_t const *, tain_t *) ; +#define s6_supervise_link_g(scandir, servicedirs, n, prefix, options, deadline) s6_supervise_link(scandir, servicedirs, n, prefix, options, (deadline), &STAMP) +extern void s6_supervise_unlink (char const *, char const *, uint32_t) ; typedef struct s6_dtally_s s6_dtally_t, *s6_dtally_ref ; struct s6_dtally_s diff --git a/src/libs6/deps-lib/s6 b/src/libs6/deps-lib/s6 index d9d4341..45e6c33 100644 --- a/src/libs6/deps-lib/s6 +++ b/src/libs6/deps-lib/s6 @@ -62,4 +62,6 @@ s6_fdholder_setdump.o s6_fdholder_start.o s6_fdholder_store.o s6_fdholder_store_async.o +s6_supervise_link.o +s6_supervise_unlink.o -lskarnet diff --git a/src/libs6/s6_supervise_link.c b/src/libs6/s6_supervise_link.c new file mode 100644 index 0000000..4724421 --- /dev/null +++ b/src/libs6/s6_supervise_link.c @@ -0,0 +1,124 @@ +/* ISC license. */ + +#include <stdint.h> +#include <string.h> +#include <unistd.h> +#include <libgen.h> +#include <errno.h> +#include <sys/stat.h> + +#include <skalibs/bitarray.h> +#include <skalibs/tai.h> +#include <skalibs/stralloc.h> +#include <skalibs/djbunix.h> + +#include <s6/ftrigr.h> +#include <s6/ftrigw.h> +#include <s6/s6-supervise.h> + +static inline void do_unlink (char const *const scandir, char const *names, size_t nameslen, uint32_t killopts) +{ + while (nameslen) + { + size_t len = strlen(names) + 1 ; + s6_supervise_unlink(scandir, names, killopts) ; + names += len ; nameslen -= len ; + } +} + +int s6_supervise_link (char const *scandir, char const *const *servicedirs, size_t n, char const *prefix, uint32_t options, tain_t const *deadline, tain_t *stamp) +{ + size_t maxlen = 0 ; + size_t ntotal = n ; + unsigned char locked[bitarray_div8(n)] ; + unsigned char logged[bitarray_div8(n)] ; + if (!n) return 0 ; + memset(locked, 0, bitarray_div8(n)) ; + memset(logged, 0, bitarray_div8(n)) ; + + for (size_t i = 0 ; i < n ; i++) + { + struct stat st ; + size_t len = strlen(servicedirs[i]) ; + int h ; + char subdir[len + 5] ; + if (len > maxlen) maxlen = len ; + h = s6_svc_ok(servicedirs[i]) ; + if (h < 0) return -1 ; + if (h) bitarray_set(locked, i) ; + memcpy(subdir, servicedirs[i], len) ; + memcpy(subdir + len, "/log", 5) ; + if (stat(subdir, &st) < 0) + { + if (errno != ENOENT) return -1 ; + } + else + { + int r ; + if (!S_ISDIR(st.st_mode)) return (errno = ENOTDIR, -1) ; + r = s6_svc_ok(subdir) ; + if (r < 0) return -1 ; + if (r != h) return (errno = EINVAL, -1) ; + bitarray_set(logged, i) ; + ntotal++ ; + } + } + + { + ftrigr_t a = FTRIGR_ZERO ; + stralloc rpsa = STRALLOC_ZERO ; + stralloc lnames = STRALLOC_ZERO ; + gid_t gid = options & 2 ? -1 : getegid() ; + size_t scandirlen = strlen(scandir) ; + size_t prefixlen = strlen(prefix) ; + unsigned int m = 0 ; + size_t i = 0 ; + size_t lstart = 0 ; + uint32_t killopts = 0 ; + int r ; + uint16_t ids[ntotal] ; + char lname[scandirlen + prefixlen + maxlen + 2] ; + char fn[maxlen + 1 + sizeof(S6_SUPERVISE_EVENTDIR)] ; + char *p ; + if (!ftrigr_startf(&a, deadline, stamp)) return -1 ; + memcpy(lname, scandir, scandirlen) ; + lname[scandirlen] = '/' ; + memcpy(lname + scandirlen + 1, prefix, prefixlen) ; + for (i = 0 ; i < n ; i++) if (!bitarray_peek(locked, i)) + { + size_t len = strlen(servicedirs[i]) ; + memcpy(fn, servicedirs[i], len) ; + memcpy(fn + len, S6_SUPERVISE_EVENTDIR, sizeof(S6_SUPERVISE_EVENTDIR)) ; + if (!ftrigw_fifodir_make(fn, gid, options & 1)) goto err ; + ids[m] = ftrigr_subscribe(&a, fn, "s", 0, deadline, stamp) ; + if (!ids[m++]) goto err ; + fn[len] = 0 ; + p = basename(fn) ; + len = strlen(p) ; + memcpy(lname + scandirlen + 1 + prefixlen, p, len + 1) ; + rpsa.len = 0 ; + lstart = lnames.len ; + if (!sarealpath(&rpsa, servicedirs[i]) || !stralloc_0(&rpsa)) goto err ; + if (!stralloc_catb(&lnames, lname + scandirlen + 1, prefixlen + len + 1)) goto err ; + if (symlink(rpsa.s, lname) < 0) goto errl ; + } + stralloc_free(&rpsa) ; + r = s6_svc_writectl(scandir, S6_SVSCAN_CTLDIR, "a", 1) ; + if (r <= 0) goto errsa ; + killopts = 3 ; + if (ftrigr_wait_and(&a, ids, m, deadline, stamp) < 0) goto errsa ; + ftrigr_end(&a) ; + stralloc_free(&lnames) ; + return m ; + + errl: + lnames.len = lstart ; + err: + stralloc_free(&rpsa) ; + errsa: + ftrigr_end(&a) ; + do_unlink(scandir, lnames.s, lnames.len, killopts) ; + stralloc_free(&lnames) ; + return -1 ; + } +} diff --git a/src/libs6/s6_supervise_unlink.c b/src/libs6/s6_supervise_unlink.c new file mode 100644 index 0000000..d4bbe73 --- /dev/null +++ b/src/libs6/s6_supervise_unlink.c @@ -0,0 +1,45 @@ +/* ISC license. */ + +#include <errno.h> +#include <string.h> +#include <unistd.h> +#include <limits.h> + +#include <skalibs/posixplz.h> +#include <skalibs/allreadwrite.h> +#include <skalibs/djbunix.h> + +#include <s6/s6-supervise.h> + +#ifdef PATH_MAX +# define S6_PATH_MAX PATH_MAX +#else +# define S6_PATH_MAX 4096 +#endif + +void s6_supervise_unlink (char const *scandir, char const *name, uint32_t options) +{ + int e = errno ; + int fd = -1 ; + size_t scandirlen = strlen(scandir) ; + size_t namelen = strlen(name) ; + char fn[scandirlen + namelen + sizeof(S6_SUPERVISE_CTLDIR) + 10] ; + memcpy(fn, scandir, scandirlen) ; + fn[scandirlen] = '/' ; + memcpy(fn + scandirlen + 1, name, namelen) ; + if (options & 1) + { + fn[scandirlen + 1 + namelen] = '/' ; + memcpy(fn + scandirlen + 1 + namelen + 1, S6_SUPERVISE_CTLDIR, sizeof(S6_SUPERVISE_CTLDIR) - 1) ; + memcpy(fn + scandirlen + 1 + namelen + sizeof(S6_SUPERVISE_CTLDIR), "/control", 9) ; + fd = open_write(fn) ; + } + fn[scandirlen + 1 + namelen] = 0 ; + unlink_void(fn) ; + if (fd >= 0) + { + fd_write(fd, "xd", 1 + !!(options & 2)) ; + fd_close(fd) ; + } + errno = e ; +} |