sbase

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

chmod.c (1595B)


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