Subject: bin/774: compress interacts in unexpected way with fdesc filesystem
To: None <gnats-admin@NetBSD.ORG>
From: Brad Spencer <brad@anduin.eldar.org>
List: netbsd-bugs
Date: 02/01/1995 20:20:05
>Number:         774
>Category:       bin
>Synopsis:       compress interacts in unexpected way with fdesc filesystem
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    bin-bug-people (Utility Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Wed Feb  1 20:20:03 1995
>Originator:     Brad Spencer
>Organization:
"	At home one day"
>Release:        NetBSD-current around 1/30 or so
>Environment:
	P90, NetBSD-current i386, standard stuff
System: NetBSD anduin.eldar.org 1.0A NetBSD 1.0A (ANDUIN) #0: Wed Feb 1 21:03:50 EST 1995 brad@anduin.eldar.org:/usr/src/sys/arch/i386/compile/ANDUIN i386


>Description:
	The compress utility acts in an unexpected way with a fdesc
	filesystem is union mounted with /dev and compress has had its
	standard in and	standard out redirected.
>How-To-Repeat:
	Following the instructions in the mount_fdesc man page and union
	mount said filesystem on /dev.  Do the following:
		cd /tmp
		cp /etc/hosts hosts
		compress < hosts > h.Z
	At this point a message will me printed on stderr asking whether or
	not '/dev/stdin' should be overwritten.  Of course, one can not
	answer this question, as stdin is currently the input file.  And
	nothing shows up in h.Z.
>Fix:
	One might debate where the bug is actually located at, but the
	reason for the interaction is because the fdesc filesystem symlinks
	/dev/std* to /dev/fd/* which are files of the same type as the file
	which is stdin, etc, be that a regular file, a pipe or tty.  So, when
	one redirects a regular file into compress, /dev/stdin suddenly
	becomes a symlink to a regular file type.  This effect causes a couple
	of the checks in compress to pass, when they should not have.
	Following is a diff which seems to cause compress to work correctly
	when a fdesc is mounted as /dev.

*** compress.c.ORIG	Sun Dec 25 06:26:26 1994
--- compress.c	Wed Feb  1 10:16:32 1995
***************
*** 201,207 ****
  	exists = !stat(out, &sb);
  	if (!force && exists && S_ISREG(sb.st_mode) && !permission(out))
  		return;
! 	isreg = oreg = !exists || S_ISREG(sb.st_mode);
  
  	ifp = ofp = NULL;
  	if ((ifp = fopen(in, "r")) == NULL) {
--- 201,207 ----
  	exists = !stat(out, &sb);
  	if (!force && exists && S_ISREG(sb.st_mode) && !permission(out))
  		return;
! 	isreg = oreg = !exists || S_ISREG(sb.st_mode) && (strcasecmp(out,"/dev/stdout") != 0);
  
  	ifp = ofp = NULL;
  	if ((ifp = fopen(in, "r")) == NULL) {
***************
*** 212,218 ****
  		cwarn("%s", in);
  		goto err;
  	}
! 	if (!S_ISREG(isb.st_mode))
  		isreg = 0;
  
  	if ((ofp = zopen(out, "w", bits)) == NULL) {
--- 212,218 ----
  		cwarn("%s", in);
  		goto err;
  	}
! 	if ((!S_ISREG(isb.st_mode)) || (strcasecmp(in,"/dev/stdin") == 0))
  		isreg = 0;
  
  	if ((ofp = zopen(out, "w", bits)) == NULL) {
***************
*** 291,297 ****
  	exists = !stat(out, &sb);
  	if (!force && exists && S_ISREG(sb.st_mode) && !permission(out))
  		return;
! 	isreg = oreg = !exists || S_ISREG(sb.st_mode);
  
  	ifp = ofp = NULL;
  	if ((ofp = fopen(out, "w")) == NULL) {
--- 291,297 ----
  	exists = !stat(out, &sb);
  	if (!force && exists && S_ISREG(sb.st_mode) && !permission(out))
  		return;
! 	isreg = oreg = !exists || S_ISREG(sb.st_mode) && (strcasecmp(out,"/dev/stdout") != 0);
  
  	ifp = ofp = NULL;
  	if ((ofp = fopen(out, "w")) == NULL) {
***************
*** 307,313 ****
  		cwarn("%s", in);
  		goto err;
  	}
! 	if (!S_ISREG(sb.st_mode))
  		isreg = 0;
  
  	while ((nr = fread(buf, 1, sizeof(buf), ifp)) != 0)
--- 307,313 ----
  		cwarn("%s", in);
  		goto err;
  	}
! 	if ((!S_ISREG(sb.st_mode)) || (strcasecmp(in,"/dev/stdin") == 0))
  		isreg = 0;
  
  	while ((nr = fread(buf, 1, sizeof(buf), ifp)) != 0)
***************
*** 384,389 ****
--- 384,391 ----
  
  	if (!isatty(fileno(stderr)))
  		return (0);
+ 	if (!isatty(fileno(stdin)))
+ 		return (1);
  	(void)fprintf(stderr, "overwrite %s? ", fname);
  	first = ch = getchar();
  	while (ch != '\n' && ch != EOF)
>Audit-Trail:
>Unformatted: