|
1 /* |
|
2 * Copyright (c) 1999 |
|
3 * Silicon Graphics Computer Systems, Inc. |
|
4 * |
|
5 * Copyright (c) 1999 |
|
6 * Boris Fomitchev |
|
7 * |
|
8 * This material is provided "as is", with absolutely no warranty expressed |
|
9 * or implied. Any use is at your own risk. |
|
10 * |
|
11 * Permission to use or copy this software for any purpose is hereby granted |
|
12 * without fee, provided the above notices are retained on all copies. |
|
13 * Permission to modify the code and to distribute modified code is granted, |
|
14 * provided the above notices are retained, and a notice that the code was |
|
15 * modified is included with the above copyright notice. |
|
16 * |
|
17 */ |
|
18 |
|
19 #if defined (__SUNPPRO_CC) && !defined (_STLP_NO_NEW_C_HEADERS) |
|
20 # include <time.h> |
|
21 // For sunpro, it chokes if time.h is included through stat.h |
|
22 #endif |
|
23 |
|
24 #include <fstream> |
|
25 |
|
26 #ifdef __CYGWIN__ |
|
27 # define __int64 long long |
|
28 #endif |
|
29 |
|
30 #include <cstdio> |
|
31 #if !defined(__ISCPP__) |
|
32 extern "C" { |
|
33 # include <sys/stat.h> |
|
34 } |
|
35 #endif |
|
36 |
|
37 #if defined( __MSL__ ) |
|
38 # include <unix.h> |
|
39 #endif |
|
40 |
|
41 #if defined(__ISCPP__) |
|
42 # include <c_locale_is/filestat.h> |
|
43 #endif |
|
44 |
|
45 #if defined(__BEOS__) && defined(__INTEL__) |
|
46 # include <fcntl.h> |
|
47 # include <sys/stat.h> // For _fstat |
|
48 #endif |
|
49 |
|
50 #if defined (_STLP_MSVC) || defined (__MINGW32__) |
|
51 # include <fcntl.h> |
|
52 # define S_IREAD _S_IREAD |
|
53 # define S_IWRITE _S_IWRITE |
|
54 # define S_IFREG _S_IFREG |
|
55 // map permission masks |
|
56 # ifndef S_IRUSR |
|
57 # define S_IRUSR _S_IREAD |
|
58 # define S_IWUSR _S_IWRITE |
|
59 # endif |
|
60 # ifndef S_IRGRP |
|
61 # define S_IRGRP _S_IREAD |
|
62 # define S_IWGRP _S_IWRITE |
|
63 # endif |
|
64 # ifndef S_IROTH |
|
65 # define S_IROTH _S_IREAD |
|
66 # define S_IWOTH _S_IWRITE |
|
67 # endif |
|
68 |
|
69 # ifndef O_RDONLY |
|
70 # define O_RDONLY _O_RDONLY |
|
71 # define O_WRONLY _O_WRONLY |
|
72 # define O_RDWR _O_RDWR |
|
73 # define O_APPEND _O_APPEND |
|
74 # define O_CREAT _O_CREAT |
|
75 # define O_TRUNC _O_TRUNC |
|
76 # define O_TEXT _O_TEXT |
|
77 # define O_BINARY _O_BINARY |
|
78 # endif |
|
79 |
|
80 # ifndef O_ACCMODE |
|
81 # define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR) |
|
82 # endif |
|
83 #endif |
|
84 |
|
85 const _STLP_fd INVALID_STLP_FD = -1; |
|
86 |
|
87 |
|
88 # ifdef __MSL__ |
|
89 # define _O_TEXT 0x0 |
|
90 # if !defined( O_TEXT ) |
|
91 # define O_TEXT _O_TEXT |
|
92 # endif |
|
93 # define _S_IFREG S_IFREG |
|
94 # define S_IREAD S_IRUSR |
|
95 # define S_IWRITE S_IWUSR |
|
96 # define S_IEXEC S_IXUSR |
|
97 # define _S_IWRITE S_IWRITE |
|
98 # define _S_IREAD S_IREAD |
|
99 # define _open open |
|
100 # define _close close |
|
101 # define _read read |
|
102 # define _write write |
|
103 # endif |
|
104 |
|
105 _STLP_BEGIN_NAMESPACE |
|
106 |
|
107 // Compare with streamoff definition in stl/char_traits.h! |
|
108 |
|
109 #if defined (_STLP_USE_DEFAULT_FILE_OFFSET) || \ |
|
110 (!defined(_LARGEFILE_SOURCE) && !defined(_LARGEFILE64_SOURCE)) |
|
111 # define FOPEN fopen |
|
112 # define FSEEK fseek |
|
113 # define FSTAT fstat |
|
114 # define STAT stat |
|
115 # define FTELL ftell |
|
116 #else |
|
117 # define FOPEN fopen64 |
|
118 # define FSEEK fseeko64 |
|
119 # define FSTAT fstat64 |
|
120 # define STAT stat64 |
|
121 # define FTELL ftello64 |
|
122 #endif |
|
123 |
|
124 _STLP_MOVE_TO_PRIV_NAMESPACE |
|
125 |
|
126 // Helper functions for _Filebuf_base. |
|
127 |
|
128 static bool __is_regular_file(_STLP_fd fd) { |
|
129 struct STAT buf; |
|
130 return FSTAT(fd, &buf) == 0 && (buf.st_mode & S_IFREG) != 0 ; |
|
131 } |
|
132 |
|
133 // Number of characters in the file. |
|
134 static streamoff __file_size(_STLP_fd fd) { |
|
135 streamoff ret = 0; |
|
136 |
|
137 struct STAT buf; |
|
138 if (FSTAT(fd, &buf) == 0 && (buf.st_mode & S_IFREG) != 0) |
|
139 ret = buf.st_size > 0 ? buf.st_size : 0; |
|
140 |
|
141 return ret; |
|
142 } |
|
143 |
|
144 _STLP_MOVE_TO_STD_NAMESPACE |
|
145 |
|
146 // All version of Unix have mmap and lseek system calls. Some also have |
|
147 // longer versions of those system calls to accommodate 64-bit offsets. |
|
148 // If we're on a Unix system, define some macros to encapsulate those |
|
149 // differences. |
|
150 |
|
151 size_t _Filebuf_base::_M_page_size = 4096; |
|
152 |
|
153 _Filebuf_base::_Filebuf_base() |
|
154 : _M_file_id(INVALID_STLP_FD), |
|
155 _M_openmode(0), |
|
156 _M_is_open(false), |
|
157 _M_should_close(false) |
|
158 {} |
|
159 |
|
160 void _Filebuf_base::_S_initialize() |
|
161 { |
|
162 |
|
163 } |
|
164 |
|
165 // Return the size of the file. This is a wrapper for stat. |
|
166 // Returns zero if the size cannot be determined or is ill-defined. |
|
167 streamoff _Filebuf_base::_M_file_size() |
|
168 { |
|
169 return _STLP_PRIV __file_size(_M_file_id); |
|
170 } |
|
171 |
|
172 bool _Filebuf_base::_M_open(const char* name, ios_base::openmode openmode, |
|
173 long permission) |
|
174 { |
|
175 _STLP_fd file_no; |
|
176 |
|
177 if (_M_is_open) |
|
178 return false; |
|
179 |
|
180 // use FILE-based i/o |
|
181 const char* flags; |
|
182 |
|
183 switch (openmode & (~ios_base::ate)) { |
|
184 case ios_base::out: |
|
185 case ios_base::out | ios_base::trunc: |
|
186 flags = "w"; |
|
187 break; |
|
188 |
|
189 case ios_base::out | ios_base::binary: |
|
190 case ios_base::out | ios_base::trunc | ios_base::binary: |
|
191 flags = "wb"; |
|
192 break; |
|
193 |
|
194 case ios_base::out | ios_base::app: |
|
195 flags = "a"; |
|
196 break; |
|
197 |
|
198 case ios_base::out | ios_base::app | ios_base::binary: |
|
199 flags = "ab"; |
|
200 break; |
|
201 |
|
202 case ios_base::in: |
|
203 flags = "r"; |
|
204 break; |
|
205 |
|
206 case ios_base::in | ios_base::binary: |
|
207 flags = "rb"; |
|
208 break; |
|
209 |
|
210 case ios_base::in | ios_base::out: |
|
211 flags = "r+"; |
|
212 break; |
|
213 |
|
214 case ios_base::in | ios_base::out | ios_base::binary: |
|
215 flags = "r+b"; |
|
216 break; |
|
217 |
|
218 case ios_base::in | ios_base::out | ios_base::trunc: |
|
219 flags = "w+"; |
|
220 break; |
|
221 |
|
222 case ios_base::in | ios_base::out | ios_base::trunc | ios_base::binary: |
|
223 flags = "w+b"; |
|
224 break; |
|
225 |
|
226 default: // The above are the only combinations of |
|
227 return false; // flags allowed by the C++ standard. |
|
228 } |
|
229 |
|
230 // fbp : TODO : set permissions ! |
|
231 (void)permission; // currently unused //*TY 02/26/2000 - added to suppress warning message |
|
232 _M_file = FOPEN(name, flags); |
|
233 |
|
234 if (_M_file) { |
|
235 file_no = fileno(_M_file); |
|
236 } else { |
|
237 return false; |
|
238 } |
|
239 |
|
240 // unset buffering immediately |
|
241 setbuf(_M_file, 0); |
|
242 |
|
243 _M_is_open = true; |
|
244 |
|
245 if (openmode & ios_base::ate) { |
|
246 if (FSEEK(_M_file, 0, SEEK_END) != 0) |
|
247 _M_is_open = false; |
|
248 } |
|
249 |
|
250 _M_file_id = file_no; |
|
251 _M_should_close = _M_is_open; |
|
252 _M_openmode = openmode; |
|
253 |
|
254 if (_M_is_open) |
|
255 _M_regular_file = _STLP_PRIV __is_regular_file(_M_file_id); |
|
256 |
|
257 return (_M_is_open != 0); |
|
258 } |
|
259 |
|
260 |
|
261 bool _Filebuf_base::_M_open(const char* name, ios_base::openmode openmode) |
|
262 { |
|
263 // This doesn't really grant everyone in the world read/write |
|
264 // access. On Unix, file-creation system calls always clear |
|
265 // bits that are set in the umask from the permissions flag. |
|
266 return this->_M_open(name, openmode, S_IRUSR | S_IWUSR | S_IRGRP | |
|
267 S_IWGRP | S_IROTH | S_IWOTH); |
|
268 } |
|
269 |
|
270 // Associated the filebuf with a file descriptor pointing to an already- |
|
271 // open file. Mode is set to be consistent with the way that the file |
|
272 // was opened. |
|
273 bool _Filebuf_base::_M_open( int file_no, ios_base::openmode ) |
|
274 { |
|
275 if (_M_is_open || file_no < 0) |
|
276 return false; |
|
277 |
|
278 struct STAT buf; |
|
279 if (FSTAT(file_no, &buf) != 0) |
|
280 return false; |
|
281 int mode = buf.st_mode; |
|
282 |
|
283 switch ( mode & (S_IWRITE | S_IREAD) ) { |
|
284 case S_IREAD: |
|
285 _M_openmode = ios_base::in; |
|
286 break; |
|
287 case S_IWRITE: |
|
288 _M_openmode = ios_base::out; |
|
289 break; |
|
290 case (S_IWRITE | S_IREAD): |
|
291 _M_openmode = ios_base::in | ios_base::out; |
|
292 break; |
|
293 default: |
|
294 return false; |
|
295 } |
|
296 _M_file_id = file_no; |
|
297 _M_is_open = true; |
|
298 _M_should_close = false; |
|
299 _M_regular_file = _STLP_PRIV __is_regular_file(_M_file_id); |
|
300 return true; |
|
301 } |
|
302 |
|
303 bool _Filebuf_base::_M_close() |
|
304 { |
|
305 if (!_M_is_open) |
|
306 return false; |
|
307 |
|
308 bool ok = _M_should_close ? (fclose(_M_file) == 0) : true; |
|
309 |
|
310 _M_is_open = _M_should_close = false; |
|
311 _M_openmode = 0; |
|
312 return ok; |
|
313 } |
|
314 |
|
315 // Read up to n characters into a buffer. Return value is number of |
|
316 // characters read. |
|
317 ptrdiff_t _Filebuf_base::_M_read(char* buf, ptrdiff_t n) { |
|
318 return fread(buf, 1, n, _M_file); |
|
319 } |
|
320 |
|
321 // Write n characters from a buffer. Return value: true if we managed |
|
322 // to write the entire buffer, false if we didn't. |
|
323 bool _Filebuf_base::_M_write(char* buf, ptrdiff_t n) |
|
324 { |
|
325 for (;;) { |
|
326 ptrdiff_t written = fwrite(buf, 1, n, _M_file); |
|
327 |
|
328 if (n == written) { |
|
329 return true; |
|
330 } |
|
331 |
|
332 if (written > 0 && written < n) { |
|
333 n -= written; |
|
334 buf += written; |
|
335 } else { |
|
336 return false; |
|
337 } |
|
338 } |
|
339 } |
|
340 |
|
341 // Wrapper for lseek or the like. |
|
342 streamoff _Filebuf_base::_M_seek(streamoff offset, ios_base::seekdir dir) |
|
343 { |
|
344 int whence; |
|
345 |
|
346 switch ( dir ) { |
|
347 case ios_base::beg: |
|
348 if (offset < 0 /* || offset > _M_file_size() */ ) |
|
349 return streamoff(-1); |
|
350 whence = SEEK_SET; |
|
351 break; |
|
352 case ios_base::cur: |
|
353 whence = SEEK_CUR; |
|
354 break; |
|
355 case ios_base::end: |
|
356 if (/* offset > 0 || */ -offset > _M_file_size() ) |
|
357 return streamoff(-1); |
|
358 whence = SEEK_END; |
|
359 break; |
|
360 default: |
|
361 return streamoff(-1); |
|
362 } |
|
363 |
|
364 if ( FSEEK(_M_file, offset, whence) == 0 ) { |
|
365 return FTELL(_M_file); |
|
366 } |
|
367 |
|
368 return streamoff(-1); |
|
369 } |
|
370 |
|
371 |
|
372 // Attempts to memory-map len bytes of the current file, starting |
|
373 // at position offset. Precondition: offset is a multiple of the |
|
374 // page size. Postcondition: return value is a null pointer if the |
|
375 // memory mapping failed. Otherwise the return value is a pointer to |
|
376 // the memory-mapped file and the file position is set to offset. |
|
377 void *_Filebuf_base::_M_mmap(streamoff, streamoff ) |
|
378 { |
|
379 return 0; |
|
380 } |
|
381 |
|
382 void _Filebuf_base::_M_unmap(void*, streamoff) |
|
383 { |
|
384 // precondition : there is a valid mapping at the moment |
|
385 } |
|
386 |
|
387 _STLP_END_NAMESPACE |