[net.lang.c] read/write same file with one open -- Query

rcj (01/27/83)

HELP!!!  A recent article in this newsgroup asked how to read a file
and then write back over it without closing it and then reopening with
write permission.  I tried a simple program to open a file for reading,
read its information, rotate that information, change the permission
bits in the _iob structure read/write flag to allow writing, and then
write the rotated info over the old stuff in the file.  Simple, no?
NO!!  The file remained unchanged.  I experimented and found that when
I used read to get the info from the file, the pointer to the next
character (fp->_ptr) was 0 before the read (immediately after opening
the file), and 0 AFTER the read as well!!  So I tried to read the
info and then do an lseek(fp->_file, 0L, 0) to 'rewind' the file and
then write back over it.  Still no dice, file remained unchanged.
Finally, I resorted to the program below:  open the file for reading,
immediately change permission to write, immediately write something into
the file, and immediately close the file.  Still no change in the file
contents.  Either I've overlooked something really dumb and simple, or
(I hope) I just don't know enough about Unix to figure this out.  I
sure hope that some of you wizards out there read lang.c, I assumed that
you do and did not send this to unix-wizards to avoid gumming the net.
Please mail me any comments, and I would also appreciate knowing what
the _IORW in stdio.h is used for.

Thanks, program follows,

The MAD Programmer
alias:  Curtis Jackson	...!floyd!burl!rcj
			...!sb1!burl!rcj
			...!mhuxv!burl!rcj


#include <stdio.h>

main()
{
	FILE *fp;

/*
Cat foobar (it initially contains the letters of the alphabet and a
	newline.
Print the values indicating that a file is open for writing/reading
	(_IOWRT=2, _IOREAD=1).  These are taken straight from <stdio.h>;
	we are running BTL 5.0 here on a Vax 11/780.
Open foobar for reading.
Print the value of the read/write flag; it is 1.
Clear the read and write permission bits in the mode flag and or the
	result with the write value to enable the file for writing.
Print the value of the read/write flag now; it is 2.
Print the string "This is a test.\n" into foobar.
Close foobar.
Cat foobar.
*/
	system("cat foobar");
	fprintf(stderr,"\n_IOWRT=%d, _IOREAD=%d\n",_IOWRT,_IOREAD);
	fp = fopen("foobar", "r");
	fprintf(stderr,"%d\n",fp->_flag);
	fp->_flag = (fp->_flag & ~(_IOREAD | _IOWRT)) | _IOWRT;
	fprintf(stderr,"%d\n",fp->_flag);
	fprintf(fp,"%s\n","This is a test.");
	fclose(fp);
	system("cat foobar");
}

ark (01/28/83)

UNIX System III and, I believe, Berkeley UNIX allow a file to
be opened read/write.  You say:

	FILE *f;
	f = fopen("file", "r+");

(or "w+")  The + means that you can read and write.  WARNING:
If you have been reading and you want to write, or vice versa,
you must "switch modes."  This can be done by executing
lseek or rewind on the file.  Normally you will do one of these
anyway when changing.  (change lseek to fseek in the above line)
Note that fseek(f,0L,1) is a no-op, except that after you do it,
you can either read or write the file.

lepreau (02/03/83)

Unfortunately the implementation is buggy-- it appears that
seeking to the same spot does not always work when switching 
directions.  Some changed data never gets flushed.

-Jay