diff --git a/src/cond-w.c b/src/cond-w.c index 8f77643f..8246f54d 100644 --- a/src/cond-w.c +++ b/src/cond-w.c @@ -25,16 +25,51 @@ #include #include #include -#include #include "finit.h" #include "cond.h" #include "service.h" +static int cond_set_gen(const char *path, unsigned int gen) +{ + FILE *fp; + int ret; + + fp = fopen(path, "w"); + if (!fp) + return -1; + + ret = fprintf(fp, "%u", gen); + fclose(fp); + + return (ret > 0) ? 0 : ret; +} + +static void cond_bump_reconf(void) +{ + unsigned int rgen; + + rgen = cond_get_gen(COND_RECONF); + /* COND_RECONF does not exist, cond_get_gen will return 0 + * meaning that rgen++ is always what we want. */ + rgen++; + + cond_set_gen(COND_RECONF, rgen); +} + int cond_set_path(const char *path, enum cond_state new) { char buf[MAX_ARG_LEN], *dir; enum cond_state old; + unsigned int rgen; + + _d("%s", path); + + rgen = cond_get_gen(COND_RECONF); + if (!rgen) { + _e("Unable to read configuration generation (%s)", path); + return -1; + } old = cond_get_path(path); @@ -50,8 +85,7 @@ int cond_set_path(const char *path, enum cond_state new) _pe("Failed creating dir '%s' for condition '%s'", dir, path); return 0; } - touch(path); - utimensat(0, path, NULL, 0); + cond_set_gen(path, rgen); break; case COND_OFF: @@ -121,8 +155,8 @@ void cond_clear(const char *name) void cond_reload(void) { _d(""); - cond_set_path(COND_RECONF, COND_ON); + cond_bump_reconf(); cond_update(NULL); } @@ -153,6 +187,15 @@ void cond_reassert(const char *type) nftw(cond_path(type), reassert, 20, FTW_DEPTH); } +void cond_init(void) +{ + if (makepath(COND_PATH) && errno != EEXIST) { + _pe("Failed creating condition base directory '%s'", COND_PATH); + return; + } + + cond_bump_reconf(); +} /** * Local Variables: diff --git a/src/cond.c b/src/cond.c index 98c3895b..d01fae2f 100644 --- a/src/cond.c +++ b/src/cond.c @@ -28,14 +28,6 @@ #include "cond.h" #include "service.h" -static inline int timespec_newer(const struct timespec *a, - const struct timespec *b) -{ - if (a->tv_sec != b->tv_sec) - return a->tv_sec > b->tv_sec; - - return a->tv_nsec >= b->tv_nsec; -} const char *condstr(enum cond_state s) { @@ -57,18 +49,35 @@ const char *cond_path(const char *name) return file; } +unsigned int cond_get_gen(const char *path) +{ + unsigned int gen; + FILE *fp; + int ret; + + fp = fopen(path, "r"); + if (!fp) + return 0; + + ret = fscanf(fp, "%u", &gen); + fclose(fp); + + return (ret == 1) ? gen : 0; +} + enum cond_state cond_get_path(const char *path) { - struct stat st, st_reconf; + int cgen, rgen; - if (stat(path, &st)) + rgen = cond_get_gen(COND_RECONF); + if (!rgen) return COND_OFF; - if (stat(COND_RECONF, &st_reconf) || - timespec_newer(&st.st_mtim, &st_reconf.st_mtim)) - return COND_ON; + cgen = cond_get_gen(path); + if (!cgen) + return COND_OFF; - return COND_FLUX; + return (cgen == rgen) ? COND_ON : COND_FLUX; } enum cond_state cond_get(const char *name) diff --git a/src/cond.h b/src/cond.h index f8c94f4e..c003cc1a 100644 --- a/src/cond.h +++ b/src/cond.h @@ -15,6 +15,7 @@ typedef enum cond_state { const char *condstr (enum cond_state s); const char *cond_path (const char *name); +unsigned int cond_get_gen (const char *path); enum cond_state cond_get_path(const char *path); enum cond_state cond_get (const char *name); enum cond_state cond_get_agg (const char *names); @@ -25,6 +26,7 @@ void cond_set (const char *name); void cond_clear (const char *name); void cond_reload (void); void cond_reassert(const char *pat); +void cond_init (void); #endif /* FINIT_COND_H_ */ diff --git a/src/finit.c b/src/finit.c index b8d445bb..27bd0c15 100644 --- a/src/finit.c +++ b/src/finit.c @@ -36,6 +36,7 @@ #include #include "finit.h" +#include "cond.h" #include "conf.h" #include "helpers.h" #include "private.h" @@ -475,6 +476,9 @@ int main(int argc, char* argv[]) /* Base FS up, enable standard SysV init signals */ sig_setup(&loop); + /* Bootstrap conditions */ + cond_init(); + /* * Reload all *.conf in /etc/finit.d, the mount command (above) * may have brought in new files (overlayfs).