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