tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

preserving full timestamps



Hi.

As you know, userland tools like cp(1) currently preserve timestamps
only up to microseconds order since there was no system call to set full
timestamps.

Nowadays, we have such system calls.  So, I'd like to change those tools
to set full timestamps unless there is an objection.

In addition, test(1) is already changed to compare full timestamps.  So,
unlike on netbsd-6 or earlier, currently the result of test -ot/nt may
be inconsistent even when timestamps are copied in a same filesystem or
between filesystems of same type.

enami.
? sbin/restore/.gdbinit
Index: bin/cp/utils.c
===================================================================
RCS file: /cvsroot/src/bin/cp/utils.c,v
retrieving revision 1.42
diff -u -r1.42 utils.c
--- bin/cp/utils.c	11 Dec 2013 06:00:11 -0000	1.42
+++ bin/cp/utils.c	27 Nov 2014 00:41:31 -0000
@@ -62,12 +62,12 @@
 int
 set_utimes(const char *file, struct stat *fs)
 {
-    static struct timeval tv[2];
+    struct timespec ts[2];
 
-    TIMESPEC_TO_TIMEVAL(&tv[0], &fs->st_atimespec);
-    TIMESPEC_TO_TIMEVAL(&tv[1], &fs->st_mtimespec);
+    ts[0] = fs->st_atimespec;
+    ts[1] = fs->st_mtimespec;
 
-    if (lutimes(file, tv)) {
+    if (lutimens(file, ts)) {
 	warn("lutimes: %s", file);
 	return (1);
     }
Index: bin/mv/mv.c
===================================================================
RCS file: /cvsroot/src/bin/mv/mv.c,v
retrieving revision 1.43
diff -u -r1.43 mv.c
--- bin/mv/mv.c	29 Aug 2011 14:46:54 -0000	1.43
+++ bin/mv/mv.c	27 Nov 2014 00:41:31 -0000
@@ -255,7 +255,11 @@
 static int
 fastcopy(char *from, char *to, struct stat *sbp)
 {
+#if defined(__NetBSD__)
+	struct timespec ts[2];
+#else
 	struct timeval tval[2];
+#endif
 	static blksize_t blen;
 	static char *bp;
 	int nread, from_fd, to_fd;
@@ -296,8 +300,13 @@
 
 	(void)close(from_fd);
 #ifdef BSD4_4
+#if defined(__NetBSD__)
+	ts[0] = sbp->st_atimespec;
+	ts[1] = sbp->st_mtimespec;
+#else
 	TIMESPEC_TO_TIMEVAL(&tval[0], &sbp->st_atimespec);
 	TIMESPEC_TO_TIMEVAL(&tval[1], &sbp->st_mtimespec);
+#endif
 #else
 	tval[0].tv_sec = sbp->st_atime;
 	tval[1].tv_sec = sbp->st_mtime;
@@ -307,8 +316,12 @@
 #ifdef __SVR4
 	if (utimes(to, tval))
 #else
+#if defined(__NetBSD__)
+	if (futimens(to_fd, ts))
+#else
 	if (futimes(to_fd, tval))
 #endif
+#endif
 		warn("%s: set times", to);
 	if (fchown(to_fd, sbp->st_uid, sbp->st_gid)) {
 		if (errno != EPERM)
Index: sbin/restore/dirs.c
===================================================================
RCS file: /cvsroot/src/sbin/restore/dirs.c,v
retrieving revision 1.50
diff -u -r1.50 dirs.c
--- sbin/restore/dirs.c	9 Jun 2013 17:57:09 -0000	1.50
+++ sbin/restore/dirs.c	27 Nov 2014 00:41:31 -0000
@@ -84,8 +84,8 @@
  */
 struct modeinfo {
 	ino_t ino;
-	struct timeval ctimep[2];
-	struct timeval mtimep[2];
+	struct timespec ctimep[2];
+	struct timespec mtimep[2];
 	mode_t mode;
 	uid_t uid;
 	gid_t gid;
@@ -625,8 +625,8 @@
 		} else {
 			if (!Nflag) {
 				cp = myname(ep);
-				(void) utimes(cp, node.ctimep);
-				(void) utimes(cp, node.mtimep);
+				(void) utimens(cp, node.ctimep);
+				(void) utimens(cp, node.mtimep);
 				(void) chown(cp, node.uid, node.gid);
 				(void) chmod(cp, node.mode);
 				if (Mtreefile) {
@@ -723,13 +723,13 @@
 		return (itp);
 	node.ino = ctxp->ino;
 	node.mtimep[0].tv_sec = ctxp->atime_sec;
-	node.mtimep[0].tv_usec = ctxp->atime_nsec / 1000;
+	node.mtimep[0].tv_nsec = ctxp->atime_nsec;
 	node.mtimep[1].tv_sec = ctxp->mtime_sec;
-	node.mtimep[1].tv_usec = ctxp->mtime_nsec / 1000;
+	node.mtimep[1].tv_nsec = ctxp->mtime_nsec;
 	node.ctimep[0].tv_sec = ctxp->atime_sec;
-	node.ctimep[0].tv_usec = ctxp->atime_nsec / 1000;
+	node.ctimep[0].tv_nsec = ctxp->atime_nsec;
 	node.ctimep[1].tv_sec = ctxp->birthtime_sec;
-	node.ctimep[1].tv_usec = ctxp->birthtime_nsec / 1000;
+	node.ctimep[1].tv_nsec = ctxp->birthtime_nsec;
 	node.mode = ctxp->mode;
 	node.flags = ctxp->file_flags;
 	node.uid = ctxp->uid;
Index: sbin/restore/tape.c
===================================================================
RCS file: /cvsroot/src/sbin/restore/tape.c,v
retrieving revision 1.67
diff -u -r1.67 tape.c
--- sbin/restore/tape.c	22 Jan 2013 09:39:13 -0000	1.67
+++ sbin/restore/tape.c	27 Nov 2014 00:41:31 -0000
@@ -624,24 +624,24 @@
 	uid_t uid;
 	gid_t gid;
 	mode_t mode;
-	struct timeval mtimep[2], ctimep[2];
+	struct timespec mtimep[2], ctimep[2];
 	struct entry *ep;
 	int setbirth;
 
 	curfile.name = name;
 	curfile.action = USING;
 	mtimep[0].tv_sec = curfile.atime_sec;
-	mtimep[0].tv_usec = curfile.atime_nsec / 1000;
+	mtimep[0].tv_nsec = curfile.atime_nsec;
 	mtimep[1].tv_sec = curfile.mtime_sec;
-	mtimep[1].tv_usec = curfile.mtime_nsec / 1000;
+	mtimep[1].tv_nsec = curfile.mtime_nsec;
 
 	setbirth = curfile.birthtime_sec != 0;
 
 	if (setbirth) {
 		ctimep[0].tv_sec = curfile.atime_sec;
-		ctimep[0].tv_usec = curfile.atime_nsec / 1000;
+		ctimep[0].tv_nsec = curfile.atime_nsec;
 		ctimep[1].tv_sec = curfile.birthtime_sec;
-		ctimep[1].tv_usec = curfile.birthtime_nsec / 1000;
+		ctimep[1].tv_nsec = curfile.birthtime_nsec;
 	}
 	uid = curfile.uid;
 	gid = curfile.gid;
@@ -683,8 +683,8 @@
 			(void) unlink(name);
 		if (linkit(lnkbuf, name, SYMLINK) == GOOD) {
 			if (setbirth)
-				(void) lutimes(name, ctimep);
-			(void) lutimes(name, mtimep);
+				(void) lutimens(name, ctimep);
+			(void) lutimens(name, mtimep);
 			(void) lchown(name, uid, gid);
 			(void) lchmod(name, mode);
 			if (Mtreefile) {
@@ -714,8 +714,8 @@
 		}
 		skipfile();
 		if (setbirth)
-			(void) utimes(name, ctimep);
-		(void) utimes(name, mtimep);
+			(void) utimens(name, ctimep);
+		(void) utimens(name, mtimep);
 		(void) chown(name, uid, gid);
 		(void) chmod(name, mode);
 		if (Mtreefile) {
@@ -743,8 +743,8 @@
 		}
 		skipfile();
 		if (setbirth)
-			(void) utimes(name, ctimep);
-		(void) utimes(name, mtimep);
+			(void) utimens(name, ctimep);
+		(void) utimens(name, mtimep);
 		(void) chown(name, uid, gid);
 		(void) chmod(name, mode);
 		if (Mtreefile) {
@@ -779,8 +779,8 @@
 		if (Nflag)
 			return (GOOD);
 		if (setbirth)
-			(void) futimes(ofile, ctimep);
-		(void) futimes(ofile, mtimep);
+			(void) futimens(ofile, ctimep);
+		(void) futimens(ofile, mtimep);
 		(void) fchown(ofile, uid, gid);
 		(void) fchmod(ofile, mode);
 		if (Mtreefile) {
Index: usr.bin/touch/touch.c
===================================================================
RCS file: /cvsroot/src/usr.bin/touch/touch.c,v
retrieving revision 1.32
diff -u -r1.32 touch.c
--- usr.bin/touch/touch.c	22 Oct 2012 21:51:58 -0000	1.32
+++ usr.bin/touch/touch.c	27 Nov 2014 00:41:31 -0000
@@ -59,10 +59,10 @@
 #include <util.h>
 #include <getopt.h>
 
-static void	stime_arg0(char *, struct timeval *);
-static void	stime_arg1(char *, struct timeval *);
-static void	stime_arg2(char *, int, struct timeval *);
-static void	stime_file(char *, struct timeval *);
+static void	stime_arg0(char *, struct timespec *);
+static void	stime_arg1(char *, struct timespec *);
+static void	stime_arg2(char *, int, struct timespec *);
+static void	stime_file(char *, struct timespec *);
 __dead static void	usage(void);
 
 struct option touch_longopts[] = {
@@ -78,17 +78,17 @@
 main(int argc, char *argv[])
 {
 	struct stat sb;
-	struct timeval tv[2];
+	struct timespec ts[2];
 	int aflag, cflag, hflag, mflag, ch, fd, len, rval, timeset;
 	char *p;
-	int (*change_file_times)(const char *, const struct timeval *);
+	int (*change_file_times)(const char *, const struct timespec *);
 	int (*get_file_status)(const char *, struct stat *);
 
 	setlocale(LC_ALL, "");
 
 	aflag = cflag = hflag = mflag = timeset = 0;
-	if (gettimeofday(&tv[0], NULL))
-		err(1, "gettimeofday");
+	if (clock_gettime(CLOCK_REALTIME, &ts[0]))
+		err(1, "clock_gettime");
 
 	while ((ch = getopt_long(argc, argv, "acd:fhmr:t:", touch_longopts,
 	    NULL)) != -1)
@@ -101,7 +101,7 @@
 			break;
 		case 'd':
 			timeset = 1;
-			stime_arg0(optarg, tv);
+			stime_arg0(optarg, ts);
 			break;
 		case 'f':
 			break;
@@ -113,11 +113,11 @@
 			break;
 		case 'r':
 			timeset = 1;
-			stime_file(optarg, tv);
+			stime_file(optarg, ts);
 			break;
 		case 't':
 			timeset = 1;
-			stime_arg1(optarg, tv);
+			stime_arg1(optarg, ts);
 			break;
 		case '?':
 		default:
@@ -132,10 +132,10 @@
 
 	if (hflag) {
 		cflag = 1;		/* Don't create new file */
-		change_file_times = lutimes;
+		change_file_times = lutimens;
 		get_file_status = lstat;
 	} else {
-		change_file_times = utimes;
+		change_file_times = utimens;
 		get_file_status = stat;
 	}
 
@@ -148,13 +148,13 @@
 		len = p - argv[0];
 		if (*p == '\0' && (len == 8 || len == 10)) {
 			timeset = 1;
-			stime_arg2(*argv++, len == 10, tv);
+			stime_arg2(*argv++, len == 10, ts);
 		}
 	}
 
 	/* Otherwise use the current time of day. */
 	if (!timeset)
-		tv[1] = tv[0];
+		ts[1] = ts[0];
 
 	if (*argv == NULL)
 		usage();
@@ -179,12 +179,12 @@
 				continue;
 		}
 		if (!aflag)
-			TIMESPEC_TO_TIMEVAL(&tv[0], &sb.st_atimespec);
+			ts[0] = sb.st_atimespec;
 		if (!mflag)
-			TIMESPEC_TO_TIMEVAL(&tv[1], &sb.st_mtimespec);
+			ts[1] = sb.st_mtimespec;
 
 		/* Try utimes(2). */
-		if (!(*change_file_times)(*argv, tv))
+		if (!(*change_file_times)(*argv, ts))
 			continue;
 
 		/* If the user specified a time, nothing else we can do. */
@@ -211,23 +211,23 @@
 #define	ATOI2(s)	((s) += 2, ((s)[-2] - '0') * 10 + ((s)[-1] - '0'))
 
 static void
-stime_arg0(char *arg, struct timeval *tvp)
+stime_arg0(char *arg, struct timespec *tsp)
 {
-	tvp[1].tv_sec = tvp[0].tv_sec = parsedate(arg, NULL, NULL);
-	if (tvp[0].tv_sec == -1)
+	tsp[1].tv_sec = tsp[0].tv_sec = parsedate(arg, NULL, NULL);
+	if (tsp[0].tv_sec == -1)
 		errx(EXIT_FAILURE, "Could not parse `%s'", arg);
-	tvp[0].tv_usec = tvp[1].tv_usec = 0;
+	tsp[0].tv_nsec = tsp[1].tv_nsec = 0;
 }
 
 static void
-stime_arg1(char *arg, struct timeval *tvp)
+stime_arg1(char *arg, struct timespec *tsp)
 {
 	struct tm *t;
 	time_t tmptime;
 	int yearset;
 	char *p;
 					/* Start with the current time. */
-	tmptime = tvp[0].tv_sec;
+	tmptime = tsp[0].tv_sec;
 	if ((t = localtime(&tmptime)) == NULL)
 		err(EXIT_FAILURE, "localtime");
 					/* [[CC]YY]MMDDhhmm[.SS] */
@@ -275,21 +275,21 @@
 	}
 
 	t->tm_isdst = -1;		/* Figure out DST. */
-	tvp[0].tv_sec = tvp[1].tv_sec = mktime(t);
-	if (tvp[0].tv_sec == -1)
+	tsp[0].tv_sec = tsp[1].tv_sec = mktime(t);
+	if (tsp[0].tv_sec == -1)
 terr:		errx(EXIT_FAILURE,
 	"out of range or illegal time specification: [[CC]YY]MMDDhhmm[.SS]");
 
-	tvp[0].tv_usec = tvp[1].tv_usec = 0;
+	tsp[0].tv_nsec = tsp[1].tv_nsec = 0;
 }
 
 static void
-stime_arg2(char *arg, int year, struct timeval *tvp)
+stime_arg2(char *arg, int year, struct timespec *tsp)
 {
 	struct tm *t;
 	time_t tmptime;
 					/* Start with the current time. */
-	tmptime = tvp[0].tv_sec;
+	tmptime = tsp[0].tv_sec;
 	if ((t = localtime(&tmptime)) == NULL)
 		err(EXIT_FAILURE, "localtime");
 
@@ -308,23 +308,23 @@
 	t->tm_sec = 0;
 
 	t->tm_isdst = -1;		/* Figure out DST. */
-	tvp[0].tv_sec = tvp[1].tv_sec = mktime(t);
-	if (tvp[0].tv_sec == -1)
+	tsp[0].tv_sec = tsp[1].tv_sec = mktime(t);
+	if (tsp[0].tv_sec == -1)
 		errx(EXIT_FAILURE,
 	"out of range or illegal time specification: MMDDhhmm[yy]");
 
-	tvp[0].tv_usec = tvp[1].tv_usec = 0;
+	tsp[0].tv_nsec = tsp[1].tv_nsec = 0;
 }
 
 static void
-stime_file(char *fname, struct timeval *tvp)
+stime_file(char *fname, struct timespec *tsp)
 {
 	struct stat sb;
 
 	if (stat(fname, &sb))
 		err(1, "%s", fname);
-	TIMESPEC_TO_TIMEVAL(&tvp[0], &sb.st_atimespec);
-	TIMESPEC_TO_TIMEVAL(&tvp[1], &sb.st_mtimespec);
+	tsp[0] = sb.st_atimespec;
+	tsp[1] = sb.st_mtimespec;
 }
 
 static void


Home | Main Index | Thread Index | Old Index