sbase/chmod.c
Michael Forney f3d05ffd0a chmod: Implement X perm symbol
Instead of clearing the format bits before calling parsemode, leave
them in so we can differentiate between directories and other files,
then clear the format bits in the result.
2020-01-06 13:47:26 -08:00

83 lines
1.6 KiB
C

/* See LICENSE file for copyright and license details. */
#include <sys/stat.h>
#include "fs.h"
#include "util.h"
static char *modestr = "";
static mode_t mask = 0;
static int ret = 0;
static void
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) {
weprintf("chmod %s:", path);
ret = 1;
} else if (S_ISDIR(st->st_mode)) {
recurse(path, NULL, r);
}
}
static void
usage(void)
{
eprintf("usage: %s [-R [-H | -L | -P]] 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 };
size_t i;
argv0 = *argv, argv0 ? (argc--, argv++) : (void *)0;
for (; *argv && (*argv)[0] == '-'; argc--, argv++) {
if (!(*argv)[1])
usage();
for (i = 1; (*argv)[i]; i++) {
switch ((*argv)[i]) {
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)
goto done;
/* fallthrough */
case '-':
/* -- terminator */
if (i == 1 && !(*argv)[i + 1]) {
argv++;
argc--;
goto done;
}
/* fallthrough */
default:
usage();
}
}
}
done:
mask = getumask();
modestr = *argv;
if (argc < 2)
usage();
for (--argc, ++argv; *argv; argc--, argv++)
recurse(*argv, NULL, &r);
return ret || recurse_status;
}