Rev 4874 | Go to most recent revision | 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; |
||
98 | int flags, oflags; |
||
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 |
||
4349 | Serge | 109 | _flockfile (fp); |
110 | |||
111 | if ((flags = __sflags (ptr, mode, &oflags)) == 0) |
||
112 | { |
||
113 | _funlockfile (fp); |
||
4921 | Serge | 114 | #ifdef _STDIO_WITH_THREAD_CANCELLATION_SUPPORT |
115 | pthread_setcancelstate (__oldcancel, &__oldcancel); |
||
116 | #endif |
||
4349 | Serge | 117 | _fclose_r (ptr, fp); |
118 | return NULL; |
||
119 | } |
||
120 | |||
121 | /* |
||
122 | * Remember whether the stream was open to begin with, and |
||
123 | * which file descriptor (if any) was associated with it. |
||
124 | * If it was attached to a descriptor, defer closing it, |
||
125 | * so that, e.g., freopen("/dev/stdin", "r", stdin) works. |
||
126 | * This is unnecessary if it was not a Unix file. |
||
127 | */ |
||
128 | |||
129 | if (fp->_flags == 0) |
||
130 | fp->_flags = __SEOF; /* hold on to it */ |
||
131 | else |
||
132 | { |
||
133 | if (fp->_flags & __SWR) |
||
134 | _fflush_r (ptr, fp); |
||
135 | /* |
||
136 | * If close is NULL, closing is a no-op, hence pointless. |
||
137 | * If file is NULL, the file should not be closed. |
||
138 | */ |
||
139 | if (fp->_close != NULL && file != NULL) |
||
140 | fp->_close (ptr, fp->_cookie); |
||
141 | } |
||
142 | |||
143 | /* |
||
144 | * Now get a new descriptor to refer to the new file, or reuse the |
||
145 | * existing file descriptor if file is NULL. |
||
146 | */ |
||
147 | |||
148 | if (file != NULL) |
||
149 | { |
||
150 | f = _open_r (ptr, (char *) file, oflags, 0666); |
||
151 | e = ptr->_errno; |
||
152 | } |
||
153 | else |
||
154 | { |
||
155 | #ifdef HAVE_FCNTL |
||
156 | int oldflags; |
||
157 | /* |
||
158 | * Reuse the file descriptor, but only if the new access mode is |
||
159 | * equal or less permissive than the old. F_SETFL correctly |
||
160 | * ignores creation flags. |
||
161 | */ |
||
162 | f = fp->_file; |
||
163 | if ((oldflags = _fcntl_r (ptr, f, F_GETFL, 0)) == -1 |
||
164 | || ! ((oldflags & O_ACCMODE) == O_RDWR |
||
165 | || ((oldflags ^ oflags) & O_ACCMODE) == 0) |
||
166 | || _fcntl_r (ptr, f, F_SETFL, oflags) == -1) |
||
167 | f = -1; |
||
168 | #else |
||
169 | /* We cannot modify without fcntl support. */ |
||
170 | f = -1; |
||
171 | #endif |
||
172 | |||
173 | #ifdef __SCLE |
||
174 | /* |
||
175 | * F_SETFL doesn't change textmode. Don't mess with modes of ttys. |
||
176 | */ |
||
177 | if (0 <= f && ! _isatty_r (ptr, f) |
||
178 | && setmode (f, oflags & (O_BINARY | O_TEXT)) == -1) |
||
179 | f = -1; |
||
180 | #endif |
||
181 | |||
182 | if (f < 0) |
||
183 | { |
||
184 | e = EBADF; |
||
185 | if (fp->_close != NULL) |
||
186 | fp->_close (ptr, fp->_cookie); |
||
187 | } |
||
188 | } |
||
189 | |||
190 | /* |
||
191 | * Finish closing fp. Even if the open succeeded above, |
||
192 | * we cannot keep fp->_base: it may be the wrong size. |
||
193 | * This loses the effect of any setbuffer calls, |
||
194 | * but stdio has always done this before. |
||
195 | */ |
||
196 | |||
197 | if (fp->_flags & __SMBF) |
||
198 | _free_r (ptr, (char *) fp->_bf._base); |
||
199 | fp->_w = 0; |
||
200 | fp->_r = 0; |
||
201 | fp->_p = NULL; |
||
202 | fp->_bf._base = NULL; |
||
203 | fp->_bf._size = 0; |
||
204 | fp->_lbfsize = 0; |
||
205 | if (HASUB (fp)) |
||
206 | FREEUB (ptr, fp); |
||
207 | fp->_ub._size = 0; |
||
208 | if (HASLB (fp)) |
||
209 | FREELB (ptr, fp); |
||
210 | fp->_lb._size = 0; |
||
4921 | Serge | 211 | fp->_flags &= ~__SORD; |
4349 | Serge | 212 | fp->_flags2 = 0; |
213 | memset (&fp->_mbstate, 0, sizeof (_mbstate_t)); |
||
214 | |||
215 | if (f < 0) |
||
216 | { /* did not get it after all */ |
||
217 | __sfp_lock_acquire (); |
||
218 | fp->_flags = 0; /* set it free */ |
||
219 | ptr->_errno = e; /* restore in case _close clobbered */ |
||
220 | _funlockfile (fp); |
||
221 | #ifndef __SINGLE_THREAD__ |
||
222 | __lock_close_recursive (fp->_lock); |
||
223 | #endif |
||
224 | __sfp_lock_release (); |
||
4921 | Serge | 225 | #ifdef _STDIO_WITH_THREAD_CANCELLATION_SUPPORT |
226 | pthread_setcancelstate (__oldcancel, &__oldcancel); |
||
227 | #endif |
||
4349 | Serge | 228 | return NULL; |
229 | } |
||
230 | |||
231 | fp->_flags = flags; |
||
232 | fp->_file = f; |
||
233 | fp->_cookie = (_PTR) fp; |
||
234 | fp->_read = __sread; |
||
235 | fp->_write = __swrite; |
||
236 | fp->_seek = __sseek; |
||
237 | fp->_close = __sclose; |
||
238 | |||
239 | #ifdef __SCLE |
||
240 | if (__stextmode (fp->_file)) |
||
241 | fp->_flags |= __SCLE; |
||
242 | #endif |
||
243 | |||
244 | _funlockfile (fp); |
||
4921 | Serge | 245 | #ifdef _STDIO_WITH_THREAD_CANCELLATION_SUPPORT |
246 | pthread_setcancelstate (__oldcancel, &__oldcancel); |
||
247 | #endif |
||
4349 | Serge | 248 | return fp; |
249 | } |
||
250 | |||
251 | #ifndef _REENT_ONLY |
||
252 | |||
253 | FILE * |
||
254 | _DEFUN(freopen, (file, mode, fp), |
||
4921 | Serge | 255 | _CONST char *__restrict file _AND |
256 | _CONST char *__restrict mode _AND |
||
257 | register FILE *__restrict fp) |
||
4349 | Serge | 258 | { |
259 | return _freopen_r (_REENT, file, mode, fp); |
||
260 | } |
||
261 | |||
262 | #endif /*!_REENT_ONLY */>>=> |