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 }