diff options
author | smh <smh@FreeBSD.org> | 2015-06-01 09:04:57 +0000 |
---|---|---|
committer | smh <smh@FreeBSD.org> | 2015-06-01 09:04:57 +0000 |
commit | 32367258066d8eaccf6cc78014ae74b397db7e4b (patch) | |
tree | 98f751cb965bcce0515d566fa6ed7a433f62a1b8 /usr.sbin/chown | |
parent | 082794a940f23e7eb4f7f03d5fbe9ba4fdd1fe60 (diff) | |
download | FreeBSD-src-32367258066d8eaccf6cc78014ae74b397db7e4b.zip FreeBSD-src-32367258066d8eaccf6cc78014ae74b397db7e4b.tar.gz |
MFC r282208:
Standardise chmod, chflags, chown and chgrp recursive symlink processing
Relnotes: Yes
Sponsored by: Multiplay
Diffstat (limited to 'usr.sbin/chown')
-rw-r--r-- | usr.sbin/chown/chgrp.1 | 15 | ||||
-rw-r--r-- | usr.sbin/chown/chown.8 | 11 | ||||
-rw-r--r-- | usr.sbin/chown/chown.c | 106 |
3 files changed, 70 insertions, 62 deletions
diff --git a/usr.sbin/chown/chgrp.1 b/usr.sbin/chown/chgrp.1 index 8a4c271..6fb0a31 100644 --- a/usr.sbin/chown/chgrp.1 +++ b/usr.sbin/chown/chgrp.1 @@ -31,7 +31,7 @@ .\" @(#)chgrp.1 8.3 (Berkeley) 3/31/94 .\" $FreeBSD$ .\" -.Dd February 21, 2010 +.Dd April 20, 2015 .Dt CHGRP 1 .Os .Sh NAME @@ -60,8 +60,9 @@ The following options are available: .It Fl H If the .Fl R -option is specified, symbolic links on the command line are followed. -(Symbolic links encountered in the tree traversal are not followed.) +option is specified, symbolic links on the command line are followed +and hence unaffected by the command. +(Symbolic links encountered during traversal are not followed.) .It Fl L If the .Fl R @@ -72,8 +73,12 @@ If the option is specified, no symbolic links are followed. This is the default. .It Fl R -Change the group ID for the file hierarchies rooted -in the files instead of just the files themselves. +Change the group ID of the file hierarchies rooted in the files, +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 The force option ignores errors, except for usage errors and does not query about strange modes (unless the user does not have proper permissions). diff --git a/usr.sbin/chown/chown.8 b/usr.sbin/chown/chown.8 index b5882a3..6b82728 100644 --- a/usr.sbin/chown/chown.8 +++ b/usr.sbin/chown/chown.8 @@ -28,7 +28,7 @@ .\" @(#)chown.8 8.3 (Berkeley) 3/31/94 .\" $FreeBSD$ .\" -.Dd February 21, 2010 +.Dd April 20, 2015 .Dt CHOWN 8 .Os .Sh NAME @@ -64,8 +64,9 @@ The options are as follows: .It Fl H If the .Fl R -option is specified, symbolic links on the command line are followed. -(Symbolic links encountered in the tree traversal are not followed.) +option is specified, symbolic links on the command line are followed +and hence unaffected by the command. +(Symbolic links encountered during traversal are not followed.) .It Fl L If the .Fl R @@ -76,8 +77,8 @@ If the option is specified, no symbolic links are followed. This is the default. .It Fl R -Change the user ID and/or the group ID of the specified directory trees -(recursively, including their contents) and files. +Change the user ID and/or the group ID of the file hierarchies rooted +in the files, instead of just the files themselves. Beware of unintentionally matching the .Dq Pa ".." hard link to the parent directory when using wildcards like diff --git a/usr.sbin/chown/chown.c b/usr.sbin/chown/chown.c index 9780f02..457068a 100644 --- a/usr.sbin/chown/chown.c +++ b/usr.sbin/chown/chown.c @@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$"); #include <err.h> #include <errno.h> +#include <fcntl.h> #include <fts.h> #include <grp.h> #include <libgen.h> @@ -119,18 +120,24 @@ main(int argc, char **argv) usage(); if (Rflag) { - fts_options = FTS_PHYSICAL; if (hflag && (Hflag || Lflag)) errx(1, "the -R%c and -h options may not be " "specified together", Hflag ? 'H' : 'L'); - if (Hflag) - fts_options |= FTS_COMFOLLOW; - else if (Lflag) { - fts_options &= ~FTS_PHYSICAL; - fts_options |= FTS_LOGICAL; + if (Lflag) { + fts_options = FTS_LOGICAL; + } else { + fts_options = FTS_PHYSICAL; + + if (Hflag) { + fts_options |= FTS_COMFOLLOW; + } } - } else - fts_options = hflag ? FTS_PHYSICAL : FTS_LOGICAL; + } else if (hflag) { + fts_options = FTS_PHYSICAL; + } else { + fts_options = FTS_LOGICAL; + } + if (xflag) fts_options |= FTS_XDEV; @@ -156,6 +163,15 @@ main(int argc, char **argv) err(1, 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) { case FTS_D: /* Change it at FTS_DP. */ if (!Rflag) @@ -170,58 +186,44 @@ main(int argc, char **argv) warnx("%s: %s", p->fts_path, strerror(p->fts_errno)); rval = 1; 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: break; } if ((uid == (uid_t)-1 || uid == p->fts_statp->st_uid) && (gid == (gid_t)-1 || gid == p->fts_statp->st_gid)) continue; - if ((hflag ? lchown : chown)(p->fts_accpath, uid, gid) == -1) { - if (!fflag) { - chownerr(p->fts_path); - rval = 1; - } - } else { - if (vflag) { - printf("%s", p->fts_path); - if (vflag > 1) { - if (ischown) { - printf(": %ju:%ju -> %ju:%ju", - (uintmax_t) - p->fts_statp->st_uid, - (uintmax_t) - p->fts_statp->st_gid, - (uid == (uid_t)-1) ? - (uintmax_t) - p->fts_statp->st_uid : - (uintmax_t)uid, - (gid == (gid_t)-1) ? - (uintmax_t) - p->fts_statp->st_gid : - (uintmax_t)gid); - } else { - printf(": %ju -> %ju", - (uintmax_t) - p->fts_statp->st_gid, - (gid == (gid_t)-1) ? - (uintmax_t) - p->fts_statp->st_gid : - (uintmax_t)gid); - } + if (fchownat(AT_FDCWD, p->fts_accpath, uid, gid, atflag) + == -1 && !fflag) { + chownerr(p->fts_path); + rval = 1; + } else if (vflag) { + printf("%s", p->fts_path); + if (vflag > 1) { + if (ischown) { + printf(": %ju:%ju -> %ju:%ju", + (uintmax_t) + p->fts_statp->st_uid, + (uintmax_t) + p->fts_statp->st_gid, + (uid == (uid_t)-1) ? + (uintmax_t) + p->fts_statp->st_uid : + (uintmax_t)uid, + (gid == (gid_t)-1) ? + (uintmax_t) + p->fts_statp->st_gid : + (uintmax_t)gid); + } else { + printf(": %ju -> %ju", + (uintmax_t) + p->fts_statp->st_gid, + (gid == (gid_t)-1) ? + (uintmax_t) + p->fts_statp->st_gid : + (uintmax_t)gid); } - printf("\n"); } + printf("\n"); } } if (errno) |