diff options
| author | Laurent Bercot <ska-skaware@skarnet.org> | 2025-07-02 21:57:16 +0000 |
|---|---|---|
| committer | Laurent Bercot <ska@appnovation.com> | 2025-07-02 21:57:16 +0000 |
| commit | 7f0aa026e16989584f4d79e50fbe75f5558a00f8 (patch) | |
| tree | 09f0383badf6791d94e632de89350490b63404c9 /src/libs6rc | |
| parent | 7e24694e178c1dbe105b6ef77d62ba4e9f6b622a (diff) | |
| download | s6-rc-7f0aa026e16989584f4d79e50fbe75f5558a00f8.tar.gz | |
s6-rc-repo-init: better error messages
Signed-off-by: Laurent Bercot <ska@appnovation.com>
Diffstat (limited to 'src/libs6rc')
| -rw-r--r-- | src/libs6rc/s6rc_repo_sync.c | 64 |
1 files changed, 58 insertions, 6 deletions
diff --git a/src/libs6rc/s6rc_repo_sync.c b/src/libs6rc/s6rc_repo_sync.c index 7ece55f..963ec3c 100644 --- a/src/libs6rc/s6rc_repo_sync.c +++ b/src/libs6rc/s6rc_repo_sync.c @@ -11,6 +11,8 @@ #include <skalibs/stat.h> #include <skalibs/direntry.h> #include <skalibs/posixplz.h> +#include <skalibs/strerr.h> +#include <skalibs/stralloc.h> #include <skalibs/djbunix.h> #include <skalibs/unix-transactional.h> @@ -23,19 +25,28 @@ static inline void cleanup (char const *fn) errno = e ; } -int s6rc_repo_sync (char const *repo, char const *const *sources, size_t sourceslen) +int s6rc_repo_sync (char const *repo, char const *const *sources, size_t sourceslen, unsigned int verbosity) { + stralloc sa = STRALLOC_ZERO ; 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 ; + if (!mkdtemp(newdir)) + { + strerr_warnfu2sys("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 ; + if (!dir) + { + strerr_warnfu2sys("opendir ", sources[i]) ; + goto err ; + } for (;;) { size_t len ; @@ -46,6 +57,7 @@ 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) ; { + struct stat st ; char dst[repolen + 25 + len] ; char src[srclen + len + 2] ; memcpy(dst, newdir, repolen + 23) ; @@ -54,14 +66,52 @@ int s6rc_repo_sync (char const *repo, char const *const *sources, size_t sources memcpy(src, sources[i], srclen) ; src[srclen] = '/' ; memcpy(src + srclen + 1, d->d_name, len + 1) ; - if (symlink(src, dst) == -1) break ; + if (stat(src, &st) == -1) + { + if (verbosity) strerr_warnwu2sys("stat ", src) ; + continue ; + } + if (!S_ISDIR(st.st_mode)) + { + errno = ENOTDIR ; + if (verbosity) strerr_warnwu2sys("link ", src) ; + continue ; + } + if (symlink(src, dst) == -1) + { + if (errno != EEXIST) + { + strerr_warnfu4sys("symlink ", src, " to ", dst) ; + dir_close(dir) ; + goto err ; + } + if (verbosity) + { + sa.len = 0 ; + if (!sareadlink(&sa, dst) || !stralloc_0(&sa)) + { + 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) ; + } + } } } dir_close(dir) ; - if (errno) goto err ; + if (errno) + { + strerr_warnfu2sys("readdir ", sources[i]) ; + goto err ; + } } - if (chmod(newdir, 02755) == -1) goto err ; + if (chmod(newdir, 02755) == -1) + { + goto err ; + } { char curdir[repolen + 13] ; @@ -70,9 +120,11 @@ int s6rc_repo_sync (char const *repo, char const *const *sources, size_t sources if (!atomic_symlink(newdir + repolen + 1, curdir, "tmp")) goto err ; } + stralloc_free(&sa) ; return s6rc_repo_cleanup(repo) ; err: + stralloc_free(&sa) ; cleanup(newdir) ; return 0 ; } |
