chmod: Remove -HLP flags, and ignore symlinks during traversal

These flags are non-POSIX and not useful since the mode of symlinks
is not used for anything.

This prevents a failure when a dangling symlink is encountered
during a recursive chmod.
This commit is contained in:
Michael Forney 2019-12-21 21:47:55 -08:00
parent 4fcb31c6e0
commit 3e160b616a
2 changed files with 8 additions and 22 deletions

19
chmod.1
View File

@ -1,4 +1,4 @@
.Dd 2015-10-08
.Dd 2019-12-21
.Dt CHMOD 1
.Os sbase
.Sh NAME
@ -6,10 +6,7 @@
.Nd change file modes
.Sh SYNOPSIS
.Nm
.Oo
.Fl R
.Op Fl H | L | P
.Oc
.Op Fl R
.Ar mode
.Ar file ...
.Sh DESCRIPTION
@ -58,19 +55,13 @@ read | write | execute | setuid and setgid | sticky
.It X
execute, if directory or at least one execute bit is already set
.El
.Pp
Symbolic links are followed if they are passed as operands, and ignored
if they are encountered during directory traversal.
.Sh OPTIONS
.Bl -tag -width Ds
.It Fl R
Change modes recursively.
.It Fl H
Dereference
.Ar file
if it is a symbolic link.
.It Fl L
Dereference all symbolic links.
.It Fl P
Preserve symbolic links.
This is the default.
.El
.Sh SEE ALSO
.Xr chgrp 1 ,

11
chmod.c
View File

@ -14,7 +14,7 @@ chmodr(const char *path, struct stat *st, void *data, struct recursor *r)
mode_t m;
m = parsemode(modestr, st->st_mode, mask);
if (chmod(path, m) < 0) {
if (!S_ISLNK(st->st_mode) && chmod(path, m) < 0) {
weprintf("chmod %s:", path);
ret = 1;
} else if (S_ISDIR(st->st_mode)) {
@ -25,14 +25,14 @@ chmodr(const char *path, struct stat *st, void *data, struct recursor *r)
static void
usage(void)
{
eprintf("usage: %s [-R [-H | -L | -P]] mode file ...\n", argv0);
eprintf("usage: %s [-R] mode file ...\n", argv0);
}
int
main(int argc, char *argv[])
{
struct recursor r = { .fn = chmodr, .hist = NULL, .depth = 0, .maxdepth = 1,
.follow = 'P', .flags = DIRFIRST };
.follow = 'H', .flags = DIRFIRST };
size_t i;
argv0 = *argv, argv0 ? (argc--, argv++) : (void *)0;
@ -45,11 +45,6 @@ main(int argc, char *argv[])
case 'R':
r.maxdepth = 0;
break;
case 'H':
case 'L':
case 'P':
r.follow = (*argv)[i];
break;
case 'r': case 'w': case 'x': case 'X': case 's': case 't':
/* -[rwxXst] are valid modes, so we're done */
if (i == 1)