[net.bugs.usg] Bug in USG 5.2 stdio package.

gupta@asgb.UUCP (10/25/84)

Description:  If a file is opened [using fopen(3S)] in the "r+" mode, read till
	the end of file is reached, and then written to using "fprintf(3S)",
	the call returns the correct number of characters written to the file
	but does NOT append to the file! To recreate the effects, try the 
	program given below.

Environment:  Vax-11/780*, running Unix* 5.2

Solution:  ??? (Use sprintf and fputs instead :-)

/* -------  Program to create the problem:  -------- */
/*
	Bug in stdio routines.
	This program finds out the number of lines (assumes line length < LEN)
	in a file and then appends line to the file containing the count.

	step 1.  Compile with code segment 1 and test.
		 It works.
	step 2.  Compile with code segment 2 and test.
		 It doesn't work!
	PROGRAM USES fopen.test AS TEST FILE. fopen.test SHOULD EXIST.
*/

#include  <stdio.h>

#define   INF  "fopen.test"
#define   LEN  80

main()
{
	FILE *fp;
	int  j = 0;
	char line[LEN], *p;
	
	fp = fopen(INF, "r+");     /* Open file for read and update */
	while ((p=fgets(line,LEN,fp)) != NULL) /* find num. of lines in file */
		j++;

	/* Begin segment 1 -- Write the number of lines to string and then
			      write string to file   */

	sprintf(line,"%d\n",j); 
	j = fputs(line,fp);

	/* End segment 1 */

	/* Begin segment 2 -- Write number of lines to file

	j = fprintf(fp,"%d\n",j);

	-- End segment 2 */

	fprintf(stdout, "Number of chars written: %d\n",j); /* print number of
							    chars written */
	fclose(fp);   		    /* Close file */
	exit(0);
}

/* -------------------------  End of program  ------------------ */

* Vax-11/780 is a trademark of Digital Equip. Corp.
  Unix is a trademark of Bell Labs.

Yogesh Gupta
sdcrdcf -- bmcg!asgb!gupta
sdcsvax -/

mp@allegra.UUCP (Mark Plotnick) (10/29/84)

This bug (sans fix) is documented in the SVR2 release notes booklet.
A helpful person at the Lisle hotline said the errors were in
*printf.c, in which the code incorrectly uses the | operator to test
bit flags.  He also pointed out that the printfs work fine on the
3B20 even though the sources are identical!
	Mark

jm@wlbr.UUCP (James Macropol) (10/31/84)

.

<stdio> usually requires an fseek() when switching between read <--> write
modes on a file opened in any of the "+" modes.  This is to insure that the
buffer pointers are set up properly.

Jim Macropol
{ihnp4,trwrb,scgvaxd,vortex}!wlbr!jm

gupta@asgb.UUCP (11/01/84)

>  <stdio> usually requires an fseek() when switching between read <--> write
>  modes on a file opened in any of the "+" modes.  This is to insure that the
>  buffer pointers are set up properly.
>  
>  Jim Macropol
>  {ihnp4,trwrb,scgvaxd,vortex}!wlbr!jm

This is what the Programmer Reference Manual states:

-  FOPEN(3S)
-   		.
-   		.
-   		.
-
-          When a file is opened for update, both input and output may
-          be done on the resulting stream.  However, output may not be
-          directly followed by input without an intervening fseek or
-          rewind, and input may not be directly followed by output
-          without an intervening fseek, rewind,[1m or an input operation
-          which encounters end-of-file.[0m

Thus, after an input operation that encounters end-of-file, the printf should
work. Also, the printf doesn't work even if an fseek is added! Once you
start reading the file, you just cannot write it using the printf!!

Yogesh Gupta
{sdcrdcf, sdcsvax}!bmcg!asgb!gupta

jim@ISM780B.UUCP (11/03/84)

><stdio> usually requires an fseek() when switching between read <--> write
>modes on a file opened in any of the "+" modes.  This is to insure that the
>buffer pointers are set up properly.

The manual says fseek isn't necessary of EOF is reached on input.

phil@qfdts.OZ (Phil Chadwick) (11/07/84)

In our release of Sys V r2.0 there were four versions of 
"printf" containing a bug which directs the output into the bit
bucket under some circumstances.  The subroutines live in the
directory "/usr/src/lib/libc/port/print".  They are:

	fprintf.c	version 1.5	) Our release may well
	printf.c	version 1.5	\ differ from yours.
	vfprintf.c	version 1.1	/ Check that the versions
	vprintf.c	version 1.1	) are the same!

These routines all fail under circumstances where:

	(a)  a stream is opened for update,
	(b)  data are read from or written to the stream,
	(c)  an fseek() is issued,
	(d)  one of the above *printf() routines is used to
	     write a small amount of data to the stream
	     (i.e. less than a buffer full),
	(e)  the stream is fflush()'d.

The cause of the problem appears to be due to a failure of the
printf routines to reset the _cnt field of the appropriate FILE
structure from zero to the size of the buffer being used prior
to writing to the stream.

I applied the following fixes to fprintf.c, printf.c, vfprintf.c
and vprintf.c some time ago and have had no further problems:

	(a) Insert "#include ../stdio/stdiom.h" in each file.

	(b) For fprintf.c and vfprintf.c replace the first 
	    compound if statement with:

		if(_WRTCHK(iop) != 0)
			return EOF;

	(c) For printf.c and vprintf.c replace the first 
	    compound if statement with:

		if(_WRTCHK(stdout) != 0)
			return EOF;

----
Phil Chadwick			Australia:	(07) 2296500
Department of Forestry		International:	+61 7 2296500
PO Box 5
Brisbane, Roma Street		SUN:	phil:qfdts		
AUSTRALIA	4001		UUCP:	{decvax,vax135}!mulga!phil:qfdts