diff options
author | Pádraig Brady <P@draigBrady.com> | 2008-11-20 10:28:31 +0000 |
---|---|---|
committer | Pádraig Brady <P@draigBrady.com> | 2009-01-28 15:14:57 +0000 |
commit | 460ebb078ed7bf249af745d8725d6c37e7f15b57 (patch) | |
tree | a421119bbced4575fad05e74245ad7995a889355 /tests/dd | |
parent | 0d5508de1358319c32b757d8593c3862465fe916 (diff) | |
download | coreutils-460ebb078ed7bf249af745d8725d6c37e7f15b57.tar.xz |
dd: Better handle user specified offsets that are too big
Following are the before and after operations for seekable files,
for the various erroneous offsets handled by this patch:
skip beyond end of file
before: immediately exit(0);
after : immediately printf("cannot skip to specified offset"); exit(0);
skip > max file size
before: read whole file and exit(0);
after : immediately printf("cannot skip: Invalid argument"); exit(1);
seek > max file size
before: immediately printf("truncate error: EFBIG"); exit(1);
after : immediately printf("truncate error: EFBIG"); exit(1);
skip > OFF_T_MAX
before: read whole device/file and exit(0);
after : immediately printf("cannot skip:"); exit(1);
seek > OFF_T_MAX
before: immediately printf("truncate error: offset too large"); exit(1);
after : immediately printf("truncate error: offset too large"); exit(1);
skip > device size
before: read whole device and exit(0);
after : immediately printf("cannot skip: Invalid argument"); exit(1);
seek > device size
before: read whole device and printf("write error: ENOSPC"); exit(1);
after : immediately printf("cannot seek: Invalid argument"); exit(1);
* NEWS: Summarize this change in behavior.
* src/dd.c (skip): Add error checking for large seek/skip offsets on
seekable files, rather than deferring to using read() to advance offset.
(dd_copy): Print a warning if skip past EOF, as per FIXME comment.
* test/Makefile.am: Add 2 new tests.
* tests/dd/seek-skip-past-file: Add tests for first 3 cases above.
* tests/dd/seek-skip-past-dev: Add root only test for last case above.
Diffstat (limited to 'tests/dd')
-rwxr-xr-x | tests/dd/skip-seek-past-dev | 63 | ||||
-rwxr-xr-x | tests/dd/skip-seek-past-file | 91 |
2 files changed, 154 insertions, 0 deletions
diff --git a/tests/dd/skip-seek-past-dev b/tests/dd/skip-seek-past-dev new file mode 100755 index 000000000..04101d222 --- /dev/null +++ b/tests/dd/skip-seek-past-dev @@ -0,0 +1,63 @@ +#!/bin/sh +# test diagnostics are printed immediately when seeking beyond device. + +# Copyright (C) 2008 Free Software Foundation, Inc. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +if test "$VERBOSE" = yes; then + set -x + dd --version +fi + +. $srcdir/test-lib.sh + +# need write access to device +# (even though we don't actually write anything) +require_root_ + +get_device_size() { + BLOCKDEV=blockdev + $BLOCKDEV -V >/dev/null 2>&1 || BLOCKDEV=/sbin/blockdev + $BLOCKDEV --getsize64 "$1" +} + +fail=0 + +# Get path to device the current dir is on. +# Note df can only get fs size, not device size. +device=$(df -P --local . | tail -n1 | cut -d' ' -f1) || + skip_test_ 'this test runs only on local file systems' + +dev_size=$(get_device_size "$device") || + skip_test_ "failed to determine size of $device" + +# Don't use shell arithimetic as older version of dash use longs +DEV_OFLOW=$(expr $dev_size + 1) + +timeout 1 dd bs=1 skip=$DEV_OFLOW count=0 status=noxfer < "$device" 2> err +test "$?" = "1" || fail=1 +echo "dd: \`standard input': cannot skip: Invalid argument +0+0 records in +0+0 records out" > err_ok || framework_failure +compare err_ok err || fail=1 + +timeout 1 dd bs=1 seek=$DEV_OFLOW count=0 status=noxfer > "$device" 2> err +test "$?" = "1" || fail=1 +echo "dd: \`standard output': cannot seek: Invalid argument +0+0 records in +0+0 records out" > err_ok || framework_failure +compare err_ok err || fail=1 + +Exit $fail diff --git a/tests/dd/skip-seek-past-file b/tests/dd/skip-seek-past-file new file mode 100755 index 000000000..cfc143963 --- /dev/null +++ b/tests/dd/skip-seek-past-file @@ -0,0 +1,91 @@ +#!/bin/sh +# test diagnostics are printed when seeking too far in seekable files. + +# Copyright (C) 2008 Free Software Foundation, Inc. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +if test "$VERBOSE" = yes; then + set -x + dd --version +fi + +. $srcdir/test-lib.sh +eval $(getlimits) #for OFF_T limits + +fail=0 + +printf "1234" > file || framework_failure + +echo "\ +dd: \`standard input': cannot skip to specified offset +0+0 records in +0+0 records out" > skip_err || framework_failure + +# skipping beyond number of blocks in file should issue a warning +dd bs=1 skip=5 count=0 status=noxfer < file 2> err || fail=1 +compare skip_err err || fail=1 + +# skipping beyond number of bytes in file should issue a warning +dd bs=3 skip=2 count=0 status=noxfer < file 2> err || fail=1 +compare skip_err err || fail=1 + +# skipping beyond number of blocks in pipe should issue a warning +cat file | dd bs=1 skip=5 count=0 status=noxfer 2> err || fail=1 +compare skip_err err || fail=1 + +# skipping beyond number of bytes in pipe should issue a warning +cat file | dd bs=3 skip=2 count=0 status=noxfer 2> err || fail=1 +compare skip_err err || fail=1 + +# Check seeking beyond file already offset into +# skipping beyond number of blocks in file should issue a warning +(dd bs=1 skip=1 count=0 2>/dev/null && + dd bs=1 skip=4 status=noxfer 2> err) < file || fail=1 +compare skip_err err || fail=1 + +# Check seeking beyond file already offset into +# skipping beyond number of bytes in file should issue a warning +(dd bs=1 skip=1 count=0 2>/dev/null && + dd bs=2 skip=2 status=noxfer 2> err) < file || fail=1 +compare skip_err err || fail=1 + +# seeking beyond end of file is OK +dd bs=1 seek=5 count=0 status=noxfer > file 2> err || fail=1 +echo "0+0 records in +0+0 records out" > err_ok || framework_failure +compare err_ok err || fail=1 + +# skipping > OFF_T_MAX should fail immediately +dd bs=1 skip=$OFF_T_OFLOW count=0 status=noxfer < file 2> err && fail=1 +echo "dd: \`standard input': cannot skip: Value too large for defined data type +0+0 records in +0+0 records out" > err_ok || framework_failure +compare err_ok err || fail=1 + +# skipping > max file size should fail immediately +# Note I'm guessing there is a small chance that an lseek() could actually work +# and only a write() would fail (with EFBIG) when offset > max file size. +# So this test will both test for that, and ensure that dd +# exits immediately with an appropriate error when lseek() does error. +if ! truncate --size=$OFF_T_MAX in 2>/dev/null; then + # truncate is to ensure file system doesn't actually support OFF_T_MAX files + dd bs=1 skip=$OFF_T_MAX count=0 status=noxfer < file 2> err && fail=1 + echo "dd: \`standard input': cannot skip: Invalid argument +0+0 records in +0+0 records out" > err_ok || framework_failure + compare err_ok err || fail=1 +fi + +Exit $fail |