fstream_stdio.cpp 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  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. #if defined (__SUNPPRO_CC) && !defined (_STLP_NO_NEW_C_HEADERS)
  19. # include <time.h>
  20. // For sunpro, it chokes if time.h is included through stat.h
  21. #endif
  22. #include <fstream>
  23. #ifdef __CYGWIN__
  24. # define __int64 long long
  25. #endif
  26. #include <cstdio>
  27. #if !defined(__ISCPP__)
  28. extern "C" {
  29. # include <sys/stat.h>
  30. }
  31. #endif
  32. #if defined( __MSL__ )
  33. # include <unix.h>
  34. #endif
  35. #if defined(__ISCPP__)
  36. # include <c_locale_is/filestat.h>
  37. #endif
  38. #if defined(__BEOS__) && defined(__INTEL__)
  39. # include <fcntl.h>
  40. # include <sys/stat.h> // For _fstat
  41. #endif
  42. #if defined (_STLP_MSVC) || defined (__MINGW32__)
  43. # include <fcntl.h>
  44. # define S_IREAD _S_IREAD
  45. # define S_IWRITE _S_IWRITE
  46. # define S_IFREG _S_IFREG
  47. // map permission masks
  48. # ifndef S_IRUSR
  49. # define S_IRUSR _S_IREAD
  50. # define S_IWUSR _S_IWRITE
  51. # endif
  52. # ifndef S_IRGRP
  53. # define S_IRGRP _S_IREAD
  54. # define S_IWGRP _S_IWRITE
  55. # endif
  56. # ifndef S_IROTH
  57. # define S_IROTH _S_IREAD
  58. # define S_IWOTH _S_IWRITE
  59. # endif
  60. # ifndef O_RDONLY
  61. # define O_RDONLY _O_RDONLY
  62. # define O_WRONLY _O_WRONLY
  63. # define O_RDWR _O_RDWR
  64. # define O_APPEND _O_APPEND
  65. # define O_CREAT _O_CREAT
  66. # define O_TRUNC _O_TRUNC
  67. # define O_TEXT _O_TEXT
  68. # define O_BINARY _O_BINARY
  69. # endif
  70. # ifndef O_ACCMODE
  71. # define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR)
  72. # endif
  73. #endif
  74. const _STLP_fd INVALID_STLP_FD = -1;
  75. # ifdef __MSL__
  76. # define _O_TEXT 0x0
  77. # if !defined( O_TEXT )
  78. # define O_TEXT _O_TEXT
  79. # endif
  80. # define _S_IFREG S_IFREG
  81. # define S_IREAD S_IRUSR
  82. # define S_IWRITE S_IWUSR
  83. # define S_IEXEC S_IXUSR
  84. # define _S_IWRITE S_IWRITE
  85. # define _S_IREAD S_IREAD
  86. # define _open open
  87. # define _close close
  88. # define _read read
  89. # define _write write
  90. # endif
  91. _STLP_BEGIN_NAMESPACE
  92. // Compare with streamoff definition in stl/char_traits.h!
  93. #if defined (_STLP_USE_DEFAULT_FILE_OFFSET) || \
  94. (!defined(_LARGEFILE_SOURCE) && !defined(_LARGEFILE64_SOURCE))
  95. # define FOPEN fopen
  96. # define FSEEK fseek
  97. # define FSTAT fstat
  98. # define STAT stat
  99. # define FTELL ftell
  100. #else
  101. # define FOPEN fopen64
  102. # define FSEEK fseeko64
  103. # define FSTAT fstat64
  104. # define STAT stat64
  105. # define FTELL ftello64
  106. #endif
  107. _STLP_MOVE_TO_PRIV_NAMESPACE
  108. // Helper functions for _Filebuf_base.
  109. static bool __is_regular_file(_STLP_fd fd) {
  110. struct STAT buf;
  111. return FSTAT(fd, &buf) == 0 && (buf.st_mode & S_IFREG) != 0 ;
  112. }
  113. // Number of characters in the file.
  114. static streamoff __file_size(_STLP_fd fd) {
  115. streamoff ret = 0;
  116. struct STAT buf;
  117. if (FSTAT(fd, &buf) == 0 && (buf.st_mode & S_IFREG) != 0)
  118. ret = buf.st_size > 0 ? buf.st_size : 0;
  119. return ret;
  120. }
  121. _STLP_MOVE_TO_STD_NAMESPACE
  122. // All version of Unix have mmap and lseek system calls. Some also have
  123. // longer versions of those system calls to accommodate 64-bit offsets.
  124. // If we're on a Unix system, define some macros to encapsulate those
  125. // differences.
  126. size_t _Filebuf_base::_M_page_size = 4096;
  127. _Filebuf_base::_Filebuf_base()
  128. : _M_file_id(INVALID_STLP_FD),
  129. _M_openmode(0),
  130. _M_is_open(false),
  131. _M_should_close(false)
  132. {}
  133. void _Filebuf_base::_S_initialize()
  134. {
  135. }
  136. // Return the size of the file. This is a wrapper for stat.
  137. // Returns zero if the size cannot be determined or is ill-defined.
  138. streamoff _Filebuf_base::_M_file_size()
  139. {
  140. return _STLP_PRIV __file_size(_M_file_id);
  141. }
  142. bool _Filebuf_base::_M_open(const char* name, ios_base::openmode openmode,
  143. long permission)
  144. {
  145. _STLP_fd file_no;
  146. if (_M_is_open)
  147. return false;
  148. // use FILE-based i/o
  149. const char* flags;
  150. switch (openmode & (~ios_base::ate)) {
  151. case ios_base::out:
  152. case ios_base::out | ios_base::trunc:
  153. flags = "w";
  154. break;
  155. case ios_base::out | ios_base::binary:
  156. case ios_base::out | ios_base::trunc | ios_base::binary:
  157. flags = "wb";
  158. break;
  159. case ios_base::out | ios_base::app:
  160. flags = "a";
  161. break;
  162. case ios_base::out | ios_base::app | ios_base::binary:
  163. flags = "ab";
  164. break;
  165. case ios_base::in:
  166. flags = "r";
  167. break;
  168. case ios_base::in | ios_base::binary:
  169. flags = "rb";
  170. break;
  171. case ios_base::in | ios_base::out:
  172. flags = "r+";
  173. break;
  174. case ios_base::in | ios_base::out | ios_base::binary:
  175. flags = "r+b";
  176. break;
  177. case ios_base::in | ios_base::out | ios_base::trunc:
  178. flags = "w+";
  179. break;
  180. case ios_base::in | ios_base::out | ios_base::trunc | ios_base::binary:
  181. flags = "w+b";
  182. break;
  183. default: // The above are the only combinations of
  184. return false; // flags allowed by the C++ standard.
  185. }
  186. // fbp : TODO : set permissions !
  187. (void)permission; // currently unused //*TY 02/26/2000 - added to suppress warning message
  188. _M_file = FOPEN(name, flags);
  189. if (_M_file) {
  190. file_no = fileno(_M_file);
  191. } else {
  192. return false;
  193. }
  194. // unset buffering immediately
  195. setbuf(_M_file, 0);
  196. _M_is_open = true;
  197. if (openmode & ios_base::ate) {
  198. if (FSEEK(_M_file, 0, SEEK_END) != 0)
  199. _M_is_open = false;
  200. }
  201. _M_file_id = file_no;
  202. _M_should_close = _M_is_open;
  203. _M_openmode = openmode;
  204. if (_M_is_open)
  205. _M_regular_file = _STLP_PRIV __is_regular_file(_M_file_id);
  206. return (_M_is_open != 0);
  207. }
  208. bool _Filebuf_base::_M_open(const char* name, ios_base::openmode openmode)
  209. {
  210. // This doesn't really grant everyone in the world read/write
  211. // access. On Unix, file-creation system calls always clear
  212. // bits that are set in the umask from the permissions flag.
  213. return this->_M_open(name, openmode, S_IRUSR | S_IWUSR | S_IRGRP |
  214. S_IWGRP | S_IROTH | S_IWOTH);
  215. }
  216. // Associated the filebuf with a file descriptor pointing to an already-
  217. // open file. Mode is set to be consistent with the way that the file
  218. // was opened.
  219. bool _Filebuf_base::_M_open( int file_no, ios_base::openmode )
  220. {
  221. if (_M_is_open || file_no < 0)
  222. return false;
  223. struct STAT buf;
  224. if (FSTAT(file_no, &buf) != 0)
  225. return false;
  226. int mode = buf.st_mode;
  227. switch ( mode & (S_IWRITE | S_IREAD) ) {
  228. case S_IREAD:
  229. _M_openmode = ios_base::in;
  230. break;
  231. case S_IWRITE:
  232. _M_openmode = ios_base::out;
  233. break;
  234. case (S_IWRITE | S_IREAD):
  235. _M_openmode = ios_base::in | ios_base::out;
  236. break;
  237. default:
  238. return false;
  239. }
  240. _M_file_id = file_no;
  241. _M_is_open = true;
  242. _M_should_close = false;
  243. _M_regular_file = _STLP_PRIV __is_regular_file(_M_file_id);
  244. return true;
  245. }
  246. bool _Filebuf_base::_M_close()
  247. {
  248. if (!_M_is_open)
  249. return false;
  250. bool ok = _M_should_close ? (fclose(_M_file) == 0) : true;
  251. _M_is_open = _M_should_close = false;
  252. _M_openmode = 0;
  253. return ok;
  254. }
  255. // Read up to n characters into a buffer. Return value is number of
  256. // characters read.
  257. ptrdiff_t _Filebuf_base::_M_read(char* buf, ptrdiff_t n) {
  258. return fread(buf, 1, n, _M_file);
  259. }
  260. // Write n characters from a buffer. Return value: true if we managed
  261. // to write the entire buffer, false if we didn't.
  262. bool _Filebuf_base::_M_write(char* buf, ptrdiff_t n)
  263. {
  264. for (;;) {
  265. ptrdiff_t written = fwrite(buf, 1, n, _M_file);
  266. if (n == written) {
  267. return true;
  268. }
  269. if (written > 0 && written < n) {
  270. n -= written;
  271. buf += written;
  272. } else {
  273. return false;
  274. }
  275. }
  276. }
  277. // Wrapper for lseek or the like.
  278. streamoff _Filebuf_base::_M_seek(streamoff offset, ios_base::seekdir dir)
  279. {
  280. int whence;
  281. switch ( dir ) {
  282. case ios_base::beg:
  283. if (offset < 0 /* || offset > _M_file_size() */ )
  284. return streamoff(-1);
  285. whence = SEEK_SET;
  286. break;
  287. case ios_base::cur:
  288. whence = SEEK_CUR;
  289. break;
  290. case ios_base::end:
  291. if (/* offset > 0 || */ -offset > _M_file_size() )
  292. return streamoff(-1);
  293. whence = SEEK_END;
  294. break;
  295. default:
  296. return streamoff(-1);
  297. }
  298. if ( FSEEK(_M_file, offset, whence) == 0 ) {
  299. return FTELL(_M_file);
  300. }
  301. return streamoff(-1);
  302. }
  303. // Attempts to memory-map len bytes of the current file, starting
  304. // at position offset. Precondition: offset is a multiple of the
  305. // page size. Postcondition: return value is a null pointer if the
  306. // memory mapping failed. Otherwise the return value is a pointer to
  307. // the memory-mapped file and the file position is set to offset.
  308. void *_Filebuf_base::_M_mmap(streamoff, streamoff )
  309. {
  310. return 0;
  311. }
  312. void _Filebuf_base::_M_unmap(void*, streamoff)
  313. {
  314. // precondition : there is a valid mapping at the moment
  315. }
  316. _STLP_END_NAMESPACE