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