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 | |
parent | 3cf69b8cea7778196db5c2616c6e7d8c73fa62fa (diff) | |
download | s6-rc-76bf614a1a7e81434bfa70b90e0d728a00478431.tar.xz |
Add rollback to s6rc_servicedir_manage; it should now be transactional
Diffstat (limited to 'src')
-rw-r--r-- | src/include/s6-rc/s6rc-servicedir.h | 1 | ||||
-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 | ||||
-rw-r--r-- | src/s6-rc/s6-rc-update.c | 20 |
5 files changed, 57 insertions, 21 deletions
diff --git a/src/include/s6-rc/s6rc-servicedir.h b/src/include/s6-rc/s6rc-servicedir.h index 93baef7..ed2f471 100644 --- a/src/include/s6-rc/s6rc-servicedir.h +++ b/src/include/s6-rc/s6rc-servicedir.h @@ -10,6 +10,7 @@ extern int s6rc_servicedir_unblock (char const *, int) ; extern int s6rc_servicedir_copy_offline (char const *, char const *) ; extern int s6rc_servicedir_copy_online (char const *, char const *) ; #define s6rc_servicedir_copy(src, dst, h) ((h) ? s6rc_servicedir_copy_online(src, dst) : s6rc_servicedir_copy_offline(src, dst)) +extern void s6rc_servicedir_unsupervise (char const *, char const *, int) ; extern int s6rc_servicedir_manage (char const *, tain_t const *, tain_t *) ; #define s6rc_servicedir_manage_g(live, deadline) s6rc_servicedir_manage(live, (deadline), &STAMP) 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) ; + } +} diff --git a/src/s6-rc/s6-rc-update.c b/src/s6-rc/s6-rc-update.c index 6d8a1aa..da56250 100644 --- a/src/s6-rc/s6-rc-update.c +++ b/src/s6-rc/s6-rc-update.c @@ -323,23 +323,6 @@ static inline void rollback_servicedirs (char const *newlive, unsigned char cons } } -static inline void unsupervise (char const *llive, char const *name, int keepsupervisor) -{ - unsigned int namelen = str_len(name) ; - unsigned int llen = str_len(llive) ; - char fn[llen + 14 + namelen] ; - byte_copy(fn, llen, llive) ; - byte_copy(fn + llen, 9, "/scandir/") ; - byte_copy(fn + llen + 9, namelen + 1, name) ; - unlink(fn) ; - if (!keepsupervisor) - { - byte_copy(fn + llen + 1, 12, "servicedirs/") ; - byte_copy(fn + llen + 13, namelen + 1, name) ; - s6_svc_writectl(fn, S6_SUPERVISE_CTLDIR, "x", 1) ; - } -} - static inline void make_new_livedir (unsigned char const *oldstate, s6rc_db_t const *olddb, unsigned char const *newstate, s6rc_db_t const *newdb, char const *newcompiled, unsigned int *invimage, stralloc *sa) { unsigned int tmpbase = satmp.len ; @@ -431,7 +414,8 @@ static inline void make_new_livedir (unsigned char const *oldstate, s6rc_db_t co if (!stralloc_catb(sa, satmp.s + tmpbase, satmp.len - tmpbase) || !stralloc_0(sa)) dienomem() ; i = olddb->nlong ; - while (i--) unsupervise(sa->s + sabase, olddb->string + olddb->services[i].name, (oldstate[i] & 33) == 1) ; + while (i--) + s6rc_servicedir_unsupervise(sa->s + sabase, olddb->string + olddb->services[i].name, (oldstate[i] & 33) == 1) ; rm_rf(sa->s + sabase) ; sa->len = sabase ; |