Audit chmod(1)

1) Update manpage, refactor the HLP-section and other wordings.
2) BUGFIX: If chmod() fails, don't recurse.
3) Rewrite the arg-loop, fixing several issues:
   BUGFIX: Handle multi-flags (e.g. -RH)
   BUGFIX: Properly handle the termination flag --, error on e.g. --x
   BUGFIX: Error out on an empty flag -.
4) Refactor logic after the arg-loop, which is now simpler thanks
   to argv-incremention.
This commit is contained in:
FRIGN 2015-03-05 19:08:28 +01:00
parent d9fa4b3ae7
commit aea256c288
3 changed files with 47 additions and 34 deletions

2
README
View File

@ -13,7 +13,7 @@ The following tools are implemented ('*' == finished, '#' == UTF-8 support,
=* cal yes none
=*| cat yes none
=* chgrp yes none
=* chmod yes none
=*| chmod yes none
=* chown yes none
=*| chroot non-posix none
=* cksum yes none

19
chmod.1
View File

@ -1,9 +1,9 @@
.Dd January 17, 2015
.Dd March 5, 2015
.Dt CHMOD 1
.Os sbase
.Sh NAME
.Nm chmod
.Nd change file mode
.Nd change file modes
.Sh SYNOPSIS
.Nm
.Oo
@ -14,8 +14,10 @@
.Ar file ...
.Sh DESCRIPTION
.Nm
changes the file mode of the given
.Ar files .
changes the file mode of each
.Ar file
to
.Ar mode .
.Pp
If
.Ar mode
@ -59,12 +61,13 @@ read | write | execute | setuid and setgid | sticky
.It Fl R
Change modes recursively.
.It Fl H
Only dereference symbolic links that are passed as command line arguments when
recursively traversing directories.
Dereference
.Ar file
if it is a symbolic link.
.It Fl L
Always dereference symbolic links while recursively traversing directories.
Dereference all symbolic links.
.It Fl P
Don't dereference symbolic links (default).
Preserve symbolic links. This is the default.
.El
.Sh SEE ALSO
.Xr chgrp 1 ,

60
chmod.c
View File

@ -24,8 +24,7 @@ chmodr(const char *path, int depth)
if (chmod(path, m) < 0) {
weprintf("chmod %s:", path);
ret = 1;
}
if (Rflag)
} else if (Rflag)
recurse(path, chmodr, depth);
}
@ -40,37 +39,48 @@ main(int argc, char *argv[])
{
size_t i;
argv0 = argv[0];
for (i = 1; i < argc && argv[i][0] == '-'; i++) {
switch (argv[i][1]) {
case 'R':
Rflag = 1;
break;
case 'H':
case 'L':
case 'P':
recurse_follow = argv[i][1];
break;
case 'r': case 'w': case 'x': case 's': case 't':
/*
* -[rwxst] are valid modes so do not interpret
* them as options - in any case we are done if
* we hit this case
*/
goto done;
default:
argv0 = *(argv++);
argc--;
for (; *argv && (*argv)[0] == '-'; argc--, argv++) {
if (!(*argv)[1])
usage();
for (i = 1; (*argv)[i]; i++) {
switch ((*argv)[i]) {
case 'R':
Rflag = 1;
break;
case 'H':
case 'L':
case 'P':
recurse_follow = (*argv)[i];
break;
case 'r': case 'w': case 'x': case 's': case 't':
/* -[rwxst] are valid modes, so we're done */
if (i == 1)
goto done;
/* fallthrough */
case '-':
/* -- terminator */
if (i == 1 && !(*argv)[i + 1]) {
argv++;
argc--;
goto done;
}
/* fallthrough */
default:
usage();
}
}
}
done:
mask = getumask();
modestr = argv[i];
modestr = *argv;
if (argc - i - 1 < 1)
if (argc < 2)
usage();
for (++i; i < argc; i++)
chmodr(argv[i], 0);
for (--argc, ++argv; *argv; argc--, argv++)
chmodr(*argv, 0);
return ret;
}