summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libs6rc/s6rc_servicedir_copy_online.c60
-rw-r--r--src/s6-rc/s6-rc-update.c16
2 files changed, 74 insertions, 2 deletions
diff --git a/src/libs6rc/s6rc_servicedir_copy_online.c b/src/libs6rc/s6rc_servicedir_copy_online.c
index 62d7c87..a3fa1f7 100644
--- a/src/libs6rc/s6rc_servicedir_copy_online.c
+++ b/src/libs6rc/s6rc_servicedir_copy_online.c
@@ -6,12 +6,14 @@
#include <unistd.h>
#include <stdio.h>
+#include <skalibs/direntry.h>
#include <skalibs/djbunix.h>
+
#include <s6/servicedir.h>
#include <s6-rc/s6rc-utils.h>
-#include "s6rc-servicedir-internal.h"
#include <s6-rc/s6rc-servicedir.h>
+#include "s6rc-servicedir-internal.h"
int s6rc_servicedir_copy_online (char const *src, char const *dst)
{
@@ -21,6 +23,8 @@ int s6rc_servicedir_copy_online (char const *src, char const *dst)
unsigned int i = 0 ;
int wantup = 0 ;
int e ;
+ struct stat st ;
+ DIR *dir ;
char srcfn[srclen + S6_SERVICEDIR_FILE_MAXLEN + 6] ;
char dstfn[dstlen + S6_SERVICEDIR_FILE_MAXLEN + 6] ;
char oldfn[dstlen + S6_SERVICEDIR_FILE_MAXLEN + 6] ;
@@ -63,6 +67,51 @@ int s6rc_servicedir_copy_online (char const *src, char const *dst)
}
oldfn[dstlen + 4] = 0 ;
rm_rf(oldfn) ;
+
+ /* New files copied, now let's update the instances with the new template */
+
+ memcpy(oldfn + dstlen + 1, "template", 9) ;
+ if (stat(oldfn, &st) == 0)
+ {
+ if (!S_ISDIR(st.st_mode)) { errno = EINVAL ; goto erri ; }
+ memcpy(dstfn + dstlen + 1, "instances", 10) ;
+ dir = opendir(dstfn) ;
+ if (!dir)
+ {
+ mode_t m ;
+ if (errno != ENOENT) goto erri ;
+ m = umask(0) ;
+ if (mkdir(dstfn, 0755) == -1) { umask(m) ; goto erri ; }
+ dstfn[dstlen + 9] = 0 ;
+ if (mkdir(dstfn, 0755) == -1) { umask(m) ; goto erri ; }
+ umask(m) ;
+ }
+ else
+ {
+ dstfn[dstlen + 10] = '/' ;
+ for (;;)
+ {
+ direntry *d ;
+ errno = 0 ;
+ d = readdir(dir) ;
+ if (!d) break ;
+ if (d->d_name[0] == '.')
+ if (((d->d_name[1] == '.') && !d->d_name[2]) || !d->d_name[1])
+ continue ;
+ {
+ size_t len = strlen(d->d_name) ;
+ char ifn[dstlen + 12 + len] ;
+ memcpy(ifn, dstfn, dstlen + 11) ;
+ memcpy(ifn + dstlen + 11, d->d_name, len + 1) ;
+ if (!s6rc_servicedir_copy_online(oldfn, ifn)) goto errd ;
+ }
+ }
+ dir_close(dir) ;
+ if (errno) goto erri ;
+ }
+ }
+ else if (errno != ENOENT) goto erri ;
+
s6rc_servicedir_unblock(dst, wantup) ;
return 1 ;
@@ -80,9 +129,18 @@ int s6rc_servicedir_copy_online (char const *src, char const *dst)
strcpy(oldfn + dstlen + 5, s6rc_servicedir_file_list[i].name) ;
rename(oldfn, dstfn) ;
}
+ s6rc_servicedir_unblock(dst, wantup) ;
errdir:
oldfn[dstlen + 4] = 0 ;
rmdir(oldfn) ;
errno = e ;
return 0 ;
+
+ errd:
+ dir_close(dir) ;
+ erri:
+ e = errno ;
+ s6rc_servicedir_unblock(dst, wantup) ;
+ errno = e ;
+ return 0 ;
}
diff --git a/src/s6-rc/s6-rc-update.c b/src/s6-rc/s6-rc-update.c
index ced42d0..617cdfb 100644
--- a/src/s6-rc/s6-rc-update.c
+++ b/src/s6-rc/s6-rc-update.c
@@ -28,6 +28,7 @@
#include <s6/config.h>
#include <s6/supervise.h>
+#include <s6/servicedir.h>
#include <s6/fdholder.h>
#include <s6-rc/config.h>
@@ -355,7 +356,20 @@ static inline void make_new_livedir (unsigned char const *oldstate, s6rc_db_t co
if (rename(oldfn, sa->s + pos) < 0) goto rollback ;
if (!s6rc_servicedir_copy_online(newfn, sa->s + pos)) { i++ ; goto rollback ; }
}
- else if (!s6rc_servicedir_copy_offline(newfn, sa->s + pos)) goto rollback ;
+ else
+ {
+ if (!s6rc_servicedir_copy_offline(newfn, sa->s + pos)) goto rollback ;
+ if (invimage[i] < olddb->nlong)
+ {
+ char const *oldname = newstate[i] & 8 ? olddb->string + olddb->services[invimage[i]].name : newdb->string + newdb->services[i].name ;
+ size_t oldnamelen = strlen(oldname) ;
+ char oldfn[livelen + 14 + oldnamelen] ;
+ memcpy(oldfn, live, livelen) ;
+ memcpy(oldfn + livelen, "/servicedirs/", 13) ;
+ memcpy(oldfn + livelen + 13, oldname, oldnamelen + 1) ;
+ if (s6_servicedir_instances_recreate_offline(oldfn, sa->s + pos) == -1) goto rollback ;
+ }
+ }
}
sa->len = newlen ;
sa->s[sa->len] = 0 ;