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 
__is_regular_file(_STLP_fd fd)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.
__file_size(_STLP_fd fd)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 
_Filebuf_base()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 
_S_initialize()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.
_M_file_size()167 streamoff _Filebuf_base::_M_file_size()
168 {
169   return _STLP_PRIV __file_size(_M_file_id);
170 }
171 
_M_open(const char * name,ios_base::openmode openmode,long permission)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 
_M_open(const char * name,ios_base::openmode openmode)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.
_M_open(int file_no,ios_base::openmode)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 
_M_open(FILE * file,ios_base::openmode openmode)303 bool _Filebuf_base::_M_open(FILE *file, ios_base::openmode openmode)
304 {
305   _STLP_fd file_no;
306 
307   if (_M_is_open)
308     return false;
309 
310   _M_file = file;
311 
312   if (_M_file) {
313     file_no = fileno(_M_file);
314   } else {
315     return false;
316   }
317 
318   // unset buffering immediately
319   setbuf(_M_file, 0);
320 
321   _M_is_open = true;
322 
323   if (openmode & ios_base::ate) {
324     if (FSEEK(_M_file, 0, SEEK_END) != 0)
325       _M_is_open = false;
326   }
327 
328   _M_file_id = file_no;
329   _M_should_close = _M_is_open;
330   _M_openmode = openmode;
331 
332   if (_M_is_open)
333     _M_regular_file = _STLP_PRIV __is_regular_file(_M_file_id);
334 
335   return (_M_is_open != 0);
336 }
337 
_M_close()338 bool _Filebuf_base::_M_close()
339 {
340   if (!_M_is_open)
341     return false;
342 
343   bool ok = _M_should_close ? (fclose(_M_file) == 0) : true;
344 
345   _M_is_open = _M_should_close = false;
346   _M_openmode = 0;
347   return ok;
348 }
349 
350 // Read up to n characters into a buffer.  Return value is number of
351 // characters read.
_M_read(char * buf,ptrdiff_t n)352 ptrdiff_t _Filebuf_base::_M_read(char* buf, ptrdiff_t n) {
353   return fread(buf, 1, n, _M_file);
354 }
355 
356 // Write n characters from a buffer.  Return value: true if we managed
357 // to write the entire buffer, false if we didn't.
_M_write(char * buf,ptrdiff_t n)358 bool _Filebuf_base::_M_write(char* buf, ptrdiff_t n)
359 {
360   for (;;) {
361     ptrdiff_t written = fwrite(buf, 1, n, _M_file);
362 
363     if (n == written) {
364       return true;
365     }
366 
367     if (written > 0 && written < n) {
368       n -= written;
369       buf += written;
370     } else {
371       return false;
372     }
373   }
374 }
375 
376 // Wrapper for lseek or the like.
_M_seek(streamoff offset,ios_base::seekdir dir)377 streamoff _Filebuf_base::_M_seek(streamoff offset, ios_base::seekdir dir)
378 {
379   int whence;
380 
381   switch ( dir ) {
382     case ios_base::beg:
383       if (offset < 0 /* || offset > _M_file_size() */ )
384         return streamoff(-1);
385       whence = SEEK_SET;
386       break;
387     case ios_base::cur:
388       whence = SEEK_CUR;
389       break;
390     case ios_base::end:
391       if (/* offset > 0 || */  -offset > _M_file_size() )
392         return streamoff(-1);
393       whence = SEEK_END;
394       break;
395     default:
396       return streamoff(-1);
397   }
398 
399   if ( FSEEK(_M_file, offset, whence) == 0 ) {
400     return FTELL(_M_file);
401   }
402 
403   return streamoff(-1);
404 }
405 
406 
407 // Attempts to memory-map len bytes of the current file, starting
408 // at position offset.  Precondition: offset is a multiple of the
409 // page size.  Postcondition: return value is a null pointer if the
410 // memory mapping failed.  Otherwise the return value is a pointer to
411 // the memory-mapped file and the file position is set to offset.
_M_mmap(streamoff,streamoff)412 void *_Filebuf_base::_M_mmap(streamoff, streamoff )
413 {
414   return 0;
415 }
416 
_M_unmap(void *,streamoff)417 void _Filebuf_base::_M_unmap(void*, streamoff)
418 {
419   // precondition : there is a valid mapping at the moment
420 }
421 
422 _STLP_END_NAMESPACE
423