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