diff options
-rw-r--r-- | src/s6-rc/s6-rc-init.c | 2 | ||||
-rw-r--r-- | src/s6-rc/s6-rc-update.c | 95 | ||||
-rw-r--r-- | src/s6-rc/s6-rc.c | 16 |
3 files changed, 104 insertions, 9 deletions
diff --git a/src/s6-rc/s6-rc-init.c b/src/s6-rc/s6-rc-init.c index b22d399..e34ed18 100644 --- a/src/s6-rc/s6-rc-init.c +++ b/src/s6-rc/s6-rc-init.c @@ -220,7 +220,7 @@ int main (int argc, char const *const *argv) unsigned int i = 0 ; int r ; uint16 ids[ndirs] ; - char srcfn[llen + 23 + maxlen] ; + char srcfn[llen + 23 + maxlen] ; /* XXX: unsafe is dir is writable by non-root */ char dstfn[llen + 9 + sizeof(S6_SVSCAN_CTLDIR "/control") + maxlen] ; rewinddir(dir) ; byte_copy(srcfn, llen + 12, lfn) ; diff --git a/src/s6-rc/s6-rc-update.c b/src/s6-rc/s6-rc-update.c index 89db68e..a146c99 100644 --- a/src/s6-rc/s6-rc-update.c +++ b/src/s6-rc/s6-rc-update.c @@ -1,11 +1,106 @@ /* ISC license. */ +#include <unistd.h> +#include <errno.h> +#include <stdio.h> +#include <skalibs/bytestr.h> #include <skalibs/sgetopt.h> #include <skalibs/strerr2.h> +#include <skalibs/djbunix.h> +#include <s6/s6-supervise.h> +#include <s6-rc/s6rc-constants.h> #define USAGE "s6-rc-update [ -l live ]" #define dieusage() strerr_dieusage(100, USAGE) +static char const *live = S6RC_LIVE_BASE ; + +static int safe_servicedir_update (char const *dst, char const *src, int h) +{ + unsigned int dstlen = str_len(dst) ; + unsigned int srclen = str_len(src) ; + int fd ; + int hasdata = 1, hasenv = 1, ok = 1 ; + char dstfn[dstlen + 15 + sizeof(S6_SUPERVISE_CTLDIR)] ; + char srcfn[srclen + 17] ; + char tmpfn[dstlen + 21] ; + byte_copy(dstfn, dstlen, dst) ; + byte_copy(srcfn, srclen, src) ; + + byte_copy(dstfn + dstlen, 6, "/down") ; + fd = open_trunc(dstfn) ; + if (fd < 0) strerr_warnwu2sys("touch ", dstfn) ; + else close(fd) ; + byte_copy(dstfn + dstlen + 1, 5, "data") ; + byte_copy(tmpfn, dstlen + 5, dstfn) ; + byte_copy(tmpfn + dstlen + 5, 5, ".old") ; + if (rename(dstfn, tmpfn) < 0) + { + if (errno == ENOENT) hasdata = 0 ; + else goto err ; + } + byte_copy(dstfn + dstlen + 1, 4, "env") ; + byte_copy(tmpfn + dstlen + 1, 8, "env.old") ; + if (rename(dstfn, tmpfn) < 0) + { + if (errno == ENOENT) hasenv = 0 ; + else goto err ; + } + byte_copy(dstfn + dstlen + 1, 9, "nosetsid") ; + if (unlink(dstfn) < 0 && errno != ENOENT) goto err ; + byte_copy(dstfn + dstlen + 3, 14, "tification-fd") ; + if (unlink(dstfn) < 0 && errno != ENOENT) goto err ; + + byte_copy(srcfn + srclen, 17, "/notification-fd") ; + hiercopy(srcfn, dstfn) ; + byte_copy(srcfn + srclen + 3, 7, "setsid") ; + byte_copy(dstfn + dstlen + 3, 7, "setsid") ; + hiercopy(srcfn, dstfn) ; + byte_copy(srcfn + srclen + 1, 5, "data") ; + byte_copy(dstfn + dstlen + 1, 5, "data") ; + hiercopy(srcfn, dstfn) ; + byte_copy(srcfn + srclen + 1, 4, "env") ; + byte_copy(dstfn + dstlen + 1, 4, "env") ; + hiercopy(srcfn, dstfn) ; + byte_copy(srcfn + srclen + 1, 4, "run") ; + 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) ; + if (h) + { + byte_copy(dstfn + dstlen + 1, 5, "down") ; + if (unlink(dstfn) < 0) + { + strerr_warnwu2sys("unlink ", dstfn) ; + ok = 0 ; + } + byte_copy(dstfn + dstlen + 1, 8 + sizeof(S6_SUPERVISE_CTLDIR), S6_SUPERVISE_CTLDIR "/control") ; + s6_svc_write(dstfn, "u", 1) ; + } + byte_copy(dstfn + dstlen + 1, 9, "data.old") ; + rm_rf(dstfn) ; + byte_copy(dstfn + dstlen + 1, 8, "env.old") ; + rm_rf(dstfn) ; + return 1 ; + + err: + if (h) + { + int e = errno ; + byte_copy(dstfn + dstlen + 1, 5, "down") ; + unlink(dstfn) ; + errno = e ; + } + return 0 ; +} + +static int servicedir_name_change (char const *live, char const *oldname, char const *newname) +{ + return 1 ; +} + int main (int argc, char const *const *argv) { PROG = "s6-rc-update" ; diff --git a/src/s6-rc/s6-rc.c b/src/s6-rc/s6-rc.c index 2190404..bd5011c 100644 --- a/src/s6-rc/s6-rc.c +++ b/src/s6-rc/s6-rc.c @@ -112,14 +112,14 @@ static pid_t start_longrun (unsigned int i, int h) unsigned int m = 0 ; char fmt[UINT32_FMT] ; char vfmt[UINT_FMT] ; - char servicefn[livelen + svdlen + 30] ; + char servicefn[livelen + svdlen + 26] ; char const *newargv[7 + !!dryrun[0] * 6] ; byte_copy(servicefn, livelen, live) ; - byte_copy(servicefn + livelen, 13, "/servicedirs/") ; - byte_copy(servicefn + livelen + 13, svdlen, db->string + db->services[i].x.longrun.servicedir) ; + byte_copy(servicefn + livelen, 9, "/scandir/") ; + byte_copy(servicefn + livelen + 9, svdlen, db->string + db->services[i].x.longrun.servicedir) ; if (h) { - byte_copy(servicefn + livelen + 13 + svdlen, 17, "/notification-fd") ; + byte_copy(servicefn + livelen + 9 + svdlen, 17, "/notification-fd") ; if (access(servicefn, F_OK) < 0) { h = 2 ; @@ -154,11 +154,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) ; - char fn[livelen + svdlen + 19] ; + char fn[livelen + svdlen + 15] ; byte_copy(fn, livelen, live) ; - byte_copy(fn + livelen, 13, "/servicedirs/") ; - byte_copy(fn + livelen + 13, svdlen, db->string + db->services[i].x.longrun.servicedir) ; - byte_copy(fn + livelen + 13 + svdlen, 6, "/down") ; + 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, 6, "/down") ; if (h) { if (unlink(fn) < 0 && verbosity) |