chown.c - sbase - suckless unix tools
 (HTM) git clone git://git.suckless.org/sbase
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) 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 }