sbase

suckless unix tools
git clone git://git.suckless.org/sbase
Log | Files | Refs | README | LICENSE

chmod.c (1553B)


      1 /* See LICENSE file for copyright and license details. */
      2 #include <fcntl.h>
      3 #include <sys/stat.h>
      4 
      5 #include "fs.h"
      6 #include "util.h"
      7 
      8 static char  *modestr = "";
      9 static mode_t mask    = 0;
     10 static int    ret     = 0;
     11 
     12 static void
     13 chmodr(int dirfd, const char *name, struct stat *st, void *data, struct recursor *r)
     14 {
     15 	mode_t m;
     16 
     17 	m = parsemode(modestr, st->st_mode, mask);
     18 	if (!S_ISLNK(st->st_mode) && fchmodat(dirfd, name, m, 0) < 0) {
     19 		weprintf("chmod %s:", r->path);
     20 		ret = 1;
     21 	} else if (S_ISDIR(st->st_mode)) {
     22 		recurse(dirfd, name, NULL, r);
     23 	}
     24 }
     25 
     26 static void
     27 usage(void)
     28 {
     29 	eprintf("usage: %s [-R] mode file ...\n", argv0);
     30 }
     31 
     32 int
     33 main(int argc, char *argv[])
     34 {
     35 	struct recursor r = { .fn = chmodr, .maxdepth = 1, .follow = 'H', .flags = DIRFIRST };
     36 	size_t i;
     37 
     38 	argv0 = *argv, argv0 ? (argc--, argv++) : (void *)0;
     39 
     40 	for (; *argv && (*argv)[0] == '-'; argc--, argv++) {
     41 		if (!(*argv)[1])
     42 			usage();
     43 		for (i = 1; (*argv)[i]; i++) {
     44 			switch ((*argv)[i]) {
     45 			case 'R':
     46 				r.maxdepth = 0;
     47 				break;
     48 			case 'r': case 'w': case 'x': case 'X': case 's': case 't':
     49 				/* -[rwxXst] are valid modes, so we're done */
     50 				if (i == 1)
     51 					goto done;
     52 				/* fallthrough */
     53 			case '-':
     54 				/* -- terminator */
     55 				if (i == 1 && !(*argv)[i + 1]) {
     56 					argv++;
     57 					argc--;
     58 					goto done;
     59 				}
     60 				/* fallthrough */
     61 			default:
     62 				usage();
     63 			}
     64 		}
     65 	}
     66 done:
     67 	mask = getumask();
     68 	modestr = *argv;
     69 
     70 	if (argc < 2)
     71 		usage();
     72 
     73 	for (--argc, ++argv; *argv; argc--, argv++)
     74 		recurse(AT_FDCWD, *argv, NULL, &r);
     75 
     76 	return ret || recurse_status;
     77 }