Particularly useful for porting coreutils to cygwin. * lib/xfreopen.c (xfreopen): Preserve O_APPEND when using xfreopen to convert an existing stream to binary.
Signed-off-by: Eric Blake <ebl...@redhat.com> --- For a long time, we've had reports against coreutils about improper use of freopen(NULL) on platforms with non-zero O_BINARY: basically, when built out of the box, things like 'cat a >> b' would overwrite data in b, because the freopen(NULL,"wb",stdout) lost the O_APPEND flag. For the longest time, the problem was in every caller in coreutils/src that directly used freopen, and I was just patching them individually when packaging coreutils for cygwin. But now that all coreutils' accesses go through xfreopen, it makes more sense to patch this in just one place. I'll apply this tomorrow, unless I get comments first. Oops, I guess I'd better also modify modules/xfreopen to add a dependency on fcntl. ChangeLog | 6 ++++++ lib/xfreopen.c | 11 +++++++++++ 2 files changed, 17 insertions(+), 0 deletions(-) diff --git a/ChangeLog b/ChangeLog index d9e17ae..9855d58 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2010-03-10 Eric Blake <ebl...@redhat.com> + + xfreopen: keep append mode when converting stdout to binary + * lib/xfreopen.c (xfreopen): Preserve O_APPEND when using xfreopen + to convert an existing stream to binary. + 2010-03-09 Simon Josefsson <si...@josefsson.org> * gnulib-tool (LIBTOOLPATH): Fix cut'n'paste bug. diff --git a/lib/xfreopen.c b/lib/xfreopen.c index 297bda4..9d3b341 100644 --- a/lib/xfreopen.c +++ b/lib/xfreopen.c @@ -18,6 +18,8 @@ #include "xfreopen.h" #include <errno.h> +#include <fcntl.h> + #include "error.h" #include "exitfail.h" #include "quote.h" @@ -26,9 +28,18 @@ #include "gettext.h" #define _(msgid) gettext (msgid) +#define STREQ(s1, s2) (strcmp (s1, s2) == 0) + void xfreopen (char const *filename, char const *mode, FILE *fp) { + /* Preserve append mode if changing an existing FILE to binary. */ + if (!filename && STREQ (mode, "wb")) + { + int flag = fcntl (fileno (fp), F_GETFL); + if (0 <= flag && (flag & O_APPEND)) + mode = "ab"; + } if (!freopen (filename, mode, fp)) { char const *f = (filename ? filename -- 1.6.6.1