diff options
| author | Laurent Bercot <ska-skaware@skarnet.org> | 2025-08-08 00:28:58 +0000 |
|---|---|---|
| committer | Laurent Bercot <ska@appnovation.com> | 2025-08-08 00:28:58 +0000 |
| commit | a92aa0997e0d367e396b02dc2d55d0c0a3cbbc38 (patch) | |
| tree | e6f21d97cfa6cfea8bab222d1b99510ea5c8ee35 /src/libs6rc/s6rc_repo_sync.c | |
| parent | f513ab225005661e9b4674a1b333abea0c6670f0 (diff) | |
| download | s6-rc-a92aa0997e0d367e396b02dc2d55d0c0a3cbbc38.tar.gz | |
Major refactors, add makesetbundle, refcompile/setcompile, etc.
Signed-off-by: Laurent Bercot <ska@appnovation.com>
Diffstat (limited to 'src/libs6rc/s6rc_repo_sync.c')
| -rw-r--r-- | src/libs6rc/s6rc_repo_sync.c | 225 |
1 files changed, 190 insertions, 35 deletions
diff --git a/src/libs6rc/s6rc_repo_sync.c b/src/libs6rc/s6rc_repo_sync.c index a0b6431..8ff1137 100644 --- a/src/libs6rc/s6rc_repo_sync.c +++ b/src/libs6rc/s6rc_repo_sync.c @@ -3,6 +3,7 @@ #include <skalibs/nonposix.h> /* mkdtemp */ #include <string.h> +#include <stdint.h> #include <unistd.h> #include <stdlib.h> #include <errno.h> @@ -12,28 +13,137 @@ #include <skalibs/strerr.h> #include <skalibs/stralloc.h> #include <skalibs/djbunix.h> +#include <skalibs/skamisc.h> #include <skalibs/unix-transactional.h> #include <s6-rc/s6rc-utils.h> #include <s6-rc/repo.h> -static inline void cleanup (char const *fn) +static inline void cleanup (char const *ato, char const *bun) { int e = errno ; - rm_rf(fn) ; + rm_rf(ato) ; + rm_rf(bun) ; errno = e ; } +static int s6rc_repo_syncsub (char const *repo, char const *set, char const *sub, uint32_t where, stralloc *sa, genalloc *ga, unsigned int verbosity) +{ + size_t repolen = strlen(repo) ; + size_t setlen = strlen(set) ; + size_t sublen = strlen(sub) ; + size_t subfnlen = repolen + setlen + sublen + 10 ; + char subfn[subfnlen + 1] ; + memcpy(subfn, repo, repolen) ; + memcpy(subfn + repolen, "/sources/", 9) ; + memcpy(subfn + repolen + 9, set, setlen) ; + subfn[repolen + 9 + setlen] = '/' ; + memcpy(subfn + repolen + 10 + setlen, sub, sublen + 1) ; + DIR *dir = opendir(subfn) ; + if (!dir) + { + strerr_warnfu2sys("opendir ", subfn) ; + 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[subfnlen + len + 2] ; + memcpy(fn, subfn, sublen) ; + fn[sublen] = '/' ; + memcpy(fn + sublen + 1, d->d_name, len+1) ; + if (access(fn, F_OK) == -1) + { + if (errno != ENOENT) + { + strerr_warnfu2sys("access ", fn) ; + goto err ; + } + unlink_void(fn) ; + if (verbosity >= 2) + strerr_warni6x("service ", d->d_name, " does not exist anymore, removed from sub ", sub, " of set ", set) ; + } + else + { + if (!genalloc_append(size_t, ga, &sa->len)) goto err ; + if (!stralloc_catb(sa, d->d_name, len+1)) goto err ; + } + } + if (errno) + { + strerr_warnfu2sys("readdir ", subfn) ; + goto err ; + } + + dir_close(dir) ; + return 1 ; + + err: + dir_close(dir) ; + return 0 ; +} + +static inline int s6rc_repo_syncset (char const *repo, size_t repolen, char const *set, stralloc *sa, genalloc *ga, unsigned int verbosity) +{ + static char const subs[3][7] = { "masked", "active", "onboot" } ; + for (unsigned int i = 0 ; i < 3 ; i++) + if (s6rc_repo_syncsub(repo, set, subs[i], i, sa, ga, verbosity)) goto err ; + + size_t n = genalloc_len(size_t, ga) ; + if (!n) + { + if (!s6rc_repo_fillset(repo, set)) goto err ; + } + + sa->len = 0 ; + genalloc_setlen(size_t, ga, 0) ; + return 1 ; + + err: + sa->len = 0 ; + genalloc_setlen(size_t, ga, 0) ; + return 0 ; +} + int s6rc_repo_sync (char const *repo, char const *const *sources, size_t sourceslen, unsigned int verbosity, char const *fdhuser) { - stralloc sa = STRALLOC_ZERO ; size_t repolen = strlen(repo) ; - char newdir[repolen + 29] ; - memcpy(newdir, repo, repolen) ; - memcpy(newdir + repolen, "/sources/..everything:XXXXXX", 29) ; - if (!mkdtemp(newdir)) + char ato[repolen + 26] ; + char bun[repolen + 26] ; + + + /* Fill new .atomics/ and .bundles/ with symlinks to real sources */ + + memcpy(ato, repo, repolen) ; + memcpy(ato + repolen, "/sources/..atomics:XXXXXX", 26) ; + memcpy(bun, ato, repolen + 26) ; + memcpy(bun + repolen + 11, "bundle", 6) ; + if (!mkdtemp(ato)) + { + strerr_warnfu2sys("mkdtemp ", ato) ; + return 0 ; + } + if (chmod(ato, 02755) == -1) + { + strerr_warnfu2sys("chmod ", ato) ; + return 0 ; + } + + if (!mkdtemp(bun)) { - strerr_warnfu2sys("mkdtemp ", newdir) ; + strerr_warnfu2sys("mkdtemp ", bun) ; + rmdir(ato) ; + return 0 ; + } + if (chmod(bun, 02755) == -1) + { + strerr_warnfu2sys("chmod ", bun) ; return 0 ; } @@ -56,19 +166,17 @@ int s6rc_repo_sync (char const *repo, char const *const *sources, size_t sources if (d->d_name[0] == '.') continue ; len = strlen(d->d_name) ; { - char dst[repolen + 30 + len] ; + char const *x ; + char dst[repolen + 28 + len] ; char src[srclen + len + 2] ; - memcpy(dst, newdir, repolen + 28) ; - dst[repolen + 28] = '/' ; - memcpy(dst + repolen + 29, d->d_name, len+1) ; memcpy(src, sources[i], srclen) ; src[srclen] = '/' ; memcpy(src + srclen + 1, d->d_name, len+1) ; switch (s6rc_type_check(-1, src)) { case 1 : - case 2 : - case 3 : break ; + case 2 : x = ato ; break ; + case 3 : x = bun ; break ; case 0 : strerr_warnf2x("invalid service type for ", src) ; dir_close(dir) ; @@ -78,6 +186,9 @@ int s6rc_repo_sync (char const *repo, char const *const *sources, size_t sources dir_close(dir) ; goto err ; } + memcpy(dst, x, repolen + 26) ; + dst[repolen + 26] = '/' ; + memcpy(dst + repolen + 27, d->d_name, len+1) ; if (symlink(src, dst) == -1) { if (errno != EEXIST) @@ -88,15 +199,15 @@ int s6rc_repo_sync (char const *repo, char const *const *sources, size_t sources } if (verbosity) { - sa.len = 0 ; - if (!sareadlink(&sa, dst) || !stralloc_0(&sa)) + if (!sareadlink(&satmp, dst) || !stralloc_0(&satmp)) { strerr_warnwu2sys("readlink ", dst) ; errno = EEXIST ; strerr_warnwu4sys("symlink ", src, " to ", dst) ; } else - strerr_warnwu6x("symlink ", src, " to ", dst, ": service is already provided by ", sa.s) ; + strerr_warnwu6x("symlink ", src, " to ", dst, ": already provided by ", satmp.s) ; + satmp.len = 0 ; } } } @@ -109,35 +220,79 @@ int s6rc_repo_sync (char const *repo, char const *const *sources, size_t sources } } - if (chmod(newdir, 02755) == -1) + + /* Compile the reference db - also checks new sources consistency */ + { - strerr_warnfu2sys("chmod ", newdir) ; - goto err ; + char const *subs[2] = { ato + repolen + 9, bun + repolen + 9 } ; + char oldc[repolen + 49] ; + int r = s6rc_repo_compile(repo, ".ref", subs, 2, oldc, verbosity, fdhuser) ; + if (r <= 0) goto err ; + if (r == 2) rm_rf(oldc) ; } + + /* Switch to the new sources, delete the old ones */ + { - char curdir[repolen + 21] ; - memcpy(curdir, repo, repolen) ; - memcpy(curdir + repolen, "/sources/.everything", 21) ; - if (!atomic_symlink4(newdir + repolen + 1, curdir, 0, 0)) goto err ; + char fn[repolen + 18] ; + char oldato[17] ; + char oldbun[17] ; + memcpy(fn, repo, repolen) ; + memcpy(fn + repolen, "/sources/.atomics", 18) ; + if (!atomic_symlink4(ato + repolen + 9, fn, oldato, 17)) goto err ; + memcpy(fn + repolen + 10, "bundle", 6) ; + if (!atomic_symlink4(bun + repolen + 9, fn, oldbun, 17)) + { + strerr_warnfu4sys("symlink ", bun + repolen + 9, " to ", fn) ; + memcpy(fn + repolen + 10, "atomic", 6) ; + if (!atomic_symlink4(oldato, fn, 0, 0)) + { + strerr_warnfu6sys("symlink ", oldato, " back to ", fn, " - weird race, manually check ", repo) ; + goto err ; + } + goto err ; + } + memcpy(ato + repolen + 9, oldato, 16) ; + memcpy(bun + repolen + 9, oldbun, 16) ; + cleanup(ato, bun) ; } - stralloc_free(&sa) ; - if (!s6rc_repo_cleanup(repo)) return 0 ; + /* Update the existing sets */ + + ato[repolen + 8] = 0 ; { - size_t buflen = S6RC_REPO_COMPILE_BUFLEN(repolen, sizeof(".everything") - 1) ; - char oldc[buflen] ; - int r = s6rc_repo_compile(repo, ".everything", 0, 0, oldc, verbosity, fdhuser) ; - if (r <= 0) goto err0 ; - if (r == 2) rm_rf(oldc) ; + stralloc sa = STRALLOC_ZERO ; + genalloc ga = GENALLOC_ZERO ; /* size_t */ + DIR *dir = opendir(ato) ; + if (!dir) + { + strerr_warnfu2sys("opendir ", ato) ; + return 0 ; + } + for (;;) + { + direntry *d ; + errno = 0 ; + d = readdir(dir) ; + if (!d) break ; + if (d->d_name[0] == '.') continue ; + if (!s6rc_repo_syncset(repo, repolen, d->d_name, &sa, &ga, verbosity)) break ; + } + dir_close(dir) ; + genalloc_free(size_t, &ga) ; + stralloc_free(&sa) ; + if (errno) + { + strerr_warnfu2sys("readdir ", ato) ; + return 0 ; + } } - + return 1 ; err: - stralloc_free(&sa) ; - err0: - cleanup(newdir) ; + cleanup(ato, bun) ; return 0 ; } |
