diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/include/s6-rc/s6rc-servicedir.h | 12 | ||||
-rw-r--r-- | src/include/s6-rc/s6rc-utils.h | 1 | ||||
-rw-r--r-- | src/include/s6-rc/s6rc.h | 1 | ||||
-rw-r--r-- | src/libs6rc/deps-lib/s6rc | 6 | ||||
-rw-r--r-- | src/libs6rc/s6rc-servicedir-internal.h | 32 | ||||
-rw-r--r-- | src/libs6rc/s6rc_read_uint.c | 16 | ||||
-rw-r--r-- | src/libs6rc/s6rc_servicedir_block.c | 27 | ||||
-rw-r--r-- | src/libs6rc/s6rc_servicedir_copy_offline.c | 18 | ||||
-rw-r--r-- | src/libs6rc/s6rc_servicedir_copy_online.c | 74 | ||||
-rw-r--r-- | src/libs6rc/s6rc_servicedir_internal.c | 83 | ||||
-rw-r--r-- | src/libs6rc/s6rc_servicedir_unblock.c | 21 | ||||
-rw-r--r-- | src/s6-rc/s6-rc-compile.c | 44 |
12 files changed, 295 insertions, 40 deletions
diff --git a/src/include/s6-rc/s6rc-servicedir.h b/src/include/s6-rc/s6rc-servicedir.h new file mode 100644 index 0000000..d52fddf --- /dev/null +++ b/src/include/s6-rc/s6rc-servicedir.h @@ -0,0 +1,12 @@ +/* ISC license. */ + +#ifndef S6RC_SERVICEDIR_H +#define S6RC_SERVICEDIR_H + +extern int s6rc_servicedir_block (char const *) ; +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)) + +#endif diff --git a/src/include/s6-rc/s6rc-utils.h b/src/include/s6-rc/s6rc-utils.h index 992d865..c51c940 100644 --- a/src/include/s6-rc/s6rc-utils.h +++ b/src/include/s6-rc/s6rc-utils.h @@ -6,5 +6,6 @@ #include <s6-rc/s6rc-db.h> extern void s6rc_graph_closure (s6rc_db_t const *, unsigned char *, unsigned int, int) ; +extern int s6rc_read_uint (char const *, unsigned int *) ; #endif diff --git a/src/include/s6-rc/s6rc.h b/src/include/s6-rc/s6rc.h index 098f38b..87a87ef 100644 --- a/src/include/s6-rc/s6rc.h +++ b/src/include/s6-rc/s6rc.h @@ -6,5 +6,6 @@ #include <s6-rc/s6rc-constants.h> #include <s6-rc/s6rc-db.h> #include <s6-rc/s6rc-utils.h> +#include <s6-rc/s6rc-servicedir.h> #endif diff --git a/src/libs6rc/deps-lib/s6rc b/src/libs6rc/deps-lib/s6rc index 194ea43..e415f45 100644 --- a/src/libs6rc/deps-lib/s6rc +++ b/src/libs6rc/deps-lib/s6rc @@ -5,4 +5,10 @@ s6rc_db_read.o s6rc_db_read_sizes.o s6rc_db_read_uint32.o s6rc_graph_closure.o +s6rc_read_uint.o +s6rc_servicedir_internal.o +s6rc_servicedir_block.o +s6rc_servicedir_unblock.o +s6rc_servicedir_copy_offline.o +s6rc_servicedir_copy_online.o -lskarnet diff --git a/src/libs6rc/s6rc-servicedir-internal.h b/src/libs6rc/s6rc-servicedir-internal.h new file mode 100644 index 0000000..fe05a40 --- /dev/null +++ b/src/libs6rc/s6rc-servicedir-internal.h @@ -0,0 +1,32 @@ +/* ISC license. */ + +#ifndef S6RC_SERVICEDIR_INTERNAL_H +#define S6RC_SERVICEDIR_INTERNAL_H + +typedef enum s6rc_filetype_e s6rc_filetype_t, *s6rc_filetype_t_ref ; +enum s6rc_filetype_e +{ + FILETYPE_NORMAL, + FILETYPE_EMPTY, + FILETYPE_UINT, + FILETYPE_DIR +} ; + +#define SVFILE_EXECUTABLE 0x01 +#define SVFILE_MANDATORY 0x02 +#define SVFILE_ATOMIC 0x04 + +typedef struct s6rc_servicedir_desc_s s6rc_servicedir_desc_t, *s6rc_servicedir_desc_t_ref ; +struct s6rc_servicedir_desc_s +{ + char const *name ; + s6rc_filetype_t type ; + unsigned char options ; +} ; + +extern s6rc_servicedir_desc_t const *s6rc_servicedir_file_list ; +extern unsigned int const s6rc_servicedir_file_maxlen ; + +extern int s6rc_servicedir_copy_one (char const *, char const *, s6rc_servicedir_desc_t const *) ; + +#endif diff --git a/src/libs6rc/s6rc_read_uint.c b/src/libs6rc/s6rc_read_uint.c new file mode 100644 index 0000000..6953190 --- /dev/null +++ b/src/libs6rc/s6rc_read_uint.c @@ -0,0 +1,16 @@ +/* ISC license. */ + +#include <errno.h> +#include <skalibs/uint.h> +#include <skalibs/bytestr.h> +#include <skalibs/djbunix.h> + +int s6rc_read_uint (char const *file, unsigned int *u) +{ + char buf[UINT_FMT + 1] ; + register int r = openreadnclose(file, buf, UINT_FMT) ; + if (r < 0) return (errno == ENOENT) ? 0 : -1 ; + buf[byte_chr(buf, r, '\n')] = 0 ; + if (!uint0_scan(buf, u)) return (errno = EINVAL, -1) ; + return 1 ; +} diff --git a/src/libs6rc/s6rc_servicedir_block.c b/src/libs6rc/s6rc_servicedir_block.c new file mode 100644 index 0000000..d01481b --- /dev/null +++ b/src/libs6rc/s6rc_servicedir_block.c @@ -0,0 +1,27 @@ +/* ISC license. */ + +#include <errno.h> +#include <unistd.h> +#include <skalibs/bytestr.h> +#include <skalibs/djbunix.h> +#include <s6/s6-supervise.h> +#include <s6-rc/s6rc-servicedir.h> + +int s6rc_servicedir_block (char const *dir) +{ + unsigned int dirlen = str_len(dir) ; + s6_svstatus_t status ; + char fn[dirlen + 6] ; + if (!s6_svstatus_read(dir, &status)) return -1 ; + byte_copy(fn, dirlen, dir) ; + byte_copy(fn + dirlen, 6, "/down") ; + if (!touch(fn)) return -1 ; + if (s6_svc_writectl(dir, S6_SUPERVISE_CTLDIR, "O", 1) < 0) + { + register int e = errno ; + unlink(fn) ; + errno = e ; + return -1 ; + } + return status.flagwantup ; +} diff --git a/src/libs6rc/s6rc_servicedir_copy_offline.c b/src/libs6rc/s6rc_servicedir_copy_offline.c new file mode 100644 index 0000000..6581a4f --- /dev/null +++ b/src/libs6rc/s6rc_servicedir_copy_offline.c @@ -0,0 +1,18 @@ +/* ISC license. */ + +#include <sys/stat.h> +#include <errno.h> +#include "s6rc-servicedir-internal.h" +#include <s6-rc/s6rc-servicedir.h> + +int s6rc_servicedir_copy_offline (char const *src, char const *dst) +{ + s6rc_servicedir_desc_t const *p = s6rc_servicedir_file_list ; + if (mkdir(dst, 0755) < 0) + { + if (errno != EEXIST) return 0 ; + } + for (; p->name ; p++) + if (!s6rc_servicedir_copy_one(src, dst, p)) return 0 ; + return 1 ; +} diff --git a/src/libs6rc/s6rc_servicedir_copy_online.c b/src/libs6rc/s6rc_servicedir_copy_online.c new file mode 100644 index 0000000..6e14844 --- /dev/null +++ b/src/libs6rc/s6rc_servicedir_copy_online.c @@ -0,0 +1,74 @@ +/* ISC license. */ + +#include <errno.h> +#include <unistd.h> +#include <stdio.h> +#include <skalibs/bytestr.h> +#include <skalibs/djbunix.h> +#include <s6-rc/s6rc-utils.h> +#include "s6rc-servicedir-internal.h" +#include <s6-rc/s6rc-servicedir.h> + +int s6rc_servicedir_copy_online (char const *src, char const *dst) +{ + unsigned int srclen = str_len(src) ; + unsigned int dstlen = str_len(dst) ; + unsigned int n ; + unsigned int i = 0 ; + int wantup = 0 ; + int e ; + char srcfn[srclen + s6rc_servicedir_file_maxlen + 6] ; + char dstfn[dstlen + s6rc_servicedir_file_maxlen + 6] ; + char oldfn[dstlen + s6rc_servicedir_file_maxlen + 6] ; + byte_copy(srcfn, srclen, src) ; + srcfn[srclen] = '/' ; + byte_copy(dstfn, dstlen + 1, dst) ; + byte_copy(oldfn, dstlen, dst) ; + byte_copy(oldfn + dstlen, 5, "/old") ; + if (rm_rf(oldfn) < 0 && errno != ENOENT) return 0 ; + if (mkdir(oldfn, 0755) < 0) return 0 ; + dstfn[dstlen] = '/' ; + oldfn[dstlen + 4] = '/' ; + wantup = s6rc_servicedir_block(dst) ; + if (wantup < 0) { e = errno ; goto errdir ; } + + for (; s6rc_servicedir_file_list[i].name ; i++) + { + str_copy(dstfn + dstlen + 1, s6rc_servicedir_file_list[i].name) ; + str_copy(oldfn + dstlen + 5, s6rc_servicedir_file_list[i].name) ; + if (rename(dstfn, oldfn) < 0) { e = errno ; goto errrename ; } + } + n = i ; + while (i--) + { + if (!s6rc_servicedir_copy_one(src, dst, s6rc_servicedir_file_list + i)) + { + e = errno ; + goto errremove ; + } + } + oldfn[dstlen + 4] = 0 ; + rm_rf(oldfn) ; + s6rc_servicedir_unblock(dst, wantup) ; + return 1 ; + + errremove: + for (; i < n ; i++) + { + str_copy(dstfn + dstlen + 1, s6rc_servicedir_file_list[i].name) ; + rm_rf(dstfn) ; + } + i = n ; + errrename: + while (i--) + { + str_copy(dstfn + dstlen + 1, s6rc_servicedir_file_list[i].name) ; + str_copy(oldfn + dstlen + 5, s6rc_servicedir_file_list[i].name) ; + rename(oldfn, dstfn) ; + } + errdir: + oldfn[dstlen + 4] = 0 ; + rmdir(oldfn) ; + errno = e ; + return 0 ; +} diff --git a/src/libs6rc/s6rc_servicedir_internal.c b/src/libs6rc/s6rc_servicedir_internal.c new file mode 100644 index 0000000..7522313 --- /dev/null +++ b/src/libs6rc/s6rc_servicedir_internal.c @@ -0,0 +1,83 @@ +/* ISC license. */ + +#include <errno.h> +#include <unistd.h> +#include <skalibs/uint.h> +#include <skalibs/bytestr.h> +#include <skalibs/djbunix.h> +#include <s6-rc/s6rc-utils.h> +#include "s6rc-servicedir-internal.h" + +static s6rc_servicedir_desc_t const svdir_file_list[] = +{ + { .name = "finish", .type = FILETYPE_NORMAL, .options = SVFILE_EXECUTABLE | SVFILE_ATOMIC }, + { .name = "finish.user", .type = FILETYPE_NORMAL, .options = SVFILE_EXECUTABLE }, + { .name = "run", .type = FILETYPE_NORMAL, .options = SVFILE_EXECUTABLE | SVFILE_MANDATORY | SVFILE_ATOMIC }, + { .name = "run.user", .type = FILETYPE_NORMAL, .options = SVFILE_EXECUTABLE }, + { .name = "nosetsid", .type = FILETYPE_EMPTY, .options = 0 }, + { .name = "notification-fd", .type = FILETYPE_UINT, .options = 0 }, + { .name = "timeout-finish", .type = FILETYPE_UINT, .options = 0 }, + { .name = "data", .type = FILETYPE_DIR, .options = 0 }, + { .name = "env", .type = FILETYPE_DIR, .options = 0 }, + { .name = 0, .options = 0 } +} ; + +s6rc_servicedir_desc_t const *s6rc_servicedir_file_list = svdir_file_list ; +unsigned int const s6rc_servicedir_file_maxlen = 15 ; + +int s6rc_servicedir_copy_one (char const *src, char const *dst, s6rc_servicedir_desc_t const *p) +{ + unsigned int srclen = str_len(src) ; + unsigned int dstlen = str_len(dst) ; + unsigned int plen = str_len(p->name) ; + char srcfn[srclen + plen + 2] ; + char dstfn[dstlen + plen + 2] ; + byte_copy(srcfn, srclen, src) ; + srcfn[srclen] = '/' ; + byte_copy(srcfn + srclen + 1, plen + 1, p->name) ; + byte_copy(dstfn, dstlen, dst) ; + dstfn[dstlen] = '/' ; + byte_copy(dstfn + dstlen + 1, plen + 1, p->name) ; + + switch (p->type) + { + case FILETYPE_NORMAL : + { + unsigned int mode = p->options & SVFILE_EXECUTABLE ? 0755 : 0644 ; + if (!(p->options & SVFILE_ATOMIC ? filecopy_suffix(srcfn, dstfn, mode, ".new") : filecopy_unsafe(srcfn, dstfn, mode))) + { + if (errno != ENOENT || p->options & SVFILE_MANDATORY) return 0 ; + } + break ; + } + case FILETYPE_EMPTY : + if (access(srcfn, F_OK) < 0) + { + if (errno != ENOENT || p->options & SVFILE_MANDATORY) return 0 ; + } + else if (!touch(dstfn)) return 0 ; + break ; + case FILETYPE_UINT : + { + unsigned int u ; + register int r = s6rc_read_uint(srcfn, &u) ; + if (r < 0 || (!r && p->options & SVFILE_MANDATORY)) return 0 ; + if (r) + { + char fmt[UINT_FMT] ; + r = uint_fmt(fmt, u) ; + fmt[r++] = '\n' ; + if (!openwritenclose_unsafe(dstfn, fmt, r)) return 0 ; + } + break ; + } + case FILETYPE_DIR : + if (!hiercopy(srcfn, dstfn)) + { + if (errno != ENOENT || p->options & SVFILE_MANDATORY) return 0 ; + } + break ; + default : return (errno = EDOM, 0) ; + } + return 1 ; +} diff --git a/src/libs6rc/s6rc_servicedir_unblock.c b/src/libs6rc/s6rc_servicedir_unblock.c new file mode 100644 index 0000000..6fd846c --- /dev/null +++ b/src/libs6rc/s6rc_servicedir_unblock.c @@ -0,0 +1,21 @@ +/* ISC license. */ + +#include <errno.h> +#include <unistd.h> +#include <skalibs/bytestr.h> +#include <s6/s6-supervise.h> +#include <s6-rc/s6rc-servicedir.h> + +int s6rc_servicedir_unblock (char const *dir, int h) +{ + if (h) + { + unsigned int dirlen = str_len(dir) ; + char fn[dirlen + 6] ; + byte_copy(fn, dirlen, dir) ; + byte_copy(fn + dirlen, 6, "/down") ; + if (unlink(fn) < 0 && errno != ENOENT) return -1 ; + if (s6_svc_writectl(dir, S6_SUPERVISE_CTLDIR, "u", 1) < 0) return -1 ; + } + return 0 ; +} diff --git a/src/s6-rc/s6-rc-compile.c b/src/s6-rc/s6-rc-compile.c index 4970840..f4ba147 100644 --- a/src/s6-rc/s6-rc-compile.c +++ b/src/s6-rc/s6-rc-compile.c @@ -1114,32 +1114,6 @@ static inline void write_resolve (char const *compiled, s6rc_db_t const *db, bun close(fd) ; } -static int filecopy (char const *src, char const *dst, mode_t mode) -{ - int d ; - int s = open_readb(src) ; - if (s < 0) return 0 ; - d = open3(dst, O_WRONLY | O_CREAT | O_TRUNC, mode) ; - if (d < 0) - { - close(s) ; - return 0 ; - } - if (fd_cat(s, d) < 0) goto err ; - close(s) ; - close(d) ; - return 1 ; - -err: - { - register int e = errno ; - close(s) ; - close(d) ; - errno = e ; - } - return 0 ; -} - static void dircopy (char const *compiled, char const *srcfn, char const *dstfn) { struct stat st ; @@ -1161,16 +1135,6 @@ static void dircopy (char const *compiled, char const *srcfn, char const *dstfn) } } -static int read_uint (char const *file, unsigned int *fd) -{ - char buf[UINT_FMT + 1] ; - register int r = openreadnclose(file, buf, UINT_FMT) ; - if (r < 0) return (errno == ENOENT) ? 0 : -1 ; - buf[byte_chr(buf, r, '\n')] = 0 ; - if (!uint0_scan(buf, fd)) return (errno = EINVAL, -1) ; - return 1 ; -} - static inline void write_run_wrapper (char const *compiled, char const *fn, s6rc_db_t const *db, unsigned int i, unsigned int fd) { unsigned int base = satmp.len ; @@ -1227,7 +1191,7 @@ static inline void write_servicedirs (char const *compiled, s6rc_db_t const *db, srcfn[srcdirlen] = '/' ; byte_copy(srcfn + srcdirlen + 1, len, db->string + db->services[i].name) ; byte_copy(srcfn + srcdirlen + 1 + len, 17, "/notification-fd") ; - r = read_uint(srcfn, &fd) ; + r = s6rc_read_uint(srcfn, &fd) ; if (r < 0) { cleanup(compiled) ; @@ -1253,17 +1217,17 @@ static inline void write_servicedirs (char const *compiled, s6rc_db_t const *db, byte_copy(dstfn + clen + 17 + len, 6, ".user") ; } byte_copy(srcfn + srcdirlen + 1 + len, 5, "/run") ; - if (!filecopy(srcfn, dstfn, 0755)) + if (!filecopy_unsafe(srcfn, dstfn, 0755)) { cleanup(compiled) ; strerr_diefu4sys(111, "copy ", srcfn, " to ", dstfn) ; } byte_copy(dstfn + clen + 14 + len, 7, "finish") ; byte_copy(srcfn + srcdirlen + len + 2, 7, "finish") ; - filecopy(srcfn, dstfn, 0755) ; + filecopy_unsafe(srcfn, dstfn, 0755) ; byte_copy(dstfn + clen + 14 + len, 15, "timeout-finish") ; byte_copy(srcfn + srcdirlen + len + 2, 15, "timeout-finish") ; - filecopy(srcfn, dstfn, 0644) ; + filecopy_unsafe(srcfn, dstfn, 0644) ; byte_copy(srcfn + srcdirlen + len + 2, 9, "nosetsid") ; if (stat(srcfn, &st) < 0) |