[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: dd skip bug?
From: |
Pádraig Brady |
Subject: |
Re: dd skip bug? |
Date: |
Fri, 18 Apr 2008 21:32:45 +0100 |
User-agent: |
Thunderbird 2.0.0.6 (X11/20071008) |
Pádraig Brady wrote:
> There are actually 3 cases to consider with large skip values.
> Currently dd does the following for various values of skip:
>
> if skip > file_size && skip < max_file_size
> lseek returns new offset, and read() returns 0
>
> if skip > file_size && skip > max file size
> lseek returns error and read() used to advance input
>
> if skip would overflow off_t
> read() used to advance input
4 cases actually:
if skip > device_size
read() used to advance input
Hopefully the attached patch makes dd more efficient/correct
in these cases. It passes the tests at least.
cheers,
Pádraig.
>From ccac25668b04d1c62f93dcec5419adb564db3ddd Mon Sep 17 00:00:00 2001
From: =?utf-8?q?P=C3=A1draig=20Brady?= <address@hidden>
Date: Fri, 18 Apr 2008 21:15:59 +0100
Subject: [PATCH] Stop dd doing redundant reading with erroneous skip offsets
* src/dd.c: Try to seek to the end of the file to stop
redundant reads when for example skip > max_file_size,
offset > dev_size, offset > OFF_T_MAX
Signed-off-by: Pádraig Brady <address@hidden>
---
src/dd.c | 12 ++++++++++++
1 files changed, 12 insertions(+), 0 deletions(-)
diff --git a/src/dd.c b/src/dd.c
index 0a7b154..711bab7 100644
--- a/src/dd.c
+++ b/src/dd.c
@@ -1178,6 +1178,7 @@ skip (int fdesc, char const *file, uintmax_t records,
size_t blocksize,
char *buf)
{
uintmax_t offset = records * blocksize;
+ off_t soffset;
/* Try lseek and if an error indicates it was an inappropriate operation --
or if the file offset is not representable as an off_t --
@@ -1194,6 +1195,17 @@ skip (int fdesc, char const *file, uintmax_t records,
size_t blocksize,
else
{
int lseek_errno = errno;
+ if (fdesc == STDIN_FILENO && input_seekable)
+ {
+ /* We probably were asked to skip past the end of device.
+ * Therefore try to seek to the end of the file,
+ * so that subsequent reads will return immediately. */
+ if ((soffset = lseek (fdesc, 0, SEEK_END)) >= 0)
+ {
+ advance_input_offset (soffset);
+ return 0;
+ }
+ }
do
{
--
1.5.3.6