Home | History | Annotate | Download | only in details
      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
    388