bug-coreutils
[Top][All Lists]
Advanced

[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


reply via email to

[Prev in Thread] Current Thread [Next in Thread]