comparison packages/language/c/libc/stdio/current/src/common/fopen.cxx @ 115:6ed91473a1cd ecos-sw-2000-08-21

Merge from eCos master repository on 2000-08-21-22:40:54-BST
author jlarmour
date Fri, 25 Aug 2000 17:32:38 +0000
parents
children d2f49caf9e38
comparison
equal deleted inserted replaced
114:5ad2b71d525e 115:6ed91473a1cd
1 //===========================================================================
2 //
3 // fopen.cxx
4 //
5 // Implementation of C library file open function as per ANSI 7.9.5.3
6 //
7 //===========================================================================
8 //####COPYRIGHTBEGIN####
9 //
10 // -------------------------------------------
11 // The contents of this file are subject to the Red Hat eCos Public License
12 // Version 1.1 (the "License"); you may not use this file except in
13 // compliance with the License. You may obtain a copy of the License at
14 // http://www.redhat.com/
15 //
16 // Software distributed under the License is distributed on an "AS IS"
17 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
18 // License for the specific language governing rights and limitations under
19 // the License.
20 //
21 // The Original Code is eCos - Embedded Configurable Operating System,
22 // released September 30, 1998.
23 //
24 // The Initial Developer of the Original Code is Red Hat.
25 // Portions created by Red Hat are
26 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
27 // All Rights Reserved.
28 // -------------------------------------------
29 //
30 //####COPYRIGHTEND####
31 //===========================================================================
32 //#####DESCRIPTIONBEGIN####
33 //
34 // Author(s): jlarmour
35 // Contributors:
36 // Date: 2000-04-20
37 // Purpose: Implements ISO C fopen() function
38 // Description:
39 // Usage:
40 //
41 //####DESCRIPTIONEND####
42 //
43 //===========================================================================
44
45 // CONFIGURATION
46
47 #include <pkgconf/libc_stdio.h> // Configuration header
48
49
50 // Do we want fopen()?
51 #if defined(CYGPKG_LIBC_STDIO_OPEN)
52
53 // INCLUDES
54
55 #include <cyg/infra/cyg_type.h> // Common project-wide type definitions
56 #include <stddef.h> // NULL and size_t from compiler
57 #include <errno.h> // Error codes
58 #include <stdio.h> // header for fopen()
59 #include <stdlib.h> // malloc()
60 #include <string.h> // strncmp() and strcmp()
61 #include <cyg/libc/stdio/stdiofiles.hxx> // C library files
62 #include <cyg/libc/stdio/stream.hxx> // C library streams
63
64 #include <cyg/libc/stdio/io.inl> // I/O system inlines
65
66 // FUNCTIONS
67
68 // process the mode string. Return true on error
69 static cyg_bool
70 process_mode( const char *mode, Cyg_StdioStream::OpenMode *rw,
71 cyg_bool *binary, cyg_bool *append )
72 {
73 *binary = *append = false; // default
74
75 switch (mode[0]) {
76 case 'r':
77 *rw = Cyg_StdioStream::CYG_STREAM_READ;
78 break;
79
80 case 'a':
81 *append = true;
82 case 'w':
83 *rw = Cyg_StdioStream::CYG_STREAM_WRITE;
84 break;
85
86 default:
87 return true;
88 } // switch
89
90 // ANSI says additional characters may follow the sequences, that we
91 // don't necessarily recognise so we just ignore them, and pretend that
92 // its the end of the string
93
94 switch (mode[1]) {
95 case 'b':
96 *binary = true;
97 break;
98 case '+':
99 *rw = Cyg_StdioStream::CYG_STREAM_READWRITE;
100 break;
101 default:
102 return false;
103 } // switch
104
105 switch (mode[2]) {
106 case 'b':
107 *binary = true;
108 break;
109 case '+':
110 *rw = Cyg_StdioStream::CYG_STREAM_READWRITE;
111 break;
112 default:
113 return false;
114 } // switch
115
116 return false;
117 } // process_mode()
118
119
120 static FILE *fopen_inner( cyg_stdio_handle_t dev,
121 Cyg_StdioStream::OpenMode open_mode,
122 cyg_bool binary,
123 cyg_bool append)
124 {
125 Cyg_StdioStream *curr_stream;
126 int i;
127 Cyg_ErrNo err;
128 int bufmode = _IOFBF;
129 cyg_ucount32 bufsize = BUFSIZ;
130
131 Cyg_libc_stdio_files::lock();
132
133 // find an empty slot
134 for (i=0; i < FOPEN_MAX; i++) {
135 curr_stream = Cyg_libc_stdio_files::get_file_stream(i);
136 if (curr_stream == NULL)
137 break;
138 } // for
139
140 if (i == FOPEN_MAX) { // didn't find an empty slot
141 errno = EMFILE;
142 cyg_stdio_close( dev );
143 return NULL;
144 } // if
145
146 // Decide the buffering mode. The default is fully buffered, but if
147 // this is an interactive stream then set it to non buffered.
148 if( (dev != CYG_STDIO_HANDLE_NULL) &&
149 cyg_stdio_interactive( dev ) )
150 bufmode = _IONBF, bufsize = 0;
151
152 // Allocate it some memory and construct it.
153 curr_stream = new Cyg_StdioStream( dev, open_mode, append, binary,
154 bufmode, bufsize );
155
156 if (curr_stream == NULL) {
157 cyg_stdio_close( dev );
158 errno = ENOMEM;
159 return NULL;
160 } // if
161
162
163 // it puts any error in its own error flag
164 if (( err=curr_stream->get_error() )) {
165
166 Cyg_libc_stdio_files::unlock();
167
168 free( curr_stream );
169
170 cyg_stdio_close( dev );
171
172 errno = err;
173
174 return NULL;
175
176 } // if
177
178 Cyg_libc_stdio_files::set_file_stream(i, curr_stream);
179
180 Cyg_libc_stdio_files::unlock();
181
182 return (FILE *)(curr_stream);
183
184 } // fopen_inner()
185
186 externC FILE *
187 fopen( const char *filename, const char *mode )
188 {
189 cyg_stdio_handle_t dev;
190 Cyg_ErrNo err;
191 Cyg_StdioStream::OpenMode open_mode;
192 cyg_bool binary, append;
193
194 // process_mode returns true on error
195 if (process_mode( mode, &open_mode, &binary, &append )) {
196 errno = EINVAL;
197 return NULL;
198 } // if
199
200 err = cyg_stdio_open( filename, open_mode, binary, append, &dev );
201
202 // if not found
203 if (err != ENOERR) {
204 errno = ENOENT;
205 return NULL;
206 } // if
207
208 return fopen_inner( dev, open_mode, binary, append );
209
210 } // fopen()
211
212
213 #endif // defined(CYGPKG_LIBC_STDIO_OPEN)
214
215 #ifdef CYGPKG_LIBC_STDIO_FILEIO
216
217 externC int fileno( FILE *stream )
218 {
219 Cyg_StdioStream *real_stream = (Cyg_StdioStream *)stream;
220
221 return real_stream->get_dev();
222 }
223
224 externC FILE *fdopen( int fd, const char *mode )
225 {
226 Cyg_StdioStream::OpenMode open_mode;
227 cyg_bool binary, append;
228 FILE *f;
229
230 // process_mode returns true on error
231 if (process_mode( mode, &open_mode, &binary, &append )) {
232 errno = EINVAL;
233 return NULL;
234 } // if
235
236 f = fopen_inner( (cyg_stdio_handle_t)fd, open_mode, binary, append );
237
238 if( f == NULL )
239 return f;
240
241 // Do a null seek to initialize the file position.
242 Cyg_StdioStream *real_stream = (Cyg_StdioStream *)f;
243 fpos_t pos = 0;
244 real_stream->set_position( pos, SEEK_CUR );
245 }
246
247 #endif // def CYGPKG_LIBC_STDIO_FILEIO
248
249
250 // EOF fopen.cxx