diff --git a/src/librc/librc-depend.c b/src/librc/librc-depend.c index b472c8a1..f52c6de2 100644 --- a/src/librc/librc-depend.c +++ b/src/librc/librc-depend.c @@ -596,7 +596,7 @@ char **rc_deptree_order (const rc_depinfo_t *deptree, const char *runlevel, } librc_hidden_def(rc_deptree_order) -static bool is_newer_than (const char *file, const char *target) +bool rc_newer_than (const char *source, const char *target) { struct stat buf; time_t mtime; @@ -604,28 +604,31 @@ static bool is_newer_than (const char *file, const char *target) DIR *dp; struct dirent *d; char *path; + int serrno = errno; - if (stat (file, &buf) != 0 || buf.st_size == 0) + if (stat (source, &buf) != 0 || buf.st_size == 0) return (false); mtime = buf.st_mtime; - /* Of course we are newever than targets that don't exist - Such as broken symlinks */ + /* Of course we are newer than targets that don't exist + such as broken symlinks */ if (stat (target, &buf) != 0) return (true); if (mtime < buf.st_mtime) return (false); - if (! (dp = opendir (target))) + if (! (dp = opendir (target))) { + errno = serrno; return (true); + } while ((d = readdir (dp))) { if (d->d_name[0] == '.') continue; path = rc_strcatpaths (target, d->d_name, (char *) NULL); - newer = is_newer_than (file, path); + newer = rc_newer_than (source, path); free (path); if (! newer) break; @@ -634,6 +637,7 @@ static bool is_newer_than (const char *file, const char *target) return (newer); } +librc_hidden_def(rc_newer_than) typedef struct deppair { @@ -679,18 +683,18 @@ bool rc_deptree_update_needed (void) fprintf (stderr, "mkdir `%s': %s\n", depdirs[i], strerror (errno)); /* Quick test to see if anything we use has changed */ - if (! is_newer_than (RC_DEPTREE, RC_INITDIR) || - ! is_newer_than (RC_DEPTREE, RC_CONFDIR) || - ! is_newer_than (RC_DEPTREE, RC_INITDIR_LOCAL) || - ! is_newer_than (RC_DEPTREE, RC_CONFDIR_LOCAL) || - ! is_newer_than (RC_DEPTREE, "/etc/rc.conf")) + if (! rc_newer_than (RC_DEPTREE, RC_INITDIR) || + ! rc_newer_than (RC_DEPTREE, RC_CONFDIR) || + ! rc_newer_than (RC_DEPTREE, RC_INITDIR_LOCAL) || + ! rc_newer_than (RC_DEPTREE, RC_CONFDIR_LOCAL) || + ! rc_newer_than (RC_DEPTREE, "/etc/rc.conf")) return (true); /* Some init scripts dependencies change depending on config files * outside of baselayout, like syslog-ng, so we check those too. */ config = rc_config_list (RC_DEPCONFIG); STRLIST_FOREACH (config, service, i) { - if (! is_newer_than (RC_DEPTREE, service)) { + if (! rc_newer_than (RC_DEPTREE, service)) { newer = true; break; } diff --git a/src/librc/librc.h b/src/librc/librc.h index 6b1e0314..0f6212fe 100644 --- a/src/librc/librc.h +++ b/src/librc/librc.h @@ -84,6 +84,7 @@ librc_hidden_proto(rc_deptree_update) librc_hidden_proto(rc_deptree_update_needed) librc_hidden_proto(rc_find_pids) librc_hidden_proto(rc_getline) +librc_hidden_proto(rc_newer_than) librc_hidden_proto(rc_runlevel_exists) librc_hidden_proto(rc_runlevel_get) librc_hidden_proto(rc_runlevel_list) diff --git a/src/librc/rc.h b/src/librc/rc.h index 95247785..516d39f0 100644 --- a/src/librc/rc.h +++ b/src/librc/rc.h @@ -61,7 +61,8 @@ bool rc_runlevel_exists (const char *runlevel); char **rc_runlevel_list (void); /*! Set the runlevel. - * This just changes the stored runlevel and does not start or stop any services. + * This just changes the stored runlevel and does not start or stop any + * services. * @param runlevel to store */ bool rc_runlevel_set (const char *runlevel); @@ -117,8 +118,8 @@ bool rc_service_delete (const char *runlevel, const char *service); * @param pidfile of the process (optional) * @param started if true, add the arguments otherwise remove existing matching arguments */ bool rc_service_daemon_set (const char *service, const char *exec, - const char *name, const char *pidfile, - bool started); + const char *name, const char *pidfile, + bool started); /*! Returns a description of what the service and/or option does. * @param service to check @@ -157,7 +158,7 @@ char *rc_service_resolve (const char *service); * @param service that starts the scheduled service when started * @param service_to_start service that will be started */ bool rc_service_schedule_start (const char *service, - const char *service_to_start); + const char *service_to_start); /*! Return a NULL terminated list of services that are scheduled to start * when the given service has started * @param service to check @@ -190,7 +191,7 @@ pid_t rc_service_stop (const char *service); * @param indx of the daemon (optional - 1st daemon, 2nd daemon, etc) * @return true if started by this service, otherwise false */ bool rc_service_started_daemon (const char *service, const char *exec, - int indx); + int indx); /*! Return a saved value for a service * @param service to check @@ -204,7 +205,7 @@ char *rc_service_value_get (const char *service, const char *option); * @param value of the option * @return true if saved, otherwise false */ bool rc_service_value_set (const char *service, const char *option, - const char *value); + const char *value); /*! List the services in a runlevel * @param runlevel to list @@ -248,6 +249,11 @@ bool rc_service_daemons_crashed (const char *service); typedef void *rc_depinfo_t; #endif +/*! Check to see if source is newer than target. + * If target is a directory then we traverse it and it's children. +* @return true if source is newer than target, otherwise false */ +bool rc_newer_than (const char *source, const char *target); + /*! Update the cached dependency tree if it's older than any init script, * its configuration file or an external configuration file the init script * has specified. @@ -271,7 +277,7 @@ rc_depinfo_t *rc_deptree_load (void); * @param service to check * @return NULL terminated list of services in order */ char **rc_deptree_depend (const rc_depinfo_t *deptree, - const char *type, const char *service); + const char *type, const char *service); /*! List all the services in order that the given services have * for the given types and options. @@ -281,9 +287,9 @@ char **rc_deptree_depend (const rc_depinfo_t *deptree, * @param options to pass * @return NULL terminated list of services in order */ char **rc_deptree_depends (const rc_depinfo_t *deptree, - const char *const *types, - const char *const *services, const char *runlevel, - int options); + const char *const *types, + const char *const *services, const char *runlevel, + int options); /*! List all the services that should be stoppned and then started, in order, * for the given runlevel, including sysinit and boot services where @@ -293,7 +299,7 @@ char **rc_deptree_depends (const rc_depinfo_t *deptree, * @param options to pass * @return NULL terminated list of services in order */ char **rc_deptree_order (const rc_depinfo_t *deptree, const char *runlevel, - int options); + int options); /*! Free a deptree and its information * @param deptree to free */ @@ -440,6 +446,6 @@ char *rc_strcatpaths (const char *path1, const char *paths, ...) SENTINEL; * @param pid to check for * @return NULL terminated list of pids */ pid_t *rc_find_pids (const char *exec, const char *cmd, - uid_t uid, pid_t pid); + uid_t uid, pid_t pid); #endif diff --git a/src/librc/rc.map b/src/librc/rc.map index 8de23c41..e60ea183 100644 --- a/src/librc/rc.map +++ b/src/librc/rc.map @@ -13,6 +13,7 @@ global: rc_environ_fd; rc_find_pids; rc_getline; + rc_newer_than; rc_runlevel_exists; rc_runlevel_get; rc_runlevel_list; diff --git a/src/rc/Makefile b/src/rc/Makefile index 1168b3f2..587d60d7 100644 --- a/src/rc/Makefile +++ b/src/rc/Makefile @@ -23,7 +23,7 @@ RC_BINLINKS= einfon einfo ewarnn ewarn eerrorn eerror ebegin eend ewend \ service_coldplugged service_started_daemon \ checkpath fstabinfo mountinfo rc-depend \ service_get_value service_set_value get_options save_options \ - shell_var + shell_var is_newer_than is_older_than RC_SBINLINKS= mark_service_starting mark_service_started \ mark_service_stopping mark_service_stopped \ mark_service_inactive mark_service_wasinactive \ diff --git a/src/rc/rc.c b/src/rc/rc.c index 567da725..93be82d4 100644 --- a/src/rc/rc.c +++ b/src/rc/rc.c @@ -913,6 +913,21 @@ int main (int argc, char **argv) if (strncmp (applet, "mark_service_", strlen ("mark_service_")) == 0) exit (do_mark_service (argc, argv)); + if (strcmp (applet, "is_newer_than") == 0 || + strcmp (applet, "is_older_than") == 0) + { + bool match = false; + if (argc < 2) + exit (EXIT_FAILURE); + if (strcmp (applet, "is_newer_than") == 0) + match = true; + while (optind < argc) { + if (rc_newer_than (argv[0], argv[optind++]) != match) + exit (EXIT_FAILURE); + } + exit (EXIT_SUCCESS); + }; + if (strcmp (applet, "is_runlevel_start") == 0) exit (rc_runlevel_starting () ? 0 : 1); else if (strcmp (applet, "is_runlevel_stop") == 0)