diff options
Diffstat (limited to 'src/libs6/s6_supervise_link.c')
-rw-r--r-- | src/libs6/s6_supervise_link.c | 158 |
1 files changed, 18 insertions, 140 deletions
diff --git a/src/libs6/s6_supervise_link.c b/src/libs6/s6_supervise_link.c index 1d2ae15..0c6852c 100644 --- a/src/libs6/s6_supervise_link.c +++ b/src/libs6/s6_supervise_link.c @@ -1,156 +1,34 @@ /* 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 *scdir, char const *prefix, size_t prefixlen, size_t maxlen, char const *names, size_t nameslen, uint32_t killopts) -{ - char fn[prefixlen + maxlen + 1] ; - memcpy(fn, prefix, prefixlen) ; - while (nameslen) - { - size_t len = strlen(names) + 1 ; - memcpy(fn + prefixlen, names, len) ; - s6_supervise_unlink(scdir, fn, killopts) ; - names += len ; nameslen -= len ; - } -} - -static uint16_t registerit (ftrigr_t *a, char *fn, size_t len, gid_t gid, uint32_t options, tain const *deadline, tain *stamp) -{ - if (options & 4) - { - int fd ; - memcpy(fn + len, "/down", 6) ; - fd = open_trunc(fn) ; - if (fd < 0) return 0 ; - fd_close(fd) ; - } - memcpy(fn + len, "/" S6_SUPERVISE_EVENTDIR, 1 + sizeof(S6_SUPERVISE_EVENTDIR)) ; - if (!ftrigw_fifodir_make(fn, gid, options & 1)) return 0 ; - return ftrigr_subscribe(a, fn, "s", 0, deadline, stamp) ; -} - int s6_supervise_link (char const *scdir, char const *const *servicedirs, size_t n, char const *prefix, uint32_t options, tain const *deadline, tain *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++) + int r ; + size_t prefixlen = strlen(prefix) ; + stralloc sa = STRALLOC_ZERO ; + char const *names[n ? n : 1] ; { - 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 + size_t indices[n ? n : 1] ; + for (size_t i = 0 ; i < n ; i++) { - 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++ ; + indices[i] = sa.len ; + if (!stralloc_catb(&sa, prefix, prefixlen) + || !sabasename(&sa, servicedirs[i], strlen(servicedirs[i])) + || !stralloc_0(&sa)) goto err ; } - } - - { - stralloc lnames = STRALLOC_ZERO ; - ftrigr_t a = FTRIGR_ZERO ; - stralloc rpsa = STRALLOC_ZERO ; - gid_t gid = options & 2 ? -1 : getegid() ; - size_t scdirlen = strlen(scdir) ; - 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[scdirlen + prefixlen + maxlen + 2] ; - char fn[maxlen + 5 + (sizeof(S6_SUPERVISE_EVENTDIR) > 5 ? sizeof(S6_SUPERVISE_EVENTDIR) : 5)] ; - if (!ftrigr_startf(&a, deadline, stamp)) return -1 ; - memcpy(lname, scdir, scdirlen) ; - lname[scdirlen] = '/' ; - memcpy(lname + scdirlen + 1, prefix, prefixlen) ; - for (i = 0 ; i < n ; i++) - { - char *p ; - char const *src ; - size_t len = strlen(servicedirs[i]) ; - int h = bitarray_peek(locked, i) ; - memcpy(fn, servicedirs[i], len) ; - if (!h) - { - ids[m] = registerit(&a, fn, len, gid, options, deadline, stamp) ; - if (!ids[m++]) goto err ; - if (bitarray_peek(logged, i)) - { - memcpy(fn + len, "/log", 4) ; - ids[m] = registerit(&a, fn, len + 4, gid, options, deadline, stamp) ; - if (!ids[m++]) goto err ; - } - } - fn[len] = 0 ; - p = basename(fn) ; - len = strlen(p) ; - memcpy(lname + scdirlen + 1 + prefixlen, p, len + 1) ; - lstart = lnames.len ; - if (!h && !stralloc_catb(&lnames, p, len + 1)) goto err ; - if (servicedirs[i][0] == '/') src = servicedirs[i] ; - else - { - rpsa.len = 0 ; - if (sarealpath(&rpsa, servicedirs[i]) < 0 || !stralloc_0(&rpsa)) goto errl ; - src = rpsa.s ; - } - if (symlink(src, lname) < 0 && (!h || errno != EEXIST)) goto errl ; - } - stralloc_free(&rpsa) ; - r = s6_svc_writectl(scdir, 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(scdir, prefix, prefixlen, maxlen, lnames.s, lnames.len, killopts | (options & 4)) ; - stralloc_free(&lnames) ; - return -1 ; + for (size_t i = 0 ; i < n ; i++) names[i] = sa.s + indices[i] ; } + r = s6_supervise_link_names(scdir, servicedirs, names, n, options, deadline, stamp) ; + stralloc_free(&sa) ; + return r ; + + err: + stralloc_free(&sa) ; + return -1 ; } |