From: Peter Avalos Date: Thu, 12 May 2016 02:31:08 +0000 (-0700) Subject: chmod(1): Bring in some changes from FreeBSD. X-Git-Tag: v4.6.0rc~423 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/c59f969a27b83c1ea2796363efdc54f022df5e5a chmod(1): Bring in some changes from FreeBSD. - Change directory permissions in pre-order. - Allow "-v -v" to mean very verbose. - Follow symbolic links named as command line arguments if run w/o -R. Obtained-from: FreeBSD --- diff --git a/bin/chmod/chmod.1 b/bin/chmod/chmod.1 index c6f98a034b..9e3d9dfaf6 100644 --- a/bin/chmod/chmod.1 +++ b/bin/chmod/chmod.1 @@ -1,3 +1,4 @@ +.\"- .\" Copyright (c) 1989, 1990, 1993, 1994 .\" The Regents of the University of California. All rights reserved. .\" @@ -29,10 +30,9 @@ .\" SUCH DAMAGE. .\" .\" @(#)chmod.1 8.4 (Berkeley) 3/31/94 -.\" $FreeBSD: src/bin/chmod/chmod.1,v 1.17.2.16 2003/02/24 03:01:00 trhodes Exp $ -.\" $DragonFly: src/bin/chmod/chmod.1,v 1.3 2006/02/17 19:33:30 swildner Exp $ +.\" $FreeBSD: head/bin/chmod/chmod.1 282208 2015-04-29 00:49:00Z smh $ .\" -.Dd March 31, 1994 +.Dd May 11, 2016 .Dt CHMOD 1 .Os .Sh NAME @@ -63,9 +63,9 @@ nor modify the exit status to reflect such failures. .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 by -default.) +option is specified, symbolic links on the command line are followed +and hence unaffected by the command. +(Symbolic links encountered during tree traversal are not followed.) .It Fl h If the file is a symbolic link, change the mode of the link itself rather than the file that the link points to. @@ -79,12 +79,20 @@ If the option is specified, no symbolic links are followed. This is the default. .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. +Beware of unintentionally matching the +.Dq Pa ".." +hard link to the parent directory when using wildcards like +.Dq Li ".*" . .It Fl v Cause .Nm to be verbose, showing filenames as the mode is modified. +If the +.Fl v +flag is specified more than once, the old and new modes of the file +will also be printed, in both octal and symbolic notation. .El .Pp The @@ -102,33 +110,6 @@ Only the owner of a file or the super-user is permitted to change the mode of a file. .Sh EXIT STATUS .Ex -std -.Sh EXAMPLES -.Bl -tag -width "u=rwx,go=u-w" -compact -.It Li 644 -make a file readable by anyone and writable by the owner only. -.Pp -.It Li go-w -deny write permission to group and others. -.Pp -.It Li =rw,+X -set the read and write permissions to the usual defaults, but -retain any execute permissions that are currently set. -.Pp -.It Li +X -make a directory or file searchable/executable by everyone if it is -already searchable/executable by anyone. -.Pp -.It Li 755 -.It Li u=rwx,go=rx -.It Li u=rwx,go=u-w -make a file readable/executable by everyone and writable by the owner only. -.Pp -.It Li go= -clear all mode bits for group and others. -.Pp -.It Li g=u-w -set the group bits equal to the user bits, but clear the group write bit. -.El .Sh MODES Modes may be absolute or symbolic. An absolute mode is an octal number constructed from the sum of @@ -251,6 +232,8 @@ If no value is supplied for each permission bit specified in .Ar perm , for which the corresponding bit in the file mode creation mask +(see +.Xr umask 2 ) is clear, is set. Otherwise, the mode bits represented by the specified .Ar who @@ -275,7 +258,9 @@ values are cleared. .It = The mode bits specified by the .Ar who -value are cleared, or, if no who value is specified, the owner, group +value are cleared, or, if no +.Ar who +value is specified, the owner, group and other mode bits are cleared. Then, if no value is supplied for .Ar who , @@ -300,6 +285,37 @@ Operations upon the other permissions only (specified by the symbol ``o'' by itself), in combination with the .Ar perm symbols ``s'' or ``t'', are ignored. +.Pp +The ``w'' permission on directories will permit file creation, relocation, +and copy into that directory. +Files created within the directory itself will inherit its group ID. +.Sh EXAMPLES +.Bl -tag -width "u=rwx,go=u-w" -compact +.It Li 644 +make a file readable by anyone and writable by the owner only. +.Pp +.It Li go-w +deny write permission to group and others. +.Pp +.It Li =rw,+X +set the read and write permissions to the usual defaults, but +retain any execute permissions that are currently set. +.Pp +.It Li +X +make a directory or file searchable/executable by everyone if it is +already searchable/executable by anyone. +.Pp +.It Li 755 +.It Li u=rwx,go=rx +.It Li u=rwx,go=u-w +make a file readable/executable by everyone and writable by the owner only. +.Pp +.It Li go= +clear all mode bits for group and others. +.Pp +.It Li g=u-w +set the group bits equal to the user bits, but clear the group write bit. +.El .Sh COMPATIBILITY The .Fl v @@ -332,6 +348,6 @@ A command appeared in .At v1 . .Sh BUGS -There's no +There is no .Ar perm -option for the naughty bits. +option for the naughty bits of a horse. diff --git a/bin/chmod/chmod.c b/bin/chmod/chmod.c index f0227e7389..8c0dc71f0c 100644 --- a/bin/chmod/chmod.c +++ b/bin/chmod/chmod.c @@ -1,4 +1,4 @@ -/* +/*- * Copyright (c) 1989, 1993, 1994 * The Regents of the University of California. All rights reserved. * @@ -28,15 +28,15 @@ * * @(#) Copyright (c) 1989, 1993, 1994 The Regents of the University of California. All rights reserved. * @(#)chmod.c 8.8 (Berkeley) 4/1/94 - * $FreeBSD: src/bin/chmod/chmod.c,v 1.16.2.6 2002/10/18 01:36:38 trhodes Exp $ - * $DragonFly: src/bin/chmod/chmod.c,v 1.9 2008/09/02 22:13:11 swildner Exp $ + * $FreeBSD: head/bin/chmod/chmod.c 283997 2015-06-04 19:18:58Z pluknet $ */ -#include +#include #include #include #include +#include #include #include #include @@ -44,19 +44,18 @@ #include #include -static void usage (void); +static void usage(void); int -main(int argc, char **argv) +main(int argc, char *argv[]) { FTS *ftsp; FTSENT *p; - mode_t newmode; void *set; int Hflag, Lflag, Rflag, ch, fflag; int fts_options, hflag, rval, vflag; char *mode; - int (*change_mode) (const char *, mode_t); + mode_t newmode; Hflag = Lflag = Rflag = fflag = hflag = vflag = 0; while ((ch = getopt(argc, argv, "HLPRXfghorstuvwx")) != -1) @@ -103,8 +102,9 @@ main(int argc, char **argv) --optind; goto done; case 'v': - vflag = 1; + vflag++; break; + case '?': default: usage(); } @@ -114,24 +114,25 @@ done: argv += optind; if (argc < 2) usage(); - fts_options = FTS_PHYSICAL; if (Rflag) { if (hflag) - errx(1, - "the -R and -h options may not be specified together."); - if (Hflag) - fts_options |= FTS_COMFOLLOW; + errx(1, "the -R and -h options may not be " + "specified together."); 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; } - if (hflag) - change_mode = lchmod; - else - change_mode = chmod; - mode = *argv; errno = 0; if ((set = setmode(mode)) == NULL) { @@ -143,50 +144,62 @@ done: argv += optind; } if ((ftsp = fts_open(++argv, fts_options, 0)) == NULL) - err(1, NULL); + err(1, "fts_open"); 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. */ + case FTS_D: if (!Rflag) fts_set(ftsp, p, FTS_SKIP); - continue; - case FTS_DNR: /* Warn, chmod, continue. */ + break; + case FTS_DNR: /* Warn, chmod. */ warnx("%s: %s", p->fts_path, strerror(p->fts_errno)); rval = 1; break; + case FTS_DP: /* Already changed at FTS_D. */ + continue; case FTS_ERR: /* Warn, continue. */ case FTS_NS: warnx("%s: %s", p->fts_path, strerror(p->fts_errno)); rval = 1; 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; - /* else */ - /* FALLTHROUGH */ default: break; } newmode = getmode(set, p->fts_statp->st_mode); if ((newmode & ALLPERMS) == (p->fts_statp->st_mode & ALLPERMS)) continue; - if ((*change_mode)(p->fts_accpath, newmode) && !fflag) { + if (fchmodat(AT_FDCWD, p->fts_accpath, newmode, atflag) == -1 + && !fflag) { warn("%s", p->fts_path); rval = 1; - } else { - if (vflag) - printf("%s\n", p->fts_accpath); + } else if (vflag) { + printf("%s", p->fts_path); + + if (vflag > 1) { + char m1[12], m2[12]; + + strmode(p->fts_statp->st_mode, m1); + strmode((p->fts_statp->st_mode & + S_IFMT) | newmode, m2); + printf(": 0%o [%s] -> 0%o [%s]", + p->fts_statp->st_mode, m1, + (p->fts_statp->st_mode & S_IFMT) | + newmode, m2); + } + printf("\n"); } } if (errno) err(1, "fts_read"); - free(set); exit(rval); }