diff options
author | peter <peter@FreeBSD.org> | 1998-06-10 06:29:23 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 1998-06-10 06:29:23 +0000 |
commit | 6aad18db892b090f8c64214c52996be7a9253023 (patch) | |
tree | 37485a164b03bf86c056a732c50e18d2199a3961 /bin | |
parent | 538c54fd9e27ac35ca3365167e7978a19cce6a14 (diff) | |
download | FreeBSD-src-6aad18db892b090f8c64214c52996be7a9253023.zip FreeBSD-src-6aad18db892b090f8c64214c52996be7a9253023.tar.gz |
Don't attempt to change owner/mode/flags that don't need to changed.
This should calm down attempts to `cp -p' to a nfs mount or some other
filesystem that doesn't accept flags or all combinations of flags.
It will warn if it fails to change flags though.
Diffstat (limited to 'bin')
-rw-r--r-- | bin/cp/utils.c | 44 |
1 files changed, 29 insertions, 15 deletions
diff --git a/bin/cp/utils.c b/bin/cp/utils.c index 3ee49f6..7e001b2 100644 --- a/bin/cp/utils.c +++ b/bin/cp/utils.c @@ -36,7 +36,7 @@ static char sccsid[] = "@(#)utils.c 8.3 (Berkeley) 4/1/94"; #endif static const char rcsid[] = - "$Id: utils.c,v 1.18 1998/05/13 07:25:17 charnier Exp $"; + "$Id: utils.c,v 1.19 1998/06/09 03:38:26 imp Exp $"; #endif /* not lint */ #include <sys/param.h> @@ -263,7 +263,9 @@ setfile(fs, fd) int fd; { static struct timeval tv[2]; + struct stat ts; int rval; + int gotstat; rval = 0; fs->st_mode &= S_ISUID | S_ISGID | S_ISVTX | @@ -275,30 +277,42 @@ setfile(fs, fd) warn("utimes: %s", to.p_path); rval = 1; } + if (fd ? fstat(fd, &ts) : stat(to.p_path, &ts)) + gotstat = 0; + else { + gotstat = 1; + ts.st_mode &= S_ISUID | S_ISGID | S_ISVTX | + S_IRWXU | S_IRWXG | S_IRWXO; + } /* * Changing the ownership probably won't succeed, unless we're root * or POSIX_CHOWN_RESTRICTED is not set. Set uid/gid before setting * 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 (errno != EPERM) { + if (!gotstat || fs->st_uid != ts.st_uid || fs->st_gid != ts.st_gid) + if (fd ? fchown(fd, fs->st_uid, fs->st_gid) : + chown(to.p_path, fs->st_uid, fs->st_gid)) { + if (errno != EPERM) { + warn("chown: %s", to.p_path); + rval = 1; + } + fs->st_mode &= ~(S_ISUID | S_ISGID); + } + + if (!gotstat || fs->st_mode != ts.st_mode) + if (fd ? fchmod(fd, fs->st_mode) : chmod(to.p_path, fs->st_mode)) { warn("chown: %s", to.p_path); rval = 1; } - fs->st_mode &= ~(S_ISUID | S_ISGID); - } - if (fd ? fchmod(fd, fs->st_mode) : chmod(to.p_path, fs->st_mode)) { - warn("chown: %s", to.p_path); - rval = 1; - } - if (fd ? - fchflags(fd, fs->st_flags) : chflags(to.p_path, fs->st_flags)) { - warn("chflags: %s", to.p_path); - rval = 1; - } + if (!gotstat || fs->st_flags != ts.st_flags) + if (fd ? + fchflags(fd, fs->st_flags) : chflags(to.p_path, fs->st_flags)) { + warn("chflags: %s", to.p_path); + rval = 1; + } + return (rval); } |