tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: fgets(3) man page clarity on when NUL appended



[summoning kre@]

On Thu, Dec 12, 2024 at 13:58:06 -0600, J. Lewis Muir wrote:

> fgets() reads EOF right away, it does not append a NUL character.  (I
> confirmed this behavior on NetBSD 9.3 release.)  I think it would be
> helpful to clarify this in the man page.

If it reads EOF right away, it returns NULL to indicate that no read
has been performed, isn't it?  When there's no read performed, why
would it touch its argument it is supposed to read into?


> I interpreted that to mean that it always appends a NUL character
> regardless of why it stopped reading.  But that's not what it does.

It didn't stop reading, when you are at EOF, it didn't even start
reading.


> The FreeBSD fgets(3) man page
> 
>   https://man.freebsd.org/cgi/man.cgi?query=fgets&sektion=3
> 
> says the following, which I think is clearer and would have likely
> helped me avoid my initial misunderstanding:
> 
>   Reading stops when a newline character is found, at end-of-file or
>   error.  The newline, if any, is retained.  If any characters are read
>   and there is no error, a `\0' character is appended to end the string.

"...and there is no error..." is equally unclear to me.  I'd venture a
guess it means that if no reading was done b/c of an error, not that
some reading was done and then there was an error.  As written, the
text above says (at least that's how I'd read it) that in the latter
case there's no NUL appended.

https://pubs.opengroup.org/onlinepubs/9799919799/functions/fgets.html
POSIX is more clear:

    The fgets() function shall read bytes from stream into the array
    pointed to by s until n-1 bytes are read, or a <newline> is read
    and transferred to s, or an end-of-file condition is encountered.
    A null byte shall be written immediately after the last byte read
    into the array.  If the end-of-file condition is encountered
    before any bytes are read, the contents of the array pointed to by
    s shall not be changed.

  RETURN VALUE

    Upon successful completion, fgets() shall return s.  If the stream
    is at end-of-file, the end-of-file indicator for the stream shall
    be set and fgets() shall return a null pointer.  If an error
    occurs, the error indicator for the stream shall be set, fgets()
    shall return a null pointer, and shall set errno to indicate the
    error.

but the error case as written seems to demand that partial read
interrupted by an error should return NULL, but the earlier text
demands that the buffer (with partial data) should be NUL-terminated.
It's not clear how a program should tell that partial read case apart
from the failed read case.


PS: Disclaimer: I didn't RTFS.

-uwe


Home | Main Index | Thread Index | Old Index