From af3ab428cf73b6beafa2405dd9229da34eec126b Mon Sep 17 00:00:00 2001 From: guenther Date: Sun, 3 May 2015 19:44:58 +0000 Subject: [PATCH] Preserve times to nanosecond precision instead of just microsecond. Prefer to set attributes by fd for regular files, and not follwing symlinks for others. ok brynet@ millert@ --- bin/cp/utils.c | 27 +++++++++++++++------------ bin/mv/mv.c | 10 +++++----- usr.bin/compress/main.c | 12 ++++++------ 3 files changed, 26 insertions(+), 23 deletions(-) diff --git a/bin/cp/utils.c b/bin/cp/utils.c index da2a27433e9..056a1a7aa21 100644 --- a/bin/cp/utils.c +++ b/bin/cp/utils.c @@ -1,4 +1,4 @@ -/* $OpenBSD: utils.c,v 1.36 2015/01/19 00:41:44 deraadt Exp $ */ +/* $OpenBSD: utils.c,v 1.37 2015/05/03 19:44:58 guenther Exp $ */ /* $NetBSD: utils.c,v 1.6 1997/02/26 14:40:51 cgd Exp $ */ /*- @@ -231,7 +231,7 @@ copy_fifo(struct stat *from_stat, int exists) warn("mkfifo: %s", to.p_path); return (1); } - return (pflag ? setfile(from_stat, 0) : 0); + return (pflag ? setfile(from_stat, -1) : 0); } int @@ -245,23 +245,24 @@ copy_special(struct stat *from_stat, int exists) warn("mknod: %s", to.p_path); return (1); } - return (pflag ? setfile(from_stat, 0) : 0); + return (pflag ? setfile(from_stat, -1) : 0); } int setfile(struct stat *fs, int fd) { - static struct timeval tv[2]; + struct timespec ts[2]; int rval; rval = 0; fs->st_mode &= S_ISTXT | S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO; - TIMESPEC_TO_TIMEVAL(&tv[0], &fs->st_atimespec); - TIMESPEC_TO_TIMEVAL(&tv[1], &fs->st_mtimespec); - if (utimes(to.p_path, tv)) { - warn("utimes: %s", to.p_path); + ts[0] = fs->st_atim; + ts[1] = fs->st_mtim; + if (fd >= 0 ? futimens(fd, ts) : + utimensat(AT_FDCWD, to.p_path, ts, AT_SYMLINK_NOFOLLOW)) { + warn("update times: %s", to.p_path); rval = 1; } /* @@ -270,15 +271,16 @@ setfile(struct stat *fs, int fd) * the mode; current BSD behavior is to remove all setuid bits on * chown. If chown fails, lose setuid/setgid bits. */ - if (fd ? fchown(fd, fs->st_uid, fs->st_gid) : - chown(to.p_path, fs->st_uid, fs->st_gid)) { + if (fd >= 0 ? fchown(fd, fs->st_uid, fs->st_gid) : + lchown(to.p_path, fs->st_uid, fs->st_gid)) { if (errno != EPERM) { warn("chown: %s", to.p_path); rval = 1; } fs->st_mode &= ~(S_ISTXT | S_ISUID | S_ISGID); } - if (fd ? fchmod(fd, fs->st_mode) : chmod(to.p_path, fs->st_mode)) { + if (fd >= 0 ? fchmod(fd, fs->st_mode) : + fchmodat(AT_FDCWD, to.p_path, fs->st_mode, AT_SYMLINK_NOFOLLOW)) { warn("chmod: %s", to.p_path); rval = 1; } @@ -291,7 +293,8 @@ setfile(struct stat *fs, int fd) * on a file that we copied, i.e., that we didn't create.) */ errno = 0; - if (fd ? fchflags(fd, fs->st_flags) : chflags(to.p_path, fs->st_flags)) + if (fd >= 0 ? fchflags(fd, fs->st_flags) : + chflagsat(AT_FDCWD, to.p_path, fs->st_flags, AT_SYMLINK_NOFOLLOW)) if (errno != EOPNOTSUPP || fs->st_flags != 0) { warn("chflags: %s", to.p_path); rval = 1; diff --git a/bin/mv/mv.c b/bin/mv/mv.c index dce0f0e2320..2019a17ddab 100644 --- a/bin/mv/mv.c +++ b/bin/mv/mv.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mv.c,v 1.38 2015/01/16 06:39:32 deraadt Exp $ */ +/* $OpenBSD: mv.c,v 1.39 2015/05/03 19:44:59 guenther Exp $ */ /* $NetBSD: mv.c,v 1.9 1995/03/21 09:06:52 cgd Exp $ */ /* @@ -254,7 +254,7 @@ do_move(char *from, char *to) int fastcopy(char *from, char *to, struct stat *sbp) { - struct timeval tval[2]; + struct timespec ts[2]; static u_int32_t blen; static char *bp; int nread, from_fd, to_fd; @@ -323,9 +323,9 @@ err: if (unlink(to)) if (errno != EOPNOTSUPP || sbp->st_flags != 0) warn("%s: set flags", to); - TIMESPEC_TO_TIMEVAL(&tval[0], &sbp->st_atimespec); - TIMESPEC_TO_TIMEVAL(&tval[1], &sbp->st_mtimespec); - if (utimes(to, tval)) + ts[0] = sbp->st_atim; + ts[1] = sbp->st_mtim; + if (futimens(to_fd, ts)) warn("%s: set times", to); if (close(to_fd)) { diff --git a/usr.bin/compress/main.c b/usr.bin/compress/main.c index c9e302598ff..4d91398b9a3 100644 --- a/usr.bin/compress/main.c +++ b/usr.bin/compress/main.c @@ -1,4 +1,4 @@ -/* $OpenBSD: main.c,v 1.83 2015/01/16 06:40:06 deraadt Exp $ */ +/* $OpenBSD: main.c,v 1.84 2015/05/03 19:44:59 guenther Exp $ */ /* * Copyright (c) 1992, 1993 @@ -750,7 +750,7 @@ dodecompress(const char *in, char *out, const struct compressor *method, void setfile(const char *name, int fd, struct stat *fs) { - struct timeval tv[2]; + struct timespec ts[2]; if (name == NULL || cat || testmode) return; @@ -784,10 +784,10 @@ setfile(const char *name, int fd, struct stat *fs) if (fs->st_flags && fchflags(fd, fs->st_flags)) warn("fchflags: %s", name); - TIMESPEC_TO_TIMEVAL(&tv[0], &fs->st_atimespec); - TIMESPEC_TO_TIMEVAL(&tv[1], &fs->st_mtimespec); - if (futimes(fd, tv)) - warn("futimes: %s", name); + ts[0] = fs->st_atim; + ts[1] = fs->st_mtim; + if (futimens(fd, ts)) + warn("futimens: %s", name); } int -- 2.20.1