Frank Adler <[EMAIL PROTECTED]> writes:
| I've seen the following strange behavior of dd on an Slackware
| 7.0 installation. I tried to restore a tar off of an amanda
| (http://www.amanda.org) tape. In order to do this you have to strip
| the first 32k block containing some amanda information. This is usually
| done with:
|
| dd bs=32k if=/dev/nst0 skip=1 | gzip -dc | tar -xf -
|
| The above does not work on this slackware 7 installation (it has worked on
| an older RedHat 4 distribution), it seems to ignore the skip parameter at all.
|
| A workaround is:
|
| dd bs=32k if=/dev/nst0 | dd skip=64 | gzip -dc | tar xf
|
| If InFile is a file on local harddisk, skip will work fine too.
|
| I recompiled fileutils-4.0 and fileutils-3.13 (same version as on the
| mentioned RedHat 4 installation), but I get the same results.

Thanks for the report.
Here's the fix (to appear in next test release):

2000-08-22  Paul Eggert  <[EMAIL PROTECTED]>

        * src/dd.c (skip):
        Assume lseek failed if it returned zero, since a zero return is
        impossible and some buggy drivers return zero.

        Use SEEK_CUR rather than SEEK_SET; this fixes a bug when the
        file descriptor is not currently rewound.

Index: dd.c
===================================================================
RCS file: /fetish/fileutils/src/dd.c,v
retrieving revision 1.105
diff -u -p -r1.105 dd.c
--- dd.c        2000/08/23 07:33:28     1.105
+++ dd.c        2000/08/23 07:34:05
@@ -720,7 +720,8 @@ swab_buffer (unsigned char *buf, size_t
 
 /* Throw away RECORDS blocks of BLOCKSIZE bytes on file descriptor FDESC,
    which is open with read permission for FILE.  Store up to BLOCKSIZE
-   bytes of the data at a time in BUF, if necessary. */
+   bytes of the data at a time in BUF, if necessary.  RECORDS must be
+   nonzero.  */
 
 static void
 skip (int fdesc, char *file, uintmax_t records, size_t blocksize,
@@ -729,10 +730,12 @@ skip (int fdesc, char *file, uintmax_t r
   off_t o;
 
   /* Try lseek and if an error indicates it was an inappropriate
-     operation, fall back on using read.  */
+     operation, fall back on using read.  Some broken versions of
+     lseek return zero, so count that as an error too as a valid zero
+     return is not possible here.  */
   o = records * blocksize;
   if (o / blocksize != records
-      || lseek (fdesc, o, SEEK_SET) == -1)
+      || lseek (fdesc, o, SEEK_CUR) <= 0)
     {
       while (records-- > 0)
        {

Reply via email to