support saving both user/group and permissions on symlinks (from PR)

also fix a slight bogon that assumed an fd of 0 was not valid.  Changed
it to be -1.

PR:		bin/25017
Submitted by:	Martin Kammerhofer
This commit is contained in:
John-Mark Gurney 2003-06-22 07:02:17 +00:00
parent 5e4e521f76
commit a6b05ab6ea
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=116673

View File

@ -233,7 +233,7 @@ copy_link(const FTSENT *p, int exists)
warn("symlink: %s", llink);
return (1);
}
return (0);
return (pflag ? setfile(p->fts_statp, -1) : 0);
}
int
@ -247,7 +247,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
@ -261,7 +261,7 @@ 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
@ -269,20 +269,22 @@ setfile(struct stat *fs, int fd)
{
static struct timeval tv[2];
struct stat ts;
int rval;
int gotstat;
int rval, gotstat, islink, fdval;
rval = 0;
fdval = fd != -1;
islink = !fdval && S_ISLNK(fs->st_mode);
fs->st_mode &= S_ISUID | S_ISGID | S_ISVTX |
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);
if (islink ? lutimes(to.p_path, tv) : utimes(to.p_path, tv)) {
warn("%sutimes: %s", islink ? "l" : "", to.p_path);
rval = 1;
}
if (fd ? fstat(fd, &ts) : stat(to.p_path, &ts))
if (fdval ? fstat(fd, &ts) :
(islink ? lstat(to.p_path, &ts) : stat(to.p_path, &ts)))
gotstat = 0;
else {
gotstat = 1;
@ -296,8 +298,9 @@ setfile(struct stat *fs, int fd)
* chown. If chown fails, lose setuid/setgid bits.
*/
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 (fdval ? fchown(fd, fs->st_uid, fs->st_gid) :
(islink ? lchown(to.p_path, 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;
@ -306,14 +309,18 @@ setfile(struct stat *fs, int fd)
}
if (!gotstat || fs->st_mode != ts.st_mode)
if (fd ? fchmod(fd, fs->st_mode) : chmod(to.p_path, fs->st_mode)) {
if (fdval ? fchmod(fd, fs->st_mode) :
(islink ? lchmod(to.p_path, fs->st_mode) :
chmod(to.p_path, fs->st_mode))) {
warn("chmod: %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)) {
if (fdval ?
fchflags(fd, fs->st_flags) :
(islink ? (errno = ENOSYS) :
chflags(to.p_path, fs->st_flags))) {
warn("chflags: %s", to.p_path);
rval = 1;
}