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 }