Rev 4921 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4349 | Serge | 1 | /* |
2 | * Copyright (c) 1990, 2007 The Regents of the University of California. |
||
3 | * All rights reserved. |
||
4 | * |
||
5 | * Redistribution and use in source and binary forms are permitted |
||
6 | * provided that the above copyright notice and this paragraph are |
||
7 | * duplicated in all such forms and that any documentation, |
||
8 | * advertising materials, and other materials related to such |
||
9 | * distribution and use acknowledge that the software was developed |
||
10 | * by the University of California, Berkeley. The name of the |
||
11 | * University may not be used to endorse or promote products derived |
||
12 | * from this software without specific prior written permission. |
||
13 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR |
||
14 | * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED |
||
15 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
||
16 | */ |
||
17 | |||
18 | /* |
||
19 | FUNCTION |
||
20 | < |
||
21 | |||
22 | INDEX |
||
23 | freopen |
||
24 | INDEX |
||
25 | _freopen_r |
||
26 | |||
27 | ANSI_SYNOPSIS |
||
28 | #include |
||
4921 | Serge | 29 | FILE *freopen(const char *restrict <[file]>, const char *restrict <[mode]>, |
30 | FILE *restrict <[fp]>); |
||
31 | FILE *_freopen_r(struct _reent *<[ptr]>, const char *restrict <[file]>, |
||
32 | const char *restrict <[mode]>, FILE *restrict <[fp]>); |
||
4349 | Serge | 33 | |
34 | TRAD_SYNOPSIS |
||
35 | #include |
||
36 | FILE *freopen(<[file]>, <[mode]>, <[fp]>) |
||
37 | char *<[file]>; |
||
38 | char *<[mode]>; |
||
39 | FILE *<[fp]>; |
||
40 | |||
41 | FILE *_freopen_r(<[ptr]>, <[file]>, <[mode]>, <[fp]>) |
||
42 | struct _reent *<[ptr]>; |
||
43 | char *<[file]>; |
||
44 | char *<[mode]>; |
||
45 | FILE *<[fp]>; |
||
46 | |||
47 | DESCRIPTION |
||
48 | Use this variant of < |
||
49 | descriptor <[fp]> (notably < |
||
50 | the file. |
||
51 | |||
52 | If <[fp]> was associated with another file or stream, < |
||
53 | closes that other file or stream (but ignores any errors while closing |
||
54 | it). |
||
55 | |||
56 | <[file]> and <[mode]> are used just as in < |
||
57 | |||
58 | If <[file]> is < |
||
59 | closed. The file cannot be given a more permissive access mode (for |
||
60 | example, a <[mode]> of "w" will fail on a read-only file descriptor), |
||
61 | but can change status such as append or binary mode. If modification |
||
62 | is not possible, failure occurs. |
||
63 | |||
64 | RETURNS |
||
65 | If successful, the result is the same as the argument <[fp]>. If the |
||
66 | file cannot be opened as specified, the result is < |
||
67 | |||
68 | PORTABILITY |
||
69 | ANSI C requires < |
||
70 | |||
71 | Supporting OS subroutines required: < |
||
72 | < |
||
73 | */ |
||
74 | |||
75 | #include <_ansi.h> |
||
76 | #include |
||
77 | #include |
||
78 | #include |
||
79 | #include |
||
80 | #include |
||
81 | #include |
||
82 | #include |
||
83 | #include |
||
84 | #include "local.h" |
||
85 | |||
86 | /* |
||
87 | * Re-direct an existing, open (probably) file to some other file. |
||
88 | */ |
||
89 | |||
90 | FILE * |
||
91 | _DEFUN(_freopen_r, (ptr, file, mode, fp), |
||
92 | struct _reent *ptr _AND |
||
4921 | Serge | 93 | const char *__restrict file _AND |
94 | const char *__restrict mode _AND |
||
95 | register FILE *__restrict fp) |
||
4349 | Serge | 96 | { |
97 | register int f; |
||
6099 | serge | 98 | int flags, oflags, oflags2; |
4349 | Serge | 99 | int e = 0; |
100 | |||
101 | CHECK_INIT (ptr, fp); |
||
102 | |||
4921 | Serge | 103 | /* We can't use the _newlib_flockfile_XXX macros here due to the |
104 | interlocked locking with the sfp_lock. */ |
||
105 | #ifdef _STDIO_WITH_THREAD_CANCELLATION_SUPPORT |
||
106 | int __oldcancel; |
||
107 | pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &__oldcancel); |
||
108 | #endif |
||
6099 | serge | 109 | oflags2 = fp->_flags2; |
110 | if (!(oflags2 & __SNLK)) |
||
111 | _flockfile (fp); |
||
4349 | Serge | 112 | |
113 | if ((flags = __sflags (ptr, mode, &oflags)) == 0) |
||
114 | { |
||
6099 | serge | 115 | if (!(oflags2 & __SNLK)) |
116 | _funlockfile (fp); |
||
4921 | Serge | 117 | #ifdef _STDIO_WITH_THREAD_CANCELLATION_SUPPORT |
118 | pthread_setcancelstate (__oldcancel, &__oldcancel); |
||
119 | #endif |
||
4349 | Serge | 120 | _fclose_r (ptr, fp); |
121 | return NULL; |
||
122 | } |
||
123 | |||
124 | /* |
||
125 | * Remember whether the stream was open to begin with, and |
||
126 | * which file descriptor (if any) was associated with it. |
||
127 | * If it was attached to a descriptor, defer closing it, |
||
128 | * so that, e.g., freopen("/dev/stdin", "r", stdin) works. |
||
129 | * This is unnecessary if it was not a Unix file. |
||
130 | */ |
||
131 | |||
132 | if (fp->_flags == 0) |
||
133 | fp->_flags = __SEOF; /* hold on to it */ |
||
134 | else |
||
135 | { |
||
136 | if (fp->_flags & __SWR) |
||
137 | _fflush_r (ptr, fp); |
||
138 | /* |
||
139 | * If close is NULL, closing is a no-op, hence pointless. |
||
140 | * If file is NULL, the file should not be closed. |
||
141 | */ |
||
142 | if (fp->_close != NULL && file != NULL) |
||
143 | fp->_close (ptr, fp->_cookie); |
||
144 | } |
||
145 | |||
146 | /* |
||
147 | * Now get a new descriptor to refer to the new file, or reuse the |
||
148 | * existing file descriptor if file is NULL. |
||
149 | */ |
||
150 | |||
151 | if (file != NULL) |
||
152 | { |
||
153 | f = _open_r (ptr, (char *) file, oflags, 0666); |
||
154 | e = ptr->_errno; |
||
155 | } |
||
156 | else |
||
157 | { |
||
158 | #ifdef HAVE_FCNTL |
||
159 | int oldflags; |
||
160 | /* |
||
161 | * Reuse the file descriptor, but only if the new access mode is |
||
162 | * equal or less permissive than the old. F_SETFL correctly |
||
163 | * ignores creation flags. |
||
164 | */ |
||
165 | f = fp->_file; |
||
166 | if ((oldflags = _fcntl_r (ptr, f, F_GETFL, 0)) == -1 |
||
167 | || ! ((oldflags & O_ACCMODE) == O_RDWR |
||
168 | || ((oldflags ^ oflags) & O_ACCMODE) == 0) |
||
169 | || _fcntl_r (ptr, f, F_SETFL, oflags) == -1) |
||
170 | f = -1; |
||
171 | #else |
||
172 | /* We cannot modify without fcntl support. */ |
||
173 | f = -1; |
||
174 | #endif |
||
175 | |||
176 | #ifdef __SCLE |
||
177 | /* |
||
178 | * F_SETFL doesn't change textmode. Don't mess with modes of ttys. |
||
179 | */ |
||
180 | if (0 <= f && ! _isatty_r (ptr, f) |
||
181 | && setmode (f, oflags & (O_BINARY | O_TEXT)) == -1) |
||
182 | f = -1; |
||
183 | #endif |
||
184 | |||
185 | if (f < 0) |
||
186 | { |
||
187 | e = EBADF; |
||
188 | if (fp->_close != NULL) |
||
189 | fp->_close (ptr, fp->_cookie); |
||
190 | } |
||
191 | } |
||
192 | |||
193 | /* |
||
194 | * Finish closing fp. Even if the open succeeded above, |
||
195 | * we cannot keep fp->_base: it may be the wrong size. |
||
196 | * This loses the effect of any setbuffer calls, |
||
197 | * but stdio has always done this before. |
||
198 | */ |
||
199 | |||
200 | if (fp->_flags & __SMBF) |
||
201 | _free_r (ptr, (char *) fp->_bf._base); |
||
202 | fp->_w = 0; |
||
203 | fp->_r = 0; |
||
204 | fp->_p = NULL; |
||
205 | fp->_bf._base = NULL; |
||
206 | fp->_bf._size = 0; |
||
207 | fp->_lbfsize = 0; |
||
208 | if (HASUB (fp)) |
||
209 | FREEUB (ptr, fp); |
||
210 | fp->_ub._size = 0; |
||
211 | if (HASLB (fp)) |
||
212 | FREELB (ptr, fp); |
||
213 | fp->_lb._size = 0; |
||
4921 | Serge | 214 | fp->_flags &= ~__SORD; |
6099 | serge | 215 | fp->_flags2 &= ~__SWID; |
4349 | Serge | 216 | memset (&fp->_mbstate, 0, sizeof (_mbstate_t)); |
217 | |||
218 | if (f < 0) |
||
219 | { /* did not get it after all */ |
||
220 | __sfp_lock_acquire (); |
||
221 | fp->_flags = 0; /* set it free */ |
||
222 | ptr->_errno = e; /* restore in case _close clobbered */ |
||
6099 | serge | 223 | if (!(oflags2 & __SNLK)) |
224 | _funlockfile (fp); |
||
4349 | Serge | 225 | #ifndef __SINGLE_THREAD__ |
226 | __lock_close_recursive (fp->_lock); |
||
227 | #endif |
||
228 | __sfp_lock_release (); |
||
4921 | Serge | 229 | #ifdef _STDIO_WITH_THREAD_CANCELLATION_SUPPORT |
230 | pthread_setcancelstate (__oldcancel, &__oldcancel); |
||
231 | #endif |
||
4349 | Serge | 232 | return NULL; |
233 | } |
||
234 | |||
235 | fp->_flags = flags; |
||
236 | fp->_file = f; |
||
237 | fp->_cookie = (_PTR) fp; |
||
238 | fp->_read = __sread; |
||
239 | fp->_write = __swrite; |
||
240 | fp->_seek = __sseek; |
||
241 | fp->_close = __sclose; |
||
242 | |||
243 | #ifdef __SCLE |
||
244 | if (__stextmode (fp->_file)) |
||
245 | fp->_flags |= __SCLE; |
||
246 | #endif |
||
247 | |||
6099 | serge | 248 | if (!(oflags2 & __SNLK)) |
249 | _funlockfile (fp); |
||
4921 | Serge | 250 | #ifdef _STDIO_WITH_THREAD_CANCELLATION_SUPPORT |
251 | pthread_setcancelstate (__oldcancel, &__oldcancel); |
||
252 | #endif |
||
4349 | Serge | 253 | return fp; |
254 | } |
||
255 | |||
256 | #ifndef _REENT_ONLY |
||
257 | |||
258 | FILE * |
||
259 | _DEFUN(freopen, (file, mode, fp), |
||
4921 | Serge | 260 | _CONST char *__restrict file _AND |
261 | _CONST char *__restrict mode _AND |
||
262 | register FILE *__restrict fp) |
||
4349 | Serge | 263 | { |
264 | return _freopen_r (_REENT, file, mode, fp); |
||
265 | } |
||
266 | |||
267 | #endif /*!_REENT_ONLY */>>=> |