mirror of
https://github.com/sheumann/hush.git
synced 2024-12-26 10:32:02 +00:00
chown: support -H -L -P if ENABLE_DESKTOP
chmod: cosmetic fixes expr: smallish help for dumb compilers
This commit is contained in:
parent
6c939e0cb4
commit
cd27c42552
@ -118,10 +118,12 @@ int chmod_main(int argc, char **argv)
|
|||||||
/*
|
/*
|
||||||
Security: chmod is too important and too subtle.
|
Security: chmod is too important and too subtle.
|
||||||
This is a test script (busybox chmod versus coreutils).
|
This is a test script (busybox chmod versus coreutils).
|
||||||
Run it in empty dir. Probably requires bash.
|
Run it in empty directory.
|
||||||
|
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
function create() {
|
t1="/tmp/busybox chmod"
|
||||||
|
t2="/usr/bin/chmod"
|
||||||
|
create() {
|
||||||
rm -rf $1; mkdir $1
|
rm -rf $1; mkdir $1
|
||||||
(
|
(
|
||||||
cd $1 || exit 1
|
cd $1 || exit 1
|
||||||
@ -134,17 +136,16 @@ function create() {
|
|||||||
ln -s ../up dir/up
|
ln -s ../up dir/up
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
function tst() {
|
tst() {
|
||||||
(cd test1; $t1 $1)
|
(cd test1; $t1 $1)
|
||||||
(cd test2; $t2 $1)
|
(cd test2; $t2 $1)
|
||||||
(cd test1; ls -lR) >out1
|
(cd test1; ls -lR) >out1
|
||||||
(cd test2; ls -lR) >out2
|
(cd test2; ls -lR) >out2
|
||||||
echo "chmod $1" >out.diff
|
echo "chmod $1" >out.diff
|
||||||
if ! diff -u out1 out2 >>out.diff; then exit 1; fi
|
if ! diff -u out1 out2 >>out.diff; then exit 1; fi
|
||||||
mv out.diff out1.diff
|
rm out.diff
|
||||||
}
|
}
|
||||||
t1="/tmp/busybox chmod"
|
echo "If script produced 'out.diff' file, then at least one testcase failed"
|
||||||
t2="/usr/bin/chmod"
|
|
||||||
create test1; create test2
|
create test1; create test2
|
||||||
tst "a+w file"
|
tst "a+w file"
|
||||||
tst "a-w dir"
|
tst "a-w dir"
|
||||||
|
@ -17,25 +17,31 @@ static struct bb_uidgid_t ugid = { -1, -1 };
|
|||||||
|
|
||||||
static int (*chown_func)(const char *, uid_t, gid_t) = chown;
|
static int (*chown_func)(const char *, uid_t, gid_t) = chown;
|
||||||
|
|
||||||
|
#define OPT_STR ("Rh" USE_DESKTOP("vcfLHP"))
|
||||||
|
#define BIT_RECURSE 1
|
||||||
|
#define BIT_NODEREF 2
|
||||||
|
#define BIT_TRAVERSE 0x20
|
||||||
|
#define BIT_TRAVERSETOP (0x20|0x40)
|
||||||
#define OPT_RECURSE (option_mask32 & 1)
|
#define OPT_RECURSE (option_mask32 & 1)
|
||||||
#define OPT_NODEREF (option_mask32 & 2)
|
#define OPT_NODEREF (option_mask32 & 2)
|
||||||
#define OPT_VERBOSE (USE_DESKTOP(option_mask32 & 4) SKIP_DESKTOP(0))
|
#define OPT_VERBOSE (USE_DESKTOP(option_mask32 & 0x04) SKIP_DESKTOP(0))
|
||||||
#define OPT_CHANGED (USE_DESKTOP(option_mask32 & 8) SKIP_DESKTOP(0))
|
#define OPT_CHANGED (USE_DESKTOP(option_mask32 & 0x08) SKIP_DESKTOP(0))
|
||||||
#define OPT_QUIET (USE_DESKTOP(option_mask32 & 0x10) SKIP_DESKTOP(0))
|
#define OPT_QUIET (USE_DESKTOP(option_mask32 & 0x10) SKIP_DESKTOP(0))
|
||||||
#define OPT_STR ("Rh" USE_DESKTOP("vcf"))
|
/* POSIX options
|
||||||
|
|
||||||
/* TODO:
|
|
||||||
* -H if a command line argument is a symbolic link to a directory, traverse it
|
|
||||||
* -L traverse every symbolic link to a directory encountered
|
* -L traverse every symbolic link to a directory encountered
|
||||||
|
* -H if a command line argument is a symbolic link to a directory, traverse it
|
||||||
* -P do not traverse any symbolic links (default)
|
* -P do not traverse any symbolic links (default)
|
||||||
*/
|
* We do not conform to the following:
|
||||||
|
* "Specifying more than one of -H, -L, and -P is not an error.
|
||||||
|
* The last option specified shall determine the behavior of the utility." */
|
||||||
|
/* -L */
|
||||||
|
#define OPT_TRAVERSE (USE_DESKTOP(option_mask32 & BIT_TRAVERSE) SKIP_DESKTOP(0))
|
||||||
|
/* -H or -L */
|
||||||
|
#define OPT_TRAVERSETOP (USE_DESKTOP(option_mask32 & BIT_TRAVERSETOP) SKIP_DESKTOP(0))
|
||||||
|
|
||||||
static int fileAction(const char *fileName, struct stat *statbuf,
|
static int fileAction(const char *fileName, struct stat *statbuf,
|
||||||
void ATTRIBUTE_UNUSED *junk, int depth)
|
void ATTRIBUTE_UNUSED *junk, int depth)
|
||||||
{
|
{
|
||||||
// TODO: -H/-L/-P
|
|
||||||
// if (depth ... && S_ISLNK(statbuf->st_mode)) ....
|
|
||||||
|
|
||||||
if (!chown_func(fileName,
|
if (!chown_func(fileName,
|
||||||
(ugid.uid == (uid_t)-1) ? statbuf->st_uid : ugid.uid,
|
(ugid.uid == (uid_t)-1) ? statbuf->st_uid : ugid.uid,
|
||||||
(ugid.gid == (gid_t)-1) ? statbuf->st_gid : ugid.gid)
|
(ugid.gid == (gid_t)-1) ? statbuf->st_gid : ugid.gid)
|
||||||
@ -62,16 +68,31 @@ int chown_main(int argc, char **argv)
|
|||||||
getopt32(argc, argv, OPT_STR);
|
getopt32(argc, argv, OPT_STR);
|
||||||
argv += optind;
|
argv += optind;
|
||||||
|
|
||||||
if (OPT_NODEREF) chown_func = lchown;
|
/* This matches coreutils behavior (almost - see below) */
|
||||||
|
if (OPT_NODEREF
|
||||||
|
/* || (OPT_RECURSE && !OPT_TRAVERSETOP): */
|
||||||
|
USE_DESKTOP( || (option_mask32 & (BIT_RECURSE|BIT_TRAVERSETOP)) == BIT_RECURSE)
|
||||||
|
) {
|
||||||
|
chown_func = lchown;
|
||||||
|
}
|
||||||
|
|
||||||
parse_chown_usergroup_or_die(&ugid, argv[0]);
|
parse_chown_usergroup_or_die(&ugid, argv[0]);
|
||||||
|
|
||||||
/* Ok, ready to do the deed now */
|
/* Ok, ready to do the deed now */
|
||||||
argv++;
|
argv++;
|
||||||
do {
|
do {
|
||||||
if (!recursive_action(*argv,
|
char *arg = *argv;
|
||||||
OPT_RECURSE, // recurse
|
|
||||||
FALSE, // follow links: TODO: -H/-L/-P
|
if (OPT_TRAVERSETOP) {
|
||||||
|
/* resolves symlink (even recursive) */
|
||||||
|
arg = xmalloc_realpath(arg);
|
||||||
|
if (!arg)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!recursive_action(arg,
|
||||||
|
OPT_RECURSE, // recurse
|
||||||
|
OPT_TRAVERSE, // follow links if -L
|
||||||
FALSE, // depth first
|
FALSE, // depth first
|
||||||
fileAction, // file action
|
fileAction, // file action
|
||||||
fileAction, // dir action
|
fileAction, // dir action
|
||||||
@ -80,7 +101,66 @@ int chown_main(int argc, char **argv)
|
|||||||
) {
|
) {
|
||||||
retval = EXIT_FAILURE;
|
retval = EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (OPT_TRAVERSETOP)
|
||||||
|
free(arg);
|
||||||
} while (*++argv);
|
} while (*++argv);
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Testcase. Run in empty directory.
|
||||||
|
|
||||||
|
#!/bin/sh
|
||||||
|
t1="/tmp/busybox chown"
|
||||||
|
t2="/usr/bin/chown"
|
||||||
|
create() {
|
||||||
|
rm -rf $1; mkdir $1
|
||||||
|
(
|
||||||
|
cd $1 || exit 1
|
||||||
|
mkdir dir dir2
|
||||||
|
>up
|
||||||
|
>file
|
||||||
|
>dir/file
|
||||||
|
>dir2/file
|
||||||
|
ln -s dir linkdir
|
||||||
|
ln -s file linkfile
|
||||||
|
ln -s ../up dir/linkup
|
||||||
|
ln -s ../dir2 dir/linkupdir2
|
||||||
|
)
|
||||||
|
chown -R 0:0 $1
|
||||||
|
}
|
||||||
|
tst() {
|
||||||
|
create test1
|
||||||
|
create test2
|
||||||
|
(cd test1; $t1 $1)
|
||||||
|
(cd test2; $t2 $1)
|
||||||
|
(cd test1; ls -lnR) >out1
|
||||||
|
(cd test2; ls -lnR) >out2
|
||||||
|
echo "chown $1" >out.diff
|
||||||
|
if ! diff -u out1 out2 >>out.diff; then exit 1; fi
|
||||||
|
rm out.diff
|
||||||
|
}
|
||||||
|
tst_for_each() {
|
||||||
|
tst "$1 1:1 file"
|
||||||
|
tst "$1 1:1 dir"
|
||||||
|
tst "$1 1:1 linkdir"
|
||||||
|
tst "$1 1:1 linkfile"
|
||||||
|
}
|
||||||
|
echo "If script produced 'out.diff' file, then at least one testcase failed"
|
||||||
|
# These match coreutils 6.8:
|
||||||
|
tst_for_each ""
|
||||||
|
tst_for_each "-R"
|
||||||
|
tst_for_each "-RP"
|
||||||
|
tst_for_each "-RL"
|
||||||
|
tst_for_each "-RH"
|
||||||
|
tst_for_each "-h"
|
||||||
|
tst_for_each "-hR"
|
||||||
|
tst_for_each "-hRP"
|
||||||
|
# Below: with "chown linkdir" coreutils 6.8 will chown linkdir _target_,
|
||||||
|
# we lchown _the link_. I believe we are "more correct".
|
||||||
|
#tst_for_each "-hRL"
|
||||||
|
#tst_for_each "-hRH"
|
||||||
|
|
||||||
|
*/
|
||||||
|
@ -136,8 +136,8 @@ static int null(VALUE * v)
|
|||||||
{
|
{
|
||||||
if (v->type == integer)
|
if (v->type == integer)
|
||||||
return v->u.i == 0;
|
return v->u.i == 0;
|
||||||
else /* string: */
|
/* string: */
|
||||||
return v->u.s[0] == '\0' || LONE_CHAR(v->u.s, '0');
|
return v->u.s[0] == '\0' || LONE_CHAR(v->u.s, '0');
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Coerce V to a string value (can't fail). */
|
/* Coerce V to a string value (can't fail). */
|
||||||
@ -194,16 +194,16 @@ static int cmp_common(VALUE * l, VALUE * r, int op)
|
|||||||
cmpval = l->u.i - r->u.i;
|
cmpval = l->u.i - r->u.i;
|
||||||
if (op == '<')
|
if (op == '<')
|
||||||
return cmpval < 0;
|
return cmpval < 0;
|
||||||
else if (op == ('L' + 'E'))
|
if (op == ('L' + 'E'))
|
||||||
return cmpval <= 0;
|
return cmpval <= 0;
|
||||||
else if (op == '=')
|
if (op == '=')
|
||||||
return cmpval == 0;
|
return cmpval == 0;
|
||||||
else if (op == '!')
|
if (op == '!')
|
||||||
return cmpval != 0;
|
return cmpval != 0;
|
||||||
else if (op == '>')
|
if (op == '>')
|
||||||
return cmpval > 0;
|
return cmpval > 0;
|
||||||
else /* >= */
|
/* >= */
|
||||||
return cmpval >= 0;
|
return cmpval >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The arithmetic operator handling functions. */
|
/* The arithmetic operator handling functions. */
|
||||||
|
Loading…
Reference in New Issue
Block a user