]> Savannah Git Hosting - gnulib.git/commitdiff
xsetmode: new module
authorPaul Eggert <eggert@cs.ucla.edu>
Wed, 15 Feb 2017 22:30:33 +0000 (14:30 -0800)
committerPaul Eggert <eggert@cs.ucla.edu>
Wed, 15 Feb 2017 22:55:07 +0000 (14:55 -0800)
This is to fix a problem noted by Eric Blake.
Code was using xfreopen to change files to binary mode, but this
fails for stdout when in append mode.  Such code should use
xsetmode instead.
* NEWS: Document incompatible changes to binary-io module.
* lib/binary-io.c (__gl_setmode_check) [__DJGPP__ || __EMX__]:
New function.
* lib/binary-io.h (__gl_setmode): Rename from set_binary_mode.
(set_binary_mode): New function, which also checks for tty.
* lib/xsetmode.c, lib/xsetmode.h, modules/xsetmode: New files.

ChangeLog
NEWS
lib/binary-io.c
lib/binary-io.h
lib/xsetmode.c [new file with mode: 0644]
lib/xsetmode.h [new file with mode: 0644]
modules/xsetmode [new file with mode: 0644]

index 10e5240cc45681935ff62283142147b4ea876901..756858d85d8450c49da86b5fb0371f1f0e4d6aec 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2017-02-15  Paul Eggert  <eggert@cs.ucla.edu>
+
+       xsetmode: new module
+       This is to fix a problem noted by Eric Blake.
+       Code was using xfreopen to change files to binary mode, but this
+       fails for stdout when in append mode.  Such code should use
+       xsetmode instead.
+       * NEWS: Document incompatible changes to binary-io module.
+       * lib/binary-io.c (__gl_setmode_check) [__DJGPP__ || __EMX__]:
+       New function.
+       * lib/binary-io.h (__gl_setmode): Rename from set_binary_mode.
+       (set_binary_mode): New function, which also checks for tty.
+       * lib/xsetmode.c, lib/xsetmode.h, modules/xsetmode: New files.
+
 2017-02-14  Paul Eggert  <eggert@cs.ucla.edu>
 
        headers: fix begin-end typos
diff --git a/NEWS b/NEWS
index 266275a9455b43c711ac92c53c6d55fefe99146e..294aa224ceccacc8696f9c84ef389fc52451ce10 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -42,6 +42,10 @@ User visible incompatible changes
 
 Date        Modules         Changes
 
+2017-02-15  binary-io       On MS-DOS and OS/2, set_binary_mode now fails
+                            on ttys, and sets errno == ENOTTY.  SET_BINARY
+                            has been removed; use set_binary_mode instead.
+
 2017-01-20  parse-datetime  The parse_datetime2 function now takes two
                             more arguments TZ and TZSTRING, for the
                             time zone and its name.
index d828bcd0153245ad8da003f7bc2ca1cc20ea5999..c721650cc54259eb46cc1b0bcdb9fc2c54bd5f14 100644 (file)
@@ -1,4 +1,37 @@
+/* Binary mode I/O.
+   Copyright 2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
 #include <config.h>
+
 #define BINARY_IO_INLINE _GL_EXTERN_INLINE
 #include "binary-io.h"
-typedef int dummy;
+
+#if defined __DJGPP__ || defined __EMX__
+# include <errno.h>
+# include <unistd.h>
+
+int
+__gl_setmode_check (int fd)
+{
+  if (isatty (fd))
+    {
+      errno = ENOTTY;
+      return -1;
+    }
+  else
+    return 0;
+}
+#endif
index f766439e2fbf46abf7b34e45a6e32dd62859f9a0..ae7690de2861b5441247903dda0cc5a974954544 100644 (file)
@@ -33,15 +33,12 @@ _GL_INLINE_HEADER_BEGIN
 # define BINARY_IO_INLINE _GL_INLINE
 #endif
 
-/* set_binary_mode (fd, mode)
-   sets the binary/text I/O mode of file descriptor fd to the given mode
-   (must be O_BINARY or O_TEXT) and returns the previous mode.  */
 #if O_BINARY
 # if defined __EMX__ || defined __DJGPP__ || defined __CYGWIN__
 #  include <io.h> /* declares setmode() */
-#  define set_binary_mode setmode
+#  define __gl_setmode setmode
 # else
