aboutsummaryrefslogtreecommitdiffstats
path: root/src
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
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')
-rw-r--r--src/include/s6-rc/repo.h2
-rw-r--r--src/libs6rc/s6rc_repo_sync.c64
-rw-r--r--src/repo/s6-rc-repo-init.c23
3 files changed, 77 insertions, 12 deletions
diff --git a/src/include/s6-rc/repo.h b/src/include/s6-rc/repo.h
index 874354f..4ae6077 100644
--- a/src/include/s6-rc/repo.h
+++ b/src/include/s6-rc/repo.h
@@ -6,6 +6,6 @@
#include <stddef.h>
extern int s6rc_repo_cleanup (char const *) ;
-extern int s6rc_repo_sync (char const *, char const *const *, size_t) ;
+extern int s6rc_repo_sync (char const *, char const *const *, size_t, unsigned int) ;
#endif
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 ;
}
diff --git a/src/repo/s6-rc-repo-init.c b/src/repo/s6-rc-repo-init.c
index d358e1a..14c34d7 100644
--- a/src/repo/s6-rc-repo-init.c
+++ b/src/repo/s6-rc-repo-init.c
@@ -41,22 +41,35 @@ static gol_bool const rgolb[1] =
{ .so = 'f', .lo = "force", .clear = 0, .set = 1 << GOLB_FORCE }
} ;
-static gol_arg const rgola[1] =
+enum gola_e
{
- { .so = 'r', .lo = "repodir", .i = 0 }
+ GOLA_VERBOSITY,
+ GOLA_REPODIR,
+ GOLA_N
+} ;
+
+static gol_arg const rgola[2] =
+{
+ { .so = 'v', .lo = "verbosity", .i = GOLA_VERBOSITY },
+ { .so = 'r', .lo = "repodir", .i = GOLA_REPODIR }
} ;
int main (int argc, char const *const *argv)
{
size_t repolen ;
char const *repo = S6RC_REPO_BASE ;
+ unsigned int verbosity = 1 ;
+ mode_t m ;
+ char const *wgola[2] = { 0 } ;
uint64_t wgolb = 0 ;
unsigned int golc ;
- mode_t m ;
PROG = "s6-rc-repo-init" ;
- golc = gol_main(argc, argv, rgolb, 1, rgola, 1, &wgolb, &repo) ;
+ golc = gol_main(argc, argv, rgolb, 1, rgola, 2, &wgolb, wgola) ;
argc -= golc ; argv += golc ;
+ if (wgola[GOLA_VERBOSITY] && !uint0_scan(wgola[GOLA_VERBOSITY], &verbosity))
+ strerr_dief1x(100, "verbosity needs to be an unsigned integer") ;
+ if (wgola[GOLA_REPODIR]) repo = wgola[GOLA_REPODIR] ;
if (repo[0] != '/')
strerr_dief2x(100, repo, " is not an absolute path") ;
for (unsigned int i = 0 ; i < argc ; i++)
@@ -103,7 +116,7 @@ int main (int argc, char const *const *argv)
umask(m) ;
- if (!s6rc_repo_sync(repotmp, argv, argc))
+ if (!s6rc_repo_sync(repotmp, argv, argc, verbosity))
{
cleanup(repotmp) ;
strerr_diefu2sys(111, "sync ", repotmp) ;