]> git.ipfire.org Git - thirdparty/glibc.git/blame - libio/freopen.c
ldbl-128ibm-compat: Add argp_error and argp_failure
[thirdparty/glibc.git] / libio / freopen.c
CommitLineData
04277e02 1/* Copyright (C) 1993-2019 Free Software Foundation, Inc.
41bdb6e2 2 This file is part of the GNU C Library.
96aa2d94 3
41bdb6e2
AJ
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
96aa2d94 8
41bdb6e2
AJ
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
40a55d20 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 12 Lesser General Public License for more details.
96aa2d94 13
41bdb6e2 14 You should have received a copy of the GNU Lesser General Public
59ba27a6 15 License along with the GNU C Library; if not, see
5a82c748 16 <https://www.gnu.org/licenses/>.
96aa2d94 17
41bdb6e2
AJ
18 As a special exception, if you link the code in this file with
19 files compiled with a GNU compiler to produce an executable,
20 that does not cause the resulting executable to be covered by
21 the GNU Lesser General Public License. This exception does not
22 however invalidate any other reasons why the executable file
23 might be covered by the GNU Lesser General Public License.
24 This exception applies to code released by its copyright holders
25 in files containing the exception. */
96aa2d94 26
0b727ed4 27#include <stdio.h>
94b7cc37 28#include <fcntl.h>
1a35b7fd 29#include <stdlib.h>
94b7cc37 30#include <unistd.h>
96aa2d94 31
0b727ed4 32#include <libioP.h>
c44a663d 33#include <fd_to_filename.h>
0b727ed4 34#include <shlib-compat.h>
37233df9 35
9d46370c
JM
36FILE *
37freopen (const char *filename, const char *mode, FILE *fp)
96aa2d94 38{
0b727ed4
AZ
39 FILE *result = NULL;
40 char fdfilename[FD_TO_FILENAME_SIZE];
41
96aa2d94 42 CHECK_FILE (fp, NULL);
0b727ed4 43
0261d33f 44 _IO_acquire_lock (fp);
0b727ed4
AZ
45 /* First flush the stream (failure should be ignored). */
46 _IO_SYNC (fp);
47
48 if (!(fp->_flags & _IO_IS_FILEBUF))
49 goto end;
50
94b7cc37 51 int fd = _IO_fileno (fp);
0b727ed4
AZ
52 const char *gfilename
53 = filename != NULL ? filename : fd_to_filename (fd, fdfilename);
54
94b7cc37 55 fp->_flags2 |= _IO_FLAGS2_NOCLOSE;
16710d58 56#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
6973fc01 57 if (&_IO_stdin_used == NULL)
81c64d40
UD
58 {
59 /* If the shared C library is used by the application binary which
60 was linked against the older version of libio, we just use the
61 older one even for internal use to avoid trouble since a pointer
62 to the old libio may be passed into shared C library and wind
63 up here. */
64 _IO_old_file_close_it (fp);
cfa61144 65 _IO_JUMPS_FUNC_UPDATE (fp, &_IO_old_file_jumps);
94b7cc37 66 result = _IO_old_file_fopen (fp, gfilename, mode);
81c64d40 67 }
6973fc01
UD
68 else
69#endif
81c64d40 70 {
d18ea0c5 71 _IO_file_close_it (fp);
e69dcccb 72 _IO_JUMPS_FILE_plus (fp) = &_IO_file_jumps;
bbdef797 73 if (_IO_vtable_offset (fp) == 0 && fp->_wide_data != NULL)
15a686af 74 fp->_wide_data->_wide_vtable = &_IO_wfile_jumps;
d18ea0c5 75 result = _IO_file_fopen (fp, gfilename, mode, 1);
81c64d40
UD
76 if (result != NULL)
77 result = __fopen_maybe_mmap (result);
78 }
94b7cc37 79 fp->_flags2 &= ~_IO_FLAGS2_NOCLOSE;
3b1de3ba 80 if (result != NULL)
c44a663d 81 {
94b7cc37
UD
82 /* unbound stream orientation */
83 result->_mode = 0;
84
f1a67a2c 85 if (fd != -1 && _IO_fileno (result) != fd)
94b7cc37 86 {
f1a67a2c
AZ
87 /* At this point we have both file descriptors already allocated,
88 so __dup3 will not fail with EBADF, EINVAL, or EMFILE. But
89 we still need to check for EINVAL and, due Linux internal
90 implementation, EBUSY. It is because on how it internally opens
91 the file by splitting the buffer allocation operation and VFS
92 opening (a dup operation may run when a file is still pending
93 'install' on VFS). */
94 if (__dup3 (_IO_fileno (result), fd,
95 (result->_flags2 & _IO_FLAGS2_CLOEXEC) != 0
96 ? O_CLOEXEC : 0) == -1)
97 {
98 _IO_file_close_it (result);
99 result = NULL;
100 goto end;
101 }
94b7cc37
UD
102 __close (_IO_fileno (result));
103 _IO_fileno (result) = fd;
104 }
c44a663d 105 }
94b7cc37
UD
106 else if (fd != -1)
107 __close (fd);
f1a67a2c
AZ
108
109end:
0261d33f 110 _IO_release_lock (fp);
7c713e28 111 return result;
96aa2d94 112}