[comp.sys.atari.st] Fcreate

daemon@stag.UUCP (11/18/87)

> I recently read on this net (by Dale Schumacher) that Gemdos Fcreate
> does not  work properly.  Can someone (maybe Dale) elaborate on that?
> I use this function in an editor program, which means quite often for
> existing files, and I never ran into problems: Existing files are
> properly deleted before  a new file with the same name is created.
> How can this bug be observed? If I can reproduce it, I have to do the
> trick with Fdelete first. But at present I see no need for that.
> 
> Roland Waldi

  The Fcreate() problem is a difficult one to pin down.  I'm still not
sure what the exact cause is.  In the version of MicroEMACS that I modified,
the Fcreate() function was used to create the output file (presumably
overwriting any existing file).  Occasionally it would create two files
with the same name in a single directory.  Several other ST owners that
I know have reported similar problems, by not frequently.  The problem
seems to occur more with smaller files (< 1K), like shell scripts.  To
avoid this problem, I implemented a creat() call in dLibs which always
deletes the file before creating it, as shown by the source code I posted.
Since Fdelete() is relatively quick and Fcreat() is quite slow, the extra
time spent deleting the file is hardly noticed.  If anyone knows anything
more about this problem, I'd like to hear about it.

                Dale Schumacher
                ..ihnp4!meccts!stag!syntel!dal
                (alias: Dalnefre')

bds@lzaz.ATT.COM (BRUCE SZABLAK) (11/18/87)

In article <260@stag.UUCP>, syntel!dal@stag.UUCP (Dale Schumacher) writes:
> Occasionally it would create two files
> with the same name in a single directory.

Some time ago I wrote a shell with a built in cat command. Whenver a
cat was interrupted by a ^C (caught by the shell which would close
the file being cat'ed) I would notice that duplicate entries in the
directory for the cat'ed file would be generated later when that
file was re-created.

apratt@atari.UUCP (Allan Pratt) (11/20/87)

>   The Fcreate() problem is a difficult one to pin down.

Yes.

> Occasionally it would create two files
> with the same name in a single directory.

I found out why: in GEMDOS, Fcreate calls Fdelete, but doesn't check to see
if the delete actually worked.  If the delete fails for some reason, Fcreate
doesn't notice, and creates another file by the same name.

> I implemented a creat() call in dLibs which always
> deletes the file before creating it[.]

This won't help, because if Fcreate's call to Fdelete fails, yours will too.

> Since Fdelete() is relatively quick and Fcreat() is quite slow [...]

Fcreate is not slow.  The first write to the file after Fcreate is slow. 
This is because the code which looks for the first free cluster on the
device is slow.  This is especially noticable for large, nearly-full
devices.  We are addressing this problem.

Now here's the tricky part:  Fdelete (as called from outside GEMDOS or
within it, like from Fcreate) checks to see if anybody has the file open.
If the current process has the file open, Fdelete closes it before deleting
it.  If some OTHER process has the file open, Fdelete returns EACCDN
("access denied").  This seems to be what is happening, but I can't
figure out why, because nobody else has the file open!

I can always reproduce this problem.  Here's how:

	Proc1:
	------
	Fcreate ("file1",0);
	Fcreate ("file2",0);
	Pexec(4,"Proc2",0L,0L);

				Proc2:
				------
				Fdelete("file1",0);
				/* returns EACCDN: Proc1 has file open */

				Fcreate("file2",0);
				/* works, even though it should fail */

				Pterm0();
	Pterm0();

Now there are two copies of "file2" in the current directory, even though
the failed Fdelete of "file1" in Proc2 shows that GEMDOS is checking for
file ownership.

I can't figure out why this happens in Emacs so much, but it happens. 
If you fix Fcreate so it does check the return code from Fdelete and
returns EACCDN, Emacs will tell you it can't open the file for writing. 
This is more correct behavior than creating two files, but still doesn't
explain why Fdelete thinks somebody else has the file open when nobody
else does. 

============================================
Opinions expressed above do not necessarily	-- Allan Pratt, Atari Corp.
reflect those of Atari Corp. or anyone else.	  ...ames!atari!apratt

jpdres13@usl-pc.UUCP (John Joubert) (11/20/87)

-----------------------------------------------

I have been using "Assempro" from Abacus and it will create more than one
bearing the same name at times, and some times not.  When I save my executable
file to disk, sometimes I will get dual files that I will notice when I leave
Assempro and look at my working directory.  Pretty weird and kind of annoying.

I will start to notice the file size and see if it is only small files that
get written out without the old one getting wiped out.

Anyone else?

----------------------------------------------------------------------------
John Joubert                         |     /\  |    /\    |     _ 
jpdres13@usl-pc.USL                  |     \|<>|>|> \|<>|>|><`|`|
or ...                               |-----/|-------/|-----------------------
ut-sally!usl-pc!jpdres13             |     \/       \/
-----------------------------------------------------------------------------

c9c-eh@dorothy.Berkeley.EDU (Warner Young (WHY)) (11/21/87)

[line-eater]  [line-eater]  oops!

	Here's a possible solution to the Fcreate() bug.  It remains
	for Netlanders to tell me if it works, as my hard disk is
	kaput right now, and I'm not sure where my C compiler is
	on floppy.

Before creating a file, use Fopen() to read it.  If you can read it,
it exists.  Then, just overwrite it with Fwrite().  If it does not
exist, use Fcreate().  The problem is, will Fopen() suffer the same
problem as Fdelete()?
						\          /
Disclaimer:  I'm not associated			 \  /\    /arner
	with the latest revision		  \/  \__/
	of SANITY.				         |oung
						     \___|
Last known address: c9c-eh@dorothy.Berkeley.EDU
			or
		    ucbvax!dorothy!c9c-eh

daemon@stag.UUCP (11/23/87)

>> Occasionally it would create two files
>> with the same name in a single directory.
>
> I found out why: in GEMDOS, Fcreate calls Fdelete, but doesn't check to see
> if the delete actually worked.  If the delete fails for some reason, Fcreate
> doesn't notice, and creates another file by the same name.
>
>> I implemented a creat() call in dLibs which always
>> deletes the file before creating it[.]
>
> This won't help, because if Fcreate's call to Fdelete fails, yours will too.
>

This WILL* help, because I check the return value from Fdelete() to be sure
that it succeeds.  The code is as follows (from the extended arg proposal):

/*
 * Create a new file <filename> with <pmode> permissions
 */
int creat(filename, pmode)
	register char *filename;
	register int pmode;
	{
	register int rv;

	rv = Fdelete(filename);
	if((rv == 0) || (rv == -33))    /* SUCCESS or FILE-NOT-FOUND */
		{
		if((rv = Fcreate(filename, pmode)) >= 0)
			iovector[rv] = 'F';
		}
	return(rv);
	}

> Now here's the tricky part:  Fdelete (as called from outside GEMDOS or
> within it, like from Fcreate) checks to see if anybody has the file open.
> If the current process has the file open, Fdelete closes it before deleting
> it.  If some OTHER process has the file open, Fdelete returns EACCDN
> ("access denied").  This seems to be what is happening, but I can't
> figure out why, because nobody else has the file open!

Yes.  In my implementation of creat(), any error except -33 (EFILNF) will
be returned without calling Fcreate().  Error code -36 (EACCDN) is therefore
returned if the file can't be deleted due to the Fcreate() bug.  In emacs,
this causes a file write error and you can then write the file out under a
different name, which is better than silently creating a duplicate.

                Dale Schumacher
                ..ihnp4!meccts!stag!syntel!dal
                (alias: Dalnefre')