home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / stlpt453.zip / STLport-4.5.3 / src / fstream.cpp < prev    next >
C/C++ Source or Header  |  2002-01-18  |  30KB  |  1,136 lines

  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.  
  20. # include "stlport_prefix.h"
  21.  
  22. # if defined  (__SUNPPRO_CC)  && !defined (_STLP_NO_NEW_C_HEADERS)
  23. #  include <time.h>
  24. // For sunpro, it chokes if time.h is included through stat.h
  25. # endif
  26.  
  27. #include <fstream>
  28.  
  29.  
  30. #ifdef __CYGWIN__
  31. #  define __int64 long long
  32. #endif
  33.  
  34. #if defined (_STLP_USE_UNIX_IO)
  35. extern "C" {
  36. // open/close/read/write
  37. #  include <sys/stat.h>           // For stat
  38. #  include <sys/mman.h>           // For mmap
  39.  
  40. //  on HP-UX 11, this one contradicts with pthread.h on pthread_atfork, unless we unset this
  41. #  if defined (__hpux) && defined (__GNUC__)
  42. #   undef _INCLUDE_POSIX1C_SOURCE
  43. #  endif
  44.  
  45. #  include <unistd.h>
  46. #  include <fcntl.h>
  47. }
  48. # ifdef __APPLE__
  49. #  include <sys/sysctl.h>
  50. # endif
  51. #elif defined (_STLP_USE_WIN32_IO)
  52. # define WIN32_LEAN_AND_MEAN
  53. #  include <windows.h>
  54.  
  55. # ifdef __BORLANDC__
  56. #  if (__BORLANDC__ > 0x530)
  57. #  include <cfcntl.h>            // For _O_RDONLY, etc
  58. #  else
  59. #  include <fcntl.h>            // For _O_RDONLY, etc
  60. #  endif
  61. #  include <sys/stat.h>         // For _fstat
  62. # elif !defined(_STLP_WINCE)
  63. #  include <io.h>               // For _get_osfhandle
  64. #  include <fcntl.h>            // For _O_RDONLY, etc
  65. #  include <sys/stat.h>         // For _fstat
  66. # endif
  67.  
  68. # define _TEXTBUF_SIZE 0x1000
  69. #elif defined (_STLP_USE_UNIX_EMULATION_IO)
  70. #  if defined( __MSL__ )
  71. #   include <unistd.h>
  72. #  else
  73. #   include <io.h>
  74. #  endif
  75. #  include <fcntl.h>
  76. #  include <sys/stat.h>
  77.  
  78. #elif defined (_STLP_USE_STDIO_IO)
  79. #  include <cstdio>
  80.  
  81. #  if !(defined(__MRC__) || defined(__SC__) || defined(__ISCPP__) )
  82. extern "C" {
  83. #   include <sys/stat.h>
  84. }
  85. #  endif
  86. #  if defined( __MSL__ )
  87. #   include <unix.h>
  88. #  endif
  89. #  if defined(__ISCPP__)
  90. #   include <c_locale_is/filestat.h>
  91. #  endif
  92. #  if defined(__BEOS__) && defined(__INTEL__)
  93. #   include <fcntl.h>
  94. #   include <sys/stat.h>         // For _fstat
  95. #   define _S_IREAD S_IREAD
  96. #   define _S_IWRITE S_IWRITE
  97. #   define _S_IFREG S_IFREG
  98. #  endif
  99. #else
  100. #error "Configure i/o !"
  101. #endif
  102.  
  103. // map permission masks
  104. #if defined (_STLP_USE_UNIX_EMULATION_IO) || defined (_STLP_USE_STDIO_IO)
  105. # ifndef S_IRUSR
  106. #  define S_IRUSR _S_IREAD
  107. #  define S_IWUSR _S_IWRITE
  108. #  define S_IRGRP _S_IREAD
  109. #  define S_IWGRP _S_IWRITE
  110. #  define S_IROTH _S_IREAD
  111. #  define S_IWOTH _S_IWRITE
  112. # endif
  113. # ifndef O_RDONLY
  114. #   define O_RDONLY _O_RDONLY
  115. #   define O_WRONLY _O_WRONLY
  116. #   define O_RDWR   _O_RDWR
  117. #   define O_APPEND _O_APPEND
  118. #   define O_CREAT  _O_CREAT
  119. #   define O_TRUNC  _O_TRUNC
  120. #   define O_TEXT   _O_TEXT
  121. #   define O_BINARY _O_BINARY
  122. # endif
  123.  
  124. # ifdef __MSL__
  125. #  define _O_TEXT 0x0
  126. #  if !defined( O_TEXT )
  127. #   define O_TEXT _O_TEXT
  128. #  endif
  129. #  define _S_IFREG S_IFREG
  130. #  define S_IREAD        S_IRUSR
  131. #  define S_IWRITE       S_IWUSR
  132. #  define S_IEXEC        S_IXUSR
  133. #  define _S_IWRITE S_IWRITE
  134. #  define _S_IREAD S_IREAD
  135. #  define _open open
  136. #  define _lseek lseek
  137. #  define _close close
  138. #  define _read read
  139. #  define _write write
  140. # endif
  141.  
  142. #endif
  143.  
  144. #ifndef O_ACCMODE
  145. #   define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR)
  146. #endif
  147.  
  148. #include "fstream_impl.h"
  149.  
  150. # ifdef _STLP_LONG_LONG
  151. # define ULL(x) ((unsigned _STLP_LONG_LONG)x)
  152. // # elif defined (_MSC_VER) || defined (__BORLANDC__)
  153. // # define ULL(x) ((__int64)x)
  154. # elif defined(__MRC__) || defined(__SC__)        //*TY 02/25/2000 - added support for MPW compilers
  155. # include <Math64.h>
  156. # define ULL(x) (U64SetU(x))
  157. # elif defined(__ISCPP__)
  158. #  include "uint64.h"
  159. # else
  160. #  error "there should be some long long type on the system!"
  161. # endif
  162.  
  163. __SGI_BEGIN_NAMESPACE
  164.  
  165. #if !defined(__MSL__) && !defined(__MRC__) && !defined(__SC__) && !defined(_STLP_WINCE)        //*TY 04/15/2000 - exclude mpw compilers also
  166. ios_base::openmode flag_to_openmode(int mode)
  167. {
  168.   ios_base::openmode ret;
  169.   
  170.   switch(mode & O_ACCMODE) {
  171.  
  172.   case O_RDONLY:
  173.     ret = ios_base::in; break;
  174.  
  175.   case O_WRONLY:
  176.     ret = ios_base::out; break;
  177.  
  178.   case O_RDWR:
  179.     ret = ios_base::in | ios_base::out; break;
  180.  
  181.   }
  182.  
  183.   if (mode & O_APPEND)
  184.     ret |= ios_base::app;
  185.   
  186. #  ifdef _STLP_USE_WIN32_IO
  187.   if (mode & O_BINARY)
  188.     ret |= ios_base::binary;
  189. #  endif // _MSC_VER
  190.  
  191.   return ret;
  192.   
  193. }
  194. # endif /* MSL */
  195.  
  196. // Helper functions for _Filebuf_base.
  197.  
  198. bool __is_regular_file(_STLP_fd fd) {
  199.  
  200. #if defined (_STLP_UNIX)
  201.  
  202.   struct stat buf;
  203.   return fstat(fd, &buf) == 0 && S_ISREG(buf.st_mode);
  204.  
  205. #elif defined(__MRC__) || defined(__SC__)        //*TY 02/25/2000 - added support for MPW compilers
  206.  
  207.   #pragma unused(fd)
  208.   return true;  // each file is a regular file under mac os, isn't it? (we don't have fstat())
  209.  
  210. #elif defined(_STLP_USE_UNIX_EMULATION_IO) || defined (_STLP_USE_STDIO_IO)
  211.  
  212.   struct stat buf;
  213.   return fstat(fd, &buf) == 0 && (buf.st_mode & _S_IFREG) != 0 ;
  214.  
  215. #   elif defined (_STLP_USE_WIN32_IO) && !defined(_STLP_WINCE)
  216.  
  217.   return (GetFileType(fd) & ~FILE_TYPE_REMOTE) == FILE_TYPE_DISK;
  218.  
  219. #else
  220.   (void)fd;    // dwa 4/27/00 - suppress unused parameter warning
  221.   return false;
  222.  
  223. #endif
  224. }
  225.  
  226. // Number of characters in the file.  
  227. streamoff __file_size(_STLP_fd fd) {
  228.  streamoff ret = 0;
  229.  
  230. #if defined (_STLP_UNIX)
  231.  
  232.   struct stat buf;
  233.   if(fstat(fd, &buf) == 0 && S_ISREG(buf.st_mode))
  234.     ret = buf.st_size > 0 ? buf.st_size : 0;
  235.  
  236. #elif defined(__MRC__) || defined(__SC__)        //*TY 02/25/2000 - added support for MPW compilers
  237.  
  238.   #pragma unused(fd)
  239.  
  240. #elif defined(_STLP_USE_UNIX_EMULATION_IO) || defined (_STLP_USE_STDIO_IO)
  241.  
  242.   struct stat buf;
  243.   if(fstat(fd, &buf) == 0 && (buf.st_mode & _S_IFREG) != 0)
  244.     ret = buf.st_size > 0 ? buf.st_size : 0;
  245.  
  246. #   elif defined (_STLP_USE_WIN32_IO)
  247.  
  248.  LARGE_INTEGER li;
  249.  li.LowPart = GetFileSize(fd, (unsigned long*) &li.HighPart);
  250.  if (li.LowPart == 0xFFFFFFFF && GetLastError() != NO_ERROR )
  251.  {
  252.    ret = 0;
  253.  } else
  254.    ret = li.QuadPart;
  255.  
  256. # else
  257.   (void)fd;    // dwa 4/27/00 - suppress unused parameter warning  
  258. # endif
  259.   
  260.   return ret;
  261. }
  262.  
  263.  
  264. // Visual C++ and Intel use this, but not Metrowerks
  265. // Also MinGW, msvcrt.dll (but not crtdll.dll) dependent version
  266. #if (!defined(__MSL__) && !defined(_STLP_WINCE) && defined( _MSC_VER ) && defined(_WIN32)) || \
  267.  (defined(__MINGW32__) && defined(__MSVCRT__))
  268.  
  269. // fcntl(fileno, F_GETFL) for Microsoft library
  270. // 'semi-documented' defines:
  271. #define IOINFO_L2E          5
  272. #define IOINFO_ARRAY_ELTS   (1 << IOINFO_L2E)
  273. #define _pioinfo(i) ( __pioinfo[(i) >> IOINFO_L2E] + \
  274.               ((i) & (IOINFO_ARRAY_ELTS - 1)) )
  275. #define FAPPEND         0x20    // O_APPEND flag
  276. #define FTEXT           0x80    // O_TEXT flag
  277. // end of 'semi-documented' defines
  278.  
  279. // fbp : empirical
  280. #define F_WRITABLE           0x04
  281.  
  282. // 'semi-documented' internal structure
  283. extern "C" {
  284.   struct ioinfo {
  285.     long osfhnd;    // the real os HANDLE
  286.     char osfile;    // file handle flags
  287.     char pipech;    // pipe buffer
  288. #   ifdef _MT
  289.     // multi-threaded locking
  290.     int lockinitflag;
  291.     CRITICAL_SECTION lock;
  292. #   endif  /* _MT */
  293.   };
  294. #ifdef __MINGW32__
  295.  __MINGW_IMPORT ioinfo * __pioinfo[];
  296. #else
  297.   extern _CRTIMP ioinfo * __pioinfo[];
  298. #endif
  299.  
  300. } // extern "C"
  301. // end of 'semi-documented' declarations 
  302.  
  303. ios_base::openmode _get_osfflags(int fd, HANDLE oshandle) {
  304.   char dosflags = 0;
  305.  
  306.   dosflags = _pioinfo(fd)->osfile;
  307.     // end of 'semi-documented' stuff 
  308.   int mode = 0;
  309.   
  310.   if (dosflags & FAPPEND)
  311.     mode |= O_APPEND;
  312.   if (dosflags & FTEXT)
  313.     mode |= O_TEXT;
  314.   else
  315.     mode |= O_BINARY;
  316.  
  317.   // we have to guess
  318. # ifdef __macintosh
  319.    DWORD dummy, dummy2;
  320.    if (WriteFile(oshandle, &dummy2, 0, &dummy, 0))
  321.      mode |= O_RDWR;
  322.    else
  323.      mode |= O_RDONLY;
  324. # else
  325.    // on Windows, this seems to work...
  326.    if (dosflags & F_WRITABLE)
  327.       mode |= O_RDWR;
  328.    else
  329.       mode |= O_RDONLY;
  330. # endif
  331.   
  332.   return flag_to_openmode(mode);
  333. }
  334.  
  335. #endif // _MSC_VER
  336.  
  337. __SGI_END_NAMESPACE
  338.  
  339. // All version of Unix have mmap and lseek system calls.  Some also have
  340. // longer versions of thos system calls to accommodate 64-bit offsets.
  341. // If we're on a Unix system, define some macros to encapsulate those
  342. // differences.
  343. #ifdef _STLP_USE_UNIX_IO
  344. # ifdef __sgi /* IRIX */
  345. #  define LSEEK lseek64
  346. #  define MMAP  mmap64
  347. # else
  348. #  define LSEEK lseek
  349. #  define MMAP  mmap
  350. # endif
  351.  
  352. #ifndef MAP_FAILED /* MMAP failure return code */
  353. # define MAP_FAILED -1
  354. #endif
  355.  
  356. #elif defined (_STLP_USE_UNIX_EMULATION_IO)
  357. #  define LSEEK _lseek
  358. #endif
  359.  
  360.  
  361. _STLP_BEGIN_NAMESPACE
  362.  
  363. size_t
  364. _Filebuf_base::_M_page_size = 4096;
  365.  
  366. _Filebuf_base::_Filebuf_base()
  367.   : _M_file_id((_STLP_fd)-1),
  368.     _M_openmode(0),
  369.     _M_is_open(false),
  370.     _M_should_close(false)
  371. {
  372.   if (!_M_page_size)
  373. #if defined (_STLP_UNIX)  && !defined(__DJGPP)
  374. #  if defined (__APPLE__)
  375.    {
  376.    int mib[2];
  377.    size_t pagesize, len;
  378.    mib[0] = CTL_HW;
  379.    mib[1] = HW_PAGESIZE;
  380.    len = sizeof(pagesize);
  381.    sysctl(mib, 2, &pagesize, &len, NULL, 0);
  382.    _M_page_size = pagesize;
  383.    }
  384. # elif defined(__DJGPP)
  385.    _M_page_size = BUFSIZ;
  386. #  else
  387.   _M_page_size = sysconf(_SC_PAGESIZE);
  388. #  endif
  389. # elif defined (_STLP_USE_WIN32_IO)
  390.   {
  391.   SYSTEM_INFO SystemInfo;
  392.   GetSystemInfo(&SystemInfo);
  393.   _M_page_size = SystemInfo.dwPageSize;
  394.   // might be .dwAllocationGranularity
  395.   }
  396.   //  _M_CRLF_trans_buf = 0,
  397.   //  _M_trans_buf_end=0,   
  398.   _M_view_id = 0;
  399. #endif
  400.  
  401.   if (_M_page_size <=0 )
  402.     _M_page_size = 4096;
  403.  
  404. }
  405.  
  406.  
  407. // Return the size of the file.  This is a wrapper for stat.
  408. // Returns zero if the size cannot be determined or is ill-defined.
  409. streamoff 
  410. _Filebuf_base::_M_file_size()
  411. {
  412.   return _SgI::__file_size(_M_file_id);
  413. }
  414.  
  415. bool _Filebuf_base::_M_open(const char* name, ios_base::openmode openmode,
  416.                             long permission)
  417. {
  418.   _STLP_fd file_no;
  419.  
  420.   if (_M_is_open)
  421.     return false;
  422.  
  423. #if defined (_STLP_USE_UNIX_IO) || defined (_STLP_USE_UNIX_EMULATION_IO)
  424.  
  425.   int flags = 0;
  426.  
  427.   // Unix makes no distinction between text and binary files.
  428.   switch(openmode & (~ios_base::ate & ~ios_base::binary)) {
  429.   case ios_base::out:
  430.   case ios_base::out | ios_base::trunc:
  431.     flags = O_WRONLY | O_CREAT | O_TRUNC;
  432.     break;
  433.   case ios_base::out | ios_base::app:
  434.     flags = O_WRONLY | O_CREAT | O_APPEND;
  435.     break;
  436.   case ios_base::in:
  437.     flags = O_RDONLY;
  438.     permission = 0;             // Irrelevant unless we're writing.
  439.     break;
  440.   case ios_base::in | ios_base::out:
  441.     flags = O_RDWR;
  442.     break;
  443.   case ios_base::in | ios_base::out | ios_base::trunc:
  444.     flags = O_RDWR | O_CREAT | O_TRUNC;
  445.     break;
  446.   default:                      // The above are the only combinations of 
  447.     return false;               // flags allowed by the C++ standard.
  448.   }
  449.  
  450. # if defined (_STLP_USE_UNIX_EMULATION_IO)
  451.  
  452.   if (openmode & ios_base::binary)
  453.     flags |= O_BINARY;
  454.   else
  455.     flags |= O_TEXT;
  456.  
  457.   file_no = _open(name, flags, permission);
  458.  
  459. # else
  460.  
  461.   file_no = open(name, flags, permission);
  462.  
  463. # endif /* _STLP_USE_UNIX_EMULATION_IO */
  464.  
  465.   if (file_no < 0)
  466.     return false;
  467.  
  468.   _M_is_open = true;
  469.  
  470.   if (openmode & ios_base::ate)
  471.     if (LSEEK(file_no, 0, SEEK_END) == -1)
  472.       _M_is_open = false;
  473.   
  474. #elif defined (_STLP_USE_STDIO_IO)
  475.   // use FILE-based i/o
  476.   const char* flags;
  477.  
  478.   switch(openmode & (~ios_base::ate)) {
  479.   case ios_base::out:
  480.   case ios_base::out | ios_base::trunc:
  481.     flags = "w";
  482.     break;
  483.  
  484.   case ios_base::out | ios_base::binary:
  485.   case ios_base::out | ios_base::trunc | ios_base::binary:
  486.     flags = "wb";
  487.     break;
  488.  
  489.   case ios_base::out | ios_base::app:
  490.     flags = "a";
  491.     break;
  492.  
  493.   case ios_base::out | ios_base::app | ios_base::binary:
  494.     flags = "ab";
  495.     break;
  496.  
  497.   case ios_base::in:
  498.     flags = "r";
  499.     break;
  500.  
  501.   case ios_base::in | ios_base::binary:
  502.     flags = "rb";
  503.     break;
  504.  
  505.   case ios_base::in | ios_base::out:
  506.     flags = "r+";
  507.     break;
  508.  
  509.   case ios_base::in | ios_base::out | ios_base::binary:
  510.     flags = "r+b";
  511.     break;
  512.  
  513.  
  514.   case ios_base::in | ios_base::out | ios_base::trunc:
  515.     flags = "w+";
  516.     break;
  517.  
  518.   case ios_base::in | ios_base::out | ios_base::trunc | ios_base::binary:
  519.     flags = "w+b";
  520.     break;
  521.  
  522.   default:                      // The above are the only combinations of 
  523.     return false;               // flags allowed by the C++ standard.
  524.   }
  525.  
  526.   // fbp : TODO : set permissions !
  527.   (void)permission; // currently unused        //*TY 02/26/2000 - added to suppress warning message
  528.   _M_file = fopen(name, flags);
  529.  
  530.   if (_M_file) {
  531.     file_no = fileno(_M_file);
  532.   }
  533.   else
  534.     return false;
  535.  
  536.   // unset buffering immediately
  537.   setbuf(_M_file, 0);
  538.  
  539.   _M_is_open = true;
  540.  
  541.   if (openmode & ios_base::ate)
  542.     if (fseek(_M_file, 0, SEEK_END) == -1)
  543.       _M_is_open = false;
  544.   
  545. #   elif defined (_STLP_USE_WIN32_IO)
  546.  
  547.   DWORD dwDesiredAccess, dwShareMode, dwCreationDisposition;
  548.   bool  doTruncate = false;
  549.  
  550.   switch(openmode & (~ios_base::ate & ~ios_base::binary)) {
  551.   case ios_base::out:
  552.   case ios_base::out | ios_base::trunc:
  553.     dwDesiredAccess = GENERIC_WRITE;
  554.     dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
  555.     dwCreationDisposition = OPEN_ALWAYS;
  556.     // boris : even though it is very non-intuitive, standard
  557.     // requires them both to behave same.
  558.     doTruncate = true;
  559.     break;
  560.  
  561.   case ios_base::out | ios_base::app:
  562.     dwDesiredAccess = GENERIC_WRITE;
  563.     dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
  564.     dwCreationDisposition = OPEN_ALWAYS;
  565.     break;
  566.   case ios_base::in:
  567.     dwDesiredAccess = GENERIC_READ;
  568.     dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
  569.     dwCreationDisposition = OPEN_EXISTING;
  570.     permission = 0;             // Irrelevant unless we're writing.
  571.     break;
  572.   case ios_base::in | ios_base::out:
  573.     dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
  574.     dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
  575.     dwCreationDisposition = OPEN_EXISTING;
  576.     break;
  577.   case ios_base::in | ios_base::out | ios_base::trunc:
  578.     dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
  579.     dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
  580.     dwCreationDisposition = OPEN_ALWAYS;
  581.     doTruncate = true;
  582.     break;
  583.   default:                      // The above are the only combinations of
  584.     return false;               // flags allowed by the C++ standard.
  585.   }
  586.  
  587.   #if defined(_STLP_WINCE)
  588.     file_no = CreateFile(__ASCIIToWide(name).c_str(),
  589.   #else
  590.     file_no = CreateFileA(name,
  591.   #endif
  592.                   dwDesiredAccess, dwShareMode, 0,
  593.             dwCreationDisposition, permission, 0);
  594.   
  595.   if ( file_no == INVALID_HANDLE_VALUE )
  596.   return false;
  597.  
  598.   if ((doTruncate && SetEndOfFile(file_no) == 0) ||
  599.       ((openmode & ios_base::ate) && SetFilePointer(file_no, 0, NULL, FILE_END) == -1)) {
  600.     CloseHandle(file_no);
  601.     return false;
  602.   }
  603.  
  604.   _M_is_open = true;
  605.  
  606. #else
  607. # error "Port!"  
  608. #endif /* __unix */
  609.  
  610.  
  611.   _M_file_id = file_no;
  612.   _M_should_close = _M_is_open;
  613.   _M_openmode = openmode;
  614.  
  615.   if (_M_is_open)
  616.     _M_regular_file = _SgI::__is_regular_file(_M_file_id);
  617.   
  618.   return _M_is_open;
  619. }
  620.  
  621.   
  622. bool _Filebuf_base::_M_open(const char* name, ios_base::openmode openmode)
  623. {
  624.   // This doesn't really grant everyone in the world read/write
  625.   // access.  On Unix, file-creation system calls always clear 
  626.   // bits that are set in the umask from the permissions flag.
  627. # ifdef _STLP_USE_WIN32_IO
  628.   return this->_M_open(name, openmode, FILE_ATTRIBUTE_NORMAL);
  629. # elif defined(__MRC__) || defined(__SC__)        //*TY 02/26/2000 - added support for MPW compilers
  630.   return this->_M_open(name, openmode, 0);
  631. # else
  632.   return this->_M_open(name, openmode, S_IRUSR | S_IWUSR | S_IRGRP | 
  633.                                        S_IWGRP | S_IROTH | S_IWOTH);
  634. # endif
  635. }
  636.  
  637.       
  638. // Associated the filebuf with a file descriptor pointing to an already-
  639. // open file.  Mode is set to be consistent with the way that the file
  640. // was opened.
  641. bool _Filebuf_base::_M_open(int file_no, ios_base::openmode init_mode) {
  642.  
  643.   if (_M_is_open || file_no < 0)
  644.     return false;
  645.  
  646. # if defined (_STLP_UNIX)
  647.   (void)init_mode;    // dwa 4/27/00 - suppress unused parameter warning
  648.   int mode ;
  649.   mode = fcntl(file_no, F_GETFL);
  650.  
  651.   if (mode == -1)
  652.     return false;
  653.  
  654.   _M_openmode = _SgI::flag_to_openmode(mode);
  655.   
  656. # elif defined(__MRC__) || defined(__SC__)        //*TY 02/26/2000 - added support for MPW compilers
  657.   (void)init_mode;    // dwa 4/27/00 - suppress unused parameter warning
  658.   switch( _iob[file_no]._flag & (_IOREAD|_IOWRT|_IORW) )
  659.   {
  660.   case _IOREAD:
  661.     _M_openmode = ios_base::in; break;
  662.   case _IOWRT:
  663.     _M_openmode = ios_base::out; break;
  664.   case _IORW:
  665.     _M_openmode = ios_base::in | ios_base::out; break;
  666.   default:
  667.       return false;
  668.   }
  669.   
  670. # elif defined (_STLP_USE_UNIX_EMULATION_IO) || defined (_STLP_USE_STDIO_IO) 
  671.   (void)init_mode;    // dwa 4/27/00 - suppress unused parameter warning
  672.   int mode ;
  673.   struct stat buf;
  674.   if (fstat(file_no, &buf) != 0)
  675.     return false;
  676.   mode = buf.st_mode;
  677.   
  678.   switch(mode & (_S_IWRITE | _S_IREAD) ) {
  679.   case _S_IREAD:
  680.     _M_openmode = ios_base::in; break;
  681.   case _S_IWRITE:
  682.     _M_openmode = ios_base::out; break;
  683.   case (_S_IWRITE | _S_IREAD):
  684.     _M_openmode = ios_base::in | ios_base::out; break;
  685.   default:
  686.     return false;
  687.   }
  688. # elif (defined(_STLP_USE_WIN32_IO) && defined (_MSC_VER) && !defined(_STLP_WINCE)) || \
  689.         (defined(__MINGW32__) && defined(__MSVCRT__))
  690.  
  691.   if (_M_is_open || file_no == -1)
  692.     return false;
  693.  
  694.   HANDLE oshandle = (HANDLE)_get_osfhandle(file_no);
  695.   
  696.   if ((long)oshandle != -1)
  697.     file_no = (int)oshandle;
  698.   else
  699.     return false;
  700.   
  701.   if (init_mode != ios_base::__default_mode)
  702.     _M_openmode = init_mode;
  703.   else
  704.     _M_openmode = _SgI::_get_osfflags(file_no, oshandle);
  705.   
  706. # else
  707.   (void)init_mode;    // dwa 4/27/00 - suppress unused parameter warning
  708.  
  709.   // not available for the API
  710.   return false;
  711.  
  712. # endif
  713.   
  714.  
  715.   _M_is_open = true;
  716.   _M_file_id = (_STLP_fd)file_no;
  717.   _M_should_close = false;
  718.   _M_regular_file = _SgI::__is_regular_file(_M_file_id);
  719.  
  720.   return true;
  721. }
  722.  
  723. bool _Filebuf_base::_M_close() {
  724.   if (!_M_is_open)
  725.     return false;
  726.  
  727.   bool ok;
  728.  
  729.   if (!_M_should_close)
  730.     ok = true;
  731.   else {
  732.     
  733. #   if defined (_STLP_USE_UNIX_IO)
  734.  
  735.     ok = (close(_M_file_id) == 0);
  736.  
  737. #   elif defined (_STLP_USE_UNIX_EMULATION_IO)
  738.  
  739.     ok = (_close(_M_file_id) == 0);
  740.  
  741. #   elif defined (_STLP_USE_STDIO_IO)
  742.  
  743.     ok = (fclose(_M_file) == 0);
  744.  
  745. #   elif defined (_STLP_USE_WIN32_IO)
  746.  
  747.     if ( _M_file_id != INVALID_HANDLE_VALUE ) {
  748.       ok = (CloseHandle(_M_file_id) != 0);
  749.     }
  750.     else {
  751.       ok = false;
  752.     }
  753.     
  754. #   else
  755.  
  756.     ok = false;
  757.  
  758. #   endif /* _STLP_USE_UNIX_IO */
  759.   }
  760.  
  761.   _M_is_open = _M_should_close = false;
  762.   _M_openmode = 0;
  763.   return ok;
  764. }
  765.  
  766.  
  767. # define _STLP_LF 10
  768. # define _STLP_CR 13
  769. # define _STLP_CTRLZ 26
  770.  
  771. // Read up to n characters into a buffer.  Return value is number of
  772. // characters read.
  773. ptrdiff_t _Filebuf_base::_M_read(char* buf, ptrdiff_t n) {
  774. #   if defined (_STLP_USE_UNIX_IO)
  775.  
  776.   return read(_M_file_id, buf, n);
  777.  
  778. #   elif defined (_STLP_USE_UNIX_EMULATION_IO)
  779.  
  780.   return _read(_M_file_id, buf, n);
  781.  
  782. #   elif defined (_STLP_USE_WIN32_IO)
  783.   
  784.   DWORD NumberOfBytesRead;
  785.   ReadFile(_M_file_id, (LPVOID)buf, (DWORD)n, 
  786.            &NumberOfBytesRead, 0);
  787.  
  788.   if ((! (_M_openmode & ios_base::binary)) && NumberOfBytesRead) { 
  789.     // translate CR-LFs to LFs in the buffer
  790.     char * to = buf, * last = buf + NumberOfBytesRead - 1;
  791.     char * from;
  792.     for (from = buf; from <= last && * from != _STLP_CTRLZ; ++ from ) {
  793.       if (* from != _STLP_CR)
  794.         * to ++ = * from;
  795.       else { // found CR
  796.         if (from < last) { // not at buffer end
  797.           if (* (from + 1) != _STLP_LF)
  798.             * to ++ = _STLP_CR;
  799.         }
  800.         else { // last char is CR, peek for LF
  801.           char peek = ' ';
  802.           DWORD NumberOfBytesPeeked;
  803.           ReadFile(_M_file_id, (LPVOID)&peek, 
  804.                         1, &NumberOfBytesPeeked, 0);
  805.           if (NumberOfBytesPeeked)
  806.             SetFilePointer(_M_file_id,(LONG)-1,0,SEEK_CUR);
  807.           if (peek != _STLP_LF)
  808.             * to ++ = _STLP_CR;
  809.         }
  810.       } // found CR
  811.     } // for
  812.     // seek back to TEXT end of file if hit CTRL-Z
  813.     if (from <= last) // terminated due to CTRLZ
  814.       SetFilePointer(_M_file_id,(LONG)((last+1) - from),0,SEEK_CUR);
  815.     NumberOfBytesRead = to - buf;
  816.   }
  817.   return (ptrdiff_t)NumberOfBytesRead;
  818.   
  819. #   elif defined (_STLP_USE_STDIO_IO)
  820.   
  821.   return fread(buf, 1, n, _M_file);
  822.   
  823. #   else 
  824. #    error "Port!"
  825. # endif /* __unix */
  826. }
  827.  
  828. // Write n characters from a buffer.  Return value: true if we managed
  829. // to write the entire buffer, false if we didn't.  
  830. bool _Filebuf_base::_M_write(char* buf, ptrdiff_t n) {
  831.   
  832.   while (true) {
  833.     ptrdiff_t written;
  834.     
  835. #   if defined (_STLP_USE_UNIX_IO)
  836.  
  837.     written = write(_M_file_id, buf, n);
  838.  
  839. #   elif defined (_STLP_USE_UNIX_EMULATION_IO)
  840.  
  841.     written = _write(_M_file_id, buf, n);
  842.  
  843. #   elif defined (_STLP_USE_WIN32_IO)
  844.  
  845.     // In append mode, every write does an implicit seek to the end
  846.     // of the file.
  847.     if (_M_openmode & ios_base::app)
  848.       _M_seek( 0, ios_base::end);
  849.     
  850.     if (_M_openmode & ios_base::binary) { 
  851.       // binary mode
  852.       DWORD NumberOfBytesWritten;
  853.       WriteFile(_M_file_id, (LPVOID)buf, (DWORD)n, 
  854.                 &NumberOfBytesWritten, 0);
  855.       written = (ptrdiff_t)NumberOfBytesWritten;
  856.     }
  857.     else {
  858.       char textbuf[_TEXTBUF_SIZE + 1]; // extra 1 in case LF at end
  859.       char * nextblock = buf, * ptrtextbuf = textbuf;
  860.       char * endtextbuf = textbuf + _TEXTBUF_SIZE;
  861.       char * endblock = buf + n;
  862.       ptrdiff_t nextblocksize = (min) (n, (ptrdiff_t)_TEXTBUF_SIZE);
  863.       char * nextlf;
  864.       
  865.       while ( (nextblocksize > 0) && 
  866.               (nextlf = (char *)memchr(nextblock, _STLP_LF, nextblocksize)) != 0) {
  867.         ptrdiff_t linelength = nextlf - nextblock;
  868.         memcpy(ptrtextbuf, nextblock, linelength);
  869.         ptrtextbuf += linelength;
  870.         nextblock += (linelength + 1);
  871.         * ptrtextbuf ++ = _STLP_CR;
  872.         * ptrtextbuf ++ = _STLP_LF;
  873.         nextblocksize = (min) (ptrdiff_t(endblock - nextblock), 
  874.                                              (max) (ptrdiff_t(0), ptrdiff_t(endtextbuf - ptrtextbuf)));
  875.       }
  876.       // write out what's left, > condition is here since for LF at the end , 
  877.       // endtextbuf may get < ptrtextbuf ...
  878.       if (nextblocksize > 0) {
  879.         memcpy(ptrtextbuf, nextblock, nextblocksize);
  880.         ptrtextbuf += nextblocksize;
  881.         nextblock += nextblocksize;
  882.       }
  883.       // now write out the translated buffer
  884.       char * writetextbuf = textbuf;
  885.       for (ptrdiff_t NumberOfBytesToWrite = ptrtextbuf - textbuf; 
  886.            NumberOfBytesToWrite;) {
  887.         DWORD NumberOfBytesWritten;
  888.         WriteFile((HANDLE)_M_file_id, (LPVOID)writetextbuf, 
  889.                   NumberOfBytesToWrite, &NumberOfBytesWritten, 0);
  890.         if (NumberOfBytesWritten == NumberOfBytesToWrite)
  891.           break;
  892.         if (!NumberOfBytesWritten) // write shortfall
  893.           return false;
  894.         writetextbuf += NumberOfBytesWritten;
  895.         NumberOfBytesToWrite -=    NumberOfBytesWritten;
  896.       }
  897.       // count non-translated characters
  898.       written = (nextblock - buf);
  899.     }
  900.  
  901. #   elif defined (_STLP_USE_STDIO_IO)
  902.  
  903.     written = fwrite(buf, 1, n, _M_file);
  904.  
  905. #   else 
  906. #    error "Port!"
  907. #   endif /* __unix */ 
  908.     
  909.     if (n == written)
  910.       return true;
  911.     else if (written > 0 && written < n) {
  912.       n -= written;
  913.       buf += written;
  914.     }
  915.     else
  916.       return false;
  917.   }
  918. }
  919.  
  920.  
  921. #ifdef _STLP_USE_WIN32_IO
  922. # define STL_SEEK_SET FILE_BEGIN
  923. # define STL_SEEK_CUR FILE_CURRENT
  924. # define STL_SEEK_END FILE_END
  925. #else
  926. # define STL_SEEK_SET SEEK_SET
  927. # define STL_SEEK_CUR SEEK_CUR
  928. # define STL_SEEK_END SEEK_END
  929. #endif
  930.  
  931. // Wrapper for lseek or the like.
  932. streamoff _Filebuf_base::_M_seek(streamoff offset, ios_base::seekdir dir)
  933. {
  934.   streamoff result = -1;
  935.  
  936.   int whence;
  937.  
  938.   switch(dir) {
  939.   case ios_base::beg:
  940.     if (offset < 0 /* || offset > _M_file_size() */ )
  941.       return streamoff(-1);
  942.     whence = STL_SEEK_SET;
  943.     break;
  944.   case ios_base::cur:
  945.     whence = STL_SEEK_CUR;
  946.     break;
  947.   case ios_base::end:
  948.     if (/* offset > 0 || */  -offset > _M_file_size() )
  949.       return streamoff(-1);
  950.     whence = STL_SEEK_END;
  951.     break;
  952.   default:
  953.     return streamoff(-1);
  954.   }
  955.  
  956. #if defined (_STLP_USE_UNIX_IO) || defined (_STLP_USE_UNIX_EMULATION_IO)
  957.  
  958.   result = LSEEK(_M_file_id, offset, whence);
  959.  
  960. #elif defined (_STLP_USE_STDIO_IO)
  961.  
  962.   result = fseek(_M_file, offset, whence);
  963.  
  964. #elif defined (_STLP_USE_WIN32_IO)
  965.  
  966.   LARGE_INTEGER li;
  967.   li.QuadPart = offset;
  968.   li.LowPart = SetFilePointer(_M_file_id, li.LowPart, &li.HighPart, whence);
  969.   if (li.LowPart == 0xFFFFFFFF && GetLastError() != NO_ERROR)
  970.     result = -1; // Error
  971.   else
  972.     result = li.QuadPart;
  973.  
  974. #else
  975. #   error "Port!"
  976. #endif
  977.  
  978.   return result;
  979. }
  980.  
  981.  
  982. // Attempts to memory-map len bytes of the current file, starting
  983. // at position offset.  Precondition: offset is a multiple of the
  984. // page size.  Postcondition: return value is a null pointer if the
  985. // memory mapping failed.  Otherwise the return value is a pointer to 
  986. // the memory-mapped file and the file position is set to offset.
  987. void* _Filebuf_base::_M_mmap(streamoff offset, streamoff len) {
  988.   void* base;
  989. #if defined (_STLP_UNIX) && !defined(__DJGPP)
  990.   base = MMAP(0, len, PROT_READ, MAP_PRIVATE, _M_file_id, offset);
  991.   if (base != (void*)MAP_FAILED) {
  992.     if (LSEEK(_M_file_id, offset + len, SEEK_SET) < 0) {
  993.       this->_M_unmap(base, len);
  994.       base = 0;
  995.     }
  996.   } else
  997.     base =0;
  998.  
  999. #elif defined (_STLP_USE_WIN32_IO)
  1000.  
  1001.   _M_view_id = CreateFileMapping(_M_file_id, (PSECURITY_ATTRIBUTES)0 ,
  1002.                  PAGE_READONLY, 0 /* len >> 32 */ , 
  1003.                  0 /* len & 0xFFFFFFFF */ ,             // low-order DWORD of size
  1004.                  0);
  1005.  
  1006.   if (_M_view_id) {
  1007. # if 0
  1008.     printf("view %x created from file %x, error = %d, size = %d, map_offset = %d map_len = %d\n", 
  1009.        _M_view_id, _M_file_id, GetLastError(), 
  1010.        (int)cur_filesize, ULL(offset) & 0xffffffff, len);
  1011. # endif
  1012.     
  1013.     base = MapViewOfFile(_M_view_id, FILE_MAP_READ, ULL(offset)>>32, 
  1014.              ULL(offset) & 0xffffffff, len);
  1015.     // check if mapping succeded and is usable
  1016.     if (base ==0  || _M_seek(offset+len, ios_base::beg) < 0) {
  1017.       this->_M_unmap(base, len);
  1018.       base = 0;
  1019.     }
  1020.   } else
  1021.     base = 0;
  1022. #else
  1023.   (void)len;        //*TY 02/26/2000 - unused variables
  1024.   (void)offset;        //*TY 02/26/2000 - 
  1025.   base = 0;
  1026. #endif
  1027.   return base;  
  1028. }
  1029.  
  1030. void _Filebuf_base::_M_unmap(void* base, streamoff len) {
  1031.   // precondition : there is a valid mapping at the moment
  1032. #if defined (_STLP_UNIX)  && !defined(__DJGPP)
  1033.   munmap((char*)base, len);
  1034. #elif defined (_STLP_USE_WIN32_IO)
  1035.   if ( base != NULL )
  1036.     UnmapViewOfFile(base);
  1037.   // destroy view handle as well
  1038.   if ( _M_view_id != NULL )
  1039.     CloseHandle(_M_view_id);
  1040.   _M_view_id = 0;
  1041.   base = 0;
  1042. #else
  1043.   (void)len;        //*TY 02/26/2000 - unused variables
  1044.   (void)base;        //*TY 02/26/2000 - 
  1045. #endif
  1046. }
  1047.  
  1048. // fbp : let us map 1 MB maximum, just be sure not to trash VM
  1049. # define MMAP_CHUNK 0x100000UL
  1050.  
  1051. int _STLP_CALL
  1052. _Underflow<char, char_traits<char> >::_M_doit (basic_filebuf<char, char_traits<char> >* __this)  
  1053. {
  1054.   if (!__this->_M_in_input_mode) {
  1055.     if (!__this->_M_switch_to_input_mode())
  1056.       return traits_type::eof();
  1057.   }
  1058.   
  1059.   else if (__this->_M_in_putback_mode) {
  1060.     __this->_M_exit_putback_mode();
  1061.     if (__this->gptr() != __this->egptr()) {
  1062.       int_type __c = traits_type::to_int_type(*__this->gptr());
  1063.       return __c;
  1064.     }
  1065.   }
  1066.     
  1067.   // If it's a disk file, and if the internal and external character
  1068.   // sequences are guaranteed to be identical, then try to use memory
  1069.   // mapped I/O.  Otherwise, revert to ordinary read.
  1070.   if (__this->_M_base.__regular_file() 
  1071.       && __this->_M_always_noconv
  1072.       && __this->_M_base._M_in_binary_mode()) {
  1073.     // If we've mmapped part of the file already, then unmap it.
  1074.     if (__this->_M_mmap_base)
  1075.       __this->_M_base._M_unmap(__this->_M_mmap_base, __this->_M_mmap_len);
  1076.     __this->_M_mmap_base = 0;
  1077.     __this->_M_mmap_len = 0;
  1078.       
  1079.     // Determine the position where we start mapping.  It has to be
  1080.     // a multiple of the page size.
  1081.     streamoff __cur = __this->_M_base._M_seek(0, ios_base::cur);
  1082.     streamoff __size = __this->_M_base._M_file_size();
  1083.     if (__size > 0 && __cur >= 0 && __cur < __size) {
  1084.       streamoff __offset    = (__cur / __this->_M_base.__page_size())
  1085.     * __this->_M_base.__page_size();
  1086.       streamoff __remainder = __cur - __offset;
  1087.  
  1088.       __this->_M_mmap_len = __size - __offset;
  1089.  
  1090.       if (__this->_M_mmap_len > MMAP_CHUNK)
  1091.     __this->_M_mmap_len = MMAP_CHUNK;
  1092.  
  1093.       if ((__this->_M_mmap_base =
  1094.        __this->_M_base._M_mmap(__offset, __this->_M_mmap_len)) != 0) {
  1095.     __this->setg((char*) __this->_M_mmap_base,
  1096.              (char*) __this->_M_mmap_base + __remainder,
  1097.              (char*) __this->_M_mmap_base + __this->_M_mmap_len);
  1098.     return traits_type::to_int_type(*__this->gptr());
  1099.       } 
  1100.     } else /* size > 0 ... */ {
  1101.       // There is nothing to map. We unmapped the file above, now zap pointers.
  1102.       __this->_M_mmap_base = 0;
  1103.       __this->_M_mmap_len = 0;
  1104.     }
  1105.   }
  1106.     
  1107.   return __this->_M_underflow_aux();
  1108. }
  1109.  
  1110.  
  1111. //----------------------------------------------------------------------
  1112. // Force instantiation of filebuf and fstream classes.
  1113. #if !defined(_STLP_NO_FORCE_INSTANTIATE)
  1114.  
  1115. template class basic_filebuf<char, char_traits<char> >;
  1116. template class basic_ifstream<char, char_traits<char> >;
  1117. template class basic_ofstream<char, char_traits<char> >;
  1118. template class basic_fstream<char, char_traits<char> >;
  1119.  
  1120. #  ifndef _STLP_NO_WCHAR_T
  1121. template class _Underflow<wchar_t, char_traits<wchar_t> >;
  1122. template class basic_filebuf<wchar_t, char_traits<wchar_t> >;
  1123. template class basic_ifstream<wchar_t, char_traits<wchar_t> >;
  1124. template class basic_ofstream<wchar_t, char_traits<wchar_t> >;
  1125. template class basic_fstream<wchar_t, char_traits<wchar_t> >;
  1126. #  endif /* _STLP_NO_WCHAR_T */
  1127.  
  1128. #endif
  1129.  
  1130. _STLP_END_NAMESPACE
  1131.  
  1132. // Local Variables:
  1133. // mode:C++
  1134. // End:
  1135.  
  1136.