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