[net.bugs.4bsd] dd

Hpda@hplabs.UUCP (HP Data Systems) (03/24/84)

Subject:	dd(1) destroys file if input and output are the same.
Index:		/usr/src/bin/dd.c
Submitter:	Eric Wertz ( ..!ucbvax!hpda!eric,
			     wertz@su-glacier.ARPA,
			     eric@cmu-ee-faraday.ARPA )

Description:
	If file arguments given via "if=" and "of=" are the same, the
	file gets trashed.
	Programs like cp(1) usually catch this.

Repeat-By:
	% cat foo
	This is a test file.
	% dd if=foo of=foo
	0+0 records in
	0+0 records out			(oh dear, this doesn't look good...)
	% cat foo
	%				(sure enough...)

Fix:
	Add <sys/types.h> and <sys/stat.h> to the list of include files.
	and insert code with change bars...

	if(ibf < 0) {
		perror(ifile);
		exit(0);
	}	
|	if (ifile && ofile) {
|		struct stat sbuf_in, sbuf_out;
|
|		/* Can I stat ifile ? */
|		if ( stat(ifile,&sbuf_in) == -1 ) {
|			perror(ifile);
|			exit(0);
|		}
|		/* If ofile exists, test to see if it's the same as ifile */
|		if ( stat(ofile,&sbuf_out) == 0 &&
|		     sbuf_in.st_dev == sbuf_out.st_dev &&
|		     sbuf_in.st_ino == sbuf_out.st_ino ) {
|			fprintf(stderr,"dd: can't copy file onto itself\n");
|			exit(0);
|		}
|	}
	if (ofile)
		obf = creat(ofile, 0666);

Comments:
	This bug occurs in System III, System V, System V.2, and
	4.[12] BSD.

	Of course, there's no way to prevent...
	% dd if=foo >foo			...from trashing a file.

dmmartindale@watcgl.UUCP (Dave Martindale) (03/26/84)

If you really want, you can wait until the input and output files are open
and then do fstat on both of them and compare inumbers and devs.
This would catch the case of dd if=foo >foo

However, I'm going to do none of this.  Dd is often used to copy data
from raw devices, and sometimes it makes sense to have the input and
output "files" the same if they are in fact not files but special files.

Hpda@hplabs.UUCP (HP Data Systems) (03/27/84)

[Sorry if anyone sees this post twice...]
The case of "dd if=foo >foo" (which is equivalent to "cat foo >foo")
is STILL a lose.

CSH opens the output file (the result of the redirection) before the
command is invoked - whether it be dd(1) or cat(1) or whatever(9).
The result is a truncated file.  However you do get a reprieve if
noclobber is set.  cat(1) chooses to tell you about your mistake,
but you can still kiss your file goodbye.
    % cat foo
    beef
    % cat foo >foo
    cat: input foo is output
    % cat foo
    %					(Where's the beef ?)

About copying from "special" devices, point taken.  I was lazy.
The test should be made for S_IFCHR or S_IFBLK as in cat(1).
Hack in the added tests with change bars (is this sufficient ?):

		if ( stat(ofile,&sbuf_out) == 0 &&
|		     sbuf_in.st_mode != S_IFCHR &&
|		     sbuf_in.st_mode != S_IFBLK &&
		     sbuf_in.st_dev == sbuf_out.st_dev &&
		     sbuf_in.st_ino == sbuf_out.st_ino ) {

ian@utcs.UUCP (Ian F. Darwin) (12/05/84)

Index:	bin/dd.c 4.2BSD 

Description:
	The man page for dd(1) is nebulous about which CONV=
	parameters can be combined. Perhaps this is an attempt
	at emulating the etymological origins of the command name,
	but the humor is lost after you waste many hours rewriting tapes.

Repeat-By:
	dd if=foo/bar of=/dev/rmt1 conv=ibm,block
	cat /dev/rmt1

	You will see that the file on tape is in ASCII,
	indicating that the `block' option has caused the `ibm'
	option to be silently ignored.

Fix:
	While `block' is new in 4.?BSD, some vagueness is present
	in V7, System V et. al, although it is unlikely to cause
	serious confusion except in 4.?BSD.

	To fix it, add the following paragraph to BUGS in the manual page:

.PP
Certain combinations of arguments to 
.I conv=
are permitted.
However, the
.I block
or
.I unblock
option cannot be combined with
.IR ascii ,
.IR ebcdic ""
or
.IR ibm .
Invalid combinations
.I "silently ignore"
all but the last mutually-exclusive keyword.
-- 
Ian Darwin, Toronto
{ihnp4|decvax}!utcs!ian