8 |
*/ |
*/ |
9 |
|
|
10 |
/* BB_AUDIT SUSv3 defects - none? */ |
/* BB_AUDIT SUSv3 defects - none? */ |
|
/* BB_AUDIT GNU defects - unsupported long options. */ |
|
11 |
/* http://www.opengroup.org/onlinepubs/007904975/utilities/chown.html */ |
/* http://www.opengroup.org/onlinepubs/007904975/utilities/chown.html */ |
12 |
|
|
13 |
#include "libbb.h" |
#include "libbb.h" |
15 |
/* This is a NOEXEC applet. Be very careful! */ |
/* This is a NOEXEC applet. Be very careful! */ |
16 |
|
|
17 |
|
|
18 |
#define OPT_STR ("Rh" USE_DESKTOP("vcfLHP")) |
#define OPT_STR ("Rh" IF_DESKTOP("vcfLHP")) |
19 |
#define BIT_RECURSE 1 |
#define BIT_RECURSE 1 |
20 |
#define OPT_RECURSE (opt & 1) |
#define OPT_RECURSE (opt & 1) |
21 |
#define OPT_NODEREF (opt & 2) |
#define OPT_NODEREF (opt & 2) |
22 |
#define OPT_VERBOSE (USE_DESKTOP(opt & 0x04) SKIP_DESKTOP(0)) |
#define OPT_VERBOSE (IF_DESKTOP(opt & 0x04) IF_NOT_DESKTOP(0)) |
23 |
#define OPT_CHANGED (USE_DESKTOP(opt & 0x08) SKIP_DESKTOP(0)) |
#define OPT_CHANGED (IF_DESKTOP(opt & 0x08) IF_NOT_DESKTOP(0)) |
24 |
#define OPT_QUIET (USE_DESKTOP(opt & 0x10) SKIP_DESKTOP(0)) |
#define OPT_QUIET (IF_DESKTOP(opt & 0x10) IF_NOT_DESKTOP(0)) |
25 |
/* POSIX options |
/* POSIX options |
26 |
* -L traverse every symbolic link to a directory encountered |
* -L traverse every symbolic link to a directory encountered |
27 |
* -H if a command line argument is a symbolic link to a directory, traverse it |
* -H if a command line argument is a symbolic link to a directory, traverse it |
31 |
* The last option specified shall determine the behavior of the utility." */ |
* The last option specified shall determine the behavior of the utility." */ |
32 |
/* -L */ |
/* -L */ |
33 |
#define BIT_TRAVERSE 0x20 |
#define BIT_TRAVERSE 0x20 |
34 |
#define OPT_TRAVERSE (USE_DESKTOP(opt & BIT_TRAVERSE) SKIP_DESKTOP(0)) |
#define OPT_TRAVERSE (IF_DESKTOP(opt & BIT_TRAVERSE) IF_NOT_DESKTOP(0)) |
35 |
/* -H or -L */ |
/* -H or -L */ |
36 |
#define BIT_TRAVERSE_TOP (0x20|0x40) |
#define BIT_TRAVERSE_TOP (0x20|0x40) |
37 |
#define OPT_TRAVERSE_TOP (USE_DESKTOP(opt & BIT_TRAVERSE_TOP) SKIP_DESKTOP(0)) |
#define OPT_TRAVERSE_TOP (IF_DESKTOP(opt & BIT_TRAVERSE_TOP) IF_NOT_DESKTOP(0)) |
38 |
|
|
39 |
|
#if ENABLE_FEATURE_CHOWN_LONG_OPTIONS |
40 |
|
static 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 |
|
|
53 |
typedef int (*chown_fptr)(const char *, uid_t, gid_t); |
typedef int (*chown_fptr)(const char *, uid_t, gid_t); |
54 |
|
|
89 |
|
|
90 |
param.ugid.uid = -1; |
param.ugid.uid = -1; |
91 |
param.ugid.gid = -1; |
param.ugid.gid = -1; |
|
param.chown_func = chown; |
|
92 |
|
|
93 |
|
#if ENABLE_FEATURE_CHOWN_LONG_OPTIONS |
94 |
|
applet_long_options = chown_longopts; |
95 |
|
#endif |
96 |
opt_complementary = "-2"; |
opt_complementary = "-2"; |
97 |
opt = getopt32(argv, OPT_STR); |
opt = getopt32(argv, OPT_STR); |
98 |
argv += optind; |
argv += optind; |
99 |
|
|
100 |
/* This matches coreutils behavior (almost - see below) */ |
/* This matches coreutils behavior (almost - see below) */ |
101 |
|
param.chown_func = chown; |
102 |
if (OPT_NODEREF |
if (OPT_NODEREF |
103 |
/* || (OPT_RECURSE && !OPT_TRAVERSE_TOP): */ |
/* || (OPT_RECURSE && !OPT_TRAVERSE_TOP): */ |
104 |
USE_DESKTOP( || (opt & (BIT_RECURSE|BIT_TRAVERSE_TOP)) == BIT_RECURSE) |
IF_DESKTOP( || (opt & (BIT_RECURSE|BIT_TRAVERSE_TOP)) == BIT_RECURSE) |
105 |
) { |
) { |
106 |
param.chown_func = lchown; |
param.chown_func = lchown; |
107 |
} |
} |
117 |
parse_chown_usergroup_or_die(¶m.ugid, argv[0]); |
parse_chown_usergroup_or_die(¶m.ugid, argv[0]); |
118 |
|
|
119 |
/* Ok, ready to do the deed now */ |
/* Ok, ready to do the deed now */ |
120 |
argv++; |
while (*++argv) { |
|
do { |
|
121 |
if (!recursive_action(*argv, |
if (!recursive_action(*argv, |
122 |
flags, /* flags */ |
flags, /* flags */ |
123 |
fileAction, /* file action */ |
fileAction, /* file action */ |
127 |
) { |
) { |
128 |
retval = EXIT_FAILURE; |
retval = EXIT_FAILURE; |
129 |
} |
} |
130 |
} while (*++argv); |
} |
131 |
|
|
132 |
return retval; |
return retval; |
133 |
} |
} |