[comp.bugs.4bsd] 4.3BSD rcp doesn't handle FIFO files nicely

dce@mips.UUCP (David Elliott) (07/16/87)

Index:	bin/rcp.c 4.3BSD

Description:
	Before you go yelling at me about FIFO files not being in
	4.3, this came about as a result of porting the 4.3 rcp
	to our System V.3-based system that has BSD TCP/IP.

	Rcp checks source file types by doing an open() followed by
	an fstat(). Since FIFO files block on open if there is no
	process on the other side, the rcp just hangs forever.

Repeat-By:
	Get on a system with FIFO files and rcp (which, according
	to an AT&T marketing person I met a couple of years ago,
	is any Unix system, though we know better) and try

		rcp fifo-file machine:

Fix:
	The easiest fix is to just not allow rcp of FIFO files, even
	though it's really a hard call to make. We decided that it's
	better to force someone to work around the restriction than
	to have a naive user get stung by a hung "rcp * machine:".

	I did this by changing rcp to do a stat() followed by an open()
	instead of the open()-fstat() sequence.

	The following can be used to patch rcp.c:


*** rcp.c.old
--- rcp.c
***************
*** 367,378 ****
  
  	for (x = 0; x < argc; x++) {
  		name = argv[x];
! 		if ((f = open(name, 0)) < 0) {
  			error("rcp: %s: %s\n", name, sys_errlist[errno]);
  			continue;
  		}
- 		if (fstat(f, &stb) < 0)
- 			goto notreg;
  		switch (stb.st_mode&S_IFMT) {
  
  		case S_IFREG:
--- 367,376 ----
  
  	for (x = 0; x < argc; x++) {
  		name = argv[x];
! 		if (stat(name, &stb) < 0) {
  			error("rcp: %s: %s\n", name, sys_errlist[errno]);
  			continue;
  		}
  		switch (stb.st_mode&S_IFMT) {
  
  		case S_IFREG:
***************
*** 380,386 ****
  
  		case S_IFDIR:
  			if (iamrecursive) {
- 				(void) close(f);
  				rsource(name, &stb);
  				continue;
  			}
--- 378,383 ----
***************
*** 387,394 ****
  			/* fall into ... */
  		default:
  notreg:
- 			(void) close(f);
  			error("rcp: %s: not a plain file\n", name);
  			continue;
  		}
  		last = rindex(name, '/');
--- 384,394 ----
  			/* fall into ... */
  		default:
  notreg:
  			error("rcp: %s: not a plain file\n", name);
+ 			continue;
+ 		}
+ 		if ((f = open(name, 0)) < 0) {
+ 			error("rcp: %s: %s\n", name, sys_errlist[errno]);
  			continue;
  		}
  		last = rindex(name, '/');
-- 
David Elliott		{decvax,ucbvax,ihnp4}!decwrl!mips!dce

dce@mips.UUCP (David Elliott) (07/17/87)

In article <520@quacky.UUCP> dce@mips.UUCP (David Elliott) writes:
>Fix:
>	The easiest fix is to just not allow rcp of FIFO files, even
>	though it's really a hard call to make. We decided that it's
>	better to force someone to work around the restriction than
>	to have a naive user get stung by a hung "rcp * machine:".

I'd like to retract this statement to avoid confusion. I don't want
people saying "his reasoning is wrong, so the fix is wrong".

The fact is that *any* user will get *stung* without this fix.
You can't copy anything but regular files with rcp (rcp -r doesn't
copy the directories, it just copies the regular files in them),
and a FIFO, like a character or block special device, is not a
regular file.

What my fix does is to stop rcp from being blocked on opening a
file that can't be copied anyway.

As a side note, when I fixed the System V cp (and mv) to not
copy FIFO files by default, I added an option to override this.
So, my thinking wasn't completely clouded, I just had marbles
in my mouth.

-- 
David Elliott		{decvax,ucbvax,ihnp4}!decwrl!mips!dce