Problem with blocked records in dd(1).
David Herron
david at ukma.UUCP
Fri Nov 30 14:49:19 AEST 1984
Index: /usr/src/bin/dd.c 4.2BSD
Problem: I had a bunch of ascii files that I was writing to a tape.
A large number of them didn't have a carraige return at the end
of the last line. I was writing these with dd(1) fixed length
records of something like 128 columns, blocked at probably
10 records per block. Some of these files would hang on the
tape drive at the end of file. Very strange.
Diagnosis: This took a while. But I found that the last lines of these
files were not being padded out. This was causing problems with
the tape drive which were creating un-killable processes that
were hogging the tape drive. (We still haven't decided if the
problem is in the driver or the drive).
Fix: See the comments in the diff below.
Notes: I am not entirely certain that this is a proper fix as it changes
the behavior of dd. With this change, using dd to block lines
doesn't gaurantee that the file will be the same if you were to
unblock it. If the last line were incomplete then it would be
blocked, and when later unblocked would now have a new-line
tacked on. I went ahead and did the patch because I decided
that blocking/unblocking only makes sense with text files, and
it doesn't make sense for text files to have incomplete lines
in them.
Repeat-by: Do this command:
echo -n "This is an incomplete line" | dd of=file conv=block cbs=80
Look at "file" with od -c. You will see just a very short line.
Cut out the following and run patch on it. (Beware the signature
at the end of the file. Also that line numbers may vary with version
and typing conditions.....)
----------------------------------->Cut Here<----------------------------
*** dd.c.orig Thu Nov 29 23:38:35 1984
--- dd.c Thu Nov 29 23:38:48 1984
***************
*** 1,9
static char *sccsid = "@(#)dd.c 4.3 (Berkeley) 4/29/83";
#include <stdio.h>
#include <signal.h>
#define BIG 2147483647
#define LCASE 01
#define UCASE 02
#define SWAB 04
#define NERR 010
--- 1,29 -----
static char *sccsid = "@(#)dd.c 4.3 (Berkeley) 4/29/83";
#include <stdio.h>
#include <signal.h>
+ /* CHANGES
+ *--- 12-Jun-84 dsh: Problem: If a text file was ended with
+ * an incomplete line (the line lacked its' '\n'), then
+ * dd was not outputting an entire buffer for it, when conv==block.
+ * Since when you want things to be blocked, it is expected that
+ * the output file be an even multiple of the file size, this
+ * is wrong. This also lead to the discovery of an unexpected
+ * problem in the tape driver where it would not write very short
+ * blocks onto the tape, but would hang and leave an unkillable
+ * process lying around.
+ * Diagnosis: The problem lies in the copying loop in main().
+ * EOF is handled fully within the "if (ibc==0 && --nfiles<=0)"
+ * statement. If a line is waiting to be blocked and readied
+ * for output, it won't be. All that gets called is flsh()
+ * which simply outputs the current buffer.
+ * Fix: If the conversion buffer is non-empty (and also not full),
+ * call block with '\n' for the argument. This forces the last
+ * buffer to get blocked.
+ */
+
#define BIG 2147483647
#define LCASE 01
#define UCASE 02
#define SWAB 04
#define NERR 010
***************
*** 317,326
if(ibuf[c] != 0)
ibc = c;
stats();
}
if(ibc == 0 && --files<=0) {
flsh();
term();
}
if(ibc != ibs) {
nipr++;
--- 337,351 -----
if(ibuf[c] != 0)
ibc = c;
stats();
}
if(ibc == 0 && --files<=0) {
+ /* CHANGE 12-Jun-84 dsh: EOF was seen, with an incomplete buffer
+ * for output. complete it.
+ */
+ if (conv==block && cbc>0 && cbc<cbs)
+ block('\n');
flsh();
term();
}
if(ibc != ibs) {
nipr++;
----------------------------------->Cut Here Also<-----------------------
David Herron Arpa: "ukma!david"@ANL-MCS
unmvax----\ /------- Arpa-Net
research >---/----------------/----------- anlams!ukma!david
boulder---/ decvax!ucbvax ---/ (or cbosgd!hasmed!qusavx!ukma!david)
More information about the Comp.unix.wizards
mailing list