summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2015-09-11 17:04:18 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2015-09-11 17:04:18 +0000
commit716dde0b12532bb814c3cc8fedd99b8d16b3cf07 (patch)
tree3f18f3a2e9e8c0527130645c66cbd5ad02a4260b
parent7df8376ba885bb87e4e84a8489bdf0f97accf4cf (diff)
downloads6-rc-716dde0b12532bb814c3cc8fedd99b8d16b3cf07.tar.xz
s6-rc-update doc, bugfix
-rw-r--r--doc/s6-rc-compile.html12
-rw-r--r--doc/s6-rc-update.html215
-rw-r--r--src/libs6rc/s6rc_servicedir_manage.c2
-rw-r--r--src/s6-rc/s6-rc-update.c102
4 files changed, 279 insertions, 52 deletions
diff --git a/doc/s6-rc-compile.html b/doc/s6-rc-compile.html
index 0c1afc1..8e4b279 100644
--- a/doc/s6-rc-compile.html
+++ b/doc/s6-rc-compile.html
@@ -86,6 +86,16 @@ to operate the database. If neither option is used, then root
(and only root) is implicitly allowed.
</p>
+<p>
+ It is important to <em>only</em> use the <tt>-u</tt> or <tt>-g</tt>
+options when the user owning the supervision tree is not root. The
+internal s6-rc mechanisms allow uids and gids specified by those
+options to run any program as the user owning the supervision tree;
+if that user is root, this becomes an easy avenue for unwanted
+privilege gain. Only specify users that have the right to operate
+the supervision tree!
+</p>
+
<h2> Source format </h2>
<p>
@@ -363,7 +373,7 @@ Linux system running
<a href="http://skarnet.org/software/">skarnet.org</a> packages; of course, only
the service definition set has been kept, and private information has been
removed, so it won't work out-of-the-box without the proper specific files,
-notably configuration in <tt>/etc/</tt> - but nevertheless, you can browse the
+notably configuration in <tt>/etc</tt> - but nevertheless, you can browse the
source and understand what it does, and adapt it to your own needs. It will
compile as is with
<tt>s6-rc-compile</tt>, and you can examine the
diff --git a/doc/s6-rc-update.html b/doc/s6-rc-update.html
index fda6885..ac8377a 100644
--- a/doc/s6-rc-update.html
+++ b/doc/s6-rc-update.html
@@ -21,13 +21,14 @@
<p>
s6-rc-update is an <em>online service database switcher</em>:
it will replace your compiled service database with another
-one, and adjust the live state accordingly.
+one, and adjust the live state accordingly. This allows you to
+change your set of services without having to reboot.
</p>
<p>
- Live upgrading a service database is no small feat, and no
+ Live upgrading a service database is not easy, and no
fully automated system can get it right in all cases.
-s6-rc-update will do its best on its own, but it lets you
+s6-rc-update will do its best on its own, but it lets the user
give it instructions to handle
difficult cases; and rather than implement doubtful
heuristics, it will fail with an error message in
@@ -36,11 +37,213 @@ situations it really cannot solve.
<h2> Interface </h2>
+<pre>
+ s6-rc-update [ -n ] [ -v <em>verbosity</em> ] [ -t <em>timeout</em> ] [ -l <em>live</em> ] [ -f <em>convfile</em> ] <em>newdb</em>
+</pre>
+
+<ul>
+ <li> s6-rc-update analyzes the current live state, the current compiled service
+database, and the compiled service database contained at <em>newdb</em>. </li>
+ <li> Additionally, it can process an optional <em>conversion file</em> containing
+instructions. </li>
+ <li> It computes the necessary service transitions to safely update the live
+database. </li>
+ <li> It shuts down the necessary services. </li>
+ <li> It updates the live directory so that <em>newdb</em> becomes the
+live compiled service database. </li>
+ <li> It starts up the necessary services. </li>
+</ul>
+
+<h2> Exit codes </h2>
+
+<ul>
+ <li> 0: success </li>
+ <li> 1: failure to perform some state transitions </li>
+ <li> 2: timed out </li>
+ <li> 3: unknown service name in the conversion file </li>
+ <li> 4: invalid service database </li>
+ <li> 5: wrong service type in the conversion file </li>
+ <li> 6: duplicate service in the conversion file </li>
+ <li> 100: wrong usage </li>
+ <li> 111: system call failed </li>
+</ul>
+
+<h2> Options </h2>
+
+<ul>
+ <li> <tt>-n</tt>&nbsp;: dry run. s6-rc-update will compute the service
+transitions, and print the <a href="s6-rc.html">s6-rc</a> command lines
+it would execute to perform those transitions. It will not actually
+run them or modify the live database. </li>
+ <li> <tt>-v&nbsp;<em>verbosity</em></tt>&nbsp;: be more or less
+verbose. Default is 1: warning and error messages will be printed to
+stderr. 0 silences warnings. 2 adds a bit more information about
+what s6-rc-update is doing. 3 or more is heavy debug output. </li>
+ <li> <tt>-t&nbsp;<em>timeout</em></tt>&nbsp;: if s6-rc-update cannot
+perform its job within <em>timeout</em> milliseconds, it will exit.
+The default is 0, meaning infinite (no timeout). Be aware that timing
+out and exiting may leave the live database in an inconsistent state,
+so use of this option is not recommended. </li>
+ <li> <tt>-l&nbsp;<em>live</em></tt>&nbsp;: look for the
+live state in <em>live</em>. Default is <tt>/run/s6-rc</tt>.
+The default can be changed at compile-time by giving the
+<tt>--livedir=<em>live</em></tt> option to <tt>./configure</tt>. </li>
+ <li> <tt>-f&nbsp;<em>convfile</em></tt>&nbsp;: use the conversion
+file located at <em>convfile</em>. Default is <tt>/dev/null</tt>,
+meaning no special instructions. </li>
+</ul>
+
+<h2> Transition details </h2>
+
+<p>
+ s6-rc-update's job is to ensure consistency of the live state across
+a change of compiled service database. To do so, it must make sure
+that the services that are up at the time of its invocation are still
+up after its invocation; but service definitions in the new compiled
+may be different from those in the old one; in particular, dependencies
+may change, or a service can change types - a oneshot can become
+a longrun and vice-versa, and an atomic service can even become a
+bundle.
+</p>
+
+<h3> Service identity </h3>
+
+<p>
+ s6-rc-update examines atomic services, as defined in the old compiled,
+that are up at invocation time, and computes what is necessary for the
+"same" service, as defined in the new compiled, to be up. Barring
+conversion file instructions, the service is "the same" if it has the
+same name in the new compiled, no matter its type.
+</p>
+
+<p>
+ So, if there is an up oneshot named <tt>sshd</tt> in the old compiled,
+and there is a longrun named <tt>sshd</tt> in the new compiled, then
+s6-rc-update will decide that the new <tt>sshd</tt> longrun will replace
+the old <tt>sshd</tt> oneshot. If the new compiled defines a <tt>sshd</tt>
+bundle instead, then s6-rc-update will decide that the old <tt>sshd</tt>
+oneshot will be replaced with the contents of the <tt>sshd</tt> bundle.
+<p>
+
+<h3> Restarts </h3>
+
+<p>
+ s6-rc-update tries to avoid needlessly restarting services. For instance,
+running it with a new compiled that is an exact copy of
+the old compiled should not cause any restarts. s6-rc-update will flag a
+service to be restarted in the following cases:
+</p>
+
+<ul>
+ <li> The service has disappeared in the new compiled. In this case, the
+old service will simply be stopped. </li>
+ <li> The service has changed types: a oneshot becomes a longrun, a longrun
+becomes a oneshot, or an atomic service becomes a bundle. In this case, the
+old service will be stopped, then the new service will be started. </li>
+ <li> The service has a dependency to a service that must restart, or to an
+old service that must stop, or to a new service that did not previously
+exist or that was previously down. </li>
+ <li> There is an instruction to restart the service in the conversion file. </li>
+</ul>
+
+<h3> Steps </h3>
+
+<p>
+ After it has decided what services it should restart, s6-rc-update will:
+</p>
+
+<ul>
+ <li> Invoke <a href="s6-rc.html">s6-rc</a> to stop old services. </li>
+ <li> Update the live directory with the data from the new compiled.
+This is the critical part; s6-rc should not be interrupted at this point.
+It does its best to avoid risking leaving behind an inconsistent state,
+but a 100% atomicity guarantee is impossible to achieve. </li>
+ <li> Adjust pipe names for the existing pipelines, if needed. </li>
+ <li> Exec into <a href="s6-rc.html">s6-rc</a> to start new services. </li>
+</ul>
+
+<h2> The conversion file </h2>
+
<p>
- To be written. s6-rc-update is currently the missing piece in the
-s6-rc suite, which is the reason why s6-rc has not been officially released
-yet. :-)
+ The conversion file is used to give s6-rc-update instructions when the
+change of databases is not entirely straightforward. Currently, it
+supports the following features:
</p>
+<ul>
+ <li> changing the name of a service </li>
+ <li> forcing a restart on a service </li>
+</ul>
+
+<h3> Format </h3>
+
+<p>
+ The conversion file is a sequence of lines; each line is parsed
+independently, there's no carrying of information from one line to
+the next.
+</p>
+
+<p>
+ A line is lexed into words by the
+<a href="http://skarnet.org/software/execline/execlineb.html">execlineb</a>
+lexer, which means that words are normally separated by whitespace, but
+can be quoted, that <tt>#</tt> comments are recognized, etc.
+</p>
+
+<p>
+ The first word in a line must be the name of an "old" atomic service, i.e.
+an atomic service contained in the current live database. The remaining
+words in the line are instructions telling s6-rc-update how to convert
+that service.
+</p>
+
+<h4> Renaming </h4>
+
+<p>
+ If the second word in the line is <tt>-></tt>, then the third word in the
+line must be the new name of the service in the new database: s6-rc-update
+will then rename it. It is possible
+to rename an atomic service to another atomic service or a bundle, but no
+matter whether a service is renamed or not, changing its type will force a
+restart.
+</p>
+
+<p>
+ Note that renaming a longrun without restarting it will keep the same
+<a href="http://skarnet.org/software/s6/s6-supervise.html">s6-supervise</a>
+process supervising the longrun: this process will appear in a
+<tt>ps</tt> output as supervising the old name. This is only cosmetic and
+will have no impact on the service; nevertheless, if you wish to avoid that,
+simply force a restart on every service you rename.
+</p>
+
+<h4> Restarting </h4>
+
+<p>
+ If the word following either the old name, or a renaming instruction, is the
+word <tt>restart</tt>, then the service will forced to restart.
+</p>
+
+<h3> Examples </h3>
+
+<p>
+ Consider the following conversion file:
+</p>
+
+<pre># Simple conversion file
+mount-var -> mount-rwfs
+httpd restart
+sqld -> mysqld restart
+</pre>
+
+<ul>
+ <li> It will rename <tt>mount-var</tt> to <tt>mount-rwfs</tt>, not restarting it
+if <tt>mount-var</tt> in the old database and <tt>mount-rwfs</tt> in the new
+database have the same type and do not depend on services that would force a
+restart. </li>
+ <li> It will restart <tt>httpd</tt> </li>
+ <li> It will rename <tt>sqld</tt> to <tt>mysqld</tt> and make it restart.
+</ul>
+
</body>
</html>
diff --git a/src/libs6rc/s6rc_servicedir_manage.c b/src/libs6rc/s6rc_servicedir_manage.c
index bad4f4b..e06d7a4 100644
--- a/src/libs6rc/s6rc_servicedir_manage.c
+++ b/src/libs6rc/s6rc_servicedir_manage.c
@@ -22,7 +22,7 @@ int s6rc_servicedir_manage (char const *live, tain_t const *deadline, tain_t *st
gid_t gid = getgid() ;
unsigned int livelen = str_len(live) ;
int ok = 1 ;
- int e ;
+ int e = 0 ;
DIR *dir ;
char dirfn[livelen + 13] ;
if (!ftrigr_startf(&a, deadline, stamp)) return 0 ;
diff --git a/src/s6-rc/s6-rc-update.c b/src/s6-rc/s6-rc-update.c
index 796f738..380d79f 100644
--- a/src/s6-rc/s6-rc-update.c
+++ b/src/s6-rc/s6-rc-update.c
@@ -53,7 +53,8 @@ static unsigned int verbosity = 1 ;
newstate flags:
1 -> is up (converted from old up)
2 -> wanted up
- 4 -> is a conversion target
+ 8 -> is a conversion target
+ 32 -> is up after closure (i.e. includes new deps)
*/
static inline void parse_line (stralloc *sa, char const *s, unsigned int slen, unsigned int *newnames, unsigned char *oldstate, cdb_t *oldc, s6rc_db_t const *olddb)
@@ -150,7 +151,7 @@ static inline void stuff_with_oldc (unsigned char *oldstate, int fdoldc, s6rc_db
close(oldfdres) ;
}
-static inline void fill_convtable_and_flags (unsigned char *conversion_table, unsigned char *oldstate, unsigned char *newstate, char const *namedata, unsigned int const *oldindex, unsigned int *newlong, cdb_t *newc, char const *newfn, s6rc_db_t const *olddb, s6rc_db_t const *newdb)
+static inline void fill_convtable_and_flags (unsigned char *conversion_table, unsigned char *oldstate, unsigned char *newstate, char const *namedata, unsigned int const *oldindex, unsigned int *invimage, cdb_t *newc, char const *newfn, s6rc_db_t const *olddb, s6rc_db_t const *newdb)
{
unsigned int newn = newdb->nshort + newdb->nlong ;
unsigned int i = olddb->nshort + olddb->nlong ;
@@ -183,22 +184,19 @@ static inline void fill_convtable_and_flags (unsigned char *conversion_table, un
uint32_unpack_big(p, &x) ; p += 4 ;
if (x >= newn)
strerr_dief3x(4, "invalid resolve database in ", newfn, "/resolve.cdb") ;
- if (newstate[x] & 4)
- strerr_dief4x(1, "bad conversion file: new service ", newdb->string + newdb->services[x].name, " is a target for more than one conversion, including old service ", olddb->string + olddb->services[i].name) ;
- newstate[x] |= 4 ;
+ if (newstate[x] & 8)
+ strerr_dief4x(6, "bad conversion file: new service ", newdb->string + newdb->services[x].name, " is a target for more than one conversion, including old service ", olddb->string + olddb->services[i].name) ;
+ newstate[x] |= 8 ;
+ invimage[x] = i ;
bitarray_set(conversion_table + i * bitarray_div8(newn), x) ;
- if (oldstate[i] & 8)
- {
- if (x < newdb->nlong) newlong[x] = i ;
- if ((i < olddb->nlong) != (x < newdb->nlong)) oldstate[i] |= 4 ;
- }
+ if (oldstate[i] & 8 && (i < olddb->nlong) != (x < newdb->nlong))
+ oldstate[i] |= 4 ;
}
}
- if (oldstate[i] & 1 && (oldstate[i] & 4 || !(oldstate[i] & 8))) oldstate[i] |= 34 ;
}
}
-static inline void stuff_with_newc (int fdnewc, char const *newfn, unsigned char *conversion_table, unsigned char *oldstate, unsigned char *newstate, char const *namedata, unsigned int const *oldindex, unsigned int *newlong, s6rc_db_t const *olddb, s6rc_db_t const *newdb)
+static inline void stuff_with_newc (int fdnewc, char const *newfn, unsigned char *conversion_table, unsigned char *oldstate, unsigned char *newstate, char const *namedata, unsigned int const *oldindex, unsigned int *invimage, s6rc_db_t const *olddb, s6rc_db_t const *newdb)
{
cdb_t newc = CDB_ZERO ;
int newfdres = open_readatb(fdnewc, "resolve.cdb") ;
@@ -206,24 +204,13 @@ static inline void stuff_with_newc (int fdnewc, char const *newfn, unsigned char
if (!cdb_init_map(&newc, newfdres, 1))
strerr_diefu3sys(111, "cdb_init ", newfn, "/compiled/resolve.cdb") ;
- fill_convtable_and_flags(conversion_table, oldstate, newstate, namedata, oldindex, newlong, &newc, newfn, olddb, newdb) ;
+ fill_convtable_and_flags(conversion_table, oldstate, newstate, namedata, oldindex, invimage, &newc, newfn, olddb, newdb) ;
cdb_free(&newc) ;
close(newfdres) ;
}
-static inline void adjust_newup (unsigned char const *oldstate, unsigned int oldn, unsigned char *newstate, unsigned int newn, unsigned char const *conversion_table)
-{
- unsigned int i = oldn ;
- while (i--) if (oldstate[i] & 1)
- {
- register unsigned int j = newn ;
- while (j--) if (bitarray_peek(conversion_table + i * bitarray_div8(newn), j))
- newstate[j] |= (oldstate[i] & 32) ? 2 : 1 ;
- }
-}
-
-static void compute_transitions (char const *convfile, unsigned char *oldstate, int fdoldc, s6rc_db_t const *olddb, unsigned char *newstate, unsigned int *newlong, int fdnewc, char const *newfn, s6rc_db_t const *newdb, stralloc *sa)
+static void compute_transitions (char const *convfile, unsigned char *oldstate, int fdoldc, s6rc_db_t const *olddb, unsigned char *newstate, unsigned int *invimage, int fdnewc, char const *newfn, s6rc_db_t const *newdb, stralloc *sa)
{
unsigned int oldn = olddb->nshort + olddb->nlong ;
unsigned int newn = newdb->nshort + newdb->nlong ;
@@ -232,10 +219,39 @@ static void compute_transitions (char const *convfile, unsigned char *oldstate,
unsigned char conversion_table[oldn * bitarray_div8(newn)] ;
byte_zero(conversion_table, oldn * bitarray_div8(newn)) ;
stuff_with_oldc(oldstate, fdoldc, olddb, convfile, oldindex, sa) ;
- stuff_with_newc(fdnewc, newfn, conversion_table, oldstate, newstate, sa->s + sabase, oldindex, newlong, olddb, newdb) ;
+ stuff_with_newc(fdnewc, newfn, conversion_table, oldstate, newstate, sa->s + sabase, oldindex, invimage, olddb, newdb) ;
sa->len = sabase ;
- s6rc_graph_closure(olddb, oldstate, 5, 0) ;
- adjust_newup(oldstate, oldn, newstate, newn, conversion_table) ;
+
+ for (;;)
+ {
+ int done = 1 ;
+ unsigned int i = oldn ;
+ while (i--)
+ {
+ if (oldstate[i] & 1 && (oldstate[i] & 4 || !(oldstate[i] & 8))) oldstate[i] |= 34 ;
+ else oldstate[i] &= 221 ;
+ }
+ s6rc_graph_closure(olddb, oldstate, 5, 0) ;
+ i = newn ; while (i--) newstate[i] &= 8 ;
+ i = oldn ;
+ while (i--) if (oldstate[i] & 1)
+ {
+ register unsigned int j = newn ;
+ while (j--) if (bitarray_peek(conversion_table + i * bitarray_div8(newn), j))
+ newstate[j] |= (oldstate[i] & 32) ? 2 : 33 ;
+ }
+ s6rc_graph_closure(newdb, newstate, 5, 1) ;
+ i = newn ;
+ while (i--) if ((newstate[i] & 33) == 32)
+ {
+ done = 0 ;
+ newstate[i] |= 4 ;
+ }
+ if (done) break ;
+ s6rc_graph_closure(newdb, newstate, 2, 0) ;
+ i = newn ;
+ while (i--) if ((newstate[i] & 5) == 5) oldstate[invimage[i]] |= 4 ;
+ }
}
@@ -243,7 +259,7 @@ static void compute_transitions (char const *convfile, unsigned char *oldstate,
/* Update the live directory while keeping active servicedirs */
-static inline void rollback_servicedirs (char const *newlive, unsigned char const *newstate, unsigned int const *newlong, s6rc_db_t const *olddb, s6rc_db_t const *newdb, unsigned int n)
+static inline void rollback_servicedirs (char const *newlive, unsigned char const *newstate, unsigned int const *invimage, s6rc_db_t const *olddb, s6rc_db_t const *newdb, unsigned int n)
{
unsigned int newllen = str_len(newlive) ;
unsigned int i = n ;
@@ -256,7 +272,7 @@ static inline void rollback_servicedirs (char const *newlive, unsigned char cons
byte_copy(newfn + newllen + 13, newnamelen + 1, newdb->string + newdb->services[i].name) ;
if (newstate[i] & 1)
{
- char const *oldname = newstate[i] & 4 ? olddb->string + olddb->services[newlong[i]].name : newdb->string + newdb->services[i].name ;
+ char const *oldname = newstate[i] & 4 ? olddb->string + olddb->services[invimage[i]].name : newdb->string + newdb->services[i].name ;
unsigned int oldnamelen = str_len(oldname) ;
char oldfn[livelen + 23 + oldnamelen] ;
byte_copy(oldfn, livelen, live) ;
@@ -288,7 +304,7 @@ static inline void unsupervise (char const *live, char const *name, int keepsupe
}
}
-static inline void make_new_livedir (unsigned char const *oldstate, s6rc_db_t const *olddb, unsigned char const *newstate, s6rc_db_t const *newdb, char const *newcompiled, unsigned int *newlong, stralloc *sa)
+static inline void make_new_livedir (unsigned char const *oldstate, s6rc_db_t const *olddb, unsigned char const *newstate, s6rc_db_t const *newdb, char const *newcompiled, unsigned int *invimage, stralloc *sa)
{
unsigned int tmpbase = satmp.len ;
unsigned int sabase = sa->len ;
@@ -343,7 +359,7 @@ static inline void make_new_livedir (unsigned char const *oldstate, s6rc_db_t co
|| !stralloc_0(sa)) { e = errno ; goto rollback ; }
if (newstate[i] & 1)
{
- char const *oldname = newstate[i] & 4 ? olddb->string + olddb->services[newlong[i]].name : newdb->string + olddb->services[i].name ;
+ char const *oldname = newstate[i] & 4 ? olddb->string + olddb->services[invimage[i]].name : newdb->string + olddb->services[i].name ;
unsigned int oldnamelen = str_len(oldname) ;
char oldfn[livelen + 13 + oldnamelen] ;
byte_copy(oldfn, livelen, live) ;
@@ -393,7 +409,7 @@ static inline void make_new_livedir (unsigned char const *oldstate, s6rc_db_t co
rollback:
sa->len = newlen ;
sa->s[sa->len++] = 0 ;
- rollback_servicedirs(sa->s + sabase, newstate, newlong, olddb, newdb, i) ;
+ rollback_servicedirs(sa->s + sabase, newstate, invimage, olddb, newdb, i) ;
err:
sa->len = newlen ;
sa->s[sa->len++] = 0 ;
@@ -481,7 +497,7 @@ static void update_fdholder (s6rc_db_t const *olddb, unsigned char const *oldsta
if (fdsocket < 0) goto hammer ;
if (!ipc_timed_connect_g(fdsocket, fnsocket, deadline))
{
- if (errno == ETIMEDOUT) strerr_dief1x(1, "timed out") ;
+ if (errno == ETIMEDOUT) strerr_dief1x(2, "timed out during s6rc-fdholder update") ;
else goto closehammer ;
}
s6_fdholder_init(&a, fdsocket) ;
@@ -510,7 +526,7 @@ static void update_fdholder (s6rc_db_t const *olddb, unsigned char const *oldsta
tain_now_g() ;
if (WIFSIGNALED(wstat) || WEXITSTATUS(wstat))
if (verbosity) strerr_warnw1x("restart s6rc-fdholder") ;
- if (!tain_future(deadline)) strerr_dief1x(1, "timed out") ;
+ if (!tain_future(deadline)) strerr_dief1x(2, "timed out during s6rc-fdholder update") ;
}
}
@@ -532,7 +548,6 @@ int main (int argc, char const *const *argv, char const *const *envp)
tain_t deadline ;
int dryrun = 0 ;
PROG = "s6-rc-update" ;
- strerr_dief1x(100, "almost there. Just a little more patience.") ;
{
unsigned int t = 0 ;
subgetopt_t l = SUBGETOPT_ZERO ;
@@ -604,7 +619,7 @@ int main (int argc, char const *const *argv, char const *const *envp)
s6rc_service_t newserviceblob[newn] ;
char const *newargvblob[newdb.nargvs] ;
uint32 newdepsblob[newdb.ndeps << 1] ;
- unsigned int newlong[newdb.nlong] ;
+ unsigned int invimage[newn] ;
char oldstringblob[olddb.stringlen] ;
char newstringblob[newdb.stringlen] ;
unsigned char oldstate[oldn] ;
@@ -633,22 +648,22 @@ int main (int argc, char const *const *argv, char const *const *envp)
/* Initial state */
- byte_zero(newstate, newn) ;
byte_copy(dbfn + livelen + 1, 6, "state") ;
r = openreadnclose(dbfn, (char *)oldstate, oldn) ;
if (r != oldn) strerr_diefu2sys(111, "read ", dbfn) ;
r = oldn ;
while (r--) oldstate[r] &= 1 ;
- r = newdb.nlong ;
- while (r--) newlong[r] = olddb.nlong + olddb.nshort ;
+ byte_zero(newstate, newn) ;
+ r = newn ;
+ while (r--) invimage[r] = olddb.nlong + olddb.nshort ;
/* Read the conversion file and compute what to do */
if (verbosity >= 2) strerr_warni1x("computing state adjustments") ;
- compute_transitions(convfile, oldstate, fdoldc, &olddb, newstate, newlong, fdnewc, argv[0], &newdb, &sa) ;
+ compute_transitions(convfile, oldstate, fdoldc, &olddb, newstate, invimage, fdnewc, argv[0], &newdb, &sa) ;
tain_now_g() ;
- if (!tain_future(&deadline)) strerr_dief1x(1, "timed out") ;
+ if (!tain_future(&deadline)) strerr_dief1x(2, "timed out while computing state adjutments") ;
/* Down transition */
@@ -690,7 +705,6 @@ int main (int argc, char const *const *argv, char const *const *envp)
tain_now_g() ;
if (WIFSIGNALED(wstat) || WEXITSTATUS(wstat))
strerr_dief1x(wait_estatus(wstat), "first s6-rc invocation failed") ;
- if (!tain_future(&deadline)) strerr_dief1x(1, "timed out") ;
}
if (!dryrun)
@@ -702,7 +716,7 @@ int main (int argc, char const *const *argv, char const *const *envp)
if (verbosity >= 2)
strerr_warni1x("updating state and service directories") ;
- make_new_livedir (oldstate, &olddb, newstate, &newdb, argv[0], newlong, &sa) ;
+ make_new_livedir(oldstate, &olddb, newstate, &newdb, argv[0], invimage, &sa) ;
r = s6rc_servicedir_manage_g(live, &deadline) ;
if (!r) strerr_diefu2sys(111, "manage new service directories in ", live) ;
if (r & 2) strerr_warnw3x("s6-svscan not running on ", live, "/scandir") ;