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 }