]> git.ipfire.org Git - thirdparty/glibc.git/blame - libio/iofdopen.c
ldbl-128ibm-compat: Add argp_error and argp_failure
[thirdparty/glibc.git] / libio / iofdopen.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
c8a89e7d 27#include <stdlib.h>
96aa2d94
RM
28#include "libioP.h"
29#include <fcntl.h>
30
5f0704b6 31#include <shlib-compat.h>
96aa2d94 32
9964a145 33FILE *
9d46370c 34_IO_new_fdopen (int fd, const char *mode)
96aa2d94
RM
35{
36 int read_write;
edf5b2d7
UD
37 struct locked_FILE
38 {
bd355af0 39 struct _IO_FILE_plus fp;
499e7464 40#ifdef _IO_MTSAFE_IO
edf5b2d7 41 _IO_lock_t lock;
499e7464 42#endif
d64b6ad0 43 struct _IO_wide_data wd;
edf5b2d7 44 } *new_f;
dd0ee2e1
UD
45 int i;
46 int use_mmap = 0;
96aa2d94 47
ae42bbc5
SP
48 /* Decide whether we modify the offset of the file we attach to and seek to
49 the end of file. We only do this if the mode is 'a' and if the file
50 descriptor did not have O_APPEND in its flags already. */
51 bool do_seek = false;
52
dd0ee2e1 53 switch (*mode)
96aa2d94
RM
54 {
55 case 'r':
56 read_write = _IO_NO_WRITES;
57 break;
58 case 'w':
59 read_write = _IO_NO_READS;
60 break;
61 case 'a':
96aa2d94
RM
62 read_write = _IO_NO_READS|_IO_IS_APPENDING;
63 break;
64 default:
30bfee26 65 __set_errno (EINVAL);
96aa2d94
RM
66 return NULL;
67 }
dd0ee2e1
UD
68 for (i = 1; i < 5; ++i)
69 {
70 switch (*++mode)
71 {
72 case '\0':
73 break;
74 case '+':
75 read_write &= _IO_IS_APPENDING;
76 break;
77 case 'm':
78 use_mmap = 1;
79 continue;
80 case 'x':
81 case 'b':
82 default:
83 /* Ignore */
84 continue;
85 }
86 break;
87 }
5f0704b6 88 int fd_flags = __fcntl (fd, F_GETFL);
2e65ca2b 89 if (fd_flags == -1)
96aa2d94 90 return NULL;
fd091d3f 91
2e65ca2b
UD
92 if (((fd_flags & O_ACCMODE) == O_RDONLY && !(read_write & _IO_NO_WRITES))
93 || ((fd_flags & O_ACCMODE) == O_WRONLY && !(read_write & _IO_NO_READS)))
94 {
30bfee26 95 __set_errno (EINVAL);
2e65ca2b
UD
96 return NULL;
97 }
96aa2d94
RM
98
99 /* The May 93 draft of P1003.4/D14.1 (redesignated as 1003.1b)
100 [System Application Program Interface (API) Amendment 1:
101 Realtime Extensions], Rationale B.8.3.3
102 Open a Stream on a File Descriptor says:
103
7e9c7b9b
RM
104 Although not explicitly required by POSIX.1, a good
105 implementation of append ("a") mode would cause the
106 O_APPEND flag to be set.
96aa2d94
RM
107
108 (Historical implementations [such as Solaris2] do a one-time
109 seek in fdopen.)
110
111 However, we do not turn O_APPEND off if the mode is "w" (even
112 though that would seem consistent) because that would be more
113 likely to break historical programs.
114 */
7e9c7b9b 115 if ((read_write & _IO_IS_APPENDING) && !(fd_flags & O_APPEND))
96aa2d94 116 {
ae42bbc5 117 do_seek = true;
5f0704b6 118 if (__fcntl (fd, F_SETFL, fd_flags | O_APPEND) == -1)
96aa2d94
RM
119 return NULL;
120 }
96aa2d94 121
edf5b2d7
UD
122 new_f = (struct locked_FILE *) malloc (sizeof (struct locked_FILE));
123 if (new_f == NULL)
96aa2d94 124 return NULL;
499e7464 125#ifdef _IO_MTSAFE_IO
bd355af0 126 new_f->fp.file._lock = &new_f->lock;
499e7464 127#endif
e42637b6 128 _IO_no_init (&new_f->fp.file, 0, 0, &new_f->wd,
63fb8f9a 129#if _G_HAVE_MMAP
dd0ee2e1
UD
130 (use_mmap && (read_write & _IO_NO_WRITES))
131 ? &_IO_wfile_jumps_maybe_mmap :
e42637b6 132#endif
15a686af 133 &_IO_wfile_jumps);
e42637b6 134 _IO_JUMPS (&new_f->fp) =
63fb8f9a 135#if _G_HAVE_MMAP
dd0ee2e1 136 (use_mmap && (read_write & _IO_NO_WRITES)) ? &_IO_file_jumps_maybe_mmap :
e42637b6 137#endif
15a686af 138 &_IO_file_jumps;
db3476af 139 _IO_new_file_init_internal (&new_f->fp);
db3476af
FW
140 /* We only need to record the fd because _IO_file_init_internal will
141 have unset the offset. It is important to unset the cached
142 offset because the real offset in the file could change between
143 now and when the handle is activated and we would then mislead
144 ftell into believing that we have a valid offset. */
fa3cd248 145 new_f->fp.file._fileno = fd;
bd355af0 146 new_f->fp.file._flags &= ~_IO_DELETE_DONT_CLOSE;
96aa2d94 147
817328ee
AS
148 _IO_mask_flags (&new_f->fp.file, read_write,
149 _IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING);
96aa2d94 150
ae42bbc5
SP
151 /* For append mode, set the file offset to the end of the file if we added
152 O_APPEND to the file descriptor flags. Don't update the offset cache
153 though, since the file handle is not active. */
154 if (do_seek && ((read_write & (_IO_IS_APPENDING | _IO_NO_READS))
155 == (_IO_IS_APPENDING | _IO_NO_READS)))
ea33158c 156 {
9964a145 157 off64_t new_pos = _IO_SYSSEEK (&new_f->fp.file, 0, _IO_seek_end);
ea33158c
SP
158 if (new_pos == _IO_pos_BAD && errno != ESPIPE)
159 return NULL;
160 }
e42637b6 161 return &new_f->fp.file;
96aa2d94 162}
d18ea0c5 163libc_hidden_ver (_IO_new_fdopen, _IO_fdopen)
96aa2d94 164
bd355af0 165strong_alias (_IO_new_fdopen, __new_fdopen)
fd091d3f
UD
166versioned_symbol (libc, _IO_new_fdopen, _IO_fdopen, GLIBC_2_1);
167versioned_symbol (libc, __new_fdopen, fdopen, GLIBC_2_1);