[comp.lang.c] C file access question

stelmack@screamer.csee.usf.edu (Gregory M. Stelmack) (09/14/90)

I've got some code I'm writing for ANSI file access, and have run into a
problem that nobody here can help me with (I've asked). What I am trying to do
is implement a free space list in a file that, when adding a record, the
code will look for an appropriate free space record. If it finds one, it
sticks the data there. If it doesn't, I want to add it on to the end of the
file.

I got this to work on my Amiga using Lattice C 5.04. But, when I uploaded it
to my school's SUN computers, it doesn't run. (SUNOS 4.0.3, cc compiler).
But, it compiles fine.

Anyway, here's the skeleton code (I will send complete code to anyone who
wishes to look further):

int error=0;
long DataLen;   /* passed to function, value checked */
FILE *db;
...
db = fopen("dd.data","rb+"); /* db is checked to make sure file opened */
...
error = fseek(db,0L,2);	/* seek end of file */
if (error==-1) return(GS_DATA_SEEK_ERROR);
error = fwrite((char *)&DataLen,sizeof(DataLen),1,db);
if (error!=1) return(GS_DATA_WRITE_ERROR);   <-- error = 0, so it returns
...

I have tried the seek both ways (EOF back, start forward), and checked all
parameters, and everything looks OK. I have called perror() before returning,
and it gives an Error 0 (no error). Nothing is written to the file. 

Any ideas from anyone who is familiar with the ANSI level 2 file functions?

Thanks in advance,
-- Greg Stelmack
-- Email: stelmack@sol.csee.usf.edu
-- USmail: USF Box 1510, Tampa, FL 33620-1510
-- Amiga: the only way to compute!

pfalstad@phoenix.Princeton.EDU (Paul John Falstad) (09/14/90)

In article <28@screamer.csee.usf.edu> stelmack@screamer.csee.usf.edu (Gregory M. Stelmack) writes:
>db = fopen("dd.data","rb+"); /* db is checked to make sure file opened */

Try this:

 db = fopen("dd.data","r+b");

With that fix, your program works fine on the Sun here.

  I think there should be more race prejudice.  <slap> LESS race prejudice.

otto@tukki.jyu.fi (Otto J. Makela) (09/14/90)

In article <28@screamer.csee.usf.edu> stelmack@screamer.csee.usf.edu (Gregory M. Stelmack) writes:
   I've got some code I'm writing for ANSI file access, and have run into a
   problem that nobody here can help me with (I've asked). [...]

   int error=0;
   long DataLen;   /* passed to function, value checked */
   FILE *db;
   ...
   db = fopen("dd.data","rb+"); /* db is checked to make sure file opened */
   ...
   error = fseek(db,0L,2);	/* seek end of file */
   if (error==-1) return(GS_DATA_SEEK_ERROR);
   error = fwrite((char *)&DataLen,sizeof(DataLen),1,db);
   if (error!=1) return(GS_DATA_WRITE_ERROR);   <-- error = 0, so it returns
   ...
[...]

Are you sure that your cc/libc is ANSI ?  Our sun4 manuals say the following
of the "type" parameter:
          r         open for reading
          w         truncate or create for writing
          a         append: open for writing at end of  file,  or
                    create for writing
          r+        open for update (reading and writing)
          w+        truncate or create for update
          a+        append; open or create for update at EOF

Thus, no support for the ANSI 'b' mode open -- there is no such thing on
Unix, anyway (it would just be ignored).  My guess is that the non-ANSI
library fopen() starts scanning your "type" string, sees the 'b' and quits.
So, no '+' is seen and thus the write mode never gets set -> writes to the
opened file fail.

If this really is the case, you should #define different values like this:
#ifdef __STDC__
#define	OPENAPPEND	"ab+"
#else
#define	OPENAPPEND	"a+"
#endif
and then do
	dp=fopen("dd.data",OPENAPPEND)
(also, using 'a' mode means you don't have to seek the file separately)

Note that this assumes that your compiler and your library match -- both
ANSI or both non-ANSI.  If you use a mixed set, you lose...
--
* * * Otto J. Makela <otto@jyu.fi> * * * * * * * * * * * * * * * * * * * * *
* Phone: +358 41 613 847, BBS: +358 41 211 562 (CCITT, Bell 2400/1200/300) *
* Mail: Kauppakatu 1 B 18, SF-40100 Jyvaskyla, Finland, EUROPE             *
* * * Computers Rule 01001111 01001011 * * * * * * * * * * * * * * * * * * *

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (09/14/90)

In article <28@screamer.csee.usf.edu>, stelmack@screamer.csee.usf.edu (Gregory M. Stelmack) writes:
> I've got some code I'm writing for ANSI file access [under SunOS 4.0.3]

> db = fopen("dd.data","rb+"); /* db is checked to make sure file opened */
                        ^^^

RTFM.  The SunOS 4.0.3 C compiler is _not_ ANSI compliant and Sun have
never pretended that it is.  If you read the manual page for fopen()
[- if you don't know how, here's all it takes:
	man fopen
] the manual page lists all the mode strings that Sun's fopen() understands,
and fb+ isn't one of them.  This "b" stuff is a kluge to work around the PC
convention of using two characters to end a line (ASCII has a "record
separator character", I've never understood why people didn't use that).
UNIX doesn't need it.  The simplest fix should be

		static char BinaryReadWriteMode[] =
	#ifdef	unix
			"r+";
	#else
			"rb+";
	#endif
		...
		db = fopen("dd.data", BinaryReadWriteMode);

-- 
Heuer's Law:  Any feature is a bug unless it can be turned off.

stelmack@screamer.csee.usf.edu (Gregory M. Stelmack) (09/14/90)

Thanks for all those who helped me with my question. We figured it was
something like that, but couldn't find it...I just didn't read the fopen()
man page close enough (didn't notice the lack of 'b'). Anyway, the net saves
another frustrated programmer...

-- Greg Stelmack
-- Email: stelmack@sol.csee.usf.edu
-- USmail: USF Box 1510, Tampa, FL 33620-1510
-- Amiga: the only way to compute!