[net.bugs.4bsd] Problem with blocked records in dd

david@ukma.UUCP (David Herron) (11/30/84)

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)