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