aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs6rc
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2025-07-02 21:57:16 +0000
committerLaurent Bercot <ska@appnovation.com>2025-07-02 21:57:16 +0000
commit7f0aa026e16989584f4d79e50fbe75f5558a00f8 (patch)
tree09f0383badf6791d94e632de89350490b63404c9 /src/libs6rc
parent7e24694e178c1dbe105b6ef77d62ba4e9f6b622a (diff)
downloads6-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.c64
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 ;
}