chmod.c - sbase - suckless unix tools
 (HTM) git clone git://git.suckless.org/sbase
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) 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 }