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