Mail Archives: djgpp-workers/2012/05/06/12:06:33
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 -