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.
83 lines
1.6 KiB
C
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;
|
|
}
|