14 |
/* BB_AUDIT GNU defects - unsupported long options. */ |
/* BB_AUDIT GNU defects - unsupported long options. */ |
15 |
/* http://www.opengroup.org/onlinepubs/007904975/utilities/chmod.html */ |
/* http://www.opengroup.org/onlinepubs/007904975/utilities/chmod.html */ |
16 |
|
|
17 |
#include "busybox.h" |
#include "libbb.h" |
18 |
|
|
19 |
|
/* This is a NOEXEC applet. Be very careful! */ |
20 |
|
|
21 |
|
|
22 |
#define OPT_RECURSE (option_mask32 & 1) |
#define OPT_RECURSE (option_mask32 & 1) |
23 |
#define OPT_VERBOSE (USE_DESKTOP(option_mask32 & 2) SKIP_DESKTOP(0)) |
#define OPT_VERBOSE (USE_DESKTOP(option_mask32 & 2) SKIP_DESKTOP(0)) |
34 |
* symbolic links encountered during recursive directory traversals. |
* symbolic links encountered during recursive directory traversals. |
35 |
*/ |
*/ |
36 |
|
|
37 |
static int fileAction(const char *fileName, struct stat *statbuf, void* junk, int depth) |
static int FAST_FUNC fileAction(const char *fileName, struct stat *statbuf, void* param, int depth) |
38 |
{ |
{ |
39 |
mode_t newmode; |
mode_t newmode; |
40 |
|
|
49 |
} |
} |
50 |
newmode = statbuf->st_mode; |
newmode = statbuf->st_mode; |
51 |
|
|
52 |
if (!bb_parse_mode((char *)junk, &newmode)) |
if (!bb_parse_mode((char *)param, &newmode)) |
53 |
bb_error_msg_and_die("invalid mode: %s", (char *)junk); |
bb_error_msg_and_die("invalid mode: %s", (char *)param); |
54 |
|
|
55 |
if (chmod(fileName, newmode) == 0) { |
if (chmod(fileName, newmode) == 0) { |
56 |
if (OPT_VERBOSE |
if (OPT_VERBOSE |
63 |
} |
} |
64 |
err: |
err: |
65 |
if (!OPT_QUIET) |
if (!OPT_QUIET) |
66 |
bb_perror_msg("%s", fileName); |
bb_simple_perror_msg(fileName); |
67 |
return FALSE; |
return FALSE; |
68 |
} |
} |
69 |
|
|
70 |
int chmod_main(int argc, char **argv) |
int chmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
71 |
|
int chmod_main(int argc UNUSED_PARAM, char **argv) |
72 |
{ |
{ |
73 |
int retval = EXIT_SUCCESS; |
int retval = EXIT_SUCCESS; |
74 |
char *arg, **argp; |
char *arg, **argp; |
93 |
|
|
94 |
/* Parse options */ |
/* Parse options */ |
95 |
opt_complementary = "-2"; |
opt_complementary = "-2"; |
96 |
getopt32(argc, argv, ("-"OPT_STR) + 1); /* Reuse string */ |
getopt32(argv, ("-"OPT_STR) + 1); /* Reuse string */ |
97 |
argv += optind; |
argv += optind; |
98 |
|
|
99 |
/* Restore option-like mode if needed */ |
/* Restore option-like mode if needed */ |
104 |
do { |
do { |
105 |
if (!recursive_action(*argv, |
if (!recursive_action(*argv, |
106 |
OPT_RECURSE, // recurse |
OPT_RECURSE, // recurse |
|
FALSE, // follow links: coreutils doesn't |
|
|
FALSE, // depth first |
|
107 |
fileAction, // file action |
fileAction, // file action |
108 |
fileAction, // dir action |
fileAction, // dir action |
109 |
smode, // user data |
smode, // user data |
119 |
/* |
/* |
120 |
Security: chmod is too important and too subtle. |
Security: chmod is too important and too subtle. |
121 |
This is a test script (busybox chmod versus coreutils). |
This is a test script (busybox chmod versus coreutils). |
122 |
Run it in empty dir. Probably requires bash. |
Run it in empty directory. |
123 |
|
|
124 |
#!/bin/sh |
#!/bin/sh |
125 |
function create() { |
t1="/tmp/busybox chmod" |
126 |
|
t2="/usr/bin/chmod" |
127 |
|
create() { |
128 |
rm -rf $1; mkdir $1 |
rm -rf $1; mkdir $1 |
129 |
( |
( |
130 |
cd $1 || exit 1 |
cd $1 || exit 1 |
137 |
ln -s ../up dir/up |
ln -s ../up dir/up |
138 |
) |
) |
139 |
} |
} |
140 |
function tst() { |
tst() { |
141 |
(cd test1; $t1 $1) |
(cd test1; $t1 $1) |
142 |
(cd test2; $t2 $1) |
(cd test2; $t2 $1) |
143 |
(cd test1; ls -lR) >out1 |
(cd test1; ls -lR) >out1 |
144 |
(cd test2; ls -lR) >out2 |
(cd test2; ls -lR) >out2 |
145 |
echo "chmod $1" >out.diff |
echo "chmod $1" >out.diff |
146 |
if ! diff -u out1 out2 >>out.diff; then exit 1; fi |
if ! diff -u out1 out2 >>out.diff; then exit 1; fi |
147 |
mv out.diff out1.diff |
rm out.diff |
148 |
} |
} |
149 |
t1="/tmp/busybox chmod" |
echo "If script produced 'out.diff' file, then at least one testcase failed" |
|
t2="/usr/bin/chmod" |
|
150 |
create test1; create test2 |
create test1; create test2 |
151 |
tst "a+w file" |
tst "a+w file" |
152 |
tst "a-w dir" |
tst "a-w dir" |