[comp.bugs.4bsd] Bug in /usr/ucb/error

michael@garfield.MUN.EDU (Mike Rendell) (04/21/89)

Description:
	Error can trash source files when the file system fills -  it checks
	to see if fwrite() calls fail but does not check to see if the fclose()
	fails.  If the inserted errors cause the file to need another block
	the fclose() fails (the file gets truncated) and the temporary
	file is removed.

Repeat-by:
	Run error on a file that is just under a block in size on a full
	file system.

Fix:
	Check the flose() on both the temporary file and the original file
	to see if it fails.

--
Mike Rendell - Dept. of Comp. Sci, Memorial University of Newfoundland

Index: errortouch.c


*** /tmp/,RCSt1015762	Fri Apr 21 09:19:32 1989
--- errortouch.c	Fri Apr 21 09:17:21 1989
***************
*** 577,583 ****
  			  processname, o_name);
  		}
  	}
! 	fclose(n_touchedfile);
  	fclose(o_touchedfile);
  	/*
  	 *	Now, copy the temp file back over the original
--- 577,588 ----
  			  processname, o_name);
  		}
  	}
! 	if (fclose(n_touchedfile) == EOF) {
! 		botch++;
! 		fprintf(stderr,
! 			"%s: close failure: No errors inserted in \"%s\"\n",
! 			processname, o_name);
! 	}
  	fclose(o_touchedfile);
  	/*
  	 *	Now, copy the temp file back over the original
***************
*** 600,612 ****
  		}
  		if (!botch)
  			oktorm = mustoverwrite(localfile, tmpfile);
! 		if (localfile != NULL)
! 			fclose(localfile);
  		if (tmpfile != NULL)
  			fclose(tmpfile);
  	}
  	if (oktorm == 0){
! 		fprintf(stderr, "%s: Catastrophe: A copy of \"%s\: was saved in \"%s\"\n",
  			processname, o_name, n_name);
  		exit(1);
  	}
--- 605,624 ----
  		}
  		if (!botch)
  			oktorm = mustoverwrite(localfile, tmpfile);
! 		if (localfile != NULL) {
! 			if (fclose(localfile) == EOF) {
! 				if (!botch)
! 					fprintf(stderr,
! 						"%s: close failure: \"%s\"\n",
! 						processname, o_name);
! 				oktorm = 0;
! 			}
! 		}
  		if (tmpfile != NULL)
  			fclose(tmpfile);
  	}
  	if (oktorm == 0){
! 		fprintf(stderr, "%s: Catastrophe: A copy of \"%s\" was saved in \"%s\"\n",
  			processname, o_name, n_name);
  		exit(1);
  	}