I missed one case in the tests, sorry.

Attached are (not necessarily in the order shown here):

1.  a diff to be applied after applying the previous patch
2.  a total diff against the original source
3.  compressed tarfile of the 'dd' tests with the new test added


 - chris sylvain



*** dd.c.prev   Mon Oct 16 13:05:29 2000
--- dd.c        Thu Oct 19 11:42:19 2000
***************
*** 1240,1250 ****
  
    if (output_file != NULL)
      {
        int omode = O_RDWR | O_CREAT;
  
!       if (seek_record == 0 && !(conversions_mask & C_NOTRUNC))
        omode |= O_TRUNC;
        output_fd = open (output_file, omode, 0666);
        if (output_fd < 0)
        error (1, errno, "%s", output_file);
  #if HAVE_FTRUNCATE
--- 1240,1251 ----
  
    if (output_file != NULL)
      {
        int omode = O_RDWR | O_CREAT;
  
!       if ((seek_record == 0 && seek_bytes == 0) 
!         && !(conversions_mask & C_NOTRUNC))
        omode |= O_TRUNC;
        output_fd = open (output_file, omode, 0666);
        if (output_fd < 0)
        error (1, errno, "%s", output_file);
  #if HAVE_FTRUNCATE
***************
*** 1252,1261 ****
--- 1253,1268 ----
        {
          off_t o = seek_record * output_blocksize;
          if (o / output_blocksize != seek_record)
            error (1, 0, _("file offset out of range"));
          if (ftruncate (output_fd, o) < 0)
+           error (0, errno, "%s", output_file);
+       }
+ 
+       if (seek_bytes != 0 && !(conversions_mask & C_NOTRUNC))
+       {
+         if (ftruncate (output_fd, seek_bytes) < 0)
            error (0, errno, "%s", output_file);
        }
  #endif
      }
    else
*** dd.c.orig   Sat Sep 19 13:09:23 1998
--- dd.c        Thu Oct 19 11:42:19 2000
***************
*** 93,102 ****
--- 93,108 ----
  static uintmax_t skip_records = 0;
  
  /* Skip this many records of `output_blocksize' bytes before output. */
  static uintmax_t seek_record = 0;
  
+ /* Skip this many bytes before input. */
+ static uintmax_t skip_bytes = 0;
+ 
+ /* Skip this many bytes before output. */
+ static uintmax_t seek_bytes = 0;
+ 
  /* Copy only this many records.  The default is effectively infinity.  */
  static uintmax_t max_records = (uintmax_t) -1;
  
  /* Bit vector of conversions to apply. */
  static int conversions_mask = 0;
***************
*** 298,311 ****
--- 304,322 ----
    ibs=BYTES       read BYTES bytes at a time\n\
    if=FILE         read from FILE instead of stdin\n\
    obs=BYTES       write BYTES bytes at a time\n\
    of=FILE         write to FILE instead of stdout\n\
    seek=BLOCKS     skip BLOCKS obs-sized blocks at start of output\n\
+   bseek=BYTES     skip BYTES at start of output\n\
    skip=BLOCKS     skip BLOCKS ibs-sized blocks at start of input\n\
+   bskip=BYTES     skip BYTES at start of input\n\
        --help      display this help and exit\n\
        --version   output version information and exit\n\
  \n\
+ Only one of each of the [b]seek or [b]skip option pairs may be used\n\
+ at any one time.\n\
+ \n\
  BYTES may be followed by the following multiplicative suffixes:\n\
  xM M, c 1, w 2, b 512, kD 1000, k 1024, MD 1,000,000, M 1,048,576,\n\
  GD 1,000,000,000, G 1,073,741,824, and so on for T, P, E, Z, Y.\n\
  Each KEYWORD may be:\n\
  \n\
***************
*** 319,329 ****
    ucase     change lower case to upper case\n\
    swab      swap every pair of input bytes\n\
    noerror   continue after read errors\n\
    sync      pad every input block with NULs to ibs-size\n\
  "));
!       puts (_("\nReport bugs to <[EMAIL PROTECTED]>."));
        close_stdout ();
      }
    exit (status);
  }
  
--- 330,340 ----
    ucase     change lower case to upper case\n\
    swab      swap every pair of input bytes\n\
    noerror   continue after read errors\n\
    sync      pad every input block with NULs to ibs-size\n\
  "));
!       puts (_("\nReport bugs to <[EMAIL PROTECTED]>."));
        close_stdout ();
      }
    exit (status);
  }
  
***************
*** 651,663 ****
              conversion_blocksize = n;
              invalid |= (conversion_blocksize != n
                          || conversion_blocksize == 0);
            }
          else if (STREQ (name, "skip"))
!           skip_records = n;
          else if (STREQ (name, "seek"))
!           seek_record = n;
          else if (STREQ (name, "count"))
            max_records = n;
          else
            {
              error (0, 0, _("unrecognized option `%s=%s'"), name, val);
--- 662,694 ----
              conversion_blocksize = n;
              invalid |= (conversion_blocksize != n
                          || conversion_blocksize == 0);
            }
          else if (STREQ (name, "skip"))
!           {
!             skip_records = n;
!             /* may use option only when bskip=BYTES option is not used */
!             invalid |= skip_bytes != 0;
!           }
          else if (STREQ (name, "seek"))
!           {
!             seek_record = n;
!             /* may use option only when bseek=BYTES option is not used */
!             invalid |= seek_bytes != 0;
!           }
!         else if (STREQ (name, "bseek"))
!           {
!             seek_bytes = n;
!             /* may use option only when seek=BLOCKS option is not used */
!             invalid |= seek_record != 0;
!           }
!         else if (STREQ (name, "bskip"))
!           {
!             skip_bytes = n;
!             /* may use option only when skip=BLOCKS option is not used */
!             invalid |= skip_records != 0;
!           }
          else if (STREQ (name, "count"))
            max_records = n;
          else
            {
              error (0, 0, _("unrecognized option `%s=%s'"), name, val);
***************
*** 833,842 ****
--- 864,930 ----
            break;
        }
      }
  }
  
+ /* Throw away BYTES on file descriptor FDESC,
+    which is open with read permission for FILE.
+    Store up to BYTES of the data (one BLOCKSIZE at a time) in BUF,
+    if necessary. */
+ 
+ static void
+ bskip (int fdesc, char *file, uintmax_t bytes, size_t blocksize,
+        unsigned char *buf)
+ {
+   struct stat stats;
+ 
+   /* Use fstat instead of checking for errno == ESPIPE because
+      lseek doesn't work on some special files but doesn't return an
+      error, either. */
+   /* FIXME: can this really happen?  What system?  */
+   if (fstat (fdesc, &stats))
+     {
+       error (0, errno, "%s", file);
+       quit (1);
+     }
+ 
+   /* Try lseek and if an error indicates it was an inappropriate
+      operation, fall back on using read.  */
+   if (lseek (fdesc, bytes, SEEK_SET) == -1)
+     {
+       int nread;
+ 
+       while ((bytes-=blocksize) >= 0)
+       {
+         nread = safe_read (fdesc, buf, blocksize);
+         if (nread < 0)
+           {
+             error (0, errno, "%s", file);
+             quit (1);
+           }
+         /* POSIX doesn't say what to do when dd detects it has been
+            asked to skip past EOF, so I assume it's non-fatal.
+            FIXME: maybe give a warning.  */
+         if (nread == 0)
+           break;
+       }
+ 
+       /* sop up any residue .. */
+       if (bytes < 0)
+       {
+         bytes += blocksize;
+ 
+         nread = safe_read (fdesc, buf, bytes);
+         if (nread < 0)
+           {
+             error (0, errno, "%s", file);
+             quit (1);
+           }
+       }
+     }
+ }
+ 
  /* Copy NREAD bytes of BUF, with no conversions.  */
  
  static void
  copy_simple (unsigned char *buf, int nread)
  {
***************
*** 952,961 ****
--- 1040,1052 ----
      obuf = ibuf;
  
    if (skip_records != 0)
      skip (input_fd, input_file, skip_records, input_blocksize, ibuf);
  
+   if (skip_bytes != 0)
+     bskip (input_fd, input_file, skip_bytes, input_blocksize, ibuf);
+ 
    if (seek_record != 0)
      {
        /* FIXME: this loses for
         % ./dd if=dd seek=1 |:
         ./dd: a1 standard output: Bad file number
***************
*** 964,973 ****
--- 1055,1067 ----
         */
  
         skip (output_fd, output_file, seek_record, output_blocksize, obuf);
      }
  
+   if (seek_bytes != 0)
+     bskip (output_fd, output_file, seek_bytes, output_blocksize, obuf);
+ 
    if (max_records == 0)
      quit (exit_status);
  
    while (1)
      {
***************
*** 1146,1156 ****
  
    if (output_file != NULL)
      {
        int omode = O_RDWR | O_CREAT;
  
!       if (seek_record == 0 && !(conversions_mask & C_NOTRUNC))
        omode |= O_TRUNC;
        output_fd = open (output_file, omode, 0666);
        if (output_fd < 0)
        error (1, errno, "%s", output_file);
  #if HAVE_FTRUNCATE
--- 1240,1251 ----
  
    if (output_file != NULL)
      {
        int omode = O_RDWR | O_CREAT;
  
!       if ((seek_record == 0 && seek_bytes == 0) 
!         && !(conversions_mask & C_NOTRUNC))
        omode |= O_TRUNC;
        output_fd = open (output_file, omode, 0666);
        if (output_fd < 0)
        error (1, errno, "%s", output_file);
  #if HAVE_FTRUNCATE
***************
*** 1158,1167 ****
--- 1253,1268 ----
        {
          off_t o = seek_record * output_blocksize;
          if (o / output_blocksize != seek_record)
            error (1, 0, _("file offset out of range"));
          if (ftruncate (output_fd, o) < 0)
+           error (0, errno, "%s", output_file);
+       }
+ 
+       if (seek_bytes != 0 && !(conversions_mask & C_NOTRUNC))
+       {
+         if (ftruncate (output_fd, seek_bytes) < 0)
            error (0, errno, "%s", output_file);
        }
  #endif
      }
    else

ddtests.tar.gz

Reply via email to