diff options
author | Jim Meyering <jim@meyering.net> | 2001-12-02 07:49:46 +0000 |
---|---|---|
committer | Jim Meyering <jim@meyering.net> | 2001-12-02 07:49:46 +0000 |
commit | e03be48b10c3bba49fc692223362d743f1e1aaa4 (patch) | |
tree | 2c83de903f1153c2d7667f422de630e4b133e998 /src | |
parent | b8efd17fe85139547a6e7eded9d07fd76293aab9 (diff) | |
download | coreutils-e03be48b10c3bba49fc692223362d743f1e1aaa4.tar.xz |
Don't emulate dd's skip=N for *all* character devices; lseek works
just fine on non-tape character devices like /dev/mem and /dev/kmem.
(buggy_lseek_support) [__linux__]: Emulate `skip=N'
behavior using reads, not lseek for Linux tape devices (major == 9).
Kernel lseek support for tapes is broken, up to and including
linux-2.4.16. Reported by Herbert Xu.
Diffstat (limited to 'src')
-rw-r--r-- | src/dd.c | 29 |
1 files changed, 11 insertions, 18 deletions
@@ -739,33 +739,26 @@ swab_buffer (char *buf, size_t *nread) /* Return nonzero iff the file referenced by FDESC is of a type for which lseek's return value is known to be invalid on some systems. Otherwise, return zero. - For example, return nonzero if FDESC references a character device - (on any system) because the lseek on many Linux systems incorrectly - returns an offset implying it succeeds for tape devices, even though + For example, return nonzero if FDESC references a Linux tape device + because that lseek returns an offset implying it succeeds, even though the function fails to perform the requested operation. In that case, - lseek should return nonzero and set errno. */ + lseek should return a negative number and set errno. The offending + behavior has been confirmed with an Exabyte SCSI tape drive accessed + via /dev/nst0 on both Linux-2.2.17 and Linux-2.4.16. */ +#ifdef __linux__ static int buggy_lseek_support (int fdesc) { - /* We have to resort to this because on some systems, lseek doesn't work - on some special files but doesn't return an error, either. - In particular, the Linux tape drivers are a problem. - For example, when I did the following using dd-4.0y or earlier on a - Linux-2.2.17 system with an Exabyte SCSI tape drive: - - dev=/dev/nst0 - reset='mt -f $dev rewind; mt -f $dev fsf 1' - eval $reset; dd if=$dev bs=32k of=out1 - eval $reset; dd if=$dev bs=32k of=out2 skip=1 - - the resulting files, out1 and out2, would compare equal. */ - struct stat stats; return (fstat (fdesc, &stats) == 0 - && (S_ISCHR (stats.st_mode))); + && (S_ISCHR (stats.st_mode)) + && major (stats.st_rdev) == 9); } +#else +# define buggy_lseek_support(Fd) 0 +#endif /* Throw away RECORDS blocks of BLOCKSIZE bytes on file descriptor FDESC, which is open with read permission for FILE. Store up to BLOCKSIZE |