Standardise chmod, chflags, chown and chgrp recursive symlink processing
chmod, chflags, chgrp, chmod and chown now affect symlinks in -R mode as defined in symlink(7); previously symlinks were silently ignored. Differential Revision: https://reviews.freebsd.org/D2316 Reviewed by: jilles MFC after: 1 month Relnotes: yes Sponsored by: Multiplay
This commit is contained in:
parent
0991d74d31
commit
091e83ecee
4
UPDATING
4
UPDATING
@ -31,6 +31,10 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 11.x IS SLOW:
|
|||||||
disable the most expensive debugging functionality run
|
disable the most expensive debugging functionality run
|
||||||
"ln -s 'abort:false,junk:false' /etc/malloc.conf".)
|
"ln -s 'abort:false,junk:false' /etc/malloc.conf".)
|
||||||
|
|
||||||
|
20150523:
|
||||||
|
chmod, chflags, chown and chgrp now affect symlinks in -R mode as
|
||||||
|
defined in symlink(7); previously symlinks were silently ignored.
|
||||||
|
|
||||||
20150415:
|
20150415:
|
||||||
The const qualifier has been removed from iconv(3) to comply with
|
The const qualifier has been removed from iconv(3) to comply with
|
||||||
POSIX. The ports tree is aware of this from r384038 onwards.
|
POSIX. The ports tree is aware of this from r384038 onwards.
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
.\" @(#)chflags.1 8.4 (Berkeley) 5/2/95
|
.\" @(#)chflags.1 8.4 (Berkeley) 5/2/95
|
||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd April 8, 2013
|
.Dd April 20, 2015
|
||||||
.Dt CHFLAGS 1
|
.Dt CHFLAGS 1
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -66,8 +66,9 @@ nor modify the exit status to reflect such failures.
|
|||||||
.It Fl H
|
.It Fl H
|
||||||
If the
|
If the
|
||||||
.Fl R
|
.Fl R
|
||||||
option is specified, symbolic links on the command line are followed.
|
option is specified, symbolic links on the command line are followed
|
||||||
(Symbolic links encountered in the tree traversal are not followed.)
|
and hence unaffected by the command.
|
||||||
|
(Symbolic links encountered during traversal are not followed.)
|
||||||
.It Fl h
|
.It Fl h
|
||||||
If the
|
If the
|
||||||
.Ar file
|
.Ar file
|
||||||
@ -83,8 +84,12 @@ If the
|
|||||||
option is specified, no symbolic links are followed.
|
option is specified, no symbolic links are followed.
|
||||||
This is the default.
|
This is the default.
|
||||||
.It Fl R
|
.It Fl R
|
||||||
Change the file flags for the file hierarchies rooted
|
Change the file flags of the file hierarchies rooted in the files,
|
||||||
in the files instead of just the files themselves.
|
instead of just the files themselves.
|
||||||
|
Beware of unintentionally matching the
|
||||||
|
.Dq Pa ".."
|
||||||
|
hard link to the parent directory when using wildcards like
|
||||||
|
.Dq Li ".*" .
|
||||||
.It Fl v
|
.It Fl v
|
||||||
Cause
|
Cause
|
||||||
.Nm
|
.Nm
|
||||||
|
@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
|
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <fts.h>
|
#include <fts.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -65,7 +66,6 @@ main(int argc, char *argv[])
|
|||||||
int Hflag, Lflag, Rflag, fflag, hflag, vflag;
|
int Hflag, Lflag, Rflag, fflag, hflag, vflag;
|
||||||
int ch, fts_options, oct, rval;
|
int ch, fts_options, oct, rval;
|
||||||
char *flags, *ep;
|
char *flags, *ep;
|
||||||
int (*change_flags)(const char *, unsigned long);
|
|
||||||
|
|
||||||
Hflag = Lflag = Rflag = fflag = hflag = vflag = 0;
|
Hflag = Lflag = Rflag = fflag = hflag = vflag = 0;
|
||||||
while ((ch = getopt(argc, argv, "HLPRfhv")) != -1)
|
while ((ch = getopt(argc, argv, "HLPRfhv")) != -1)
|
||||||
@ -104,20 +104,23 @@ main(int argc, char *argv[])
|
|||||||
usage();
|
usage();
|
||||||
|
|
||||||
if (Rflag) {
|
if (Rflag) {
|
||||||
fts_options = FTS_PHYSICAL;
|
|
||||||
if (hflag)
|
if (hflag)
|
||||||
errx(1, "the -R and -h options "
|
errx(1, "the -R and -h options may not be "
|
||||||
"may not be specified together");
|
"specified together.");
|
||||||
if (Hflag)
|
|
||||||
fts_options |= FTS_COMFOLLOW;
|
|
||||||
if (Lflag) {
|
if (Lflag) {
|
||||||
fts_options &= ~FTS_PHYSICAL;
|
fts_options = FTS_LOGICAL;
|
||||||
fts_options |= FTS_LOGICAL;
|
} else {
|
||||||
}
|
fts_options = FTS_PHYSICAL;
|
||||||
} else
|
|
||||||
fts_options = hflag ? FTS_PHYSICAL : FTS_LOGICAL;
|
|
||||||
|
|
||||||
change_flags = hflag ? lchflags : chflags;
|
if (Hflag) {
|
||||||
|
fts_options |= FTS_COMFOLLOW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (hflag) {
|
||||||
|
fts_options = FTS_PHYSICAL;
|
||||||
|
} else {
|
||||||
|
fts_options = FTS_LOGICAL;
|
||||||
|
}
|
||||||
|
|
||||||
flags = *argv;
|
flags = *argv;
|
||||||
if (*flags >= '0' && *flags <= '7') {
|
if (*flags >= '0' && *flags <= '7') {
|
||||||
@ -142,12 +145,21 @@ main(int argc, char *argv[])
|
|||||||
err(1, NULL);
|
err(1, NULL);
|
||||||
|
|
||||||
for (rval = 0; (p = fts_read(ftsp)) != NULL;) {
|
for (rval = 0; (p = fts_read(ftsp)) != NULL;) {
|
||||||
|
int atflag;
|
||||||
|
|
||||||
|
if ((fts_options & FTS_LOGICAL) ||
|
||||||
|
((fts_options & FTS_COMFOLLOW) &&
|
||||||
|
p->fts_level == FTS_ROOTLEVEL))
|
||||||
|
atflag = 0;
|
||||||
|
else
|
||||||
|
atflag = AT_SYMLINK_NOFOLLOW;
|
||||||
|
|
||||||
switch (p->fts_info) {
|
switch (p->fts_info) {
|
||||||
case FTS_D: /* Change it at FTS_DP if we're recursive. */
|
case FTS_D: /* Change it at FTS_DP if we're recursive. */
|
||||||
if (!Rflag)
|
if (!Rflag)
|
||||||
fts_set(ftsp, p, FTS_SKIP);
|
fts_set(ftsp, p, FTS_SKIP);
|
||||||
continue;
|
continue;
|
||||||
case FTS_DNR: /* Warn, chflag, continue. */
|
case FTS_DNR: /* Warn, chflags. */
|
||||||
warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
|
warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
|
||||||
rval = 1;
|
rval = 1;
|
||||||
break;
|
break;
|
||||||
@ -156,16 +168,6 @@ main(int argc, char *argv[])
|
|||||||
warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
|
warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
|
||||||
rval = 1;
|
rval = 1;
|
||||||
continue;
|
continue;
|
||||||
case FTS_SL: /* Ignore. */
|
|
||||||
case FTS_SLNONE:
|
|
||||||
/*
|
|
||||||
* The only symlinks that end up here are ones that
|
|
||||||
* don't point to anything and ones that we found
|
|
||||||
* doing a physical walk.
|
|
||||||
*/
|
|
||||||
if (!hflag)
|
|
||||||
continue;
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -175,7 +177,8 @@ main(int argc, char *argv[])
|
|||||||
newflags = (p->fts_statp->st_flags | set) & clear;
|
newflags = (p->fts_statp->st_flags | set) & clear;
|
||||||
if (newflags == p->fts_statp->st_flags)
|
if (newflags == p->fts_statp->st_flags)
|
||||||
continue;
|
continue;
|
||||||
if ((*change_flags)(p->fts_accpath, newflags) && !fflag) {
|
if (chflagsat(AT_FDCWD, p->fts_accpath, newflags,
|
||||||
|
atflag) == -1 && !fflag) {
|
||||||
warn("%s", p->fts_path);
|
warn("%s", p->fts_path);
|
||||||
rval = 1;
|
rval = 1;
|
||||||
} else if (vflag) {
|
} else if (vflag) {
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
.\" @(#)chmod.1 8.4 (Berkeley) 3/31/94
|
.\" @(#)chmod.1 8.4 (Berkeley) 3/31/94
|
||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd January 26, 2009
|
.Dd April 20, 2015
|
||||||
.Dt CHMOD 1
|
.Dt CHMOD 1
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -63,9 +63,9 @@ nor modify the exit status to reflect such failures.
|
|||||||
.It Fl H
|
.It Fl H
|
||||||
If the
|
If the
|
||||||
.Fl R
|
.Fl R
|
||||||
option is specified, symbolic links on the command line are followed.
|
option is specified, symbolic links on the command line are followed
|
||||||
(Symbolic links encountered in the tree traversal are not followed by
|
and hence unaffected by the command.
|
||||||
default.)
|
(Symbolic links encountered during tree traversal are not followed.)
|
||||||
.It Fl h
|
.It Fl h
|
||||||
If the file is a symbolic link, change the mode of the link itself
|
If the file is a symbolic link, change the mode of the link itself
|
||||||
rather than the file that the link points to.
|
rather than the file that the link points to.
|
||||||
@ -79,8 +79,12 @@ If the
|
|||||||
option is specified, no symbolic links are followed.
|
option is specified, no symbolic links are followed.
|
||||||
This is the default.
|
This is the default.
|
||||||
.It Fl R
|
.It Fl R
|
||||||
Change the modes of the file hierarchies rooted in the files
|
Change the modes of the file hierarchies rooted in the files,
|
||||||
instead of just the files themselves.
|
instead of just the files themselves.
|
||||||
|
Beware of unintentionally matching the
|
||||||
|
.Dq Pa ".."
|
||||||
|
hard link to the parent directory when using wildcards like
|
||||||
|
.Dq Li ".*" .
|
||||||
.It Fl v
|
.It Fl v
|
||||||
Cause
|
Cause
|
||||||
.Nm
|
.Nm
|
||||||
|
@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
|
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <fts.h>
|
#include <fts.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -62,7 +63,7 @@ main(int argc, char *argv[])
|
|||||||
FTS *ftsp;
|
FTS *ftsp;
|
||||||
FTSENT *p;
|
FTSENT *p;
|
||||||
mode_t *set;
|
mode_t *set;
|
||||||
int Hflag, Lflag, Rflag, ch, error, fflag, fts_options, hflag, rval;
|
int Hflag, Lflag, Rflag, ch, fflag, fts_options, hflag, rval;
|
||||||
int vflag;
|
int vflag;
|
||||||
char *mode;
|
char *mode;
|
||||||
mode_t newmode;
|
mode_t newmode;
|
||||||
@ -126,18 +127,23 @@ done: argv += optind;
|
|||||||
usage();
|
usage();
|
||||||
|
|
||||||
if (Rflag) {
|
if (Rflag) {
|
||||||
fts_options = FTS_PHYSICAL;
|
|
||||||
if (hflag)
|
if (hflag)
|
||||||
errx(1,
|
errx(1, "the -R and -h options may not be "
|
||||||
"the -R and -h options may not be specified together.");
|
"specified together.");
|
||||||
if (Hflag)
|
|
||||||
fts_options |= FTS_COMFOLLOW;
|
|
||||||
if (Lflag) {
|
if (Lflag) {
|
||||||
fts_options &= ~FTS_PHYSICAL;
|
fts_options = FTS_LOGICAL;
|
||||||
fts_options |= FTS_LOGICAL;
|
} else {
|
||||||
|
fts_options = FTS_PHYSICAL;
|
||||||
|
|
||||||
|
if (Hflag) {
|
||||||
|
fts_options |= FTS_COMFOLLOW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (hflag) {
|
||||||
|
fts_options = FTS_PHYSICAL;
|
||||||
|
} else {
|
||||||
|
fts_options = FTS_LOGICAL;
|
||||||
}
|
}
|
||||||
} else
|
|
||||||
fts_options = hflag ? FTS_PHYSICAL : FTS_LOGICAL;
|
|
||||||
|
|
||||||
mode = *argv;
|
mode = *argv;
|
||||||
if ((set = setmode(mode)) == NULL)
|
if ((set = setmode(mode)) == NULL)
|
||||||
@ -146,12 +152,21 @@ done: argv += optind;
|
|||||||
if ((ftsp = fts_open(++argv, fts_options, 0)) == NULL)
|
if ((ftsp = fts_open(++argv, fts_options, 0)) == NULL)
|
||||||
err(1, "fts_open");
|
err(1, "fts_open");
|
||||||
for (rval = 0; (p = fts_read(ftsp)) != NULL;) {
|
for (rval = 0; (p = fts_read(ftsp)) != NULL;) {
|
||||||
|
int atflag;
|
||||||
|
|
||||||
|
if ((fts_options & FTS_LOGICAL) ||
|
||||||
|
((fts_options & FTS_COMFOLLOW) &&
|
||||||
|
p->fts_level == FTS_ROOTLEVEL))
|
||||||
|
atflag = 0;
|
||||||
|
else
|
||||||
|
atflag = AT_SYMLINK_NOFOLLOW;
|
||||||
|
|
||||||
switch (p->fts_info) {
|
switch (p->fts_info) {
|
||||||
case FTS_D: /* Change it at FTS_DP. */
|
case FTS_D: /* Change it at FTS_DP. */
|
||||||
if (!Rflag)
|
if (!Rflag)
|
||||||
fts_set(ftsp, p, FTS_SKIP);
|
fts_set(ftsp, p, FTS_SKIP);
|
||||||
continue;
|
continue;
|
||||||
case FTS_DNR: /* Warn, chmod, continue. */
|
case FTS_DNR: /* Warn, chmod. */
|
||||||
warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
|
warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
|
||||||
rval = 1;
|
rval = 1;
|
||||||
break;
|
break;
|
||||||
@ -160,16 +175,6 @@ done: argv += optind;
|
|||||||
warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
|
warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
|
||||||
rval = 1;
|
rval = 1;
|
||||||
continue;
|
continue;
|
||||||
case FTS_SL: /* Ignore. */
|
|
||||||
case FTS_SLNONE:
|
|
||||||
/*
|
|
||||||
* The only symlinks that end up here are ones that
|
|
||||||
* don't point to anything and ones that we found
|
|
||||||
* doing a physical walk.
|
|
||||||
*/
|
|
||||||
if (!hflag)
|
|
||||||
continue;
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -182,17 +187,11 @@ done: argv += optind;
|
|||||||
if (may_have_nfs4acl(p, hflag) == 0 &&
|
if (may_have_nfs4acl(p, hflag) == 0 &&
|
||||||
(newmode & ALLPERMS) == (p->fts_statp->st_mode & ALLPERMS))
|
(newmode & ALLPERMS) == (p->fts_statp->st_mode & ALLPERMS))
|
||||||
continue;
|
continue;
|
||||||
if (hflag)
|
if (fchmodat(AT_FDCWD, p->fts_accpath, newmode, atflag) == -1
|
||||||
error = lchmod(p->fts_accpath, newmode);
|
&& !fflag) {
|
||||||
else
|
|
||||||
error = chmod(p->fts_accpath, newmode);
|
|
||||||
if (error) {
|
|
||||||
if (!fflag) {
|
|
||||||
warn("%s", p->fts_path);
|
warn("%s", p->fts_path);
|
||||||
rval = 1;
|
rval = 1;
|
||||||
}
|
} else if (vflag) {
|
||||||
} else {
|
|
||||||
if (vflag) {
|
|
||||||
(void)printf("%s", p->fts_path);
|
(void)printf("%s", p->fts_path);
|
||||||
|
|
||||||
if (vflag > 1) {
|
if (vflag > 1) {
|
||||||
@ -209,7 +208,6 @@ done: argv += optind;
|
|||||||
(void)printf("\n");
|
(void)printf("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (errno)
|
if (errno)
|
||||||
err(1, "fts_read");
|
err(1, "fts_read");
|
||||||
exit(rval);
|
exit(rval);
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
.\" @(#)chgrp.1 8.3 (Berkeley) 3/31/94
|
.\" @(#)chgrp.1 8.3 (Berkeley) 3/31/94
|
||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd February 21, 2010
|
.Dd April 20, 2015
|
||||||
.Dt CHGRP 1
|
.Dt CHGRP 1
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -60,8 +60,9 @@ The following options are available:
|
|||||||
.It Fl H
|
.It Fl H
|
||||||
If the
|
If the
|
||||||
.Fl R
|
.Fl R
|
||||||
option is specified, symbolic links on the command line are followed.
|
option is specified, symbolic links on the command line are followed
|
||||||
(Symbolic links encountered in the tree traversal are not followed.)
|
and hence unaffected by the command.
|
||||||
|
(Symbolic links encountered during traversal are not followed.)
|
||||||
.It Fl L
|
.It Fl L
|
||||||
If the
|
If the
|
||||||
.Fl R
|
.Fl R
|
||||||
@ -72,8 +73,12 @@ If the
|
|||||||
option is specified, no symbolic links are followed.
|
option is specified, no symbolic links are followed.
|
||||||
This is the default.
|
This is the default.
|
||||||
.It Fl R
|
.It Fl R
|
||||||
Change the group ID for the file hierarchies rooted
|
Change the group ID of the file hierarchies rooted in the files,
|
||||||
in the files instead of just the files themselves.
|
instead of just the files themselves.
|
||||||
|
Beware of unintentionally matching the
|
||||||
|
.Dq Pa ".."
|
||||||
|
hard link to the parent directory when using wildcards like
|
||||||
|
.Dq Li ".*" .
|
||||||
.It Fl f
|
.It Fl f
|
||||||
The force option ignores errors, except for usage errors and does not
|
The force option ignores errors, except for usage errors and does not
|
||||||
query about strange modes (unless the user does not have proper permissions).
|
query about strange modes (unless the user does not have proper permissions).
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
.\" @(#)chown.8 8.3 (Berkeley) 3/31/94
|
.\" @(#)chown.8 8.3 (Berkeley) 3/31/94
|
||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd February 21, 2010
|
.Dd April 20, 2015
|
||||||
.Dt CHOWN 8
|
.Dt CHOWN 8
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -64,8 +64,9 @@ The options are as follows:
|
|||||||
.It Fl H
|
.It Fl H
|
||||||
If the
|
If the
|
||||||
.Fl R
|
.Fl R
|
||||||
option is specified, symbolic links on the command line are followed.
|
option is specified, symbolic links on the command line are followed
|
||||||
(Symbolic links encountered in the tree traversal are not followed.)
|
and hence unaffected by the command.
|
||||||
|
(Symbolic links encountered during traversal are not followed.)
|
||||||
.It Fl L
|
.It Fl L
|
||||||
If the
|
If the
|
||||||
.Fl R
|
.Fl R
|
||||||
@ -76,8 +77,8 @@ If the
|
|||||||
option is specified, no symbolic links are followed.
|
option is specified, no symbolic links are followed.
|
||||||
This is the default.
|
This is the default.
|
||||||
.It Fl R
|
.It Fl R
|
||||||
Change the user ID and/or the group ID of the specified directory trees
|
Change the user ID and/or the group ID of the file hierarchies rooted
|
||||||
(recursively, including their contents) and files.
|
in the files, instead of just the files themselves.
|
||||||
Beware of unintentionally matching the
|
Beware of unintentionally matching the
|
||||||
.Dq Pa ".."
|
.Dq Pa ".."
|
||||||
hard link to the parent directory when using wildcards like
|
hard link to the parent directory when using wildcards like
|
||||||
|
@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
|
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <fts.h>
|
#include <fts.h>
|
||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
@ -119,18 +120,24 @@ main(int argc, char **argv)
|
|||||||
usage();
|
usage();
|
||||||
|
|
||||||
if (Rflag) {
|
if (Rflag) {
|
||||||
fts_options = FTS_PHYSICAL;
|
|
||||||
if (hflag && (Hflag || Lflag))
|
if (hflag && (Hflag || Lflag))
|
||||||
errx(1, "the -R%c and -h options may not be "
|
errx(1, "the -R%c and -h options may not be "
|
||||||
"specified together", Hflag ? 'H' : 'L');
|
"specified together", Hflag ? 'H' : 'L');
|
||||||
if (Hflag)
|
if (Lflag) {
|
||||||
|
fts_options = FTS_LOGICAL;
|
||||||
|
} else {
|
||||||
|
fts_options = FTS_PHYSICAL;
|
||||||
|
|
||||||
|
if (Hflag) {
|
||||||
fts_options |= FTS_COMFOLLOW;
|
fts_options |= FTS_COMFOLLOW;
|
||||||
else if (Lflag) {
|
|
||||||
fts_options &= ~FTS_PHYSICAL;
|
|
||||||
fts_options |= FTS_LOGICAL;
|
|
||||||
}
|
}
|
||||||
} else
|
}
|
||||||
fts_options = hflag ? FTS_PHYSICAL : FTS_LOGICAL;
|
} else if (hflag) {
|
||||||
|
fts_options = FTS_PHYSICAL;
|
||||||
|
} else {
|
||||||
|
fts_options = FTS_LOGICAL;
|
||||||
|
}
|
||||||
|
|
||||||
if (xflag)
|
if (xflag)
|
||||||
fts_options |= FTS_XDEV;
|
fts_options |= FTS_XDEV;
|
||||||
|
|
||||||
@ -156,6 +163,15 @@ main(int argc, char **argv)
|
|||||||
err(1, NULL);
|
err(1, NULL);
|
||||||
|
|
||||||
for (rval = 0; (p = fts_read(ftsp)) != NULL;) {
|
for (rval = 0; (p = fts_read(ftsp)) != NULL;) {
|
||||||
|
int atflag;
|
||||||
|
|
||||||
|
if ((fts_options & FTS_LOGICAL) ||
|
||||||
|
((fts_options & FTS_COMFOLLOW) &&
|
||||||
|
p->fts_level == FTS_ROOTLEVEL))
|
||||||
|
atflag = 0;
|
||||||
|
else
|
||||||
|
atflag = AT_SYMLINK_NOFOLLOW;
|
||||||
|
|
||||||
switch (p->fts_info) {
|
switch (p->fts_info) {
|
||||||
case FTS_D: /* Change it at FTS_DP. */
|
case FTS_D: /* Change it at FTS_DP. */
|
||||||
if (!Rflag)
|
if (!Rflag)
|
||||||
@ -170,30 +186,17 @@ main(int argc, char **argv)
|
|||||||
warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
|
warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
|
||||||
rval = 1;
|
rval = 1;
|
||||||
continue;
|
continue;
|
||||||
case FTS_SL:
|
|
||||||
case FTS_SLNONE:
|
|
||||||
/*
|
|
||||||
* The only symlinks that end up here are ones that
|
|
||||||
* don't point to anything and ones that we found
|
|
||||||
* doing a physical walk.
|
|
||||||
*/
|
|
||||||
if (hflag)
|
|
||||||
break;
|
|
||||||
else
|
|
||||||
continue;
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ((uid == (uid_t)-1 || uid == p->fts_statp->st_uid) &&
|
if ((uid == (uid_t)-1 || uid == p->fts_statp->st_uid) &&
|
||||||
(gid == (gid_t)-1 || gid == p->fts_statp->st_gid))
|
(gid == (gid_t)-1 || gid == p->fts_statp->st_gid))
|
||||||
continue;
|
continue;
|
||||||
if ((hflag ? lchown : chown)(p->fts_accpath, uid, gid) == -1) {
|
if (fchownat(AT_FDCWD, p->fts_accpath, uid, gid, atflag)
|
||||||
if (!fflag) {
|
== -1 && !fflag) {
|
||||||
chownerr(p->fts_path);
|
chownerr(p->fts_path);
|
||||||
rval = 1;
|
rval = 1;
|
||||||
}
|
} else if (vflag) {
|
||||||
} else {
|
|
||||||
if (vflag) {
|
|
||||||
printf("%s", p->fts_path);
|
printf("%s", p->fts_path);
|
||||||
if (vflag > 1) {
|
if (vflag > 1) {
|
||||||
if (ischown) {
|
if (ischown) {
|
||||||
@ -223,7 +226,6 @@ main(int argc, char **argv)
|
|||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (errno)
|
if (errno)
|
||||||
err(1, "fts_read");
|
err(1, "fts_read");
|
||||||
exit(rval);
|
exit(rval);
|
||||||
|
Loading…
Reference in New Issue
Block a user