diff options
author | Laurent Bercot <ska-skaware@skarnet.org> | 2016-03-17 01:00:04 +0000 |
---|---|---|
committer | Laurent Bercot <ska-skaware@skarnet.org> | 2016-03-17 01:00:04 +0000 |
commit | 76bf614a1a7e81434bfa70b90e0d728a00478431 (patch) | |
tree | 0bf0987e4e5c2f9aa7806ce4ee085012ca4daee9 /src/libs6rc | |
parent | 3cf69b8cea7778196db5c2616c6e7d8c73fa62fa (diff) | |
download | s6-rc-76bf614a1a7e81434bfa70b90e0d728a00478431.tar.xz |
Add rollback to s6rc_servicedir_manage; it should now be transactional
Diffstat (limited to 'src/libs6rc')
-rw-r--r-- | src/libs6rc/deps-lib/s6rc | 1 | ||||
-rw-r--r-- | src/libs6rc/s6rc_servicedir_manage.c | 33 | ||||
-rw-r--r-- | src/libs6rc/s6rc_servicedir_unsupervise.c | 23 |
3 files changed, 54 insertions, 3 deletions
diff --git a/src/libs6rc/deps-lib/s6rc b/src/libs6rc/deps-lib/s6rc index 2390c75..5e6263d 100644 --- a/src/libs6rc/deps-lib/s6rc +++ b/src/libs6rc/deps-lib/s6rc @@ -14,5 +14,6 @@ s6rc_servicedir_unblock.o s6rc_servicedir_copy_offline.o s6rc_servicedir_copy_online.o s6rc_servicedir_manage.o +s6rc_servicedir_unsupervise.o -ls6 -lskarnet diff --git a/src/libs6rc/s6rc_servicedir_manage.c b/src/libs6rc/s6rc_servicedir_manage.c index a6775f1..795c982 100644 --- a/src/libs6rc/s6rc_servicedir_manage.c +++ b/src/libs6rc/s6rc_servicedir_manage.c @@ -9,15 +9,27 @@ #include <skalibs/tai.h> #include <skalibs/direntry.h> #include <skalibs/djbunix.h> +#include <skalibs/stralloc.h> #include <skalibs/genalloc.h> #include <s6/s6-supervise.h> #include <s6/ftrigr.h> #include <s6/ftrigw.h> #include <s6-rc/s6rc-servicedir.h> +static void rollback (char const *live, char const *s, unsigned int len) +{ + while (len) + { + unsigned int n = str_len(s) + 1 ; + s6rc_servicedir_unsupervise(live, s, 0) ; + s += n ; len -= n ; + } +} + int s6rc_servicedir_manage (char const *live, tain_t const *deadline, tain_t *stamp) { ftrigr_t a = FTRIGR_ZERO ; + stralloc newnames = STRALLOC_ZERO ; genalloc ids = GENALLOC_ZERO ; /* uint16 */ gid_t gid = getgid() ; unsigned int livelen = str_len(live) ; @@ -62,7 +74,19 @@ int s6rc_servicedir_manage (char const *live, tain_t const *deadline, tain_t *st byte_copy(dstfn, livelen, live) ; byte_copy(dstfn + livelen, 9, "/scandir/") ; byte_copy(dstfn + livelen + 9, len + 1, d->d_name) ; - if (symlink(srcfn, dstfn) < 0 && (!r || errno != EEXIST)) { e = errno ; goto err ; } + if (symlink(srcfn, dstfn) < 0) + { + if (!r || errno != EEXIST) { e = errno ; goto err ; } + } + else if (!r) + { + if (!stralloc_catb(&newnames, d->d_name, len + 1)) + { + e = errno ; + s6rc_servicedir_unsupervise(live, d->d_name, 0) ; + goto err ; + } + } } } if (errno) { e = errno ; goto err ; } @@ -79,15 +103,18 @@ int s6rc_servicedir_manage (char const *live, tain_t const *deadline, tain_t *st { e = errno ; goto closederr ; } } - genalloc_free(uint16, &ids) ; ftrigr_end(&a) ; + genalloc_free(uint16, &ids) ; + stralloc_free(&newnames) ; return ok ; err: dir_close(dir) ; closederr: - genalloc_free(uint16, &ids) ; ftrigr_end(&a) ; + genalloc_free(uint16, &ids) ; + rollback(live, newnames.s, newnames.len) ; + stralloc_free(&newnames) ; errno = e ; return 0 ; } diff --git a/src/libs6rc/s6rc_servicedir_unsupervise.c b/src/libs6rc/s6rc_servicedir_unsupervise.c new file mode 100644 index 0000000..14a1164 --- /dev/null +++ b/src/libs6rc/s6rc_servicedir_unsupervise.c @@ -0,0 +1,23 @@ +/* ISC license. */ + +#include <unistd.h> +#include <skalibs/bytestr.h> +#include <s6/s6-supervise.h> +#include <s6-rc/s6rc-servicedir.h> + +void s6rc_servicedir_unsupervise (char const *live, char const *name, int keepsupervisor) +{ + unsigned int namelen = str_len(name) ; + unsigned int livelen = str_len(live) ; + char fn[livelen + 14 + namelen] ; + byte_copy(fn, livelen, live) ; + byte_copy(fn + livelen, 9, "/scandir/") ; + byte_copy(fn + livelen + 9, namelen + 1, name) ; + unlink(fn) ; + if (!keepsupervisor) + { + byte_copy(fn + livelen + 1, 12, "servicedirs/") ; + byte_copy(fn + livelen + 13, namelen + 1, name) ; + s6_svc_writectl(fn, S6_SUPERVISE_CTLDIR, "x", 1) ; + } +} |