Diff below switches restore(8) to using utimensat() instead of utimes() so that file timestamps are restored with full nanosecond precision. Eliminates some pointless divisions...
ok? Index: dirs.c =================================================================== RCS file: /cvs/src/sbin/restore/dirs.c,v retrieving revision 1.40 diff -u -p -r1.40 dirs.c --- dirs.c 20 Jan 2015 18:22:21 -0000 1.40 +++ dirs.c 24 Aug 2015 00:12:48 -0000 @@ -75,8 +75,8 @@ static struct inotab *inotab[HASHSIZE]; */ 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; @@ -618,8 +618,8 @@ setdirmodes(int flags) (void)chown(cp, node.uid, node.gid); (void)chmod(cp, node.mode); (void)chflags(cp, node.flags); - (void)utimes(cp, node.ctimep); - (void)utimes(cp, node.mtimep); + (void)utimensat(AT_FDCWD, cp, node.ctimep, 0); + (void)utimensat(AT_FDCWD, cp, node.mtimep, 0); } ep->e_flags &= ~NEW; } @@ -696,13 +696,13 @@ allocinotab(FILE *mf, struct context *ct 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: tape.c =================================================================== RCS file: /cvs/src/sbin/restore/tape.c,v retrieving revision 1.45 diff -u -p -r1.45 tape.c --- tape.c 16 Jan 2015 06:40:00 -0000 1.45 +++ tape.c 24 Aug 2015 00:12:48 -0000 @@ -505,23 +505,23 @@ extractfile(char *name) 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; @@ -583,8 +583,8 @@ extractfile(char *name) (void)chflags(name, flags); skipfile(); if (setbirth) - (void)utimes(name, ctimep); - (void)utimes(name, mtimep); + (void)utimensat(AT_FDCWD, name, ctimep, 0); + (void)utimensat(AT_FDCWD, name, mtimep, 0); return (GOOD); case IFIFO: @@ -603,8 +603,8 @@ extractfile(char *name) (void)chflags(name, flags); skipfile(); if (setbirth) - (void)utimes(name, ctimep); - (void)utimes(name, mtimep); + (void)utimensat(AT_FDCWD, name, ctimep, 0); + (void)utimensat(AT_FDCWD, name, mtimep, 0); return (GOOD); case IFREG: @@ -625,8 +625,8 @@ extractfile(char *name) getfile(xtrfile, xtrskip); (void)close(ofile); if (setbirth) - (void)utimes(name, ctimep); - (void)utimes(name, mtimep); + (void)utimensat(AT_FDCWD, name, ctimep, 0); + (void)utimensat(AT_FDCWD, name, mtimep, 0); return (GOOD); } /* NOTREACHED */