r+ on fopen.

Guy Harris guy at rlgvax.UUCP
Fri Sep 23 14:50:38 AEST 1983


If this was under V7, I'd be somewhat surprised as the differences between
System III "stdio" (where the documentation claims it works) and V7 "stdio"
are miniscule.  Under 4.?BSD, however, the description (odd vs. even seek
offsets) seems to fit a bug in the 4.?BSD "fseek".  The fix follows:

*** /tmp/,RCSt1011421	Fri Sep 23 00:45:21 1983
--- /tmp/,RCSt2011421	Fri Sep 23 00:45:22 1983
***************
*** 36,41
  		if (iop->_flag & _IORW) {
  			iop->_ptr = iop->_base;
  			iop->_flag &= ~_IOREAD;
  		}
  		p = lseek(fileno(iop), offset-resync, ptrname);
  		iop->_cnt = 0;

--- 36,42 -----
  		if (iop->_flag & _IORW) {
  			iop->_ptr = iop->_base;
  			iop->_flag &= ~_IOREAD;
+ 			resync = 0;
  		}
  		p = lseek(fileno(iop), offset-resync, ptrname);
  		iop->_cnt = 0;

The problem is that if you are switching from reading a stream to writing it,
or vice versa, you must do an "fseek" between the last read and the first
write (this is documented in the System III documentation).  However, on a
stream where the last operation was a read, if told to seek to an odd offset
the 4.?BSD "fseek" will seek to that offset - 1 and then read the next
character.  I presume this was done because copies between kernel and user
space on a PDP-11 are more efficient if both buffers are aligned on word
boundaries (so check 2.?BSD for this as well!).  Unfortunately, this means
that the sequence:

	read
	seek to odd boundary
	write

becomes:

	read
	seek to even boundary
	read one character
	write

which violates the rule that an "fseek" must separate reads and writes.  The
fix merely turns off the seek to even boundary and read on streams open for
reading and writing.  Given this fix, I believe that "[rwa]+" on 4.?BSD will
work as reliably as it does on V7 and System III, so everybody stick this
fix in and then we can rewrite our code to use "[rwa]+".

	Guy Harris
	{seismo,mcnc,we13,brl-bmd,allegra}!rlgvax!guy



More information about the Comp.unix.wizards mailing list