1*cf5a6c84SAndroid Build Coastguard Worker /* chgrp.c - Change user and group ownership
2*cf5a6c84SAndroid Build Coastguard Worker *
3*cf5a6c84SAndroid Build Coastguard Worker * Copyright 2012 Georgi Chorbadzhiyski <[email protected]>
4*cf5a6c84SAndroid Build Coastguard Worker *
5*cf5a6c84SAndroid Build Coastguard Worker * See http://opengroup.org/onlinepubs/9699919799/utilities/chown.html
6*cf5a6c84SAndroid Build Coastguard Worker * See http://opengroup.org/onlinepubs/9699919799/utilities/chgrp.html
7*cf5a6c84SAndroid Build Coastguard Worker
8*cf5a6c84SAndroid Build Coastguard Worker USE_CHGRP(NEWTOY(chgrp, "<2h(no-dereference)PLHRfv[-HLP]", TOYFLAG_BIN))
9*cf5a6c84SAndroid Build Coastguard Worker USE_CHOWN(OLDTOY(chown, chgrp, TOYFLAG_BIN))
10*cf5a6c84SAndroid Build Coastguard Worker
11*cf5a6c84SAndroid Build Coastguard Worker config CHGRP
12*cf5a6c84SAndroid Build Coastguard Worker bool "chgrp"
13*cf5a6c84SAndroid Build Coastguard Worker default y
14*cf5a6c84SAndroid Build Coastguard Worker help
15*cf5a6c84SAndroid Build Coastguard Worker usage: chgrp/chown [-RHLP] [-fvh] GROUP FILE...
16*cf5a6c84SAndroid Build Coastguard Worker
17*cf5a6c84SAndroid Build Coastguard Worker Change group of one or more files.
18*cf5a6c84SAndroid Build Coastguard Worker
19*cf5a6c84SAndroid Build Coastguard Worker -f Suppress most error messages
20*cf5a6c84SAndroid Build Coastguard Worker -h Change symlinks instead of what they point to
21*cf5a6c84SAndroid Build Coastguard Worker -R Recurse into subdirectories (implies -h)
22*cf5a6c84SAndroid Build Coastguard Worker -H With -R change target of symlink, follow command line symlinks
23*cf5a6c84SAndroid Build Coastguard Worker -L With -R change target of symlink, follow all symlinks
24*cf5a6c84SAndroid Build Coastguard Worker -P With -R change symlink, do not follow symlinks (default)
25*cf5a6c84SAndroid Build Coastguard Worker -v Verbose
26*cf5a6c84SAndroid Build Coastguard Worker
27*cf5a6c84SAndroid Build Coastguard Worker config CHOWN
28*cf5a6c84SAndroid Build Coastguard Worker bool "chown"
29*cf5a6c84SAndroid Build Coastguard Worker default y
30*cf5a6c84SAndroid Build Coastguard Worker help
31*cf5a6c84SAndroid Build Coastguard Worker see: chgrp
32*cf5a6c84SAndroid Build Coastguard Worker */
33*cf5a6c84SAndroid Build Coastguard Worker
34*cf5a6c84SAndroid Build Coastguard Worker #define FOR_chgrp
35*cf5a6c84SAndroid Build Coastguard Worker #define FORCE_FLAGS
36*cf5a6c84SAndroid Build Coastguard Worker #include "toys.h"
37*cf5a6c84SAndroid Build Coastguard Worker
38*cf5a6c84SAndroid Build Coastguard Worker GLOBALS(
39*cf5a6c84SAndroid Build Coastguard Worker uid_t owner;
40*cf5a6c84SAndroid Build Coastguard Worker gid_t group;
41*cf5a6c84SAndroid Build Coastguard Worker char *owner_name, *group_name;
42*cf5a6c84SAndroid Build Coastguard Worker int symfollow;
43*cf5a6c84SAndroid Build Coastguard Worker )
44*cf5a6c84SAndroid Build Coastguard Worker
do_chgrp(struct dirtree * node)45*cf5a6c84SAndroid Build Coastguard Worker static int do_chgrp(struct dirtree *node)
46*cf5a6c84SAndroid Build Coastguard Worker {
47*cf5a6c84SAndroid Build Coastguard Worker int fd, ret;
48*cf5a6c84SAndroid Build Coastguard Worker
49*cf5a6c84SAndroid Build Coastguard Worker // Depth first search
50*cf5a6c84SAndroid Build Coastguard Worker if (!dirtree_notdotdot(node)) return 0;
51*cf5a6c84SAndroid Build Coastguard Worker if (FLAG(R) && !(node->again&DIRTREE_COMEAGAIN) && S_ISDIR(node->st.st_mode))
52*cf5a6c84SAndroid Build Coastguard Worker return DIRTREE_COMEAGAIN|DIRTREE_SYMFOLLOW*FLAG(L);
53*cf5a6c84SAndroid Build Coastguard Worker
54*cf5a6c84SAndroid Build Coastguard Worker fd = dirtree_parentfd(node);
55*cf5a6c84SAndroid Build Coastguard Worker ret = fchownat(fd, node->name, TT.owner, TT.group,
56*cf5a6c84SAndroid Build Coastguard Worker AT_SYMLINK_NOFOLLOW*(!(FLAG(L)|FLAG(H)) && (FLAG(h)|FLAG(R))));
57*cf5a6c84SAndroid Build Coastguard Worker
58*cf5a6c84SAndroid Build Coastguard Worker if (ret || FLAG(v)) {
59*cf5a6c84SAndroid Build Coastguard Worker char *path = dirtree_path(node, 0);
60*cf5a6c84SAndroid Build Coastguard Worker if (FLAG(v))
61*cf5a6c84SAndroid Build Coastguard Worker xprintf("%s %s%s%s %s\n", toys.which->name, TT.owner_name,
62*cf5a6c84SAndroid Build Coastguard Worker (toys.which->name[2]=='o' && *TT.group_name) ? ":" : "",
63*cf5a6c84SAndroid Build Coastguard Worker TT.group_name, path);
64*cf5a6c84SAndroid Build Coastguard Worker if (ret == -1 && !FLAG(f))
65*cf5a6c84SAndroid Build Coastguard Worker perror_msg("'%s' to '%s:%s'", path, TT.owner_name, TT.group_name);
66*cf5a6c84SAndroid Build Coastguard Worker free(path);
67*cf5a6c84SAndroid Build Coastguard Worker }
68*cf5a6c84SAndroid Build Coastguard Worker toys.exitval |= ret;
69*cf5a6c84SAndroid Build Coastguard Worker
70*cf5a6c84SAndroid Build Coastguard Worker return 0;
71*cf5a6c84SAndroid Build Coastguard Worker }
72*cf5a6c84SAndroid Build Coastguard Worker
chgrp_main(void)73*cf5a6c84SAndroid Build Coastguard Worker void chgrp_main(void)
74*cf5a6c84SAndroid Build Coastguard Worker {
75*cf5a6c84SAndroid Build Coastguard Worker int ischown = toys.which->name[2] == 'o';
76*cf5a6c84SAndroid Build Coastguard Worker char **s, *own;
77*cf5a6c84SAndroid Build Coastguard Worker
78*cf5a6c84SAndroid Build Coastguard Worker TT.owner = TT.group = -1;
79*cf5a6c84SAndroid Build Coastguard Worker TT.owner_name = TT.group_name = "";
80*cf5a6c84SAndroid Build Coastguard Worker
81*cf5a6c84SAndroid Build Coastguard Worker // Distinguish chown from chgrp
82*cf5a6c84SAndroid Build Coastguard Worker if (ischown) {
83*cf5a6c84SAndroid Build Coastguard Worker char *grp;
84*cf5a6c84SAndroid Build Coastguard Worker
85*cf5a6c84SAndroid Build Coastguard Worker own = xstrdup(*toys.optargs);
86*cf5a6c84SAndroid Build Coastguard Worker if ((grp = strchr(own, ':')) || (grp = strchr(own, '.'))) {
87*cf5a6c84SAndroid Build Coastguard Worker *(grp++) = 0;
88*cf5a6c84SAndroid Build Coastguard Worker TT.group_name = grp;
89*cf5a6c84SAndroid Build Coastguard Worker }
90*cf5a6c84SAndroid Build Coastguard Worker if (*own) TT.owner = xgetuid(TT.owner_name = own);
91*cf5a6c84SAndroid Build Coastguard Worker } else TT.group_name = *toys.optargs;
92*cf5a6c84SAndroid Build Coastguard Worker
93*cf5a6c84SAndroid Build Coastguard Worker if (TT.group_name && *TT.group_name)
94*cf5a6c84SAndroid Build Coastguard Worker TT.group = xgetgid(TT.group_name);
95*cf5a6c84SAndroid Build Coastguard Worker
96*cf5a6c84SAndroid Build Coastguard Worker for (s=toys.optargs+1; *s; s++)
97*cf5a6c84SAndroid Build Coastguard Worker dirtree_flagread(*s, DIRTREE_SYMFOLLOW*(FLAG(H)|FLAG(L)), do_chgrp);
98*cf5a6c84SAndroid Build Coastguard Worker
99*cf5a6c84SAndroid Build Coastguard Worker if (CFG_TOYBOX_FREE && ischown) free(own);
100*cf5a6c84SAndroid Build Coastguard Worker }
101