diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/include/s6-rc/repo.h | 11 | ||||
| -rw-r--r-- | src/include/s6-rc/s6rc.h | 1 | ||||
| -rw-r--r-- | src/libs6rc/deps-lib/s6rc | 2 | ||||
| -rw-r--r-- | src/libs6rc/s6rc_repo_cleanup.c | 76 | ||||
| -rw-r--r-- | src/libs6rc/s6rc_repo_sync.c | 78 | ||||
| -rw-r--r-- | src/repo/deps-exe/s6-rc-repo-init | 1 | ||||
| -rw-r--r-- | src/repo/deps-exe/s6-rc-repo-populate | 1 | ||||
| -rw-r--r-- | src/repo/s6-rc-repo-init.c | 80 | ||||
| -rw-r--r-- | src/repo/s6-rc-repo-populate.c | 72 |
9 files changed, 240 insertions, 82 deletions
diff --git a/src/include/s6-rc/repo.h b/src/include/s6-rc/repo.h new file mode 100644 index 0000000..874354f --- /dev/null +++ b/src/include/s6-rc/repo.h @@ -0,0 +1,11 @@ +/* ISC license. */ + +#ifndef S6RC_REPO_H +#define S6RC_REPO_H + +#include <stddef.h> + +extern int s6rc_repo_cleanup (char const *) ; +extern int s6rc_repo_sync (char const *, char const *const *, size_t) ; + +#endif diff --git a/src/include/s6-rc/s6rc.h b/src/include/s6-rc/s6rc.h index 87a87ef..c01ff29 100644 --- a/src/include/s6-rc/s6rc.h +++ b/src/include/s6-rc/s6rc.h @@ -7,5 +7,6 @@ #include <s6-rc/s6rc-db.h> #include <s6-rc/s6rc-utils.h> #include <s6-rc/s6rc-servicedir.h> +#include <s6-rc/repo.h> #endif diff --git a/src/libs6rc/deps-lib/s6rc b/src/libs6rc/deps-lib/s6rc index 3b0bf75..71a1616 100644 --- a/src/libs6rc/deps-lib/s6rc +++ b/src/libs6rc/deps-lib/s6rc @@ -13,6 +13,8 @@ s6rc_livedir_prefix.o s6rc_livedir_prefixsize.o s6rc_lock.o s6rc_read_uint.o +s6rc_repo_cleanup.o +s6rc_repo_sync.o s6rc_sanitize_dir.o s6rc_servicedir_internal.o s6rc_servicedir_block.o diff --git a/src/libs6rc/s6rc_repo_cleanup.c b/src/libs6rc/s6rc_repo_cleanup.c new file mode 100644 index 0000000..9b42c06 --- /dev/null +++ b/src/libs6rc/s6rc_repo_cleanup.c @@ -0,0 +1,76 @@ +/* ISC license. */ + +#include <skalibs/bsdsnowflake.h> + +#include <string.h> +#include <unistd.h> +#include <errno.h> + +#include <skalibs/stat.h> +#include <skalibs/direntry.h> +#include <skalibs/posixplz.h> +#include <skalibs/djbunix.h> + +#include <s6-rc/repo.h> + +static inline int sub_cleanup (char const *subdir) +{ + size_t dirlen = strlen(subdir) ; + DIR *dir = opendir(subdir) ; + if (!dir) return 0 ; + for (;;) + { + size_t len ; + direntry *d ; + errno = 0 ; + d = readdir(dir) ; + if (!d) break ; + if (d->d_name[0] == '.') continue ; + len = strlen(d->d_name) ; + { + char fn[dirlen + len + 2] ; + memcpy(fn, dir, dirlen) ; + fn[dirlen] = '/' ; + memcpy(fn + dirlen + 1, d->d_name, len + 1) ; + if (access(fn, F_OK) == -1) + { + if (errno == ENOENT) unlink_void(fn) ; + else break ; + } + else + { + struct stat st ; + if (lstat(fn, &st) == -1) break ; + if (!S_ISLNK(st.st_mode)) rm_rf(fn) ; + } + } + } + dir_close(dir) ; + return !errno ; +} + +int s6rc_repo_cleanup (char const *repo) +{ + size_t repolen = strlen(repo) ; + DIR *dir = opendir(repo) ; + if (!dir) return 0 ; + for (;;) + { + size_t len ; + direntry *d ; + errno = 0 ; + d = readdir(dir) ; + if (!d) break ; + if (d->d_name[0] == '.') continue ; + len = strlen(d->d_name) ; + { + char fn[repolen + len + 2] ; + memcpy(fn, repo, repolen) ; + fn[repolen] = '/' ; + memcpy(fn + repolen + 1, d->d_name, len + 1) ; + if (!sub_cleanup(fn)) break ; + } + } + dir_close(dir) ; + return !errno ; +} diff --git a/src/libs6rc/s6rc_repo_sync.c b/src/libs6rc/s6rc_repo_sync.c new file mode 100644 index 0000000..7ece55f --- /dev/null +++ b/src/libs6rc/s6rc_repo_sync.c @@ -0,0 +1,78 @@ +/* ISC license. */ + +#include <skalibs/bsdsnowflake.h> /* stat */ +#include <skalibs/nonposix.h> /* mkdtemp */ + +#include <string.h> +#include <unistd.h> +#include <stdlib.h> +#include <errno.h> + +#include <skalibs/stat.h> +#include <skalibs/direntry.h> +#include <skalibs/posixplz.h> +#include <skalibs/djbunix.h> +#include <skalibs/unix-transactional.h> + +#include <s6-rc/repo.h> + +static inline void cleanup (char const *fn) +{ + int e = errno ; + rm_rf(fn) ; + errno = e ; +} + +int s6rc_repo_sync (char const *repo, char const *const *sources, size_t sourceslen) +{ + size_t repolen = strlen(repo) ; + char newdir[repolen + 24] ; + memcpy(newdir, repo, repolen) ; + memcpy(newdir + repolen, "/.everything:cur:XXXXXX", 24) ; + if (!mkdtemp(newdir)) return 0 ; + + for (size_t i = 0 ; i < sourceslen ; i++) + { + size_t srclen = strlen(sources[i]) ; + DIR *dir = opendir(sources[i]) ; + if (!dir) goto err ; + for (;;) + { + size_t len ; + direntry *d ; + errno = 0 ; + d = readdir(dir) ; + if (!d) break ; + if (d->d_name[0] == '.') continue ; + len = strlen(d->d_name) ; + { + char dst[repolen + 25 + len] ; + char src[srclen + len + 2] ; + memcpy(dst, newdir, repolen + 23) ; + dst[repolen + 23] = '/' ; + memcpy(dst + repolen + 24, d->d_name, len + 1) ; + memcpy(src, sources[i], srclen) ; + src[srclen] = '/' ; + memcpy(src + srclen + 1, d->d_name, len + 1) ; + if (symlink(src, dst) == -1) break ; + } + } + dir_close(dir) ; + if (errno) goto err ; + } + + if (chmod(newdir, 02755) == -1) goto err ; + + { + char curdir[repolen + 13] ; + memcpy(curdir, repo, repolen) ; + memcpy(curdir + repolen, "/.everything", 13) ; + if (!atomic_symlink(newdir + repolen + 1, curdir, "tmp")) goto err ; + } + + return s6rc_repo_cleanup(repo) ; + + err: + cleanup(newdir) ; + return 0 ; +} diff --git a/src/repo/deps-exe/s6-rc-repo-init b/src/repo/deps-exe/s6-rc-repo-init index e7187fe..152b051 100644 --- a/src/repo/deps-exe/s6-rc-repo-init +++ b/src/repo/deps-exe/s6-rc-repo-init @@ -1 +1,2 @@ +${LIBS6RC} -lskarnet diff --git a/src/repo/deps-exe/s6-rc-repo-populate b/src/repo/deps-exe/s6-rc-repo-populate deleted file mode 100644 index e7187fe..0000000 --- a/src/repo/deps-exe/s6-rc-repo-populate +++ /dev/null @@ -1 +0,0 @@ --lskarnet diff --git a/src/repo/s6-rc-repo-init.c b/src/repo/s6-rc-repo-init.c index 296216a..660b046 100644 --- a/src/repo/s6-rc-repo-init.c +++ b/src/repo/s6-rc-repo-init.c @@ -15,11 +15,12 @@ #include <skalibs/prog.h> #include <skalibs/strerr.h> #include <skalibs/djbunix.h> +#include <skalibs/random.h> #include <s6-rc/config.h> #include <s6-rc/s6rc.h> -#define USAGE "s6-rc-repo-init [ -r repo ]" +#define USAGE "s6-rc-repo-init [ -r repo ] sources..." #define dieusage() strerr_dieusage(100, USAGE) static void cleanup (char const *fn) @@ -29,6 +30,17 @@ static void cleanup (char const *fn) errno = e ; } +enum golb_e +{ + GOLB_FORCE, + GOLB_N +} ; + +static gol_bool const rgolb[1] = +{ + { .so = 'f', .lo = "force", .clear = 0, .set = 1 << GOLB_FORCE } +} ; + static gol_arg const rgola[1] = { { .so = 'r', .lo = "repodir", .i = 0 } @@ -38,20 +50,26 @@ int main (int argc, char const *const *argv) { size_t repolen ; char const *repo = S6RC_REPO_BASE ; + uint64_t wgolb = 0 ; unsigned int golc ; + mode_t m ; PROG = "s6-rc-repo-init" ; - golc = gol_main(argc, argv, 0, 0, rgola, 1, 0, &repo) ; + golc = gol_main(argc, argv, rgolb, 1, rgola, 1, &wgolb, &repo) ; argc -= golc ; argv += golc ; + if (!argc) dieusage() ; if (repo[0] != '/') strerr_dief2x(100, repo, " is not an absolute path") ; + for (unsigned int i = 0 ; i < argc ; i++) + if (argv[i][0] != '/') + strerr_dief2x(100, argv[i], " is not an absolute path") ; repolen = strlen(repo) ; char repotmp[repolen + 12] ; char tmp[repolen + 39] ; memcpy(repotmp, repo, repolen) ; memcpy(repotmp + repolen, "-tmp.XXXXXX", 12) ; - umask(0) ; + m = umask(0) ; if (!mkdtemp(repotmp)) { size_t i = repolen ; @@ -62,7 +80,7 @@ int main (int argc, char const *const *argv) if (mkdirp2(repotmp, 02755) == -1) strerr_diefu2sys(111, "mkdir ", repotmp) ; repotmp[i] = '/' ; - memcpy(repotmp + repolen, "-tmp.XXXXXX", 12) ; + memcpy(repotmp + repolen, ":new:XXXXXX", 12) ; if (!mkdtemp(repotmp)) strerr_diefu2sys(111, "mkdtemp ", repotmp) ; } @@ -71,26 +89,70 @@ int main (int argc, char const *const *argv) memcpy(tmp + repolen + 12, "compiled", 9) ; if (mkdir(tmp, 02755) == -1) + { + cleanup(repotmp) ; strerr_diefu2sys(111, "mkdir ", tmp) ; + } memcpy(tmp + repolen + 12, "source", 7) ; if (mkdir(tmp, 02755) == -1) + { + cleanup(repotmp) ; strerr_diefu2sys(111, "mkdir ", tmp) ; + } - memcpy(tmp + repolen + 18, "/.everything-initial", 21) ; + memcpy(tmp + repolen + 18, "/.everything:initial", 21) ; if (mkdir(tmp, 02755) == -1) + { + cleanup(repotmp) ; strerr_diefu2sys(111, "mkdir ", tmp) ; + } tmp[repolen + 30] = 0 ; - if (symlink(".everything-initial", tmp) == -1) - strerr_diefu4sys(111, "symlink ", ".everything-initial", " to ", tmp) ; + if (symlink(".everything:initial", tmp) == -1) + { + cleanup(repotmp) ; + strerr_diefu4sys(111, "symlink ", ".everything:initial", " to ", tmp) ; + } + + umask(m) ; + + if (!s6rc_repo_sync(repotmp, argv, argc)) + { + cleanup(repotmp) ; + strerr_diefu2sys(111, "sync ", repotmp) ; + } if (chmod(repotmp, 02755) == -1) strerr_diefu2sys(111, "chmod ", repotmp) ; if (rename(repotmp, repo) == -1) { - cleanup(repotmp) ; - strerr_diefu4sys(111, "rename ", repotmp, " to ", repo) ; + if (errno != EEXIST || !(wgolb & 1 << GOLB_FORCE)) + { + cleanup(repotmp) ; + strerr_diefu4sys(111, "rename ", repotmp, " to ", repo) ; + } + else + { + char oldrepo[repolen + 22] ; + memcpy(oldrepo, repo, repolen) ; + memcpy(oldrepo + repolen, ":old:", 5) ; + random_name(oldrepo + repolen + 5, 16) ; + if (rename(repo, oldrepo) == -1) + { + cleanup(repotmp) ; + strerr_diefu4sys(111, "rename ", repo, " to ", oldrepo) ; + } + if (rename(repotmp, repo) == -1) + { + int e = errno ; + if (rename(oldrepo, repo) == -1) + strerr_diefu7sys(111, "rename directories to ", repo, ": weird race happened. Old repository is at ", repotmp, " and new repository is at ", oldrepo, " - reported error was") ; + errno = e ; + cleanup(repotmp) ; + strerr_diefu4sys(111, "rename ", repotmp, " to ", repo) ; + } + } } return 0 ; diff --git a/src/repo/s6-rc-repo-populate.c b/src/repo/s6-rc-repo-populate.c deleted file mode 100644 index 7733a56..0000000 --- a/src/repo/s6-rc-repo-populate.c +++ /dev/null @@ -1,72 +0,0 @@ -/* ISC license. */ - -#include <skalibs/bsdsnowflake.h> /* stat */ - -#include <string.h> -#include <stdlib.h> -#include <stdio.h> /* rename */ -#include <errno.h> - -#include <skalibs/stat.h> -#include <skalibs/uint64.h> -#include <skalibs/posixplz.h> -#include <skalibs/gol.h> -#include <skalibs/prog.h> -#include <skalibs/strerr.h> -#include <skalibs/djbunix.h> - -#include <s6-rc/config.h> -#include <s6-rc/s6rc.h> - -#define USAGE "s6-rc-repo-populate [ -r repo ] sourcedirs..." -#define dieusage() strerr_dieusage(100, USAGE) - -static void cleanup (char const *fn) -{ - int e = errno ; - rm_rf(fn) ; - errno = e ; -} - -enum golb_e -{ - GOLB_FORCE, - GOLB_N -} ; - -static gol_bool const rgolb[1] = -{ - { .so = 'f', .lo = "force", .clear = 0, .set = 1 << GOLB_FORCE } -} ; - -static gol_arg const rgola[1] = -{ - { .so = 'r', .lo = "repodir", .i = 0 } -} ; - -int main (int argc, char const *const *argv) -{ - size_t repolen ; - char const *repo = S6RC_REPO_BASE ; - uint64_t wgolb = 0 ; - unsigned int golc ; - - PROG = "s6-rc-repo-populate" ; - golc = gol_main(argc, argv, rgolb, 1, rgola, 1, &wgolb, &repo) ; - argc -= golc ; argv += golc ; - if (!argc) dieusage() ; - if (repo[0] != '/') - strerr_dief2x(100, repo, " is not an absolute path") ; - - repolen = strlen(repo) ; - char sub[repolen + 30] ; - memcpy(sub, repo, repolen) ; - if (!(wgolb & 1 << GOLB_FORCE)) - { - struct stat st ; - - } - memcpy(sub + repolen, "/.everything-tmp.XXXXXX", 12) ; - - return 0 ; -} |
