summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2001-08-19 18:30:39 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2001-08-19 18:30:39 +0000
commitd0eae1b3c9b6b0068e9e2920f5ab4c32f58af829 (patch)
tree8f96f8b466cdb8003f15e18c8b785366bf4bee34
parent71fd3643a55f28fd036318d785605467bc355b1c (diff)
Better file change detection:
o when copying to temp file set utimes on temp file equal to original o use st_mtimespec instead of st_mtime for better granularity
-rw-r--r--usr.sbin/cron/crontab.c26
-rw-r--r--usr.sbin/vipw/vipw.c15
2 files changed, 28 insertions, 13 deletions
diff --git a/usr.sbin/cron/crontab.c b/usr.sbin/cron/crontab.c
index 5fb78c5c75e..fee68e0670a 100644
--- a/usr.sbin/cron/crontab.c
+++ b/usr.sbin/cron/crontab.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: crontab.c,v 1.21 2001/08/11 20:47:14 millert Exp $ */
+/* $OpenBSD: crontab.c,v 1.22 2001/08/19 18:30:38 millert Exp $ */
/* Copyright 1988,1990,1993,1994 by Paul Vixie
* All rights reserved
*/
@@ -21,7 +21,7 @@
*/
#if !defined(lint) && !defined(LINT)
-static char rcsid[] = "$OpenBSD: crontab.c,v 1.21 2001/08/11 20:47:14 millert Exp $";
+static char rcsid[] = "$OpenBSD: crontab.c,v 1.22 2001/08/19 18:30:38 millert Exp $";
#endif
/* crontab - install and manage per-user crontab files
@@ -285,7 +285,8 @@ edit_cmd(void) {
FILE *f;
int ch, t, x;
struct stat statbuf;
- time_t mtime;
+ struct timespec mtimespec;
+ struct timeval tv[2];
off_t size;
WAIT_T waiter;
PID_T pid, xpid;
@@ -308,6 +309,15 @@ edit_cmd(void) {
}
}
+ if (fstat(fileno(f), &statbuf) < 0) {
+ perror("fstat");
+ goto fatal;
+ }
+ size = statbuf.st_size;
+ memcpy(&mtimespec, &statbuf.st_mtimespec, sizeof(mtimespec));
+ TIMESPEC_TO_TIMEVAL(&tv[0], &statbuf.st_atimespec);
+ TIMESPEC_TO_TIMEVAL(&tv[1], &statbuf.st_mtimespec);
+
/* Turn off signals. */
(void)signal(SIGHUP, SIG_IGN);
(void)signal(SIGINT, SIG_IGN);
@@ -367,6 +377,7 @@ edit_cmd(void) {
perror(Filename);
exit(ERROR_EXIT);
}
+ (void)futimes(t, tv);
again:
rewind(NewCrontab);
if (ferror(NewCrontab)) {
@@ -376,12 +387,6 @@ edit_cmd(void) {
unlink(Filename);
exit(ERROR_EXIT);
}
- if (fstat(t, &statbuf) < 0) {
- perror("fstat");
- goto fatal;
- }
- mtime = statbuf.st_mtime;
- size = statbuf.st_size;
if (((editor = getenv("VISUAL")) == NULL || *editor == '\0') &&
((editor = getenv("EDITOR")) == NULL || *editor == '\0')) {
@@ -461,7 +466,8 @@ edit_cmd(void) {
perror("fstat");
goto fatal;
}
- if (mtime == statbuf.st_mtime && size == statbuf.st_size) {
+ if (timespeccmp(&mtimespec, &statbuf.st_mtimespec, -) == 0 &&
+ size == statbuf.st_size) {
fprintf(stderr, "%s: no changes made to crontab\n",
ProgramName);
goto remove;
diff --git a/usr.sbin/vipw/vipw.c b/usr.sbin/vipw/vipw.c
index 6a2d07b228a..9d32fa659dc 100644
--- a/usr.sbin/vipw/vipw.c
+++ b/usr.sbin/vipw/vipw.c
@@ -43,7 +43,7 @@ static char copyright[] =
static char sccsid[] = "@(#)vipw.c 8.3 (Berkeley) 4/2/94";
#endif /* not lint */
-#include <sys/types.h>
+#include <sys/time.h>
#include <sys/stat.h>
#include <err.h>
@@ -96,7 +96,7 @@ main(argc, argv)
pw_edit(0, NULL);
if (stat(_PATH_MASTERPASSWD_LOCK, &end))
pw_error(_PATH_MASTERPASSWD_LOCK, 1, 1);
- if (begin.st_mtime == end.st_mtime &&
+ if (!timespeccmp(&begin.st_mtimespec, &end.st_mtimespec, -) &&
begin.st_size == end.st_size) {
warnx("no changes made");
pw_error((char *)NULL, 0, 0);
@@ -114,19 +114,28 @@ copyfile(from, to)
{
int nr, nw, off;
char buf[8*1024];
+ struct stat sb;
+ struct timeval tv[2];
+ if (fstat(from, &sb) == -1)
+ pw_error(_PATH_MASTERPASSWD, 1, 1);
while ((nr = read(from, buf, sizeof(buf))) > 0)
for (off = 0; off < nr; nr -= nw, off += nw)
if ((nw = write(to, buf + off, nr)) < 0)
pw_error(_PATH_MASTERPASSWD_LOCK, 1, 1);
if (nr < 0)
pw_error(_PATH_MASTERPASSWD, 1, 1);
+
+ TIMESPEC_TO_TIMEVAL(&tv[0], &sb.st_atimespec);
+ TIMESPEC_TO_TIMEVAL(&tv[1], &sb.st_mtimespec);
+ (void) futimes(to, tv);
}
void
usage()
{
+ extern char *__progname;
- (void)fprintf(stderr, "usage: vipw\n");
+ (void)fprintf(stderr, "usage: %s\n", __progname);
exit(1);
}