|
1 /* FREOPEN.C |
|
2 * |
|
3 * Portions Copyright (c) 1990-1999 Nokia Corporation and/or its subsidiary(-ies). |
|
4 * All rights reserved. |
|
5 */ |
|
6 |
|
7 /* |
|
8 * Copyright (c) 1990 The Regents of the University of California. |
|
9 * All rights reserved. |
|
10 * |
|
11 * Redistribution and use in source and binary forms are permitted |
|
12 * provided that the above copyright notice and this paragraph are |
|
13 * duplicated in all such forms and that any documentation, |
|
14 * advertising materials, and other materials related to such |
|
15 * distribution and use acknowledge that the software was developed |
|
16 * by the University of California, Berkeley. The name of the |
|
17 * University may not be used to endorse or promote products derived |
|
18 * from this software without specific prior written permission. |
|
19 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR |
|
20 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED |
|
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
|
22 */ |
|
23 |
|
24 /* |
|
25 FUNCTION |
|
26 <<freopen>>---open a file using an existing file descriptor |
|
27 |
|
28 INDEX |
|
29 freopen |
|
30 |
|
31 ANSI_SYNOPSIS |
|
32 #include <stdio.h> |
|
33 FILE *freopen(const char *<[file]>, const char *<[mode]>, |
|
34 FILE *<[fp]>); |
|
35 |
|
36 TRAD_SYNOPSIS |
|
37 #include <stdio.h> |
|
38 FILE *freopen(<[file]>, <[mode]>, <[fp]>) |
|
39 char *<[file]>; |
|
40 char *<[mode]>; |
|
41 FILE *<[fp]>; |
|
42 |
|
43 DESCRIPTION |
|
44 Use this variant of <<fopen>> if you wish to specify a particular file |
|
45 descriptor <[fp]> (notably <<stdin>>, <<stdout>>, or <<stderr>>) for |
|
46 the file. |
|
47 |
|
48 If <[fp]> was associated with another file or stream, <<freopen>> |
|
49 closes that other file or stream (but ignores any errors while closing |
|
50 it). |
|
51 |
|
52 <[file]> and <[mode]> are used just as in <<fopen>>. |
|
53 |
|
54 RETURNS |
|
55 If successful, the result is the same as the argument <[fp]>. If the |
|
56 file cannot be opened as specified, the result is <<NULL>>. |
|
57 |
|
58 PORTABILITY |
|
59 ANSI C requires <<freopen>>. |
|
60 |
|
61 Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>, |
|
62 <<lseek>>, <<open>>, <<read>>, <<sbrk>>, <<write>>. |
|
63 */ |
|
64 |
|
65 #include <time.h> |
|
66 #include <stdio_r.h> |
|
67 #include <fcntl.h> |
|
68 #include <stdlib_r.h> |
|
69 #include "LOCAL.H" |
|
70 #include <errno.h> |
|
71 |
|
72 /* |
|
73 * Re-direct an existing, open (probably) file to some other file. |
|
74 */ |
|
75 |
|
76 #define MaxFullName 255 |
|
77 |
|
78 /** |
|
79 Reopen a stream with a different file and mode. |
|
80 @return If the file has been succesfully reopened the function returns a pointer to the file. |
|
81 Otherwise a NULL pointer is returned. |
|
82 @param file name of the file to be opened. |
|
83 This paramenter must follow operating system's specifications and can include a path |
|
84 if the system supports it. |
|
85 @param mode type of access requested. |
|
86 @param fp pointer to open file that has to be reopened. |
|
87 */ |
|
88 EXPORT_C FILE * freopen (const char *file, const char *mode, FILE *fp) |
|
89 { |
|
90 wchar_t _wfile[MaxFullName+1]; |
|
91 wchar_t _wmode[MaxFullName+1]; |
|
92 struct _reent *ptr; |
|
93 |
|
94 if ((-1 != mbstowcs(_wfile, file, MaxFullName)) && |
|
95 (-1 != mbstowcs(_wmode, mode, MaxFullName))) |
|
96 { |
|
97 return wfreopen(_wfile, _wmode, fp); |
|
98 } |
|
99 |
|
100 CHECK_INIT (fp); |
|
101 ptr = fp->_data; |
|
102 ptr->_errno = EILSEQ; |
|
103 return NULL; |
|
104 } |
|
105 |
|
106 EXPORT_C FILE * wfreopen (const wchar_t *file, const wchar_t *mode, FILE *fp) |
|
107 { |
|
108 register int f; |
|
109 int isopen, flags, oflags, e; |
|
110 struct _reent *ptr; |
|
111 |
|
112 CHECK_INIT (fp); |
|
113 ptr = fp->_data; |
|
114 |
|
115 if ((flags = __sflags (ptr, mode, &oflags)) == 0) |
|
116 { |
|
117 (void) fclose (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 { |
|
131 fp->_flags = __SEOF; /* hold on to it */ |
|
132 isopen = 0; |
|
133 } |
|
134 else |
|
135 { |
|
136 if (fp->_flags & __SWR) |
|
137 (void) fflush (fp); |
|
138 /* if close is NULL, closing is a no-op, hence pointless */ |
|
139 isopen = fp->_close != NULL; |
|
140 if (fp->_file < 0 && isopen) |
|
141 { |
|
142 (void) (*fp->_close) (fp->_cookie); |
|
143 isopen = 0; |
|
144 } |
|
145 } |
|
146 |
|
147 /* |
|
148 * Now get a new descriptor to refer to the new file. |
|
149 */ |
|
150 |
|
151 f = _wopen_r (ptr, (wchar_t *)file, oflags, 0666); |
|
152 if (f < 0 && isopen) |
|
153 { |
|
154 /* |
|
155 * May have used up all descriptors, so close the old |
|
156 * and try again. |
|
157 */ |
|
158 (void) (*fp->_close) (fp->_cookie); |
|
159 isopen = 0; |
|
160 f = _wopen_r (ptr, (wchar_t *) file, oflags, 0666); |
|
161 } |
|
162 e = ptr->_errno; |
|
163 |
|
164 /* |
|
165 * Finish closing fp. Even if the open succeeded above, |
|
166 * we cannot keep fp->_base: it may be the wrong size. |
|
167 * This loses the effect of any setbuffer calls, |
|
168 * but stdio has always done this before. |
|
169 */ |
|
170 |
|
171 if (isopen) |
|
172 (void) (*fp->_close) (fp->_cookie); |
|
173 if (fp->_flags & __SMBF) |
|
174 _free_r (ptr, (char *) fp->_bf._base); |
|
175 fp->_w = 0; |
|
176 fp->_r = 0; |
|
177 fp->_p = NULL; |
|
178 fp->_bf._base = NULL; |
|
179 fp->_bf._size = 0; |
|
180 fp->_lbfsize = 0; |
|
181 if (HASUB (fp)) |
|
182 FREEUB (fp); |
|
183 fp->_ub._size = 0; |
|
184 if (HASLB (fp)) |
|
185 FREELB (fp); |
|
186 fp->_lb._size = 0; |
|
187 |
|
188 if (f < 0) |
|
189 { /* did not get it after all */ |
|
190 fp->_flags = 0; /* set it free */ |
|
191 ptr->_errno = e; /* restore in case _close clobbered */ |
|
192 return NULL; |
|
193 } |
|
194 |
|
195 fp->_flags = (short)flags; |
|
196 fp->_file = (short)f; |
|
197 fp->_cookie = (void*) fp; |
|
198 fp->_read = __sread; |
|
199 fp->_write = __swrite; |
|
200 fp->_seek = __sseek; |
|
201 fp->_close = __sclose; |
|
202 return fp; |
|
203 } |