www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/1998/07/16/06:25:33

Date: Thu, 16 Jul 1998 13:24:19 +0300 (IDT)
From: Eli Zaretskii <eliz AT is DOT elta DOT co DOT il>
To: cssl AT geocities DOT com
cc: djgpp-workers AT delorie DOT com
Subject: Re: FSEXT bug ?
In-Reply-To: <199807152043.NAA16544@geocities.com>
Message-ID: <Pine.SUN.3.91.980716132222.17398L-100000@is>
MIME-Version: 1.0

On Sat, 11 Jul 1998 cssl AT geocities DOT com wrote:

> Getting strange results from FSEXT family of functions, I decided to 
> investigate a bit, so I wrote a test program to see what really happens.
> Well, I think that's NOT the correct behaviour.

Please in the future always explain just *what* is the incorrect
behavior.  Not everybody has time to copy your source to a development
machine, compile it, and debug it.  A verbal explanation of what seems
to be incorrect behavior will usually allow to grasp the problem(s)
much more quickly.  Also, you shouldn't assume that your program will
behave on my machine exactly as it does on yours.

> Well, I think that's NOT the correct behaviour. Please try this little 
> program. Shouldn't it call WRITE only once ? Or at least once for every 
> character, but it shouldn't call it with different parts of the same 
> string ! Uh, try both WITH and WITHOUT the setvbuf(). Without it 
> apparently the first character is lost.

These are all manifestations of two bugs in your code.

First, you unconditionally assign a value of 10 to the *rv parameter:

>  // Just for testing !
>  *rv=10;

But functions like _read and _write (which call your handler) expect
to see the number of bytes read/written in that parameter.  A complete
emulation such as yours should return there the same number as passed
in the nbytes parameter by the caller.  Otherwise, the buffered I/O
machinery will take it that only part of the buffer was written, and
will then repeatedly try to write out the rest.  Which is exactly what
you see: on each repeated call, your handler is called with the nbytes
argument decreased by 10.

You should keep in mind that when you work with Filesystem Extensions,
you get access to the guts of the library which can be easily broken.
Don't lie to the library, or you *will* be punished!

The second bug is here:

>   printf("\nfopen : ");  hnd= fopen("!.tst", "r+b");
> /*  setvbuf(hnd, NULL, _IONBF, 0);*/
>   printf("\nfgets : ");       fgets(buff, 10, hnd);
>   printf("\nfputs : ");       fputs("Hello, world ! I'm here !", hnd);

You are opening the same file with "r+", i.e. for both input and
output.  But such streams require that between input and output you
reposition the stream (e.g. with fseek), otherwise you wreak havoc on
the buffered I/O machinery.  This is an ANSI requirement.  Since you
don't call fseek between fgets and the following fputs, you get
garbled output (``the first character is lost'' etc.), and that is
also the reason that setvbuf changes some of the garbled behaviour.

Last, but not least, your general design looks scary, since you
unconditionally take over every handle opened by the program.
However, some library functions sometimes open special files behind
the scene, on behalf of your program.  For example, time-related
functions might open a file in the zoneinfo directory, to read the
daylight-saving time rules, etc.  You obviously cannot emulate these
cases correctly, so some library functions will mysteriously break.

Once again, you are messing with the library internals at a very low
level here, so a solid design should try to interfere as little as you
can.

For the same reason, it is a bad idea to use stdio functions such as
printf from a handler which catches writes: you might find yourself
calling the handler recursively, and the results might be very
surprising, to say the least ;-).

And btw, your printf uses %s to print a buffer passed to the write 
function, but the buffer you get is not null-terminated.  So you better 
use something like %.*s and pass the nbytes argument to printf as well.

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019