From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: <gentoo-commits+bounces-987460-garchives=archives.gentoo.org@lists.gentoo.org> Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by finch.gentoo.org (Postfix) with ESMTPS id 5CA35139082 for <garchives@archives.gentoo.org>; Thu, 30 Nov 2017 19:58:16 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id B7824E0CAE; Thu, 30 Nov 2017 19:58:15 +0000 (UTC) Received: from smtp.gentoo.org (dev.gentoo.org [IPv6:2001:470:ea4a:1:5054:ff:fec7:86e4]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id 8A23EE0CAE for <gentoo-commits@lists.gentoo.org>; Thu, 30 Nov 2017 19:58:15 +0000 (UTC) Received: from oystercatcher.gentoo.org (unknown [IPv6:2a01:4f8:202:4333:225:90ff:fed9:fc84]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id DD90B341665 for <gentoo-commits@lists.gentoo.org>; Thu, 30 Nov 2017 19:58:13 +0000 (UTC) Received: from localhost.localdomain (localhost [IPv6:::1]) by oystercatcher.gentoo.org (Postfix) with ESMTP id 9433AAD18 for <gentoo-commits@lists.gentoo.org>; Thu, 30 Nov 2017 19:58:12 +0000 (UTC) From: "William Hubbs" <williamh@gentoo.org> To: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: 8bit Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "William Hubbs" <williamh@gentoo.org> Message-ID: <1512071814.a7c99506d9de81b9a2a7547bd11715073de1ce95.williamh@OpenRC> Subject: [gentoo-commits] proj/openrc:master commit in: src/librc/ X-VCS-Repository: proj/openrc X-VCS-Files: src/librc/librc-depend.c X-VCS-Directories: src/librc/ X-VCS-Committer: williamh X-VCS-Committer-Name: William Hubbs X-VCS-Revision: a7c99506d9de81b9a2a7547bd11715073de1ce95 X-VCS-Branch: master Date: Thu, 30 Nov 2017 19:58:12 +0000 (UTC) Precedence: bulk List-Post: <mailto:gentoo-commits@lists.gentoo.org> List-Help: <mailto:gentoo-commits+help@lists.gentoo.org> List-Unsubscribe: <mailto:gentoo-commits+unsubscribe@lists.gentoo.org> List-Subscribe: <mailto:gentoo-commits+subscribe@lists.gentoo.org> List-Id: Gentoo Linux mail <gentoo-commits.gentoo.org> X-BeenThere: gentoo-commits@lists.gentoo.org X-Archives-Salt: 545060c3-3788-4df4-8e48-0f68a907cc98 X-Archives-Hash: ea472c850d05be33524ed4a3617ed0b3 commit: a7c99506d9de81b9a2a7547bd11715073de1ce95 Author: Will Miles <wmiles <AT> sgl <DOT> com> AuthorDate: Thu Aug 24 01:53:16 2017 +0000 Commit: William Hubbs <williamh <AT> gentoo <DOT> org> CommitDate: Thu Nov 30 19:56:54 2017 +0000 URL: https://gitweb.gentoo.org/proj/openrc.git/commit/?id=a7c99506 Fix repeated dependency cache rebuild if clock skewed rc_deptree_update_needed would return early as soon as it found any file newer than the existing dependency cache. Unfortunately, the first file found may not be the newest one there; so the clock skew workaround in rc-misc:_rc_deptree_load would be given a timestamp that was still too old. This fix forces a full scan of all relevant files, so as to ensure that we return a timestamp that will allow the clock skew fix to operate. The runtime cost is no worse than the case where the cache is up to date (ie. we must check every possible file). This fixes #161. src/librc/librc-depend.c | 123 +++++++++++++++++++++++++++-------------------- 1 file changed, 71 insertions(+), 52 deletions(-) diff --git a/src/librc/librc-depend.c b/src/librc/librc-depend.c index 1c993998..37f0b60d 100644 --- a/src/librc/librc-depend.c +++ b/src/librc/librc-depend.c @@ -542,52 +542,41 @@ rc_deptree_order(const RC_DEPTREE *deptree, const char *runlevel, int options) } librc_hidden_def(rc_deptree_order) + +/* Given a time, recurse the target path to find out if there are + any older (or newer) files. If false, sets the time to the + oldest (or newest) found. +*/ static bool -mtime_check(const char *source, const char *target, bool newer, +deep_mtime_check(const char *target, bool newer, time_t *rel, char *file) { struct stat buf; - time_t mtime; bool retval = true; DIR *dp; struct dirent *d; char path[PATH_MAX]; int serrno = errno; - /* We have to exist */ - if (stat(source, &buf) != 0) - return false; - mtime = buf.st_mtime; - /* If target does not exist, return true to mimic shell test */ if (stat(target, &buf) != 0) return true; if (newer) { - if (mtime < buf.st_mtime) { - if (rel == NULL) - return false; + if (*rel < buf.st_mtime) { retval = false; - } - if (rel != NULL) { - if (*rel < buf.st_mtime) { - if (file) - strlcpy(file, target, PATH_MAX); - *rel = buf.st_mtime; - } + + if (file) + strlcpy(file, target, PATH_MAX); + *rel = buf.st_mtime; } } else { - if (mtime > buf.st_mtime) { - if (rel == NULL) - return false; + if (*rel > buf.st_mtime) { retval = false; - } - if (rel != NULL) { - if (*rel > buf.st_mtime) { - if (file) - strlcpy(file, target, PATH_MAX); - *rel = buf.st_mtime; - } + + if (file) + strlcpy(file, target, PATH_MAX); + *rel = buf.st_mtime; } } @@ -602,16 +591,38 @@ mtime_check(const char *source, const char *target, bool newer, if (d->d_name[0] == '.') continue; snprintf(path, sizeof(path), "%s/%s", target, d->d_name); - if (!mtime_check(source, path, newer, rel, file)) { + if (!deep_mtime_check(path, newer, rel, file)) { retval = false; - if (rel == NULL) - break; } } closedir(dp); return retval; } +/* Recursively check if target is older/newer than source. + * If false, return the filename and most different time (if + * the return value arguments are non-null). + */ +static bool +mtime_check(const char *source, const char *target, bool newer, + time_t *rel, char *file) +{ + struct stat buf; + time_t mtime; + bool retval = true; + + /* We have to exist */ + if (stat(source, &buf) != 0) + return false; + mtime = buf.st_mtime; + + retval = deep_mtime_check(target,newer,&mtime,file); + if (rel) { + *rel = mtime; + } + return retval; +} + bool rc_newer_than(const char *source, const char *target, time_t *newest, char *file) @@ -670,6 +681,8 @@ rc_deptree_update_needed(time_t *newest, char *file) RC_STRINGLIST *config; RC_STRING *s; int i; + struct stat buf; + time_t mtime; /* Create base directories if needed */ for (i = 0; depdirs[i]; i++) @@ -677,42 +690,48 @@ rc_deptree_update_needed(time_t *newest, char *file) fprintf(stderr, "mkdir `%s': %s\n", depdirs[i], strerror(errno)); /* Quick test to see if anything we use has changed and we have - * data in our deptree */ - if (!existss(RC_DEPTREE_CACHE)) - return true; - if (!rc_newer_than(RC_DEPTREE_CACHE, RC_INITDIR, newest, file)) - return true; - if (!rc_newer_than(RC_DEPTREE_CACHE, RC_CONFDIR, newest, file)) - return true; + * data in our deptree. */ + + if (stat(RC_DEPTREE_CACHE, &buf) == 0) { + mtime = buf.st_mtime; + } else { + /* No previous cache found. + * We still run the scan, in case of clock skew; we still need to return + * the newest time. + */ + newer = true; + mtime = time(NULL); + } + + newer |= !deep_mtime_check(RC_INITDIR,true,&mtime,file); + newer |= !deep_mtime_check(RC_CONFDIR,true,&mtime,file); #ifdef RC_PKG_INITDIR - if (!rc_newer_than(RC_DEPTREE_CACHE, RC_PKG_INITDIR, newest, file)) - return true; + newer |= !deep_mtime_check(RC_PKG_INITDIR,true,&mtime,file); #endif #ifdef RC_PKG_CONFDIR - if (!rc_newer_than(RC_DEPTREE_CACHE, RC_PKG_CONFDIR, newest, file)) - return true; + newer |= !deep_mtime_check(RC_PKG_CONFDIR,true,&mtime,file); #endif -#ifdef RC_LOCAL_INITDIR - if (!rc_newer_than(RC_DEPTREE_CACHE, RC_LOCAL_INITDIR, newest, file)) - return true; +#ifdef RC_LOCAL_INITDIRs + newer |= !deep_mtime_check(RC_LOCAL_INITDIR,true,&mtime,file); #endif #ifdef RC_LOCAL_CONFDIR - if (!rc_newer_than(RC_DEPTREE_CACHE, RC_LOCAL_CONFDIR, newest, file)) - return true; + newer |= !deep_mtime_check(RC_LOCAL_CONFDIR,true,&mtime,file); #endif - if (!rc_newer_than(RC_DEPTREE_CACHE, RC_CONF, newest, file)) - return true; + newer |= !deep_mtime_check(RC_CONF,true,&mtime,file); /* 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); TAILQ_FOREACH(s, config, entries) { - if (!rc_newer_than(RC_DEPTREE_CACHE, s->value, newest, file)) { - newer = true; - break; - } + newer |= !deep_mtime_check(s->value, true, &mtime, file); } rc_stringlist_free(config); + + /* Return newest file time, if requested */ + if ((newer) && (newest != NULL)) { + *newest = mtime; + } + return newer; } librc_hidden_def(rc_deptree_update_needed)