aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2026-10-17 04:10:16 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2026-10-17 04:10:16 +0000
commit6ada80ed7e45ed630e4d9877a9b11e2dfddb4758 (patch)
tree61d28af958e9922d1a2380b42b8137a0ac64be51
parentdb3fb428599c9c8fe105dcf4ba8d1c914c54cc26 (diff)
downloads6-rc-6ada80ed7e45ed630e4d9877a9b11e2dfddb4758.tar.gz
Third part of the format-upgrade inclusion: add support in s6-rc-set-install
Now that everything is in place, we go for the main thing: add snapshot support to s6-rc-set install. The workflow is: - check the major version of the old db against the current s6-rc - if the old db is up to date, nothing changes - otherwise: + find the snapshot corresponding to the old db + compile it + copy the snapshot db to the bootdir + call s6-rc-format-upgrade on it + atomically switch the bootdb to it. At this point the snapshot is the new bootdb: same as the old db, but with the correct major version. + unconditionally remove the old db + and now we can perform the regular s6-rc-update with the wanted set, since they have the same major. We also add --no-snapshot options to s6-rc-set-commit and s6-rc-set-install, and propagate them in the supporting functions, so users can manually skip all this bloat (and this is important for the initial install). All that remains is cleaning up obsolete snapshots. This will probably go at the end of s6-rc-set-install as well.
-rw-r--r--package/deps.mak1
-rw-r--r--src/include/s6-rc/repo.h6
-rw-r--r--src/repo/deps-lib/s6rcrepo1
-rw-r--r--src/repo/s6-rc-set-commit.c11
-rw-r--r--src/repo/s6-rc-set-install.c323
-rw-r--r--src/repo/s6rc_repo_cleanup.c1
-rw-r--r--src/repo/s6rc_repo_compile.c4
-rw-r--r--src/repo/s6rc_repo_makedefbundle.c1
-rw-r--r--src/repo/s6rc_repo_makesetbundles.c1
-rw-r--r--src/repo/s6rc_repo_setcompile.c4
-rw-r--r--src/repo/s6rc_repo_setuptodate.c3
-rw-r--r--src/repo/s6rc_repo_sync.c2
-rw-r--r--src/s6-rc/s6-rc-compile.c2
13 files changed, 254 insertions, 106 deletions
diff --git a/package/deps.mak b/package/deps.mak
index 16e54b6..30207bc 100644
--- a/package/deps.mak
+++ b/package/deps.mak
@@ -71,7 +71,6 @@ src/repo/s6rc_repo_setcompile.o src/repo/s6rc_repo_setcompile.lo: src/repo/s6rc_
src/repo/s6rc_repo_setcopy.o src/repo/s6rc_repo_setcopy.lo: src/repo/s6rc_repo_setcopy.c src/include/s6-rc/repo.h
src/repo/s6rc_repo_setdelete.o src/repo/s6rc_repo_setdelete.lo: src/repo/s6rc_repo_setdelete.c src/include/s6-rc/repo.h
src/repo/s6rc_repo_setuptodate.o src/repo/s6rc_repo_setuptodate.lo: src/repo/s6rc_repo_setuptodate.c src/include/s6-rc/config.h src/include/s6-rc/repo.h src/include/s6-rc/s6rc-utils.h
-src/repo/s6rc_repo_snap_from_compiled.o src/repo/s6rc_repo_snap_from_compiled.lo: src/repo/s6rc_repo_snap_from_compiled.c src/include/s6-rc/repo.h
src/repo/s6rc_repo_sv_bcmpr.o src/repo/s6rc_repo_sv_bcmpr.lo: src/repo/s6rc_repo_sv_bcmpr.c src/include/s6-rc/repo.h
src/repo/s6rc_repo_sv_cmpr.o src/repo/s6rc_repo_sv_cmpr.lo: src/repo/s6rc_repo_sv_cmpr.c src/include/s6-rc/repo.h
src/repo/s6rc_repo_sync.o src/repo/s6rc_repo_sync.lo: src/repo/s6rc_repo_sync.c src/include/s6-rc/repo.h
diff --git a/src/include/s6-rc/repo.h b/src/include/s6-rc/repo.h
index 6c9b17b..5cd5674 100644
--- a/src/include/s6-rc/repo.h
+++ b/src/include/s6-rc/repo.h
@@ -43,7 +43,7 @@ extern int s6rc_repo_lock (char const *, int) ;
extern int s6rc_repo_touch (char const *) ;
extern int s6rc_repo_touchset (char const *, char const *) ;
extern int s6rc_repo_checkset (char const *, char const *) ;
-extern int s6rc_repo_setuptodate (char const *, char const *) ;
+extern int s6rc_repo_setuptodate (char const *, char const *, unsigned int) ;
extern int s6rc_repo_setcopy (char const *, char const *, char const *, unsigned int) ;
extern void s6rc_repo_setdelete (char const *, char const *) ;
@@ -51,9 +51,9 @@ extern int s6rc_repo_makesetbundles (char const *, char const *, unsigned int) ;
extern int s6rc_repo_makedefbundle (char const *, char const *, char const *) ;
#define S6RC_REPO_COMPILE_BUFLEN(repolen, setlen) ((repolen) + (setlen) + 45)
-extern int s6rc_repo_compile (char const *, char const *, char const *const *, uint8_t, char *, unsigned int, char const *, char const *) ;
+extern int s6rc_repo_compile (char const *, char const *, char const *const *, uint8_t, char *, unsigned int, char const *, char const *, char const *, unsigned int) ;
extern int s6rc_repo_refcompile (char const *, char *, unsigned int, char const *) ;
-extern int s6rc_repo_setcompile (char const *, char const *, char const *, char *, unsigned int, char const *, char const *) ;
+extern int s6rc_repo_setcompile (char const *, char const *, char const *, char *, unsigned int, char const *, char const *, unsigned int) ;
extern int s6rc_repo_list_sets (char const *, stralloc *, genalloc *) ;
extern int s6rc_repo_listrx (char const *, char const *, char const *, stralloc *, genalloc *) ;
diff --git a/src/repo/deps-lib/s6rcrepo b/src/repo/deps-lib/s6rcrepo
index eb1ead9..aee5f34 100644
--- a/src/repo/deps-lib/s6rcrepo
+++ b/src/repo/deps-lib/s6rcrepo
@@ -7,7 +7,6 @@ s6rc_repo_fillset.o
s6rc_repo_fixset.o
s6rc_repo_flattenservices.o
s6rc_repo_getserviceflags.o
-s6rc_repo_install_needs_upgrade.o
s6rc_repo_list_sets.o
s6rc_repo_listalldeps.o
s6rc_repo_listcontents.o
diff --git a/src/repo/s6-rc-set-commit.c b/src/repo/s6-rc-set-commit.c
index 6bfe03d..3bc0f4a 100644
--- a/src/repo/s6-rc-set-commit.c
+++ b/src/repo/s6-rc-set-commit.c
@@ -26,7 +26,8 @@
enum golb_e
{
GOLB_KEEPOLD = 0x01,
- GOLB_FORCE = 0x02
+ GOLB_FORCE = 0x02,
+ GOLB_NOSNAP = 0x04,
} ;
enum gola_e
@@ -42,7 +43,9 @@ enum gola_e
static gol_bool const rgolb[] =
{
{ .so = 'K', .lo = "keep-old", .clear = 0, .set = GOLB_KEEPOLD },
- { .so = 'f', .lo = "force", .clear = 0, .set = GOLB_FORCE }
+ { .so = 'f', .lo = "force", .clear = 0, .set = GOLB_FORCE },
+ { .so = 0, .lo = "snapshot", .clear = GOLB_NOSNAP, .set = 0 },
+ { .so = 0, .lo = "no-snapshot", .clear = 0, .set = GOLB_NOSNAP },
} ;
static gol_arg const rgola[] =
@@ -86,7 +89,7 @@ int main (int argc, char const *const *argv)
if (r) _exit(r) ;
if (!(wgolb & GOLB_FORCE))
{
- r = s6rc_repo_setuptodate(wgola[GOLA_REPODIR], argv[0]) ;
+ r = s6rc_repo_setuptodate(wgola[GOLA_REPODIR], argv[0], !!(wgolb & GOLB_NOSNAP)) ;
if (r == -1) _exit(111) ;
if (r)
{
@@ -112,7 +115,7 @@ int main (int argc, char const *const *argv)
size_t oldclen = S6RC_REPO_COMPILE_BUFLEN(strlen(wgola[GOLA_REPODIR]), strlen(argv[0])) ;
char oldc[oldclen] ;
- r = s6rc_repo_setcompile(wgola[GOLA_REPODIR], argv[0], wgola[GOLA_DEFBUNDLE], oldc, verbosity, wgola[GOLA_FDHUSER], wgola[GOLA_CATCHALL]) ;
+ r = s6rc_repo_setcompile(wgola[GOLA_REPODIR], argv[0], wgola[GOLA_DEFBUNDLE], oldc, verbosity, wgola[GOLA_FDHUSER], wgola[GOLA_CATCHALL], !!(wgolb & GOLB_NOSNAP)) ;
if (r == -1) _exit(111) ;
if (!r) _exit(1) ;
if (r == 2)
diff --git a/src/repo/s6-rc-set-install.c b/src/repo/s6-rc-set-install.c
index e2ecd6f..3940aba 100644
--- a/src/repo/s6-rc-set-install.c
+++ b/src/repo/s6-rc-set-install.c
@@ -36,6 +36,7 @@ enum golb_e
GOLB_KEEPOLD = 0x02,
GOLB_NOUPDATE = 0x04,
GOLB_NOFORCEESSENTIALS = 0x08,
+ GOLB_NOSNAP = 0x10,
} ;
enum gola_e
@@ -48,6 +49,104 @@ enum gola_e
GOLA_N
} ;
+#define DSTFNLEN(bootdir, set) (strlen(bootdir) + strlen(set) + 36)
+
+static int install_needs_upgrade (char const *livedir)
+{
+ size_t llen = strlen(livedir) ;
+ char livedb[llen + 10] ;
+ memcpy(livedb, livedir, llen) ;
+ memcpy(livedb + llen, "/compiled", 10) ;
+ return s6rc_repo_read_major(livedb) < s6rc_get_major(S6RC_VERSION) ;
+}
+
+static void snapcompile (char const *livedir, char const *repo, unsigned int verbosity, stralloc *sa)
+{
+ int r ;
+ size_t llen = strlen(livedir) ;
+ size_t snappos = sa->len, fdhuserpos, catchallpos, defbundlepos ;
+ char fn[llen + 28] ;
+ memcpy(fn, livedir, llen) ;
+ memcpy(fn + llen, "/compiled", 10) ;
+ if (!stralloc_catb(sa, ".snapshot.", 10)) strerr_diefusys(111, "stralloc_catb") ;
+ if (sareadlink(sa, fn) == -1 || !stralloc_0(sa)) strerr_diefusys(111, "readlink ", fn) ;
+ fdhuserpos = sa->len ;
+ memcpy(fn + llen + 9, "metainfo/fdhuser", 17) ;
+ if (!openslurpnclose(fn, sa, 4096) || !stralloc_0(sa)) strerr_diefusys(111, "read ", fn) ;
+ catchallpos = sa->len ;
+ memcpy(fn + llen + 18, "catchall", 9) ;
+ if (!openslurpnclose(fn, sa, 4096) || !stralloc_0(sa)) strerr_diefusys(111, "read ", fn) ;
+ defbundlepos = sa->len ;
+ memcpy(fn + llen + 18, "defbundle", 10) ;
+ if (!openslurpnclose(fn, sa, 4096) || !stralloc_0(sa)) strerr_diefusys(111, "read ", fn) ;
+
+ size_t oldclen = S6RC_REPO_COMPILE_BUFLEN(strlen(repo), fdhuserpos - 1) ;
+ char oldc[oldclen] ;
+
+ r = s6rc_repo_setcompile(repo, sa->s + snappos, sa->s + defbundlepos, oldc, verbosity, sa->s + fdhuserpos, sa->s + catchallpos, 1) ;
+ if (r == -1) _exit(111) ;
+ if (!r) _exit(1) ;
+ if (r == 2) rm_rf(oldc) ;
+ sa->len = fdhuserpos ;
+}
+
+static void copy_compiled_to_bootdir (char *dstfn, char const *repo, char const *set, char const *bootdir, char const *livedir, stralloc *olddbsa)
+{
+ size_t repolen = strlen(repo) ;
+ size_t setlen = strlen(set) ;
+ size_t bootdirlen = strlen(bootdir) ;
+ size_t clen = S6RC_REPO_COMPILE_BUFLEN(repolen, setlen) ;
+ ssize_t l ;
+ char clink[repolen + setlen + 11] ;
+ char cfull[clen] ;
+ memcpy(clink, repo, repolen) ;
+ memcpy(clink + repolen, "/compiled/", 10) ;
+ memcpy(clink + repolen + 10, set, setlen + 1) ;
+ memcpy(cfull, clink, repolen + 10) ;
+ memcpy(dstfn, bootdir, bootdirlen) ;
+ dstfn[bootdirlen] = '/' ;
+ l = readlink(clink, cfull + repolen + 10, setlen + 35) ;
+ if (l == -1) strerr_diefusys(111, "readlink ", clink) ;
+ if (l >= setlen + 35) strerr_dief(102, "incorrect/unexpected link contents for ", clink) ;
+ cfull[repolen + 10 + l] = 0 ;
+ memcpy(dstfn + bootdirlen + 1, cfull + repolen + 10, l+1) ;
+ l = 0 ;
+
+ {
+ struct stat stsource, stdest ;
+ if (stat(cfull, &stsource) == -1) strerr_diefusys(111, "stat ", cfull) ;
+ if (stat(dstfn, &stdest) == -1)
+ {
+ if (errno != ENOENT)
+ strerr_diefusys(111, "stat ", dstfn) ;
+ }
+ 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("set ", set, " is already installed as ", dstfn) ;
+ _exit(0) ;
+ }
+ else strerr_dief(102, "huh? ", dstfn, " already exists") ;
+ }
+
+ {
+ size_t llen = strlen(livedir) ;
+ char cfn[llen + 10] ;
+ memcpy(cfn, livedir, llen) ;
+ memcpy(cfn + llen, "/compiled", 10) ;
+ if (sarealpath(olddbsa, cfn) == -1 && errno != ENOENT)
+ strerr_diefusys(111, "realpath ", cfn) ;
+ if (!stralloc_0(olddbsa)) strerr_diefusys(111, "stralloc_catb") ;
+ }
+
+ if (!hiercopy(cfull, dstfn))
+ {
+ int e = errno ;
+ rm_rf(dstfn) ;
+ errno = e ;
+ strerr_diefusys(111, "recursively copy ", cfull, " to ", dstfn) ;
+ }
+}
+
int main (int argc, char const *const *argv)
{
static gol_bool const rgolb[] =
@@ -57,6 +156,8 @@ int main (int argc, char const *const *argv)
{ .so = 0, .lo = "no-update", .set = GOLB_NOUPDATE },
{ .so = 'e', .lo = "force-essentials", .clear = GOLB_NOFORCEESSENTIALS, .set = 0 },
{ .so = 'E', .lo = "no-force-essentials", .clear = 0, .set = GOLB_NOFORCEESSENTIALS },
+ { .so = 0, .lo = "snapshot", .clear = GOLB_NOSNAP, .set = 0 },
+ { .so = 0, .lo = "no-snapshot", .clear = 0, .set = GOLB_NOSNAP },
} ;
static gol_arg const rgola[] =
{
@@ -73,7 +174,7 @@ int main (int argc, char const *const *argv)
uint64_t wgolb = 0 ;
unsigned int golc ;
int r ;
- stralloc sa = STRALLOC_ZERO ;
+ stralloc bootdirsa = STRALLOC_ZERO ;
PROG = "s6-rc-set-install" ;
wgola[GOLA_BOOTDB] = S6RC_BOOTDB ;
@@ -97,139 +198,181 @@ int main (int argc, char const *const *argv)
r = s6rc_repo_checkset(wgola[GOLA_REPODIR], argv[0]) ;
if (r) _exit(r) ;
- r = s6rc_repo_setuptodate(wgola[GOLA_REPODIR], argv[0]) ;
+ r = s6rc_repo_setuptodate(wgola[GOLA_REPODIR], argv[0], !!(wgolb & GOLB_NOSNAP)) ;
if (r == -1) _exit(111) ;
if (!r) strerr_dief3x(7, "set ", argv[0], " is not up-to-date; commit it first") ;
- if (!sadirname(&sa, wgola[GOLA_BOOTDB], strlen(wgola[GOLA_BOOTDB]))
- || !stralloc_0(&sa)) strerr_diefu1sys(111, "sadirname") ;
- sa.len-- ;
+ if (!sadirname(&bootdirsa, wgola[GOLA_BOOTDB], strlen(wgola[GOLA_BOOTDB]))
+ || !stralloc_0(&bootdirsa)) strerr_diefu1sys(111, "sadirname") ;
+ bootdirsa.len-- ;
{
- size_t repolen = strlen(wgola[GOLA_REPODIR]) ;
- size_t setlen = strlen(argv[0]) ;
- size_t clen = S6RC_REPO_COMPILE_BUFLEN(repolen, setlen) ;
- ssize_t l ;
- pid_t pid ;
- int wstat ;
- char *olddb = 0 ;
- char const *uargv[12] ;
+ int needupgrade = install_needs_upgrade(wgola[GOLA_LIVEDIR]) ;
+ stralloc olddbsa = STRALLOC_ZERO ;
+ char dstfn[DSTFNLEN(bootdirsa.s, argv[0])] ;
char fmtv[UINT_FMT] ;
- char clink[repolen + setlen + 11] ;
- char cfull[clen] ;
- char dstfn[sa.len + setlen + 36] ;
fmtv[uint_fmt(fmtv, verbosity)] = 0 ;
- memcpy(clink, wgola[GOLA_REPODIR], repolen) ;
- memcpy(clink + repolen, "/compiled/", 10) ;
- memcpy(clink + repolen + 10, argv[0], setlen + 1) ;
- memcpy(cfull, clink, repolen + 10) ;
- memcpy(dstfn, sa.s, sa.len) ;
- dstfn[sa.len] = '/' ;
- l = readlink(clink, cfull + repolen + 10, setlen + 35) ;
- if (l == -1) strerr_diefu2sys(111, "readlink ", clink) ;
- if (l >= setlen + 35) strerr_diefu2x(102, "incorrect/unexpected link contents for ", clink) ;
- cfull[repolen + 10 + l] = 0 ;
- memcpy(dstfn + sa.len + 1, cfull + repolen + 10, l+1) ;
- l = 0 ;
- {
- 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 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]) ;
- char cfn[llen + 10] ;
- memcpy(cfn, wgola[GOLA_LIVEDIR], llen) ;
- memcpy(cfn + llen, "/compiled", 10) ;
- olddb = realpath(cfn, 0) ;
- if (!olddb && errno != ENOENT) strerr_diefu2sys(111, "realpath ", cfn) ;
- }
- if (!hiercopy(cfull, dstfn))
- {
- int e = errno ;
- rm_rf(dstfn) ;
- errno = e ;
- strerr_diefu4sys(111, "recursively copy ", cfull, " to ", dstfn) ;
- }
- if (!(wgolb & GOLB_NOUPDATE))
+ /* If we need a format-upgrade and the user isn't opposed to it */
+ if (needupgrade && !(wgolb & GOLB_NOUPDATE) && !(wgolb & GOLB_NOSNAP))
{
- uargv[l++] = S6RC_BINPREFIX "s6-rc-update" ;
- if (wgolb & GOLB_BLOCK) uargv[l++] = "-b" ;
- uargv[l++] = wgolb & GOLB_NOFORCEESSENTIALS ? "-E" : "-e" ;
+ pid_t pid ;
+ int wstat ;
+ char const *uargv[9] ;
+ unsigned int l = 0 ;
+ char snapfn[DSTFNLEN(bootdirsa.s, olddbsa.s)] ;
+
+ /* We find the snapshot corresponding to the current live db and we compile it */
+ snapcompile(wgola[GOLA_LIVEDIR], wgola[GOLA_REPODIR], verbosity, &olddbsa) ;
+ olddbsa.len = 0 ;
+
+ /* We copy the compiled snapshot to the bootdir. It has the correct major. */
+ copy_compiled_to_bootdir(snapfn, wgola[GOLA_REPODIR], olddbsa.s, bootdirsa.s, wgola[GOLA_LIVEDIR], &olddbsa) ;
+
+ /* We perform the format-upgrade */
+ uargv[l++] = S6RC_BINPREFIX "s6-rc-format-upgrade" ;
uargv[l++] = "-v" ;
uargv[l++] = fmtv ;
uargv[l++] = "-l" ;
uargv[l++] = wgola[GOLA_LIVEDIR] ;
- if (wgola[GOLA_CONVFILE])
- {
- uargv[l++] = "-f" ;
- uargv[l++] = wgola[GOLA_CONVFILE] ;
- }
+ if (wgolb & GOLB_BLOCK) uargv[l++] = "-b" ;
uargv[l++] = "--" ;
- uargv[l++] = dstfn ;
+ uargv[l++] = snapfn ;
uargv[l++] = 0 ;
-
pid = cspawn(uargv[0], uargv, (char const *const *)environ, 0, 0, 0) ;
if (!pid)
{
int e = errno ;
- rm_rf(dstfn) ;
+ rm_rf(snapfn) ;
errno = e ;
- strerr_diefu2sys(111, "spawn ", uargv[0]) ;
+ strerr_diefusys(111, "spawn ", uargv[0]) ;
}
r = wait_pid(pid, &wstat) ;
- if (r == -1) strerr_diefu3sys(111, "wait for the ", uargv[0], " process (updating may yet succeed)") ;
+ if (r == -1) strerr_diefusys(111, "wait for the ", uargv[0], " process") ;
if (WIFSIGNALED(wstat))
{
char fmt[INT_FMT] ;
fmt[int_fmt(fmt, WTERMSIG(wstat))] = 0 ;
- strerr_dief3x(wait_estatus(wstat), uargv[0], " crashed with signal ", fmt) ;
+ strerr_dief(wait_estatus(wstat), uargv[0], " crashed with signal ", fmt) ;
}
- r = WEXITSTATUS(wstat) ;
- if (r == 111)
- strerr_dief2x(111, uargv[0], " exited 111, unable to know the state of the live db or clean up") ;
- if ((r >= 3 && r <= 10) || r == 100)
+ if (WEXITSTATUS(wstat))
{
- int e = errno ;
char fmt[INT_FMT] ;
- fmt[int_fmt(fmt, r)] = 0 ;
+ fmt[int_fmt(fmt, WEXITSTATUS(wstat))] = 0 ;
+ strerr_dief(wait_estatus(wstat), uargv[0], " exited with signal ", fmt) ;
+ }
+
+ /* Now the live db has the same major version number as the new db we want. */
+
+ if (!atomic_symlink4(snapfn + bootdirsa.len + 1, wgola[GOLA_BOOTDB], 0, 0))
+ strerr_diefusys(111, "symlink ", snapfn + bootdirsa.len + 1, " to ", wgola[GOLA_BOOTDB], " (live database switch was performed to snapshot, not to new set)", " (update that link manually then retry the command)") ;
+ if (olddbsa.s[0]) rm_rf(olddbsa.s) ; /* we don't keep the db with the obsolete major */
+ olddbsa.len = 0 ;
+
+ /* The compiled snapshot is now in place and serves as the db to update from. */
+ }
+
+ /* We copy the compiled committed set to the bootdir */
+ copy_compiled_to_bootdir(dstfn, wgola[GOLA_REPODIR], argv[0], bootdirsa.s, wgola[GOLA_LIVEDIR], &olddbsa) ;
+
+ if (!(wgolb & GOLB_NOUPDATE))
+ {
+ pid_t pid ;
+ int wstat ;
+ char const *uargv[12] ;
+ unsigned int l = 0 ;
+
+ /* If --no-snapshot AND we need an upgrade, we assume the user knows what they're doing
+ and the dbs represent the same state: so we just format-upgrade directly to the new compiled db */
+ if (needupgrade && wgolb & GOLB_NOSNAP)
+ {
+ uargv[l++] = S6RC_BINPREFIX "s6-rc-format-upgrade" ;
+ uargv[l++] = "-v" ;
+ uargv[l++] = fmtv ;
+ uargv[l++] = "-l" ;
+ uargv[l++] = wgola[GOLA_LIVEDIR] ;
+ if (wgolb & GOLB_BLOCK) uargv[l++] = "-b" ;
+ uargv[l++] = "--" ;
+ uargv[l++] = dstfn ;
+ uargv[l++] = 0 ;
+ if (verbosity)
+ strerr_warnw("installing set without a snapshot after a major version update; assuming the same service state") ;
+ }
+ else
+ /* We know the new db has the same major as the live db (either naturally or after a format-upgrade
+ via a snapshot), but we don't know if they represent the same state. This is the common case.
+ So we s6-rc-update, to switch live dbs. */
+ {
+ uargv[l++] = S6RC_BINPREFIX "s6-rc-update" ;
+ if (wgolb & GOLB_BLOCK) uargv[l++] = "-b" ;
+ uargv[l++] = wgolb & GOLB_NOFORCEESSENTIALS ? "-E" : "-e" ;
+ uargv[l++] = "-v" ;
+ uargv[l++] = fmtv ;
+ uargv[l++] = "-l" ;
+ uargv[l++] = wgola[GOLA_LIVEDIR] ;
+ if (wgola[GOLA_CONVFILE])
+ {
+ uargv[l++] = "-f" ;
+ uargv[l++] = wgola[GOLA_CONVFILE] ;
+ }
+ uargv[l++] = "--" ;
+ uargv[l++] = dstfn ;
+ uargv[l++] = 0 ;
+ }
+
+ pid = cspawn(uargv[0], uargv, (char const *const *)environ, 0, 0, 0) ;
+ if (!pid)
+ {
+ int e = errno ;
rm_rf(dstfn) ;
errno = e ;
- strerr_dief4x(r, uargv[0], " exited with code ", fmt, " (live database switch was NOT performed)") ;
+ strerr_diefusys(111, "spawn ", uargv[0]) ;
+ }
+ r = wait_pid(pid, &wstat) ;
+ if (r == -1) strerr_diefusys(111, "wait for the ", uargv[0], " process (updating may yet succeed)") ;
+ if (WIFSIGNALED(wstat))
+ {
+ char fmt[INT_FMT] ;
+ fmt[int_fmt(fmt, WTERMSIG(wstat))] = 0 ;
+ strerr_dief(wait_estatus(wstat), uargv[0], " crashed with signal ", fmt) ;
}
- if (olddb)
+ r = WEXITSTATUS(wstat) ;
+ if (!needupgrade || !(wgolb & GOLB_NOSNAP))
{
- if (wgolb & GOLB_KEEPOLD)
+ if (r == 111)
+ strerr_dief(111, uargv[0], " exited 111, unable to know the state of the live db or clean up") ;
+ if ((r >= 3 && r <= 10) || r == 100)
{
- if (buffer_puts(buffer_1small, olddb) == -1
- || !buffer_putflush(buffer_1small, "\n", 1))
- strerr_diefu2sys(111, "write to stdout", " (live database switch was performed)") ;
+ int e = errno ;
+ char fmt[INT_FMT] ;
+ fmt[int_fmt(fmt, r)] = 0 ;
+ rm_rf(dstfn) ;
+ errno = e ;
+ strerr_dief(r, uargv[0], " exited with code ", fmt, " (live database switch was NOT performed)") ;
}
- else rm_rf(olddb) ;
}
if (r)
{
char fmt[INT_FMT] ;
fmt[int_fmt(fmt, r)] = 0 ;
- strerr_dief4x(r, uargv[0], " exited with code ", fmt, " (live database switch was performed") ;
+ strerr_dief(r, uargv[0], " exited with code ", fmt, " (live database switch was performed") ;
}
}
- 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)") ;
+ if (!atomic_symlink4(dstfn + bootdirsa.len + 1, wgola[GOLA_BOOTDB], 0, 0))
+ strerr_diefusys(111, "symlink ", dstfn + bootdirsa.len + 1, " to ", wgola[GOLA_BOOTDB], " (live database switch was performed)", " (update that link manually or next boot might fail)") ;
+
+ if (olddbsa.s[0])
+ {
+ if (wgolb & GOLB_KEEPOLD)
+ {
+ if (buffer_puts(buffer_1small, olddbsa.s) == -1
+ || !buffer_putflush(buffer_1small, "\n", 1))
+ strerr_diefusys(111, "write to stdout", " (live database switch was performed)") ;
+ }
+ else rm_rf(olddbsa.s) ;
+ }
}
- // stralloc_free(&sa) ;
_exit(0) ;
}
diff --git a/src/repo/s6rc_repo_cleanup.c b/src/repo/s6rc_repo_cleanup.c
index 47cb936..0a6d8dc 100644
--- a/src/repo/s6rc_repo_cleanup.c
+++ b/src/repo/s6rc_repo_cleanup.c
@@ -1,6 +1,7 @@
/* ISC license. */
#include <skalibs/bsdsnowflake.h>
+#include <skalibs/nonposix.h>
#include <string.h>
#include <unistd.h>
diff --git a/src/repo/s6rc_repo_compile.c b/src/repo/s6rc_repo_compile.c
index fc7d8ea..3eea8bb 100644
--- a/src/repo/s6rc_repo_compile.c
+++ b/src/repo/s6rc_repo_compile.c
@@ -16,13 +16,13 @@
#include <s6-rc/config.h>
#include <s6-rc/repo.h>
-int s6rc_repo_compile (char const *repo, char const *set, char const *const *rxs, uint8_t nrxs, char *oldc, unsigned int verbosity, char const *fdhuser, char const *catchall, char const *defbundle)
+int s6rc_repo_compile (char const *repo, char const *set, char const *const *rxs, uint8_t nrxs, char *oldc, unsigned int verbosity, char const *fdhuser, char const *catchall, char const *defbundle, unsigned int flags)
{
size_t repolen = strlen(repo) ;
size_t setlen = strlen(set) ;
size_t totrxlen = 0 ;
int needprefix = strcmp(set, ".ref") ;
- int needsnapshot = needprefix && memcmp(set, ".snapshot.", 10) ;
+ int needsnapshot = needprefix && !(flags & 1) ;
char snap[setlen + 44] ;
char newc[repolen + setlen + 45] ;
memcpy(newc, repo, repolen) ;
diff --git a/src/repo/s6rc_repo_makedefbundle.c b/src/repo/s6rc_repo_makedefbundle.c
index c31262f..50fd68f 100644
--- a/src/repo/s6rc_repo_makedefbundle.c
+++ b/src/repo/s6rc_repo_makedefbundle.c
@@ -1,6 +1,7 @@
/* ISC license. */
#include <skalibs/bsdsnowflake.h>
+#include <skalibs/nonposix.h>
#include <string.h>
#include <unistd.h>
diff --git a/src/repo/s6rc_repo_makesetbundles.c b/src/repo/s6rc_repo_makesetbundles.c
index 91ab05d..d6a263f 100644
--- a/src/repo/s6rc_repo_makesetbundles.c
+++ b/src/repo/s6rc_repo_makesetbundles.c
@@ -1,6 +1,7 @@
/* ISC license. */
#include <skalibs/bsdsnowflake.h>
+#include <skalibs/nonposix.h>
#include <string.h>
#include <unistd.h>
diff --git a/src/repo/s6rc_repo_setcompile.c b/src/repo/s6rc_repo_setcompile.c
index f894f64..9ac2eaf 100644
--- a/src/repo/s6rc_repo_setcompile.c
+++ b/src/repo/s6rc_repo_setcompile.c
@@ -7,13 +7,13 @@
#include <s6-rc/repo.h>
-int s6rc_repo_setcompile (char const *repo, char const *set, char const *defbundle, char *oldc, unsigned int verbosity, char const *fdhuser, char const *catchall)
+int s6rc_repo_setcompile (char const *repo, char const *set, char const *defbundle, char *oldc, unsigned int verbosity, char const *fdhuser, char const *catchall, unsigned int flags)
{
static char const *const rxs[4] = { "bundle", s6rc_repo_rxnames[1], s6rc_repo_rxnames[2], s6rc_repo_rxnames[3] } ;
int r ;
if (!s6rc_repo_makesetbundles(repo, set, verbosity)) return -1 ;
if (!s6rc_repo_makedefbundle(repo, set, defbundle)) return -1 ;
- r = s6rc_repo_compile(repo, set, rxs, 4, oldc, verbosity, fdhuser, catchall, defbundle) ;
+ r = s6rc_repo_compile(repo, set, rxs, 4, oldc, verbosity, fdhuser, catchall, defbundle, flags) ;
{
int e = errno ;
diff --git a/src/repo/s6rc_repo_setuptodate.c b/src/repo/s6rc_repo_setuptodate.c
index cfc6731..bd7261c 100644
--- a/src/repo/s6rc_repo_setuptodate.c
+++ b/src/repo/s6rc_repo_setuptodate.c
@@ -15,7 +15,7 @@
#include <s6-rc/s6rc-utils.h>
#include <s6-rc/repo.h>
-int s6rc_repo_setuptodate (char const *repo, char const *set)
+int s6rc_repo_setuptodate (char const *repo, char const *set, unsigned int flags)
{
struct stat stsource ;
struct stat stcompiled ;
@@ -45,6 +45,7 @@ int s6rc_repo_setuptodate (char const *repo, char const *set)
}
/* Do we have a snapshot of the source set for the compiled db? */
+ if (!(flags & 1))
{
struct stat stsnap ;
char snap[repolen + 54 + setlen] ;
diff --git a/src/repo/s6rc_repo_sync.c b/src/repo/s6rc_repo_sync.c
index a2b5886..feece42 100644
--- a/src/repo/s6rc_repo_sync.c
+++ b/src/repo/s6rc_repo_sync.c
@@ -153,7 +153,7 @@ int s6rc_repo_sync (char const *repo, unsigned int verbosity, char const *fdhuse
{
char const *rxs[2] = { ato + repolen + 9, bun + repolen + 9 } ;
char oldc[repolen + 49] ;
- int r = s6rc_repo_compile(repo, ".ref", rxs, 2, oldc, verbosity, fdhuser, 0) ;
+ int r = s6rc_repo_compile(repo, ".ref", rxs, 2, oldc, verbosity, fdhuser, 0, 0, 1) ;
if (r < 0) goto err ;
if (!r) { cleanup(ato, bun) ; return 0 ; }
if (r == 2) rm_rf(oldc) ;
diff --git a/src/s6-rc/s6-rc-compile.c b/src/s6-rc/s6-rc-compile.c
index 8e9af59..ec8f46a 100644
--- a/src/s6-rc/s6-rc-compile.c
+++ b/src/s6-rc/s6-rc-compile.c
@@ -1605,7 +1605,7 @@ static inline void write_db (char const *compiled, s6rc_db_t const *db)
strerr_diefusys(111, "write to ", dbfn) ;
}
-static inline void write_meta (char const *compiled, char const *fdhuser, char const *catchall)
+static inline void write_meta (char const *compiled, char const *fdhuser, char const *catchall, char const *defbundle)
{
char pack[4] ;
char fn[19] ;