aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--coreutils/dd.c41
-rwxr-xr-xtestsuite/runtest92
2 files changed, 63 insertions, 70 deletions
diff --git a/coreutils/dd.c b/coreutils/dd.c
index fd4e7e8a2..7552c8518 100644
--- a/coreutils/dd.c
+++ b/coreutils/dd.c
@@ -14,6 +14,11 @@
14/* This is a NOEXEC applet. Be very careful! */ 14/* This is a NOEXEC applet. Be very careful! */
15 15
16 16
17enum {
18 ifd = STDIN_FILENO,
19 ofd = STDOUT_FILENO,
20};
21
17static const struct suffix_mult dd_suffixes[] = { 22static const struct suffix_mult dd_suffixes[] = {
18 { "c", 1 }, 23 { "c", 1 },
19 { "w", 2 }, 24 { "w", 2 },
@@ -45,19 +50,19 @@ static void dd_output_status(int ATTRIBUTE_UNUSED cur_signal)
45 G.out_full, G.out_part); 50 G.out_full, G.out_part);
46} 51}
47 52
48static ssize_t full_write_or_warn(int fd, const void *buf, size_t len, 53static ssize_t full_write_or_warn(const void *buf, size_t len,
49 const char *const filename) 54 const char *const filename)
50{ 55{
51 ssize_t n = full_write(fd, buf, len); 56 ssize_t n = full_write(ofd, buf, len);
52 if (n < 0) 57 if (n < 0)
53 bb_perror_msg("writing '%s'", filename); 58 bb_perror_msg("writing '%s'", filename);
54 return n; 59 return n;
55} 60}
56 61
57static bool write_and_stats(int fd, const void *buf, size_t len, size_t obs, 62static bool write_and_stats(const void *buf, size_t len, size_t obs,
58 const char *filename) 63 const char *filename)
59{ 64{
60 ssize_t n = full_write_or_warn(fd, buf, len, filename); 65 ssize_t n = full_write_or_warn(buf, len, filename);
61 if (n < 0) 66 if (n < 0)
62 return 1; 67 return 1;
63 if (n == obs) 68 if (n == obs)
@@ -105,13 +110,13 @@ int dd_main(int argc, char **argv)
105 OP_conv_noerror, 110 OP_conv_noerror,
106#endif 111#endif
107 }; 112 };
113 int exitcode = EXIT_FAILURE;
108 size_t ibs = 512, obs = 512; 114 size_t ibs = 512, obs = 512;
109 ssize_t n, w; 115 ssize_t n, w;
110 char *ibuf, *obuf; 116 char *ibuf, *obuf;
111 /* And these are all zeroed at once! */ 117 /* And these are all zeroed at once! */
112 struct { 118 struct {
113 int flags; 119 int flags;
114 int ifd, ofd;
115 size_t oc; 120 size_t oc;
116 off_t count; 121 off_t count;
117 off_t seek, skip; 122 off_t seek, skip;
@@ -121,8 +126,6 @@ int dd_main(int argc, char **argv)
121#endif 126#endif
122 } Z; 127 } Z;
123#define flags (Z.flags ) 128#define flags (Z.flags )
124#define ifd (Z.ifd )
125#define ofd (Z.ofd )
126#define oc (Z.oc ) 129#define oc (Z.oc )
127#define count (Z.count ) 130#define count (Z.count )
128#define seek (Z.seek ) 131#define seek (Z.seek )
@@ -133,6 +136,7 @@ int dd_main(int argc, char **argv)
133 136
134 memset(&Z, 0, sizeof(Z)); 137 memset(&Z, 0, sizeof(Z));
135 INIT_G(); 138 INIT_G();
139 //fflush(NULL); - is this needed because of NOEXEC?
136 140
137#if ENABLE_FEATURE_DD_SIGNAL_HANDLING 141#if ENABLE_FEATURE_DD_SIGNAL_HANDLING
138 sigact.sa_handler = dd_output_status; 142 sigact.sa_handler = dd_output_status;
@@ -227,9 +231,8 @@ int dd_main(int argc, char **argv)
227 obuf = xmalloc(obs); 231 obuf = xmalloc(obs);
228 } 232 }
229 if (infile != NULL) 233 if (infile != NULL)
230 ifd = xopen(infile, O_RDONLY); 234 xmove_fd(xopen(infile, O_RDONLY), ifd);
231 else { 235 else {
232 /* ifd = STDIN_FILENO; - it's zero and it's already there */
233 infile = bb_msg_standard_input; 236 infile = bb_msg_standard_input;
234 } 237 }
235 if (outfile != NULL) { 238 if (outfile != NULL) {
@@ -238,7 +241,7 @@ int dd_main(int argc, char **argv)
238 if (!seek && !(flags & FLAG_NOTRUNC)) 241 if (!seek && !(flags & FLAG_NOTRUNC))
239 oflag |= O_TRUNC; 242 oflag |= O_TRUNC;
240 243
241 ofd = xopen(outfile, oflag); 244 xmove_fd(xopen(outfile, oflag), ofd);
242 245
243 if (seek && !(flags & FLAG_NOTRUNC)) { 246 if (seek && !(flags & FLAG_NOTRUNC)) {
244 if (ftruncate(ofd, seek * obs) < 0) { 247 if (ftruncate(ofd, seek * obs) < 0) {
@@ -250,7 +253,6 @@ int dd_main(int argc, char **argv)
250 } 253 }
251 } 254 }
252 } else { 255 } else {
253 ofd = STDOUT_FILENO;
254 outfile = bb_msg_standard_output; 256 outfile = bb_msg_standard_output;
255 } 257 }
256 if (skip) { 258 if (skip) {
@@ -276,11 +278,10 @@ int dd_main(int argc, char **argv)
276 if (n == 0) 278 if (n == 0)
277 break; 279 break;
278 if (n < 0) { 280 if (n < 0) {
279 if (flags & FLAG_NOERROR) { 281 if (!(flags & FLAG_NOERROR))
280 n = ibs;
281 bb_simple_perror_msg(infile);
282 } else
283 goto die_infile; 282 goto die_infile;
283 n = ibs;
284 bb_simple_perror_msg(infile);
284 } 285 }
285 if ((size_t)n == ibs) 286 if ((size_t)n == ibs)
286 G.in_full++; 287 G.in_full++;
@@ -303,17 +304,17 @@ int dd_main(int argc, char **argv)
303 tmp += d; 304 tmp += d;
304 oc += d; 305 oc += d;
305 if (oc == obs) { 306 if (oc == obs) {
306 if (write_and_stats(ofd, obuf, obs, obs, outfile)) 307 if (write_and_stats(obuf, obs, obs, outfile))
307 goto out_status; 308 goto out_status;
308 oc = 0; 309 oc = 0;
309 } 310 }
310 } 311 }
311 } else if (write_and_stats(ofd, ibuf, n, obs, outfile)) 312 } else if (write_and_stats(ibuf, n, obs, outfile))
312 goto out_status; 313 goto out_status;
313 } 314 }
314 315
315 if (ENABLE_FEATURE_DD_IBS_OBS && oc) { 316 if (ENABLE_FEATURE_DD_IBS_OBS && oc) {
316 w = full_write_or_warn(ofd, obuf, oc, outfile); 317 w = full_write_or_warn(obuf, oc, outfile);
317 if (w < 0) goto out_status; 318 if (w < 0) goto out_status;
318 if (w > 0) 319 if (w > 0)
319 G.out_part++; 320 G.out_part++;
@@ -327,8 +328,10 @@ int dd_main(int argc, char **argv)
327 die_outfile: 328 die_outfile:
328 bb_simple_perror_msg_and_die(outfile); 329 bb_simple_perror_msg_and_die(outfile);
329 } 330 }
331
332 exitcode = EXIT_SUCCESS;
330 out_status: 333 out_status:
331 dd_output_status(0); 334 dd_output_status(0);
332 335
333 return EXIT_SUCCESS; 336 return exitcode;
334} 337}
diff --git a/testsuite/runtest b/testsuite/runtest
index 92cbfdf4e..93d5ed6e1 100755
--- a/testsuite/runtest
+++ b/testsuite/runtest
@@ -1,20 +1,20 @@
1#!/bin/sh 1#!/bin/sh
2 2
3# Run old-style test. 3# Run one old-style test.
4 4# Tests are stored in applet/testcase shell scripts.
5# They are run using "sh -x -e applet/testcase".
6# Option -e will make testcase stop on the first failed command.
5run_applet_testcase() 7run_applet_testcase()
6{ 8{
7 local applet=$1 9 local applet=$1
8 local testcase=$2 10 local testcase=$2
9 11
10 local status=0 12 local status
11 local RES=
12
13 local uc_applet=$(echo $applet | tr a-z A-Z) 13 local uc_applet=$(echo $applet | tr a-z A-Z)
14 local testname=$(basename $testcase) 14 local testname=$(basename $testcase)
15 15
16 if grep -q "^# CONFIG_${uc_applet} is not set$" $bindir/.config; then 16 if grep -q "^# CONFIG_${uc_applet} is not set$" $bindir/.config; then
17 echo UNTESTED: $testname 17 echo "UNTESTED: $testname"
18 return 0 18 return 0
19 fi 19 fi
20 20
@@ -22,72 +22,67 @@ run_applet_testcase()
22 local feature=`sed -ne 's/^# FEATURE: //p' $testcase` 22 local feature=`sed -ne 's/^# FEATURE: //p' $testcase`
23 23
24 if grep -q "^# ${feature} is not set$" $bindir/.config; then 24 if grep -q "^# ${feature} is not set$" $bindir/.config; then
25 echo UNTESTED: $testname 25 echo "UNTESTED: $testname"
26 return 0 26 return 0
27 fi 27 fi
28 fi 28 fi
29 29
30 rm -rf tmp 30 rm -rf ".tmpdir.$applet"
31 mkdir -p tmp 31 mkdir -p ".tmpdir.$applet"
32 pushd tmp > /dev/null 32 cd ".tmpdir.$applet" || return 1
33 33
34# echo Running testcase $testcase 34# echo "Running testcase $testcase"
35 d=$tsdir sh -x -e $testcase >.logfile.txt 2>&1 || status=$? 35 d="$tsdir" sh -x -e "$testcase" >"$testname.stdout.txt" 2>&1
36 36 status=$?
37 if [ $status -ne 0 ]; then 37 if [ $status != 0 ]; then
38 echo FAIL: $testname 38 echo "FAIL: $testname"
39 if [ $verbose -gt 0 ]; then 39 if [ x"$VERBOSE" != x ]; then
40 cat .logfile.txt 40 cat "$testname.stdout.txt"
41 fi 41 fi
42 status=$?
43 else 42 else
44 echo PASS: $testname 43 echo "PASS: $testname"
45 rm -f .logfile.txt
46 status=$?
47 fi 44 fi
48 45
49 popd > /dev/null 46 cd ..
50 rm -rf tmp 47 rm -rf ".tmpdir.$applet"
51 48
52 return $status 49 return $status
53} 50}
54 51
52# Run all old-style tests for given applet
55run_applet_tests() 53run_applet_tests()
56{ 54{
57 local applet=$1 55 local applet=$1
58
59 local status=0 56 local status=0
60
61 for testcase in $tsdir/$applet/*; do 57 for testcase in $tsdir/$applet/*; do
62 if [ "$testcase" = "$tsdir/$applet/CVS" ]; then 58 if [ "$testcase" = "$tsdir/$applet/CVS" ]; then
63 continue 59 continue
64 fi 60 fi
65 if ! run_applet_testcase $applet $testcase; then 61 run_applet_testcase $applet $testcase
66 status=1 62 test $? = 0 || status=1
67 fi
68 done 63 done
69
70 return $status 64 return $status
71} 65}
72 66
73 67
74status=0
75verbose=0
76 68
77[ -n "$tsdir" ] || tsdir=$(pwd) 69[ -n "$tsdir" ] || tsdir=$(pwd)
78[ -n "$bindir" ] || bindir=$(dirname $(pwd)) 70[ -n "$bindir" ] || bindir=$(dirname $(pwd))
79PATH="$bindir:$PATH" 71PATH="$bindir:$PATH"
80 72
73if [ x"$VERBOSE" = x ]; then
74 export VERBOSE=
75fi
76
81if [ x"$1" = x"-v" ]; then 77if [ x"$1" = x"-v" ]; then
82 verbose=1 78 export VERBOSE=1
83 export VERBOSE=$verbose
84 shift 79 shift
85fi 80fi
86 81
87implemented=$( 82implemented=$(
88 $bindir/busybox 2>&1 | 83 $bindir/busybox 2>&1 |
89 while read line; do 84 while read line; do
90 if test x"$line" = x"Currently defined functions:"; then 85 if [ x"$line" = x"Currently defined functions:" ]; then
91 xargs | sed 's/,//g' 86 xargs | sed 's/,//g'
92 break 87 break
93 fi 88 fi
@@ -109,39 +104,34 @@ for i in $implemented; do
109done 104done
110 105
111# Set up option flags so tests can be selective. 106# Set up option flags so tests can be selective.
107export OPTIONFLAGS=:$(sed -nr 's/^CONFIG_//p' $bindir/.config | sed 's/=.*//' | xargs | sed 's/ /:/g')
112 108
113configfile=${bindir}/.config 109status=0
114export OPTIONFLAGS=:$(sed -nr 's/^CONFIG_(.*)=.*/\1/p' $configfile | xargs | sed 's/ /:/g')
115
116for applet in $applets; do 110for applet in $applets; do
117 if [ "$applet" = "links" ]; then continue; fi 111 if [ "$applet" = "links" ]; then continue; fi
112
113 # Any old-style tests for this applet?
118 if [ "$applet" != "CVS" -a -d "$tsdir/$applet" ]; then 114 if [ "$applet" != "CVS" -a -d "$tsdir/$applet" ]; then
119 if ! run_applet_tests $applet; then 115 run_applet_tests "$applet"
120 status=1 116 test $? = 0 || status=1
121 fi
122 fi 117 fi
123 118
124 # Is this a new-style test? 119 # Is this a new-style test?
125 if [ -f ${applet}.tests ]; then 120 if [ -f "${applet}.tests" ]; then
126 if [ ! -h "$LINKSDIR/$applet" ] && [ "${applet:0:4}" != "all_" ]; then 121 if [ ! -h "$LINKSDIR/$applet" ] && [ "${applet:0:4}" != "all_" ]; then
127 echo "SKIPPED: $applet (not built)" 122 echo "SKIPPED: $applet (not built)"
128 continue 123 continue
129 fi 124 fi
130 if PATH="$LINKSDIR:$tsdir:$bindir:$PATH" \ 125# echo "Running test ${tsdir:-.}/${applet}.tests"
131 "${tsdir:-.}/$applet".tests 126 PATH="$LINKSDIR:$tsdir:$bindir:$PATH" "${tsdir:-.}/${applet}.tests"
132 then 127 test $? = 0 || status=1
133 :
134 else
135 status=1
136 fi
137 fi 128 fi
138
139done 129done
140 130
141# Leaving the dir makes it somewhat easier to run failed test by hand 131# Leaving the dir makes it somewhat easier to run failed test by hand
142#rm -rf "$LINKSDIR" 132#rm -rf "$LINKSDIR"
143 133
144if [ $status != 0 -a x"$VERBOSE" = x ]; then 134if [ $status != 0 -a x"$VERBOSE" = x ]; then
145 echo "Failures detected, running with VERBOSE=1 will give more info" 135 echo "Failures detected, running with -v (verbose) will give more info"
146fi 136fi
147exit $status 137exit $status