aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2025-12-21 16:27:04 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2025-12-21 16:27:04 +0000
commitaff2e0c6435433a6f73b9d29c93a3109bfe146ca (patch)
treecc17ac2c7228646c035d233412340ad885008cb9
parentb24a07fca1f2a410b3d97d1e3dc5de7720ad1d76 (diff)
downloads6-rc-aff2e0c6435433a6f73b9d29c93a3109bfe146ca.tar.gz
s6-rc-set-install fixes
-rw-r--r--src/repo/s6-rc-set-change.c93
-rw-r--r--src/repo/s6-rc-set-install.c53
-rw-r--r--src/repo/s6rc_repo_lock.c2
3 files changed, 77 insertions, 71 deletions
diff --git a/src/repo/s6-rc-set-change.c b/src/repo/s6-rc-set-change.c
index d413eb1..e763d25 100644
--- a/src/repo/s6-rc-set-change.c
+++ b/src/repo/s6-rc-set-change.c
@@ -42,53 +42,6 @@ struct subname_s
uint8_t sub ;
} ;
-static gol_bool const rgolb[] =
-{
- { .so = 'E', .lo = "no-force-essential", .clear = GOLB_FORCE_ESSENTIAL, .set = 0 },
- { .so = 'e', .lo = "force-essential", .clear = 0, .set = GOLB_FORCE_ESSENTIAL },
- { .so = 'f', .lo = "ignore-dependencies", .clear = 0, .set = GOLB_IGNORE_DEPENDENCIES },
- { .so = 'n', .lo = "dry-run", .clear = 0, .set = GOLB_DRYRUN }
-} ;
-
-static gol_arg const rgola[] =
-{
- { .so = 'v', .lo = "verbosity", .i = GOLA_VERBOSITY },
- { .so = 'r', .lo = "repodir", .i = GOLA_REPODIR },
- { .so = 'I', .lo = "if-dependencies-found", .i = GOLA_FORCELEVEL }
-} ;
-
-static struct subname_s const accepted_forcelevels[] =
-{
- { .name = "fail", .sub = 0 },
- { .name = "pull", .sub = 2 },
- { .name = "warn", .sub = 1 }
-} ;
-
-static uint64_t wgolb = 0 ;
-
-static struct subname_s const accepted_subs[] =
-{
- { .name = "activate", .sub = 2 },
- { .name = "active", .sub = 2 },
- { .name = "always", .sub = 3 },
- { .name = "deactivate", .sub = 1 },
- { .name = "disable", .sub = 1 },
- { .name = "disabled", .sub = 1 },
- { .name = "enable", .sub = 2 },
- { .name = "enabled", .sub = 2 },
- { .name = "essential", .sub = 3 },
- { .name = "inactive", .sub = 1 },
- { .name = "latent", .sub = 1 },
- { .name = "make-essential", .sub = 3 },
- { .name = "mask", .sub = 0 },
- { .name = "masked", .sub = 0 },
- { .name = "onboot", .sub = 2 },
- { .name = "suppress", .sub = 0 },
- { .name = "unmask", .sub = 1 },
- { .name = "unmasked", .sub = 1 },
- { .name = "usable", .sub = 1 }
-} ;
-
static int subname_cmp (void const *a, void const *b)
{
return strcmp((char const *)a, ((struct subname_s const *)b)->name) ;
@@ -96,14 +49,56 @@ static int subname_cmp (void const *a, void const *b)
int main (int argc, char const *const *argv)
{
+ static gol_bool const rgolb[] =
+ {
+ { .so = 'E', .lo = "no-force-essential", .clear = GOLB_FORCE_ESSENTIAL, .set = 0 },
+ { .so = 'e', .lo = "force-essential", .clear = 0, .set = GOLB_FORCE_ESSENTIAL },
+ { .so = 'f', .lo = "ignore-dependencies", .clear = 0, .set = GOLB_IGNORE_DEPENDENCIES },
+ { .so = 'n', .lo = "dry-run", .clear = 0, .set = GOLB_DRYRUN }
+ } ;
+ static gol_arg const rgola[] =
+ {
+ { .so = 'v', .lo = "verbosity", .i = GOLA_VERBOSITY },
+ { .so = 'r', .lo = "repodir", .i = GOLA_REPODIR },
+ { .so = 'I', .lo = "if-dependencies-found", .i = GOLA_FORCELEVEL }
+ } ;
+ static struct subname_s const accepted_forcelevels[] =
+ {
+ { .name = "fail", .sub = 0 },
+ { .name = "pull", .sub = 2 },
+ { .name = "warn", .sub = 1 }
+ } ;
+ static struct subname_s const accepted_subs[] =
+ {
+ { .name = "activate", .sub = 2 },
+ { .name = "active", .sub = 2 },
+ { .name = "always", .sub = 3 },
+ { .name = "deactivate", .sub = 1 },
+ { .name = "disable", .sub = 1 },
+ { .name = "disabled", .sub = 1 },
+ { .name = "enable", .sub = 2 },
+ { .name = "enabled", .sub = 2 },
+ { .name = "essential", .sub = 3 },
+ { .name = "inactive", .sub = 1 },
+ { .name = "latent", .sub = 1 },
+ { .name = "make-essential", .sub = 3 },
+ { .name = "mask", .sub = 0 },
+ { .name = "masked", .sub = 0 },
+ { .name = "onboot", .sub = 2 },
+ { .name = "suppress", .sub = 0 },
+ { .name = "unmask", .sub = 1 },
+ { .name = "unmasked", .sub = 1 },
+ { .name = "usable", .sub = 1 }
+ } ;
stralloc storage = STRALLOC_ZERO ;
genalloc svlist = GENALLOC_ZERO ; /* s6rc_repo_sv */
genalloc indices = GENALLOC_ZERO ; /* size_t then uint32_t */
- genalloc gatmp = GENALLOC_ZERO ; /* size_t */
+ genalloc gatmp = GENALLOC_ZERO ; /* size_t whatever */
int fdlock ;
unsigned int verbosity = 1 ;
unsigned int forcelevel = 1 ;
char const *wgola[GOLA_N] = { 0 } ;
+ uint64_t wgolb = 0 ;
unsigned int golc ;
struct subname_s *newsub ;
size_t max = 0, sabase ;
@@ -126,7 +121,7 @@ int main (int argc, char const *const *argv)
if (argc < 3) dieusage() ;
s6rc_repo_sanitize_setname(argv[0]) ;
newsub = bsearch(argv[1], accepted_subs, sizeof(accepted_subs)/sizeof(struct subname_s), sizeof(struct subname_s), &subname_cmp) ;
- if (!newsub) strerr_dief2x(100, "unrecognized state change directive:", argv[1]) ;
+ if (!newsub) strerr_dief2x(100, "unrecognized state change directive: ", argv[1]) ;
if (newsub->sub == 3 && !(wgolb & GOLB_FORCE_ESSENTIAL))
strerr_diefu1x(100, "artificially mark a service as essential without --force-essential") ;
for (unsigned int i = 2 ; i < argc ; i++) s6rc_repo_sanitize_svname(argv[i]) ;
diff --git a/src/repo/s6-rc-set-install.c b/src/repo/s6-rc-set-install.c
index a3a82df..27c58cf 100644
--- a/src/repo/s6-rc-set-install.c
+++ b/src/repo/s6-rc-set-install.c
@@ -1,7 +1,10 @@
/* ISC license. */
#include <skalibs/bsdsnowflake.h>
+#include <skalibs/nonposix.h>
+#include <skalibs/stat.h>
+#include <time.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
@@ -9,7 +12,6 @@
#include <errno.h>
#include <skalibs/uint64.h>
-#include <skalibs/stat.h>
#include <skalibs/types.h>
#include <skalibs/posixplz.h>
#include <skalibs/prog.h>
@@ -44,23 +46,22 @@ enum gola_e
GOLA_N
} ;
-static gol_bool const rgolb[] =
-{
- { .so = 'b', .lo = "block", .clear = 0, .set = GOLB_BLOCK },
- { .so = 'K', .lo = "keep-old", .clear = 0, .set = GOLB_KEEPOLD }
-} ;
-
-static gol_arg const rgola[] =
-{
- { .so = 'v', .lo = "verbosity", .i = GOLA_VERBOSITY },
- { .so = 'c', .lo = "bootdb", .i = GOLA_BOOTDB },
- { .so = 'l', .lo = "livedir", .i = GOLA_LIVEDIR },
- { .so = 'r', .lo = "repodir", .i = GOLA_REPODIR },
- { .so = 'f', .lo = "conversion-file", .i = GOLA_CONVFILE }
-} ;
-
int main (int argc, char const *const *argv)
{
+ static gol_bool const rgolb[] =
+ {
+ { .so = 'b', .lo = "block", .clear = 0, .set = GOLB_BLOCK },
+ { .so = 'K', .lo = "keep-old", .clear = 0, .set = GOLB_KEEPOLD }
+ } ;
+ static gol_arg const rgola[] =
+ {
+ { .so = 'v', .lo = "verbosity", .i = GOLA_VERBOSITY },
+ { .so = 'c', .lo = "bootdb", .i = GOLA_BOOTDB },
+ { .so = 'l', .lo = "livedir", .i = GOLA_LIVEDIR },
+ { .so = 'r', .lo = "repodir", .i = GOLA_REPODIR },
+ { .so = 'f', .lo = "conversion-file", .i = GOLA_CONVFILE }
+ } ;
+
int fdlock ;
unsigned int verbosity = 1 ;
char const *wgola[GOLA_N] = { 0 } ;
@@ -78,6 +79,10 @@ int main (int argc, char const *const *argv)
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_BOOTDB][0] != '/')
+ strerr_dief2x(100, "bootdb", " needs to be an absolute path") ;
+ if (wgola[GOLA_LIVEDIR][0] != '/')
+ strerr_dief2x(100, "livedir", " needs to be an absolute path") ;
if (!argc) dieusage() ;
s6rc_repo_sanitize_setname(argv[0]) ;
@@ -122,13 +127,19 @@ int main (int argc, char const *const *argv)
memcpy(dstfn + sa.len + 1, cfull + repolen + 10, l+1) ;
l = 0 ;
{
- struct stat st ;
- if (stat(dstfn, &st) == -1)
+ struct stat stsource, stdest ;
+ if (stat(cfull, &stsource) == -1) strerr_diefu2sys(111, "stat ", cfull) ;
+ if (stat(dstfn, &stdest) == -1)
{
if (errno != ENOENT)
strerr_diefu2sys(111, "stat ", dstfn) ;
}
- else strerr_dief2x(102, dstfn, " already exists") ;
+ else if (stdest.st_mtim.tv_sec > stsource.st_mtim.tv_sec || (stdest.st_mtim.tv_sec == stsource.st_mtim.tv_sec && stdest.st_mtim.tv_nsec >= stsource.st_mtim.tv_nsec))
+ {
+ strerr_warni(0, "set ", argv[0], " is already installed as ", dstfn) ;
+ _exit(0) ;
+ }
+ else strerr_dief(102, "huh? ", dstfn, " already exists") ;
}
{
size_t llen = strlen(wgola[GOLA_LIVEDIR]) ;
@@ -206,8 +217,8 @@ int main (int argc, char const *const *argv)
fmt[int_fmt(fmt, r)] = 0 ;
strerr_dief4x(r, uargv[0], " exited with code ", fmt, " (live database switch was performed") ;
}
- if (!atomic_symlink4(dstfn + sa.len + 1, argv[1], 0, 0))
- strerr_diefu6sys(111, "symlink ", dstfn + sa.len + 1, " to ", argv[1], " (live database switch was performed)", " (update that link manually or next boot might fail)") ;
+ if (!atomic_symlink4(dstfn + sa.len + 1, wgola[GOLA_BOOTDB], 0, 0))
+ strerr_diefu6sys(111, "symlink ", dstfn + sa.len + 1, " to ", wgola[GOLA_BOOTDB], " (live database switch was performed)", " (update that link manually or next boot might fail)") ;
}
// stralloc_free(&sa) ;
_exit(0) ;
diff --git a/src/repo/s6rc_repo_lock.c b/src/repo/s6rc_repo_lock.c
index 472ff15..ba13fc7 100644
--- a/src/repo/s6rc_repo_lock.c
+++ b/src/repo/s6rc_repo_lock.c
@@ -13,7 +13,7 @@ int s6rc_repo_lock (char const *repo, int w)
char fn[repolen + 13] ;
memcpy(fn, repo, repolen) ;
memcpy(fn + repolen, "/lock", 6) ;
- fd = openc_write(fn) ;
+ fd = w ? openc_write(fn) : openc_read(fn) ;
if (fd == -1) return -1 ;
if (fd_lock(fd, w, 0) < 1) return -1 ;
return fd ;