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
On 12/13, Valery Ushakov wrote:
> [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?
Yeah, I see your point. Unfortunately, that's not how I was thinking
nor what I understood when I read the NetBSD fgets(3) man page and then
wrote my application that used fgets(3).
> > Here's what the NetBSD man page says at the end of the first paragraph
> > in the Description section:
> >
> > Reading stops when a newline character is found, at end-of-file or
> > error. The newline, if any, is retained, and a `\0' character is
> > appended to end the string.
> >
> > 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.
OK, but I don't think the NetBSD man page makes that distinction, so it
wasn't clear to me.
> > 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.
Agreed that that too is not clear.
> 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.
Agreed that the POSIX wording is even more clear.
> 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.
Agreed that the partial-read-then-error case is not clear.
Thanks for your comments!
I think that adding the sentence that FreeBSD has would be an
improvement. I agree that addressing the things you brought up would be
even better. But I haven't looked at the source to know what happens
for the partial-read-then-error case, and I'm not sure I know how to
reproduce that case to test it either, so I'd find it difficult to add
wording for that. But if someone knows how it handles that case and
could tell me, and if it would be helpful (as opposed to that someone
just editing the man page themselves), I could come up with a proposed
edit that would address both issues?
Thanks!
Lewis
Home |
Main Index |
Thread Index |
Old Index