C99 freopen
Jakub Jelinek
jakub@redhat.com
Mon Apr 9 09:21:00 GMT 2001
On Mon, Apr 09, 2001 at 03:36:07PM +0200, Andreas Schwab wrote:
> freopen(NULL, ...) has a defined meaning in C99:
>
> [#3] If filename is a null pointer, the freopen function
> attempts to change the mode of the stream to that specified
> by mode, as if the name of the file currently associated
> with the stream had been used. It is implementation-defined
> which changes of mode are permitted (if any), and under what
> circumstances.
>
> Anyone who wants to implement this? Currently we always return NULL with
> errno == EFAULT.
You mean something like following?
We could go without the dup/close pair as well, but it would require more
changes.
2001-04-09 Jakub Jelinek <jakub@redhat.com>
* sysdeps/generic/fd_to_filename.h: New.
* sysdeps/unix/sysv/linux/fd_to_filename.h: New.
* libio/freopen.c (freopen): If FILENAME is NULL, try to get
filename from the open file descriptor.
* libio/freopen64.c (freopen64): Likewise.
--- libc/libio/freopen.c.jj Mon Nov 20 13:48:11 2000
+++ libc/libio/freopen.c Mon Apr 9 18:08:57 2001
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993,95,96,97,98,2000 Free Software Foundation, Inc.
+/* Copyright (C) 1993,95,96,97,98,2000,2001 Free Software Foundation, Inc.
This file is part of the GNU IO Library.
This library is free software; you can redistribute it and/or
@@ -27,6 +27,7 @@
#include "stdio.h"
#include <shlib-compat.h>
+#include <fd_to_filename.h>
FILE*
freopen (filename, mode, fp)
@@ -35,11 +36,18 @@ freopen (filename, mode, fp)
FILE* fp;
{
FILE *result;
+ int fd = -1;
CHECK_FILE (fp, NULL);
if (!(fp->_flags & _IO_IS_FILEBUF))
return NULL;
_IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
_IO_flockfile (fp);
+ if (filename == NULL && _IO_fileno (fp) >= 0)
+ {
+ fd = dup (_IO_fileno (fp));
+ if (fd != -1)
+ filename = fd_to_filename (fd);
+ }
#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
if (&_IO_stdin_used == NULL)
/* If the shared C library is used by the application binary which
@@ -54,6 +62,12 @@ freopen (filename, mode, fp)
if (result != NULL)
/* unbound stream orientation */
result->_mode = 0;
+ if (fd != -1)
+ {
+ close (fd);
+ if (filename != NULL)
+ free (filename);
+ }
_IO_funlockfile (fp);
_IO_cleanup_region_end (0);
return result;
--- libc/libio/freopen64.c.jj Mon Nov 20 13:48:11 2000
+++ libc/libio/freopen64.c Mon Apr 9 18:11:33 2001
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993,1995,1996,1997,1998,2000 Free Software Foundation, Inc.
+/* Copyright (C) 1993,1995,1996,1997,1998,2000,2001 Free Software Foundation, Inc.
This file is part of the GNU IO Library.
This library is free software; you can redistribute it and/or
@@ -26,6 +26,8 @@
#include "libioP.h"
#include "stdio.h"
+#include <fd_to_filename.h>
+
FILE *
freopen64 (filename, mode, fp)
const char* filename;
@@ -34,15 +36,28 @@ freopen64 (filename, mode, fp)
{
#ifdef _G_OPEN64
FILE *result;
+ int fd = -1;
CHECK_FILE (fp, NULL);
if (!(fp->_flags & _IO_IS_FILEBUF))
return NULL;
_IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
_IO_flockfile (fp);
+ if (filename == NULL && _IO_fileno (fp) >= 0)
+ {
+ fd = dup (_IO_fileno (fp));
+ if (fd != -1)
+ filename = fd_to_filename (fd);
+ }
result = _IO_freopen64 (filename, mode, fp);
if (result != NULL)
/* unbound stream orientation */
result->_mode = 0;
+ if (fd != -1)
+ {
+ close (fd);
+ if (filename != NULL)
+ free (filename);
+ }
_IO_funlockfile (fp);
_IO_cleanup_region_end (0);
return result;
--- libc/sysdeps/generic/fd_to_filename.h.jj Mon Apr 9 17:57:08 2001
+++ libc/sysdeps/generic/fd_to_filename.h Mon Apr 9 18:12:28 2001
@@ -0,0 +1,26 @@
+/* Query filename corresponding to an open FD. Generic version.
+ Copyright (C) 2001 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+/* There is no generic way how to query filename for an open file
+ descriptor. */
+
+static inline const char *fd_to_filename (int fd)
+{
+ return NULL;
+}
--- libc/sysdeps/unix/sysv/linux/fd_to_filename.h.jj Mon Apr 9 17:57:08 2001
+++ libc/sysdeps/unix/sysv/linux/fd_to_filename.h Mon Apr 9 18:13:01 2001
@@ -0,0 +1,30 @@
+/* Query filename corresponding to an open FD. Linux version.
+ Copyright (C) 2001 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <string.h>
+#include <stdio-common/_itoa.h>
+
+static inline const char *fd_to_filename (int fd)
+{
+ char *ret = malloc (30);
+
+ if (ret)
+ *_fitoa_word (fd, __stpcpy (ret, "/proc/self/fd/"), 10, 0) = '\0';
+ return (const char *) ret;
+}
Jakub
More information about the Libc-hacker
mailing list