michael@0: /* michael@0: * Copyright (c) 1999 michael@0: * Silicon Graphics Computer Systems, Inc. michael@0: * michael@0: * Copyright (c) 1999 michael@0: * Boris Fomitchev michael@0: * michael@0: * This material is provided "as is", with absolutely no warranty expressed michael@0: * or implied. Any use is at your own risk. michael@0: * michael@0: * Permission to use or copy this software for any purpose is hereby granted michael@0: * without fee, provided the above notices are retained on all copies. michael@0: * Permission to modify the code and to distribute modified code is granted, michael@0: * provided the above notices are retained, and a notice that the code was michael@0: * modified is included with the above copyright notice. michael@0: * michael@0: */ michael@0: michael@0: #if defined (__SUNPPRO_CC) && !defined (_STLP_NO_NEW_C_HEADERS) michael@0: # include michael@0: // For sunpro, it chokes if time.h is included through stat.h michael@0: #endif michael@0: michael@0: #include michael@0: michael@0: #ifdef __CYGWIN__ michael@0: # define __int64 long long michael@0: #endif michael@0: michael@0: #include michael@0: #if !defined(__ISCPP__) michael@0: extern "C" { michael@0: # include michael@0: } michael@0: #endif michael@0: michael@0: #if defined( __MSL__ ) michael@0: # include michael@0: #endif michael@0: michael@0: #if defined(__ISCPP__) michael@0: # include michael@0: #endif michael@0: michael@0: #if defined(__BEOS__) && defined(__INTEL__) michael@0: # include michael@0: # include // For _fstat michael@0: #endif michael@0: michael@0: #if defined (_STLP_MSVC) || defined (__MINGW32__) michael@0: # include michael@0: # define S_IREAD _S_IREAD michael@0: # define S_IWRITE _S_IWRITE michael@0: # define S_IFREG _S_IFREG michael@0: // map permission masks michael@0: # ifndef S_IRUSR michael@0: # define S_IRUSR _S_IREAD michael@0: # define S_IWUSR _S_IWRITE michael@0: # endif michael@0: # ifndef S_IRGRP michael@0: # define S_IRGRP _S_IREAD michael@0: # define S_IWGRP _S_IWRITE michael@0: # endif michael@0: # ifndef S_IROTH michael@0: # define S_IROTH _S_IREAD michael@0: # define S_IWOTH _S_IWRITE michael@0: # endif michael@0: michael@0: # ifndef O_RDONLY michael@0: # define O_RDONLY _O_RDONLY michael@0: # define O_WRONLY _O_WRONLY michael@0: # define O_RDWR _O_RDWR michael@0: # define O_APPEND _O_APPEND michael@0: # define O_CREAT _O_CREAT michael@0: # define O_TRUNC _O_TRUNC michael@0: # define O_TEXT _O_TEXT michael@0: # define O_BINARY _O_BINARY michael@0: # endif michael@0: michael@0: # ifndef O_ACCMODE michael@0: # define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR) michael@0: # endif michael@0: #endif michael@0: michael@0: const _STLP_fd INVALID_STLP_FD = -1; michael@0: michael@0: michael@0: # ifdef __MSL__ michael@0: # define _O_TEXT 0x0 michael@0: # if !defined( O_TEXT ) michael@0: # define O_TEXT _O_TEXT michael@0: # endif michael@0: # define _S_IFREG S_IFREG michael@0: # define S_IREAD S_IRUSR michael@0: # define S_IWRITE S_IWUSR michael@0: # define S_IEXEC S_IXUSR michael@0: # define _S_IWRITE S_IWRITE michael@0: # define _S_IREAD S_IREAD michael@0: # define _open open michael@0: # define _close close michael@0: # define _read read michael@0: # define _write write michael@0: # endif michael@0: michael@0: _STLP_BEGIN_NAMESPACE michael@0: michael@0: // Compare with streamoff definition in stl/char_traits.h! michael@0: michael@0: #if defined (_STLP_USE_DEFAULT_FILE_OFFSET) || \ michael@0: (!defined(_LARGEFILE_SOURCE) && !defined(_LARGEFILE64_SOURCE)) michael@0: # define FOPEN fopen michael@0: # define FSEEK fseek michael@0: # define FSTAT fstat michael@0: # define STAT stat michael@0: # define FTELL ftell michael@0: #else michael@0: # define FOPEN fopen64 michael@0: # define FSEEK fseeko64 michael@0: # define FSTAT fstat64 michael@0: # define STAT stat64 michael@0: # define FTELL ftello64 michael@0: #endif michael@0: michael@0: _STLP_MOVE_TO_PRIV_NAMESPACE michael@0: michael@0: // Helper functions for _Filebuf_base. michael@0: michael@0: static bool __is_regular_file(_STLP_fd fd) { michael@0: struct STAT buf; michael@0: return FSTAT(fd, &buf) == 0 && (buf.st_mode & S_IFREG) != 0 ; michael@0: } michael@0: michael@0: // Number of characters in the file. michael@0: static streamoff __file_size(_STLP_fd fd) { michael@0: streamoff ret = 0; michael@0: michael@0: struct STAT buf; michael@0: if (FSTAT(fd, &buf) == 0 && (buf.st_mode & S_IFREG) != 0) michael@0: ret = buf.st_size > 0 ? buf.st_size : 0; michael@0: michael@0: return ret; michael@0: } michael@0: michael@0: _STLP_MOVE_TO_STD_NAMESPACE michael@0: michael@0: // All version of Unix have mmap and lseek system calls. Some also have michael@0: // longer versions of those system calls to accommodate 64-bit offsets. michael@0: // If we're on a Unix system, define some macros to encapsulate those michael@0: // differences. michael@0: michael@0: size_t _Filebuf_base::_M_page_size = 4096; michael@0: michael@0: _Filebuf_base::_Filebuf_base() michael@0: : _M_file_id(INVALID_STLP_FD), michael@0: _M_openmode(0), michael@0: _M_is_open(false), michael@0: _M_should_close(false) michael@0: {} michael@0: michael@0: void _Filebuf_base::_S_initialize() michael@0: { michael@0: michael@0: } michael@0: michael@0: // Return the size of the file. This is a wrapper for stat. michael@0: // Returns zero if the size cannot be determined or is ill-defined. michael@0: streamoff _Filebuf_base::_M_file_size() michael@0: { michael@0: return _STLP_PRIV __file_size(_M_file_id); michael@0: } michael@0: michael@0: bool _Filebuf_base::_M_open(const char* name, ios_base::openmode openmode, michael@0: long permission) michael@0: { michael@0: _STLP_fd file_no; michael@0: michael@0: if (_M_is_open) michael@0: return false; michael@0: michael@0: // use FILE-based i/o michael@0: const char* flags; michael@0: michael@0: switch (openmode & (~ios_base::ate)) { michael@0: case ios_base::out: michael@0: case ios_base::out | ios_base::trunc: michael@0: flags = "w"; michael@0: break; michael@0: michael@0: case ios_base::out | ios_base::binary: michael@0: case ios_base::out | ios_base::trunc | ios_base::binary: michael@0: flags = "wb"; michael@0: break; michael@0: michael@0: case ios_base::out | ios_base::app: michael@0: flags = "a"; michael@0: break; michael@0: michael@0: case ios_base::out | ios_base::app | ios_base::binary: michael@0: flags = "ab"; michael@0: break; michael@0: michael@0: case ios_base::in: michael@0: flags = "r"; michael@0: break; michael@0: michael@0: case ios_base::in | ios_base::binary: michael@0: flags = "rb"; michael@0: break; michael@0: michael@0: case ios_base::in | ios_base::out: michael@0: flags = "r+"; michael@0: break; michael@0: michael@0: case ios_base::in | ios_base::out | ios_base::binary: michael@0: flags = "r+b"; michael@0: break; michael@0: michael@0: case ios_base::in | ios_base::out | ios_base::trunc: michael@0: flags = "w+"; michael@0: break; michael@0: michael@0: case ios_base::in | ios_base::out | ios_base::trunc | ios_base::binary: michael@0: flags = "w+b"; michael@0: break; michael@0: michael@0: default: // The above are the only combinations of michael@0: return false; // flags allowed by the C++ standard. michael@0: } michael@0: michael@0: // fbp : TODO : set permissions ! michael@0: (void)permission; // currently unused //*TY 02/26/2000 - added to suppress warning message michael@0: _M_file = FOPEN(name, flags); michael@0: michael@0: if (_M_file) { michael@0: file_no = fileno(_M_file); michael@0: } else { michael@0: return false; michael@0: } michael@0: michael@0: // unset buffering immediately michael@0: setbuf(_M_file, 0); michael@0: michael@0: _M_is_open = true; michael@0: michael@0: if (openmode & ios_base::ate) { michael@0: if (FSEEK(_M_file, 0, SEEK_END) != 0) michael@0: _M_is_open = false; michael@0: } michael@0: michael@0: _M_file_id = file_no; michael@0: _M_should_close = _M_is_open; michael@0: _M_openmode = openmode; michael@0: michael@0: if (_M_is_open) michael@0: _M_regular_file = _STLP_PRIV __is_regular_file(_M_file_id); michael@0: michael@0: return (_M_is_open != 0); michael@0: } michael@0: michael@0: michael@0: bool _Filebuf_base::_M_open(const char* name, ios_base::openmode openmode) michael@0: { michael@0: // This doesn't really grant everyone in the world read/write michael@0: // access. On Unix, file-creation system calls always clear michael@0: // bits that are set in the umask from the permissions flag. michael@0: return this->_M_open(name, openmode, S_IRUSR | S_IWUSR | S_IRGRP | michael@0: S_IWGRP | S_IROTH | S_IWOTH); michael@0: } michael@0: michael@0: // Associated the filebuf with a file descriptor pointing to an already- michael@0: // open file. Mode is set to be consistent with the way that the file michael@0: // was opened. michael@0: bool _Filebuf_base::_M_open( int file_no, ios_base::openmode ) michael@0: { michael@0: if (_M_is_open || file_no < 0) michael@0: return false; michael@0: michael@0: struct STAT buf; michael@0: if (FSTAT(file_no, &buf) != 0) michael@0: return false; michael@0: int mode = buf.st_mode; michael@0: michael@0: switch ( mode & (S_IWRITE | S_IREAD) ) { michael@0: case S_IREAD: michael@0: _M_openmode = ios_base::in; michael@0: break; michael@0: case S_IWRITE: michael@0: _M_openmode = ios_base::out; michael@0: break; michael@0: case (S_IWRITE | S_IREAD): michael@0: _M_openmode = ios_base::in | ios_base::out; michael@0: break; michael@0: default: michael@0: return false; michael@0: } michael@0: _M_file_id = file_no; michael@0: _M_is_open = true; michael@0: _M_should_close = false; michael@0: _M_regular_file = _STLP_PRIV __is_regular_file(_M_file_id); michael@0: return true; michael@0: } michael@0: michael@0: bool _Filebuf_base::_M_close() michael@0: { michael@0: if (!_M_is_open) michael@0: return false; michael@0: michael@0: bool ok = _M_should_close ? (fclose(_M_file) == 0) : true; michael@0: michael@0: _M_is_open = _M_should_close = false; michael@0: _M_openmode = 0; michael@0: return ok; michael@0: } michael@0: michael@0: // Read up to n characters into a buffer. Return value is number of michael@0: // characters read. michael@0: ptrdiff_t _Filebuf_base::_M_read(char* buf, ptrdiff_t n) { michael@0: return fread(buf, 1, n, _M_file); michael@0: } michael@0: michael@0: // Write n characters from a buffer. Return value: true if we managed michael@0: // to write the entire buffer, false if we didn't. michael@0: bool _Filebuf_base::_M_write(char* buf, ptrdiff_t n) michael@0: { michael@0: for (;;) { michael@0: ptrdiff_t written = fwrite(buf, 1, n, _M_file); michael@0: michael@0: if (n == written) { michael@0: return true; michael@0: } michael@0: michael@0: if (written > 0 && written < n) { michael@0: n -= written; michael@0: buf += written; michael@0: } else { michael@0: return false; michael@0: } michael@0: } michael@0: } michael@0: michael@0: // Wrapper for lseek or the like. michael@0: streamoff _Filebuf_base::_M_seek(streamoff offset, ios_base::seekdir dir) michael@0: { michael@0: int whence; michael@0: michael@0: switch ( dir ) { michael@0: case ios_base::beg: michael@0: if (offset < 0 /* || offset > _M_file_size() */ ) michael@0: return streamoff(-1); michael@0: whence = SEEK_SET; michael@0: break; michael@0: case ios_base::cur: michael@0: whence = SEEK_CUR; michael@0: break; michael@0: case ios_base::end: michael@0: if (/* offset > 0 || */ -offset > _M_file_size() ) michael@0: return streamoff(-1); michael@0: whence = SEEK_END; michael@0: break; michael@0: default: michael@0: return streamoff(-1); michael@0: } michael@0: michael@0: if ( FSEEK(_M_file, offset, whence) == 0 ) { michael@0: return FTELL(_M_file); michael@0: } michael@0: michael@0: return streamoff(-1); michael@0: } michael@0: michael@0: michael@0: // Attempts to memory-map len bytes of the current file, starting michael@0: // at position offset. Precondition: offset is a multiple of the michael@0: // page size. Postcondition: return value is a null pointer if the michael@0: // memory mapping failed. Otherwise the return value is a pointer to michael@0: // the memory-mapped file and the file position is set to offset. michael@0: void *_Filebuf_base::_M_mmap(streamoff, streamoff ) michael@0: { michael@0: return 0; michael@0: } michael@0: michael@0: void _Filebuf_base::_M_unmap(void*, streamoff) michael@0: { michael@0: // precondition : there is a valid mapping at the moment michael@0: } michael@0: michael@0: _STLP_END_NAMESPACE