mirror of
https://github.com/sheumann/hush.git
synced 2025-01-10 01:30:04 +00:00
dd: fix a bug where we don't report write errors
testsuite: small cleanup full_write_or_warn 38 40 +2 write_and_stats 66 67 +1 dd_main 1358 1335 -23 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/1 up/down: 3/-23) Total: -20 bytes
This commit is contained in:
parent
1796e2c495
commit
e2532ab5f2
@ -14,6 +14,11 @@
|
|||||||
/* This is a NOEXEC applet. Be very careful! */
|
/* This is a NOEXEC applet. Be very careful! */
|
||||||
|
|
||||||
|
|
||||||
|
enum {
|
||||||
|
ifd = STDIN_FILENO,
|
||||||
|
ofd = STDOUT_FILENO,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct suffix_mult dd_suffixes[] = {
|
static const struct suffix_mult dd_suffixes[] = {
|
||||||
{ "c", 1 },
|
{ "c", 1 },
|
||||||
{ "w", 2 },
|
{ "w", 2 },
|
||||||
@ -45,19 +50,19 @@ static void dd_output_status(int ATTRIBUTE_UNUSED cur_signal)
|
|||||||
G.out_full, G.out_part);
|
G.out_full, G.out_part);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t full_write_or_warn(int fd, const void *buf, size_t len,
|
static ssize_t full_write_or_warn(const void *buf, size_t len,
|
||||||
const char *const filename)
|
const char *const filename)
|
||||||
{
|
{
|
||||||
ssize_t n = full_write(fd, buf, len);
|
ssize_t n = full_write(ofd, buf, len);
|
||||||
if (n < 0)
|
if (n < 0)
|
||||||
bb_perror_msg("writing '%s'", filename);
|
bb_perror_msg("writing '%s'", filename);
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool write_and_stats(int fd, const void *buf, size_t len, size_t obs,
|
static bool write_and_stats(const void *buf, size_t len, size_t obs,
|
||||||
const char *filename)
|
const char *filename)
|
||||||
{
|
{
|
||||||
ssize_t n = full_write_or_warn(fd, buf, len, filename);
|
ssize_t n = full_write_or_warn(buf, len, filename);
|
||||||
if (n < 0)
|
if (n < 0)
|
||||||
return 1;
|
return 1;
|
||||||
if (n == obs)
|
if (n == obs)
|
||||||
@ -105,13 +110,13 @@ int dd_main(int argc, char **argv)
|
|||||||
OP_conv_noerror,
|
OP_conv_noerror,
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
int exitcode = EXIT_FAILURE;
|
||||||
size_t ibs = 512, obs = 512;
|
size_t ibs = 512, obs = 512;
|
||||||
ssize_t n, w;
|
ssize_t n, w;
|
||||||
char *ibuf, *obuf;
|
char *ibuf, *obuf;
|
||||||
/* And these are all zeroed at once! */
|
/* And these are all zeroed at once! */
|
||||||
struct {
|
struct {
|
||||||
int flags;
|
int flags;
|
||||||
int ifd, ofd;
|
|
||||||
size_t oc;
|
size_t oc;
|
||||||
off_t count;
|
off_t count;
|
||||||
off_t seek, skip;
|
off_t seek, skip;
|
||||||
@ -121,8 +126,6 @@ int dd_main(int argc, char **argv)
|
|||||||
#endif
|
#endif
|
||||||
} Z;
|
} Z;
|
||||||
#define flags (Z.flags )
|
#define flags (Z.flags )
|
||||||
#define ifd (Z.ifd )
|
|
||||||
#define ofd (Z.ofd )
|
|
||||||
#define oc (Z.oc )
|
#define oc (Z.oc )
|
||||||
#define count (Z.count )
|
#define count (Z.count )
|
||||||
#define seek (Z.seek )
|
#define seek (Z.seek )
|
||||||
@ -133,6 +136,7 @@ int dd_main(int argc, char **argv)
|
|||||||
|
|
||||||
memset(&Z, 0, sizeof(Z));
|
memset(&Z, 0, sizeof(Z));
|
||||||
INIT_G();
|
INIT_G();
|
||||||
|
//fflush(NULL); - is this needed because of NOEXEC?
|
||||||
|
|
||||||
#if ENABLE_FEATURE_DD_SIGNAL_HANDLING
|
#if ENABLE_FEATURE_DD_SIGNAL_HANDLING
|
||||||
sigact.sa_handler = dd_output_status;
|
sigact.sa_handler = dd_output_status;
|
||||||
@ -227,9 +231,8 @@ int dd_main(int argc, char **argv)
|
|||||||
obuf = xmalloc(obs);
|
obuf = xmalloc(obs);
|
||||||
}
|
}
|
||||||
if (infile != NULL)
|
if (infile != NULL)
|
||||||
ifd = xopen(infile, O_RDONLY);
|
xmove_fd(xopen(infile, O_RDONLY), ifd);
|
||||||
else {
|
else {
|
||||||
/* ifd = STDIN_FILENO; - it's zero and it's already there */
|
|
||||||
infile = bb_msg_standard_input;
|
infile = bb_msg_standard_input;
|
||||||
}
|
}
|
||||||
if (outfile != NULL) {
|
if (outfile != NULL) {
|
||||||
@ -238,7 +241,7 @@ int dd_main(int argc, char **argv)
|
|||||||
if (!seek && !(flags & FLAG_NOTRUNC))
|
if (!seek && !(flags & FLAG_NOTRUNC))
|
||||||
oflag |= O_TRUNC;
|
oflag |= O_TRUNC;
|
||||||
|
|
||||||
ofd = xopen(outfile, oflag);
|
xmove_fd(xopen(outfile, oflag), ofd);
|
||||||
|
|
||||||
if (seek && !(flags & FLAG_NOTRUNC)) {
|
if (seek && !(flags & FLAG_NOTRUNC)) {
|
||||||
if (ftruncate(ofd, seek * obs) < 0) {
|
if (ftruncate(ofd, seek * obs) < 0) {
|
||||||
@ -250,7 +253,6 @@ int dd_main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ofd = STDOUT_FILENO;
|
|
||||||
outfile = bb_msg_standard_output;
|
outfile = bb_msg_standard_output;
|
||||||
}
|
}
|
||||||
if (skip) {
|
if (skip) {
|
||||||
@ -276,11 +278,10 @@ int dd_main(int argc, char **argv)
|
|||||||
if (n == 0)
|
if (n == 0)
|
||||||
break;
|
break;
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
if (flags & FLAG_NOERROR) {
|
if (!(flags & FLAG_NOERROR))
|
||||||
|
goto die_infile;
|
||||||
n = ibs;
|
n = ibs;
|
||||||
bb_simple_perror_msg(infile);
|
bb_simple_perror_msg(infile);
|
||||||
} else
|
|
||||||
goto die_infile;
|
|
||||||
}
|
}
|
||||||
if ((size_t)n == ibs)
|
if ((size_t)n == ibs)
|
||||||
G.in_full++;
|
G.in_full++;
|
||||||
@ -303,17 +304,17 @@ int dd_main(int argc, char **argv)
|
|||||||
tmp += d;
|
tmp += d;
|
||||||
oc += d;
|
oc += d;
|
||||||
if (oc == obs) {
|
if (oc == obs) {
|
||||||
if (write_and_stats(ofd, obuf, obs, obs, outfile))
|
if (write_and_stats(obuf, obs, obs, outfile))
|
||||||
goto out_status;
|
goto out_status;
|
||||||
oc = 0;
|
oc = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (write_and_stats(ofd, ibuf, n, obs, outfile))
|
} else if (write_and_stats(ibuf, n, obs, outfile))
|
||||||
goto out_status;
|
goto out_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ENABLE_FEATURE_DD_IBS_OBS && oc) {
|
if (ENABLE_FEATURE_DD_IBS_OBS && oc) {
|
||||||
w = full_write_or_warn(ofd, obuf, oc, outfile);
|
w = full_write_or_warn(obuf, oc, outfile);
|
||||||
if (w < 0) goto out_status;
|
if (w < 0) goto out_status;
|
||||||
if (w > 0)
|
if (w > 0)
|
||||||
G.out_part++;
|
G.out_part++;
|
||||||
@ -327,8 +328,10 @@ int dd_main(int argc, char **argv)
|
|||||||
die_outfile:
|
die_outfile:
|
||||||
bb_simple_perror_msg_and_die(outfile);
|
bb_simple_perror_msg_and_die(outfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exitcode = EXIT_SUCCESS;
|
||||||
out_status:
|
out_status:
|
||||||
dd_output_status(0);
|
dd_output_status(0);
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return exitcode;
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
# Run old-style test.
|
# Run one old-style test.
|
||||||
|
# Tests are stored in applet/testcase shell scripts.
|
||||||
|
# They are run using "sh -x -e applet/testcase".
|
||||||
|
# Option -e will make testcase stop on the first failed command.
|
||||||
run_applet_testcase()
|
run_applet_testcase()
|
||||||
{
|
{
|
||||||
local applet=$1
|
local applet=$1
|
||||||
local testcase=$2
|
local testcase=$2
|
||||||
|
|
||||||
local status=0
|
local status
|
||||||
local RES=
|
|
||||||
|
|
||||||
local uc_applet=$(echo $applet | tr a-z A-Z)
|
local uc_applet=$(echo $applet | tr a-z A-Z)
|
||||||
local testname=$(basename $testcase)
|
local testname=$(basename $testcase)
|
||||||
|
|
||||||
if grep -q "^# CONFIG_${uc_applet} is not set$" $bindir/.config; then
|
if grep -q "^# CONFIG_${uc_applet} is not set$" $bindir/.config; then
|
||||||
echo UNTESTED: $testname
|
echo "UNTESTED: $testname"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -22,72 +22,67 @@ run_applet_testcase()
|
|||||||
local feature=`sed -ne 's/^# FEATURE: //p' $testcase`
|
local feature=`sed -ne 's/^# FEATURE: //p' $testcase`
|
||||||
|
|
||||||
if grep -q "^# ${feature} is not set$" $bindir/.config; then
|
if grep -q "^# ${feature} is not set$" $bindir/.config; then
|
||||||
echo UNTESTED: $testname
|
echo "UNTESTED: $testname"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
rm -rf tmp
|
rm -rf ".tmpdir.$applet"
|
||||||
mkdir -p tmp
|
mkdir -p ".tmpdir.$applet"
|
||||||
pushd tmp > /dev/null
|
cd ".tmpdir.$applet" || return 1
|
||||||
|
|
||||||
# echo Running testcase $testcase
|
# echo "Running testcase $testcase"
|
||||||
d=$tsdir sh -x -e $testcase >.logfile.txt 2>&1 || status=$?
|
d="$tsdir" sh -x -e "$testcase" >"$testname.stdout.txt" 2>&1
|
||||||
|
|
||||||
if [ $status -ne 0 ]; then
|
|
||||||
echo FAIL: $testname
|
|
||||||
if [ $verbose -gt 0 ]; then
|
|
||||||
cat .logfile.txt
|
|
||||||
fi
|
|
||||||
status=$?
|
status=$?
|
||||||
|
if [ $status != 0 ]; then
|
||||||
|
echo "FAIL: $testname"
|
||||||
|
if [ x"$VERBOSE" != x ]; then
|
||||||
|
cat "$testname.stdout.txt"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo PASS: $testname
|
echo "PASS: $testname"
|
||||||
rm -f .logfile.txt
|
|
||||||
status=$?
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
popd > /dev/null
|
cd ..
|
||||||
rm -rf tmp
|
rm -rf ".tmpdir.$applet"
|
||||||
|
|
||||||
return $status
|
return $status
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Run all old-style tests for given applet
|
||||||
run_applet_tests()
|
run_applet_tests()
|
||||||
{
|
{
|
||||||
local applet=$1
|
local applet=$1
|
||||||
|
|
||||||
local status=0
|
local status=0
|
||||||
|
|
||||||
for testcase in $tsdir/$applet/*; do
|
for testcase in $tsdir/$applet/*; do
|
||||||
if [ "$testcase" = "$tsdir/$applet/CVS" ]; then
|
if [ "$testcase" = "$tsdir/$applet/CVS" ]; then
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
if ! run_applet_testcase $applet $testcase; then
|
run_applet_testcase $applet $testcase
|
||||||
status=1
|
test $? = 0 || status=1
|
||||||
fi
|
|
||||||
done
|
done
|
||||||
|
|
||||||
return $status
|
return $status
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status=0
|
|
||||||
verbose=0
|
|
||||||
|
|
||||||
[ -n "$tsdir" ] || tsdir=$(pwd)
|
[ -n "$tsdir" ] || tsdir=$(pwd)
|
||||||
[ -n "$bindir" ] || bindir=$(dirname $(pwd))
|
[ -n "$bindir" ] || bindir=$(dirname $(pwd))
|
||||||
PATH="$bindir:$PATH"
|
PATH="$bindir:$PATH"
|
||||||
|
|
||||||
|
if [ x"$VERBOSE" = x ]; then
|
||||||
|
export VERBOSE=
|
||||||
|
fi
|
||||||
|
|
||||||
if [ x"$1" = x"-v" ]; then
|
if [ x"$1" = x"-v" ]; then
|
||||||
verbose=1
|
export VERBOSE=1
|
||||||
export VERBOSE=$verbose
|
|
||||||
shift
|
shift
|
||||||
fi
|
fi
|
||||||
|
|
||||||
implemented=$(
|
implemented=$(
|
||||||
$bindir/busybox 2>&1 |
|
$bindir/busybox 2>&1 |
|
||||||
while read line; do
|
while read line; do
|
||||||
if test x"$line" = x"Currently defined functions:"; then
|
if [ x"$line" = x"Currently defined functions:" ]; then
|
||||||
xargs | sed 's/,//g'
|
xargs | sed 's/,//g'
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
@ -109,39 +104,34 @@ for i in $implemented; do
|
|||||||
done
|
done
|
||||||
|
|
||||||
# Set up option flags so tests can be selective.
|
# Set up option flags so tests can be selective.
|
||||||
|
export OPTIONFLAGS=:$(sed -nr 's/^CONFIG_//p' $bindir/.config | sed 's/=.*//' | xargs | sed 's/ /:/g')
|
||||||
|
|
||||||
configfile=${bindir}/.config
|
status=0
|
||||||
export OPTIONFLAGS=:$(sed -nr 's/^CONFIG_(.*)=.*/\1/p' $configfile | xargs | sed 's/ /:/g')
|
|
||||||
|
|
||||||
for applet in $applets; do
|
for applet in $applets; do
|
||||||
if [ "$applet" = "links" ]; then continue; fi
|
if [ "$applet" = "links" ]; then continue; fi
|
||||||
|
|
||||||
|
# Any old-style tests for this applet?
|
||||||
if [ "$applet" != "CVS" -a -d "$tsdir/$applet" ]; then
|
if [ "$applet" != "CVS" -a -d "$tsdir/$applet" ]; then
|
||||||
if ! run_applet_tests $applet; then
|
run_applet_tests "$applet"
|
||||||
status=1
|
test $? = 0 || status=1
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Is this a new-style test?
|
# Is this a new-style test?
|
||||||
if [ -f ${applet}.tests ]; then
|
if [ -f "${applet}.tests" ]; then
|
||||||
if [ ! -h "$LINKSDIR/$applet" ] && [ "${applet:0:4}" != "all_" ]; then
|
if [ ! -h "$LINKSDIR/$applet" ] && [ "${applet:0:4}" != "all_" ]; then
|
||||||
echo "SKIPPED: $applet (not built)"
|
echo "SKIPPED: $applet (not built)"
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
if PATH="$LINKSDIR:$tsdir:$bindir:$PATH" \
|
# echo "Running test ${tsdir:-.}/${applet}.tests"
|
||||||
"${tsdir:-.}/$applet".tests
|
PATH="$LINKSDIR:$tsdir:$bindir:$PATH" "${tsdir:-.}/${applet}.tests"
|
||||||
then
|
test $? = 0 || status=1
|
||||||
:
|
|
||||||
else
|
|
||||||
status=1
|
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
|
|
||||||
done
|
done
|
||||||
|
|
||||||
# Leaving the dir makes it somewhat easier to run failed test by hand
|
# Leaving the dir makes it somewhat easier to run failed test by hand
|
||||||
#rm -rf "$LINKSDIR"
|
#rm -rf "$LINKSDIR"
|
||||||
|
|
||||||
if [ $status != 0 -a x"$VERBOSE" = x ]; then
|
if [ $status != 0 -a x"$VERBOSE" = x ]; then
|
||||||
echo "Failures detected, running with VERBOSE=1 will give more info"
|
echo "Failures detected, running with -v (verbose) will give more info"
|
||||||
fi
|
fi
|
||||||
exit $status
|
exit $status
|
||||||
|
Loading…
x
Reference in New Issue
Block a user