1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38#include "libbb.h"
39
40
41
42
43#define OPT_STR ("Rh" IF_DESKTOP("vcfLHP"))
44#define BIT_RECURSE 1
45#define OPT_RECURSE (opt & 1)
46#define OPT_NODEREF (opt & 2)
47#define OPT_VERBOSE (IF_DESKTOP(opt & 0x04) IF_NOT_DESKTOP(0))
48#define OPT_CHANGED (IF_DESKTOP(opt & 0x08) IF_NOT_DESKTOP(0))
49#define OPT_QUIET (IF_DESKTOP(opt & 0x10) IF_NOT_DESKTOP(0))
50
51
52
53
54
55
56
57
58#define BIT_TRAVERSE 0x20
59#define OPT_TRAVERSE (IF_DESKTOP(opt & BIT_TRAVERSE) IF_NOT_DESKTOP(0))
60
61#define BIT_TRAVERSE_TOP (0x20|0x40)
62#define OPT_TRAVERSE_TOP (IF_DESKTOP(opt & BIT_TRAVERSE_TOP) IF_NOT_DESKTOP(0))
63
64#if ENABLE_FEATURE_CHOWN_LONG_OPTIONS
65static const char chown_longopts[] ALIGN1 =
66 "recursive\0" No_argument "R"
67 "dereference\0" No_argument "\xff"
68 "no-dereference\0" No_argument "h"
69# if ENABLE_DESKTOP
70 "changes\0" No_argument "c"
71 "silent\0" No_argument "f"
72 "quiet\0" No_argument "f"
73 "verbose\0" No_argument "v"
74# endif
75 ;
76#endif
77
78typedef int (*chown_fptr)(const char *, uid_t, gid_t);
79
80struct param_t {
81 struct bb_uidgid_t ugid;
82 chown_fptr chown_func;
83};
84
85static int FAST_FUNC fileAction(const char *fileName, struct stat *statbuf,
86 void *vparam, int depth UNUSED_PARAM)
87{
88#define param (*(struct param_t*)vparam)
89#define opt option_mask32
90 uid_t u = (param.ugid.uid == (uid_t)-1L) ? statbuf->st_uid : param.ugid.uid;
91 gid_t g = (param.ugid.gid == (gid_t)-1L) ? statbuf->st_gid : param.ugid.gid;
92
93 if (param.chown_func(fileName, u, g) == 0) {
94 if (OPT_VERBOSE
95 || (OPT_CHANGED && (statbuf->st_uid != u || statbuf->st_gid != g))
96 ) {
97 printf("changed ownership of '%s' to %u:%u\n",
98 fileName, (unsigned)u, (unsigned)g);
99 }
100 return TRUE;
101 }
102 if (!OPT_QUIET)
103 bb_simple_perror_msg(fileName);
104 return FALSE;
105#undef opt
106#undef param
107}
108
109int chown_main(int argc UNUSED_PARAM, char **argv)
110{
111 int retval = EXIT_SUCCESS;
112 int opt, flags;
113 struct param_t param;
114
115
116 param.ugid.uid = -1L;
117 param.ugid.gid = -1L;
118
119#if ENABLE_FEATURE_CHOWN_LONG_OPTIONS
120 applet_long_options = chown_longopts;
121#endif
122 opt_complementary = "-2";
123 opt = getopt32(argv, OPT_STR);
124 argv += optind;
125
126
127 param.chown_func = chown;
128 if (OPT_NODEREF
129
130 IF_DESKTOP( || (opt & (BIT_RECURSE|BIT_TRAVERSE_TOP)) == BIT_RECURSE)
131 ) {
132 param.chown_func = lchown;
133 }
134
135 flags = ACTION_DEPTHFIRST;
136 if (OPT_RECURSE)
137 flags |= ACTION_RECURSE;
138 if (OPT_TRAVERSE_TOP)
139 flags |= ACTION_FOLLOWLINKS_L0;
140 if (OPT_TRAVERSE)
141 flags |= ACTION_FOLLOWLINKS;
142
143 parse_chown_usergroup_or_die(¶m.ugid, argv[0]);
144
145
146 while (*++argv) {
147 if (!recursive_action(*argv,
148 flags,
149 fileAction,
150 fileAction,
151 ¶m,
152 0)
153 ) {
154 retval = EXIT_FAILURE;
155 }
156 }
157
158 return retval;
159}
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222