chgrp.c - sbase - suckless unix tools
 (HTM) git clone git://git.suckless.org/sbase
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       chgrp.c (1400B)
       ---
            1 /* See LICENSE file for copyright and license details. */
            2 #include <sys/stat.h>
            3 
            4 #include <errno.h>
            5 #include <fcntl.h>
            6 #include <grp.h>
            7 #include <unistd.h>
            8 
            9 #include "fs.h"
           10 #include "util.h"
           11 
           12 static int   hflag = 0;
           13 static gid_t gid = -1;
           14 static int   ret = 0;
           15 
           16 static void
           17 chgrp(int dirfd, const char *name, struct stat *st, void *data, struct recursor *r)
           18 {
           19         int flags = 0;
           20 
           21         if ((r->maxdepth == 0 && r->follow == 'P') || (r->follow == 'H' && r->depth) || (hflag && !(r->depth)))
           22                 flags |= AT_SYMLINK_NOFOLLOW;
           23         if (fchownat(dirfd, name, -1, gid, flags) < 0) {
           24                 weprintf("chown %s:", r->path);
           25                 ret = 1;
           26         } else if (S_ISDIR(st->st_mode)) {
           27                 recurse(dirfd, name, NULL, r);
           28         }
           29 }
           30 
           31 static void
           32 usage(void)
           33 {
           34         eprintf("usage: %s [-h] [-R [-H | -L | -P]] group file ...\n", argv0);
           35 }
           36 
           37 int
           38 main(int argc, char *argv[])
           39 {
           40         struct group *gr;
           41         struct recursor r = { .fn = chgrp, .maxdepth = 1, .follow = 'P' };
           42 
           43         ARGBEGIN {
           44         case 'h':
           45                 hflag = 1;
           46                 break;
           47         case 'R':
           48                 r.maxdepth = 0;
           49                 break;
           50         case 'H':
           51         case 'L':
           52         case 'P':
           53                 r.follow = ARGC();
           54                 break;
           55         default:
           56                 usage();
           57         } ARGEND
           58 
           59         if (argc < 2)
           60                 usage();
           61 
           62         errno = 0;
           63         if ((gr = getgrnam(argv[0]))) {
           64                 gid = gr->gr_gid;
           65         } else {
           66                 if (errno)
           67                         eprintf("getgrnam %s:", argv[0]);
           68                 gid = estrtonum(argv[0], 0, UINT_MAX);
           69         }
           70 
           71         for (argc--, argv++; *argv; argc--, argv++)
           72                 recurse(AT_FDCWD, *argv, NULL, &r);
           73 
           74         return ret || recurse_status;
           75 }