[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

dd should be more aggressive about seeking

From: Castor Fu
Subject: dd should be more aggressive about seeking
Date: Tue, 29 Oct 2002 17:51:51 -0800 (PST)

The following code in version 4.1 of fileutils dd seems overly aggressive.
It damns all character devices on all operating systems seems harsh.

There should probably be a flag to ignore the buggy_lseek_support function,
or the testing should be done in a significantly more OS dependent way.

As an example, on NetBSD's in-house dd, they test explicitly for being a pipe
by doing an lseek, and they also do an MTIOCGET to see if they are a tapedrive.


NetBSD code:

    static void
    getfdtype(IO *io)
            struct mtget mt;
            struct stat sb;

            if (fstat(io->fd, &sb))
                    err(1, "%s", io->name);
            if (S_ISCHR(sb.st_mode))
                    io->flags |= ioctl(io->fd, MTIOCGET, &mt) ? ISCHR : ISTAPE;
            else if (lseek(io->fd, (off_t)0, SEEK_CUR) == -1 && errno == ESPIPE)
                    io->flags |= ISPIPE;            /* XXX fixed in 4.4BSD */

4.1 fileutils dd:

    * 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
       the function fails to perform the requested operation.  In that case,
       lseek should return nonzero and set errno.  */

    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:

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

reply via email to

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