-#  define set_binary_mode _setmode
+#  define __gl_setmode _setmode
 #  undef fileno
 #  define fileno _fileno
 # endif
@@ -50,7 +47,7 @@ _GL_INLINE_HEADER_BEGIN
   /* Use a function rather than a macro, to avoid gcc warnings
      "warning: statement with no effect".  */
 BINARY_IO_INLINE int
-set_binary_mode (int fd, int mode)
+__gl_setmode (int fd, int mode)
 {
   (void) fd;
   (void) mode;
@@ -58,18 +55,23 @@ set_binary_mode (int fd, int mode)
 }
 #endif
 
-/* SET_BINARY (fd);
-   changes the file descriptor fd to perform binary I/O.  */
+/* Set FD's mode to MODE.  Return the old mode if successful, -1
+   (setting errno) on failure.  */
+
 #if defined __DJGPP__ || defined __EMX__
-# include <unistd.h> /* declares isatty() */
-  /* Avoid putting stdin/stdout in binary mode if it is connected to
-     the console, because that would make it impossible for the user
-     to interrupt the program through Ctrl-C or Ctrl-Break.  */
-# define SET_BINARY(fd) ((void) (!isatty (fd) ? (set_binary_mode (fd, O_BINARY), 0) : 0))
+extern int __gl_setmode_check (int);
 #else
-# define SET_BINARY(fd) ((void) set_binary_mode (fd, O_BINARY))
+BINARY_IO_INLINE int
+__gl_setmode_check (int fd) { return 0; }
 #endif
 
+BINARY_IO_INLINE int
+set_binary_mode (int fd, int mode)
+{
+  int r = __gl_setmode_check (fd);
+  return r != 0 ? r : __gl_setmode (fd, mode);
+}
+
 _GL_INLINE_HEADER_END
 
 #endif /* _BINARY_H */
diff --git a/lib/xsetmode.c b/lib/xsetmode.c
new file mode 100644 (file)
index 0000000..628f4f0
--- /dev/null
@@ -0,0 +1,38 @@
+/* Binary mode I/O with checking
+   Copyright 2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#define XSETMODE_INLINE _GL_EXTERN_INLINE
+#include "xsetmode.h"
+
+#include <errno.h>
+#include <error.h>
+#include <stdbool.h>
+#include "exitfail.h"
+#include "verify.h"
+
+#if O_BINARY
+
+_Noreturn void
+xsetmode_error (void)
+{
+  error (exit_failure, errno,
+         _("failed to set file descriptor text/binary mode"));
+  assume (false);
+}
+
+#endif
diff --git a/lib/xsetmode.h b/lib/xsetmode.h
new file mode 100644 (file)
index 0000000..c88d915
--- /dev/null
@@ -0,0 +1,45 @@
+/* Binary mode I/O with checking
+   Copyright 2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _XSETMODE_H
+#define _XSETMODE_H
+
+#include "binary-io.h"
+
+#ifndef _GL_INLINE_HEADER_BEGIN
+ #error "Please include config.h first."
+#endif
+_GL_INLINE_HEADER_BEGIN
+#ifndef XSETMODE_INLINE
+# define XSETMODE_INLINE _GL_INLINE
+#endif
+
+#if O_BINARY
+extern _Noreturn void xsetmode_error (void);
+#else
+XSETMODE_INLINE void xsetmode_error (void) {}
+#endif
+
+XSETMODE_INLINE void
+xsetmode (int fd, int mode)
+{
+  if (set_binary_mode (fd, mode) < 0)
+    xsetmode_error ();
+}
+
+_GL_INLINE_HEADER_END
+
+#endif /* _XSETMODE_H */
diff --git a/modules/xsetmode b/modules/xsetmode
new file mode 100644 (file)
index 0000000..360a054
--- /dev/null
@@ -0,0 +1,28 @@
+Description:
+Checked Binary mode I/O.
+
+Files:
+lib/xsetmode.h
+lib/xsetmode.c
+
+Depends-on:
+binary-io
+error
+exitfail
+extern-inline
+stdbool
+verify
+
+configure.ac:
+
+Makefile.am:
+lib_SOURCES += xsetmode.h xsetmode.c
+
+Include:
+"xsetmode.h"
+
+License:
+LGPLv2+
+
+Maintainer:
+all