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)
{