sbase

suckless unix tools
git clone git://git.suckless.org/sbase
Log | Files | Refs | README | 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 }