delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2012/05/06/12:06:33

X-Authentication-Warning: delorie.com: mail set sender to djgpp-workers-bounces using -f
X-Recipient: djgpp-workers AT delorie DOT com
X-Authenticated: #27081556
X-Provags-ID: V01U2FsdGVkX1+HeClKmDuHrCxpUIXzprQ5cUZ8v+uLrVGHidENTl
Zk1F/1SsEDfgiZ
From: Juan Manuel Guerrero <juan DOT guerrero AT gmx DOT de>
To: djgpp-workers AT delorie DOT com
Subject: NULL pointer support for freopen
Date: Sun, 6 May 2012 18:06:08 +0200
User-Agent: KMail/1.9.10
MIME-Version: 1.0
Message-Id: <201205061806.08510.juan.guerrero@gmx.de>
X-Y-GMX-Trusted: 0
Reply-To: djgpp-workers AT delorie DOT com

I have tried to implement the case when a NULL pointer is passed as filename.
Because DOS does not allow to change file descriptor flags of open files, only
the change of textmode using setmode() is supported.  Any other function call
with a NULL pointer as filename argument will fail with EBADF.
Please note that a different file acces mode will make the call fail,
e.g.: if the new mode is O_WRONLY but the old mode was O_RDWR then the call
will fail.  No file access mode is allowed.
Suggestions, objections, comments are welcome.

Regards,
Juan M. Guerrero



diff -aprNU5 djgpp.orig/src/docs/kb/wc204.txi djgpp/src/docs/kb/wc204.txi
--- djgpp.orig/src/docs/kb/wc204.txi	2012-01-22 23:40:28 +0000
+++ djgpp/src/docs/kb/wc204.txi	2012-05-06 14:57:30 +0000
@@ -1244,5 +1244,9 @@ the modul with @code{libc.a} to resolve
 @findex STYP_NRELOC_OVFL AT r{, new flag bit added to @code{s_flags} of @acronym{COFF} section header}
 The @code{s_flags} of the @acronym{COFF} section header now honors the new @code{STYP_NRELOC_OVFL} bit
 that signals that the section contains extended relocations and that the @code{s_nreloc} counter has
 overflown.  The bit set in case of overflow by @code{STYP_NRELOC_OVFL} is @code{0x01000000}.
 
+@findex freopen AT r{, and support of @code{NULL} pointer as @var{filename} argument}
+@code{freopen} now accepts a @code{NULL} pointer as first argument.  In this
+case the textmode of the file associated to the third argument is changed according
+to the the second argument.
diff -aprNU5 djgpp.orig/src/libc/ansi/stdio/freopen.c djgpp/src/libc/ansi/stdio/freopen.c
--- djgpp.orig/src/libc/ansi/stdio/freopen.c	2012-05-06 13:30:26 +0000
+++ djgpp/src/libc/ansi/stdio/freopen.c	2012-05-06 16:57:16 +0000
@@ -1,5 +1,6 @@
+/* Copyright (C) 2012 DJ Delorie, see COPYING.DJ for details */
 /* Copyright (C) 2003 DJ Delorie, see COPYING.DJ for details */
 /* Copyright (C) 2002 DJ Delorie, see COPYING.DJ for details */
 /* Copyright (C) 2001 DJ Delorie, see COPYING.DJ for details */
 /* Copyright (C) 1999 DJ Delorie, see COPYING.DJ for details */
 /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
@@ -10,25 +11,23 @@
 #include <unistd.h>
 #include <libc/file.h>
 #include <libc/dosio.h>
 #include <io.h>
 #include <libc/fd_props.h>
+#include <errno.h>
 
 FILE *
 freopen(const char *file, const char *mode, FILE *f)
 {
   int fd, fdo, rw, oflags = 0;
   char tbchar;
 
-  if (file == NULL || mode == NULL || f == NULL)
+  if (mode == NULL || f == NULL)
     return NULL;
 
   rw = (mode[1] == '+') || (mode[1] && (mode[2] == '+'));
 
-  fdo = fileno(f);
-  fclose(f);
-
   switch (*mode)
   {
   case 'a':
     oflags = O_CREAT | (rw ? O_RDWR : O_WRONLY) | O_APPEND;
     break;
@@ -50,11 +49,40 @@ freopen(const char *file, const char *mo
   else if (tbchar == 'b')
     oflags |= O_BINARY;
   else
     oflags |= (_fmode & (O_TEXT | O_BINARY));
 
-  fd = open(file, oflags, 0666);
+  fdo = fileno(f);
+  if (fd = fdo, file)
+  {
+    fclose(f);
+    fd = open(file, oflags, 0666);
+  }
+  else
+  {
+    /* If file is NULL, the file should not be closed but reused.
+       DOS does not allow to change descriptor flags of open files.
+       Only O_BINARY and O_TEXT flag changes are supported.  */
+    int oldflags = fcntl(fdo, F_GETFL);
+    if (oldflags == -1 || ((oflags & O_ACCMODE) != (oldflags & O_ACCMODE)))
+    {
+      errno = EBADF;
+      fd = -1;
+    }
+    else if (!(oflags & _fmode & (O_BINARY ^ O_TEXT)))
+    {
+      if (fflush(f) == -1 || (tbchar != 'b' && tbchar != 't')
+          || (setmode(fdo, tbchar == 'b' ?  O_BINARY : O_TEXT) == -1))
+      {
+        errno = EBADF;
+        fd = -1;
+      }
+      else
+        fd = fdo;
+    }
+  }
+
   if (fd < 0)
     return NULL;
 
   if (fd != fdo && fdo >= 0)
   {
diff -aprNU5 djgpp.orig/src/libc/ansi/stdio/freopen.txh djgpp/src/libc/ansi/stdio/freopen.txh
--- djgpp.orig/src/libc/ansi/stdio/freopen.txh	2003-03-26 19:47:36 +0000
+++ djgpp/src/libc/ansi/stdio/freopen.txh	2012-05-06 16:09:22 +0000
@@ -14,19 +14,31 @@ This function closes @var{file} if it wa
 file like @code{fopen(filename, mode)} (@pxref{fopen})
 but it reuses @var{file}.
 
 This is useful to, for example, associate @code{stdout} with a new file. 
 
+If @var{filename} is a @code{NULL} pointer, the function will attempt to change
+the mode of @var{file} to that specified by @var{mode}.  In this case, the file
+descriptor associated with @var{file} need not be closed if the call to @var{freopen}
+succeeds.
+This fails in all but one case, and sets @code{errno} to @code{EBADF}, since DOS
+and Windows do not allow changing the descriptor flags after the file is open.
+The one allowed case is for @code{O_BINARY} and @code{O_TEXT}.  That is, calls
+that @strong{only} change the file textmode will succeed and all others will
+fail.
+
 @subheading Return Value
 
-The new file, or @code{NULL} on error. 
+The new file, or @code{NULL} on error and @code{errno} is set.
 
 @subheading Portability
 
 @portability ansi, posix
 
 @subheading Example
 
 @example
 freopen("/tmp/stdout.dat", "wb", stdout);
+
+freopen(NULL, "rb", stdin);  /* Change stdin to O_BINARY mode.  */
 @end example
 

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019