Hi Eric, Thank you for digging out the previous threads on this topic.
Eric Blake wrote: > Waaaay back when, coreutils used to use SET_BINARY. We changed that to > use freopen(NULL) because of the POSIX wording that allowed NULL to > change mode, because cygwin honored the mode change, and because Paul > preferred using a POSIX interface over a complete extension interface. > > Commit 8770c00ef, Jul 2005 > https://lists.gnu.org/archive/html/bug-coreutils/2005-07/msg00059.html > > Also, at one point, I proposed a patch to xfreopen, to which Bruno > counterproposed a new API fchangemode() that would alter a FILE* to be > binary without the baggage of freopen(NULL), although I never really > pursued it: > > https://lists.gnu.org/archive/html/bug-gnulib/2010-03/msg00111.html > > Now it looks like we've come full circle, and that the POSIX wording of > freopen(NULL) is so broken as to not be worth using via gnulib Yes. Aside the issue with O_TEXT / O_BINARY being out of scope of POSIX, there is also the issue with the file position. As I understand it, freopen (NULL, ...) shall - if it succeeds - set the file position back to 0. Citing POSIX [1]: "even though the 'b' is ignored, a successful call to freopen (NULL, "wb", stdout) does have an effect. In particular, for regular files it truncates the file and sets the file-position indicator for the stream to the start of the file." Similarly, for stdin, a successful call to freopen (NULL, "rb", stdin) must rewind the read-position of stdin to 0. Thus when used in a program 'prog', in the command { dd of=/dev/null count=1; prog; } < regular_file 'prog' will start reading from the beginning of regular_file, as if the dd command was not present. I think this is unintended. Most coreutils will *just* want to switch to binary mode without rewinding. So, I continue to be in favour of APIs which don't need to fiddle with FILE internals and with the file position. Like the proposed [2] fsetbinary() for O_BINARY, or an fchangemode() that supports at least O_RDONLY, O_WRONLY, O_RDWR, O_APPEND, O_TEXT, O_BINARY. Bruno [1] http://pubs.opengroup.org/onlinepubs/9699919799/functions/freopen.html [2] https://lists.gnu.org/archive/html/bug-gnulib/2010-03/msg00111.html