fstream_unistd.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  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. extern "C" {
  27. // open/close/read/write
  28. #include <sys/stat.h> // For stat
  29. #if !defined (_CRAY) && ! defined (__EMX__)
  30. # include <sys/mman.h> // For mmap
  31. #endif
  32. // on HP-UX 11, this one contradicts with pthread.h on pthread_atfork, unless we unset this
  33. #if defined (__hpux) && defined (__GNUC__)
  34. # undef _INCLUDE_POSIX1C_SOURCE
  35. #endif
  36. #include <unistd.h>
  37. #include <fcntl.h>
  38. }
  39. #ifdef __APPLE__
  40. # include <sys/sysctl.h>
  41. #endif
  42. const _STLP_fd INVALID_STLP_FD = -1;
  43. #ifndef O_ACCMODE
  44. # define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR)
  45. #endif
  46. // Compare with streamoff definition in stl/char_traits.h!
  47. #if defined (_STLP_USE_DEFAULT_FILE_OFFSET) || \
  48. (!defined(_LARGEFILE_SOURCE) && !defined (_LARGEFILE64_SOURCE))
  49. # define FSTAT fstat
  50. # define STAT stat
  51. # define LSEEK lseek
  52. # define MMAP mmap
  53. # define OPEN open
  54. #else
  55. # define FSTAT fstat64
  56. # define STAT stat64
  57. # define LSEEK lseek64
  58. # define MMAP mmap64
  59. # define OPEN open64
  60. #endif
  61. #ifndef MAP_FAILED /* MMAP failure return code */
  62. # define MAP_FAILED -1
  63. #endif
  64. _STLP_BEGIN_NAMESPACE
  65. static ios_base::openmode flag_to_openmode(int mode)
  66. {
  67. ios_base::openmode ret = ios_base::__default_mode;
  68. switch ( mode & O_ACCMODE ) {
  69. case O_RDONLY:
  70. ret = ios_base::in;
  71. break;
  72. case O_WRONLY:
  73. ret = ios_base::out;
  74. break;
  75. case O_RDWR:
  76. ret = ios_base::in | ios_base::out;
  77. break;
  78. }
  79. if ( mode & O_APPEND )
  80. ret |= ios_base::app;
  81. return ret;
  82. }
  83. _STLP_MOVE_TO_PRIV_NAMESPACE
  84. // Helper functions for _Filebuf_base.
  85. static bool __is_regular_file(_STLP_fd fd) {
  86. struct STAT buf;
  87. return FSTAT(fd, &buf) == 0 && S_ISREG(buf.st_mode);
  88. }
  89. // Number of characters in the file.
  90. static streamoff __file_size(_STLP_fd fd) {
  91. streamoff ret = 0;
  92. struct STAT buf;
  93. if (FSTAT(fd, &buf) == 0 && S_ISREG(buf.st_mode))
  94. ret = buf.st_size > 0 ? buf.st_size : 0;
  95. return ret;
  96. }
  97. _STLP_MOVE_TO_STD_NAMESPACE
  98. size_t _Filebuf_base::_M_page_size = 4096;
  99. _Filebuf_base::_Filebuf_base()
  100. : _M_file_id(INVALID_STLP_FD),
  101. _M_openmode(0),
  102. _M_is_open(false),
  103. _M_should_close(false)
  104. {}
  105. void _Filebuf_base::_S_initialize()
  106. {
  107. #if defined (__APPLE__)
  108. int mib[2];
  109. size_t pagesize, len;
  110. mib[0] = CTL_HW;
  111. mib[1] = HW_PAGESIZE;
  112. len = sizeof(pagesize);
  113. sysctl(mib, 2, &pagesize, &len, NULL, 0);
  114. _M_page_size = pagesize;
  115. #elif defined (__DJGPP) && defined (_CRAY)
  116. _M_page_size = BUFSIZ;
  117. #else
  118. _M_page_size = sysconf(_SC_PAGESIZE);
  119. #endif
  120. }
  121. // Return the size of the file. This is a wrapper for stat.
  122. // Returns zero if the size cannot be determined or is ill-defined.
  123. streamoff _Filebuf_base::_M_file_size()
  124. {
  125. return _STLP_PRIV __file_size(_M_file_id);
  126. }
  127. bool _Filebuf_base::_M_open(const char* name, ios_base::openmode openmode,
  128. long permission)
  129. {
  130. _STLP_fd file_no;
  131. if (_M_is_open)
  132. return false;
  133. int flags = 0;
  134. // Unix makes no distinction between text and binary files.
  135. switch ( openmode & (~ios_base::ate & ~ios_base::binary) ) {
  136. case ios_base::out:
  137. case ios_base::out | ios_base::trunc:
  138. flags = O_WRONLY | O_CREAT | O_TRUNC;
  139. break;
  140. case ios_base::app:
  141. case ios_base::out | ios_base::app:
  142. flags = O_WRONLY | O_CREAT | O_APPEND;
  143. break;
  144. case ios_base::in:
  145. flags = O_RDONLY;
  146. permission = 0; // Irrelevant unless we're writing.
  147. break;
  148. case ios_base::in | ios_base::out:
  149. flags = O_RDWR;
  150. break;
  151. case ios_base::in | ios_base::out | ios_base::trunc:
  152. flags = O_RDWR | O_CREAT | O_TRUNC;
  153. break;
  154. case ios_base::in | ios_base::app:
  155. case ios_base::in | ios_base::out | ios_base::app:
  156. flags = O_RDWR | O_CREAT | O_APPEND;
  157. break;
  158. default: // The above are the only combinations of
  159. return false; // flags allowed by the C++ standard.
  160. }
  161. file_no = OPEN(name, flags, permission);
  162. if (file_no < 0)
  163. return false;
  164. _M_is_open = true;
  165. if ((openmode & (ios_base::ate | ios_base::app)) && (LSEEK(file_no, 0, SEEK_END) == -1)) {
  166. _M_is_open = false;
  167. }
  168. _M_file_id = file_no;
  169. _M_should_close = _M_is_open;
  170. _M_openmode = openmode;
  171. if (_M_is_open)
  172. _M_regular_file = _STLP_PRIV __is_regular_file(_M_file_id);
  173. return (_M_is_open != 0);
  174. }
  175. bool _Filebuf_base::_M_open(const char* name, ios_base::openmode openmode)
  176. {
  177. // This doesn't really grant everyone in the world read/write
  178. // access. On Unix, file-creation system calls always clear
  179. // bits that are set in the umask from the permissions flag.
  180. return this->_M_open(name, openmode, S_IRUSR | S_IWUSR | S_IRGRP |
  181. S_IWGRP | S_IROTH | S_IWOTH);
  182. }
  183. // Associated the filebuf with a file descriptor pointing to an already-
  184. // open file. Mode is set to be consistent with the way that the file
  185. // was opened.
  186. bool _Filebuf_base::_M_open(int file_no, ios_base::openmode)
  187. {
  188. if (_M_is_open || file_no < 0)
  189. return false;
  190. int mode = fcntl(file_no, F_GETFL);
  191. if (mode == -1)
  192. return false;
  193. _M_openmode = flag_to_openmode(mode);
  194. _M_file_id = file_no;
  195. _M_is_open = true;
  196. _M_should_close = false;
  197. _M_regular_file = _STLP_PRIV __is_regular_file(_M_file_id);
  198. return true;
  199. }
  200. bool _Filebuf_base::_M_close()
  201. {
  202. if (!_M_is_open)
  203. return false;
  204. bool ok = _M_should_close ? (close(_M_file_id) == 0) : true;
  205. _M_is_open = _M_should_close = false;
  206. _M_openmode = 0;
  207. return ok;
  208. }
  209. // Read up to n characters into a buffer. Return value is number of
  210. // characters read.
  211. ptrdiff_t _Filebuf_base::_M_read(char* buf, ptrdiff_t n)
  212. {
  213. return read(_M_file_id, buf, n);
  214. }
  215. // Write n characters from a buffer. Return value: true if we managed
  216. // to write the entire buffer, false if we didn't.
  217. bool _Filebuf_base::_M_write(char* buf, ptrdiff_t n)
  218. {
  219. for (;;) {
  220. ptrdiff_t written = write(_M_file_id, buf, n);
  221. if (n == written) {
  222. return true;
  223. }
  224. if (written > 0 && written < n) {
  225. n -= written;
  226. buf += written;
  227. } else {
  228. return false;
  229. }
  230. }
  231. }
  232. // Wrapper for lseek or the like.
  233. streamoff _Filebuf_base::_M_seek(streamoff offset, ios_base::seekdir dir)
  234. {
  235. int whence;
  236. switch ( dir ) {
  237. case ios_base::beg:
  238. if (offset < 0 /* || offset > _M_file_size() */ )
  239. return streamoff(-1);
  240. whence = SEEK_SET;
  241. break;
  242. case ios_base::cur:
  243. whence = SEEK_CUR;
  244. break;
  245. case ios_base::end:
  246. if (/* offset > 0 || */ -offset > _M_file_size() )
  247. return streamoff(-1);
  248. whence = SEEK_END;
  249. break;
  250. default:
  251. return streamoff(-1);
  252. }
  253. return LSEEK(_M_file_id, offset, whence);
  254. }
  255. // Attempts to memory-map len bytes of the current file, starting
  256. // at position offset. Precondition: offset is a multiple of the
  257. // page size. Postcondition: return value is a null pointer if the
  258. // memory mapping failed. Otherwise the return value is a pointer to
  259. // the memory-mapped file and the file position is set to offset.
  260. void* _Filebuf_base::_M_mmap(streamoff offset, streamoff len)
  261. {
  262. void* base;
  263. #if !defined (__DJGPP) && !defined (_CRAY)
  264. base = MMAP(0, len, PROT_READ, MAP_PRIVATE, _M_file_id, offset);
  265. if (base != (void*)MAP_FAILED) {
  266. if (LSEEK(_M_file_id, offset + len, SEEK_SET) < 0) {
  267. this->_M_unmap(base, len);
  268. base = 0;
  269. }
  270. } else
  271. base =0;
  272. #else
  273. _STLP_MARK_PARAMETER_AS_UNUSED(&offset)
  274. _STLP_MARK_PARAMETER_AS_UNUSED(&len)
  275. base = 0;
  276. #endif
  277. return base;
  278. }
  279. void _Filebuf_base::_M_unmap(void* base, streamoff len)
  280. {
  281. // precondition : there is a valid mapping at the moment
  282. #if !defined (__DJGPP) && !defined (_CRAY)
  283. munmap((char*)base, len);
  284. #else
  285. _STLP_MARK_PARAMETER_AS_UNUSED(&len)
  286. _STLP_MARK_PARAMETER_AS_UNUSED(base)
  287. #endif
  288. }
  289. _STLP_END_NAMESPACE