xref: /aosp_15_r20/external/toybox/toys/posix/chgrp.c (revision cf5a6c84e2b8763fc1a7db14496fd4742913b199)
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