sbase

suckless unix tools
git clone git://git.suckless.org/sbase
Log | Files | Refs | README | LICENSE

chown.c (1992B)


      1 /* See LICENSE file for copyright and license details. */
      2 #include <errno.h>
      3 #include <fcntl.h>
      4 #include <grp.h>
      5 #include <limits.h>
      6 #include <pwd.h>
      7 #include <stdlib.h>
      8 #include <string.h>
      9 #include <unistd.h>
     10 
     11 #include "fs.h"
     12 #include "util.h"
     13 
     14 static int   hflag = 0;
     15 static uid_t uid = -1;
     16 static gid_t gid = -1;
     17 static int   ret = 0;
     18 
     19 static void
     20 chownpwgr(int dirfd, const char *name, struct stat *st, void *data, struct recursor *r)
     21 {
     22 	int flags = 0;
     23 
     24 	if ((r->maxdepth == 0 && r->follow == 'P') || (r->follow == 'H' && r->depth) || (hflag && !(r->depth)))
     25 		flags |= AT_SYMLINK_NOFOLLOW;
     26 
     27 	if (fchownat(dirfd, name, uid, gid, flags) < 0) {
     28 		weprintf("chown %s:", r->path);
     29 		ret = 1;
     30 	} else if (S_ISDIR(st->st_mode)) {
     31 		recurse(dirfd, name, NULL, r);
     32 	}
     33 }
     34 
     35 static void
     36 usage(void)
     37 {
     38 	eprintf("usage: %s [-h] [-R [-H | -L | -P]] owner[:[group]] file ...\n"
     39 	        "       %s [-h] [-R [-H | -L | -P]] :group file ...\n",
     40 	        argv0, argv0);
     41 }
     42 
     43 int
     44 main(int argc, char *argv[])
     45 {
     46 	struct group *gr;
     47 	struct passwd *pw;
     48 	struct recursor r = { .fn = chownpwgr, .maxdepth = 1, .follow = 'P' };
     49 	char *owner, *group;
     50 
     51 	ARGBEGIN {
     52 	case 'h':
     53 		hflag = 1;
     54 		break;
     55 	case 'r':
     56 	case 'R':
     57 		r.maxdepth = 0;
     58 		break;
     59 	case 'H':
     60 	case 'L':
     61 	case 'P':
     62 		r.follow = ARGC();
     63 		break;
     64 	default:
     65 		usage();
     66 	} ARGEND
     67 
     68 	if (argc < 2)
     69 		usage();
     70 
     71 	owner = argv[0];
     72 	if ((group = strchr(owner, ':')))
     73 		*group++ = '\0';
     74 
     75 	if (owner && *owner) {
     76 		errno = 0;
     77 		pw = getpwnam(owner);
     78 		if (pw) {
     79 			uid = pw->pw_uid;
     80 		} else {
     81 			if (errno)
     82 				eprintf("getpwnam %s:", owner);
     83 			uid = estrtonum(owner, 0, UINT_MAX);
     84 		}
     85 	}
     86 	if (group && *group) {
     87 		errno = 0;
     88 		gr = getgrnam(group);
     89 		if (gr) {
     90 			gid = gr->gr_gid;
     91 		} else {
     92 			if (errno)
     93 				eprintf("getgrnam %s:", group);
     94 			gid = estrtonum(group, 0, UINT_MAX);
     95 		}
     96 	}
     97 	if (uid == (uid_t)-1 && gid == (gid_t)-1)
     98 		usage();
     99 
    100 	for (argc--, argv++; *argv; argc--, argv++)
    101 		recurse(AT_FDCWD, *argv, NULL, &r);
    102 
    103 	return ret || recurse_status;
    104 }