Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

395 lines
10 KiB

  1. /***
  2. *filebuf.cpp - core filebuf member functions
  3. *
  4. * Copyright (c) 1991-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * Contains the core member functions for filebuf class.
  8. *
  9. *Revision History:
  10. * 08-08-91 KRS Created.
  11. * 08-20-91 KRS Added virtual xsgetn()/xsputn() functions.
  12. * 08-21-91 KRS Fix circular reference between sync() and seekoff().
  13. * Close file in destructor only if we opened it!
  14. * 09-06-91 KRS Fix ios::ate case in filebuf::open().
  15. * 09-09-91 KRS Add support for ios::binary in filebuf::open().
  16. * 09-10-91 KRS Remove virtual xsputn()/xsgetn().
  17. * 09-11-91 KRS Fix filebuf::seekoff() for ios::cur and in_avail().
  18. * 09-12-91 KRS Make sure close() always closes even if sync() fails.
  19. * Fix seekoff call in filebuf::sync() and pbackfail().
  20. * 09-16-91 KRS Make virtual filebuf::setbuf() more robust.
  21. * 09-19-91 KRS Add calls to delbuf(1) in constructors.
  22. * 09-20-91 KRS C700 #4453: Improve efficiency in overflow().
  23. * 09-29-91 KRS Granularity split. Move fstream into separate file.
  24. * 10-24-91 KRS Avoid virtual calls from virtual functions.
  25. * 11-13-91 KRS Use allocate() properly in overflow() and underflow().
  26. * Fix constructor.
  27. * 01-03-92 KRS Remove virtual keyword. Add function headers and PCH.
  28. * 01-20-92 KRS In text mode, account for CR/LF pairs in sync().
  29. * 02-03-92 KRS Change for new compiler destructor behavior.
  30. * 08-19-92 KRS Remove sh_compat for NT.
  31. * 08-27-92 KRS Fix bug in close() introduced in MTHREAD work.
  32. * 02-23-95 CFW Fix bug: buffer overwritten when disk full.
  33. * 06-14-95 CFW Comment cleanup.
  34. * 06-19-95 GJF Replaced _osfile[] with _osfile() (which references
  35. * a field in the ioinfo struct).
  36. * 05-17-99 PML Remove all Macintosh support.
  37. *
  38. *******************************************************************************/
  39. #include <cruntime.h>
  40. #include <internal.h>
  41. #include <string.h>
  42. #include <stdio.h>
  43. #include <fcntl.h>
  44. #include <crtdbg.h>
  45. #include <sys\types.h>
  46. #include <io.h>
  47. #include <fstream.h>
  48. #pragma hdrstop
  49. #include <msdos.h>
  50. #include <sys\stat.h>
  51. const int filebuf::openprot = 0644;
  52. const int filebuf::sh_none = 04000; // deny rw
  53. const int filebuf::sh_read = 05000; // deny wr
  54. const int filebuf::sh_write = 06000; // deny rd
  55. const int filebuf::binary = O_BINARY;
  56. const int filebuf::text = O_TEXT;
  57. /***
  58. *filebuf::filebuf() - filebuf default constructor
  59. *
  60. *Purpose:
  61. * Default constructor.
  62. *
  63. *Entry:
  64. *
  65. *******************************************************************************/
  66. filebuf::filebuf()
  67. : streambuf()
  68. {
  69. x_fOpened = 0;
  70. x_fd = -1;
  71. }
  72. /***
  73. *filebuf::filebuf(filedesc fd) - filebuf constructor
  74. *
  75. *Purpose:
  76. * Constructor. Initialize filebuf and attach to file descriptor.
  77. *
  78. *Entry:
  79. * fd = file descriptor to attach to filebuf
  80. *
  81. *******************************************************************************/
  82. filebuf::filebuf(filedesc fd)
  83. : streambuf()
  84. {
  85. x_fOpened = 0;
  86. x_fd=fd;
  87. }
  88. /***
  89. *filebuf::filebuf(filedesc fd, char* p, int len) - filebuf constructor
  90. *
  91. *Purpose:
  92. * Constructor. Initialize filebuf and attach to file descriptor.
  93. *
  94. *Entry:
  95. * fd = file descriptor to attach to filebuf
  96. * p = user-supplied buffer
  97. * len = length of buffer
  98. *
  99. *******************************************************************************/
  100. filebuf::filebuf(filedesc fd, char* p, int len)
  101. : streambuf()
  102. {
  103. filebuf::setbuf(p,len);
  104. x_fOpened = 0;
  105. x_fd=fd;
  106. }
  107. /***
  108. *filebuf::~filebuf() - filebuf destructor
  109. *
  110. *Purpose:
  111. * Destructor. Close attached file only if we opened it.
  112. *
  113. *Entry:
  114. * None.
  115. *
  116. *******************************************************************************/
  117. filebuf::~filebuf()
  118. {
  119. lock(); // no need to unlock...
  120. if (x_fOpened)
  121. close(); // calls filebuf::sync()
  122. else
  123. filebuf::sync();
  124. }
  125. /***
  126. *filebuf* filebuf::close() - close an attached file
  127. *
  128. *Purpose:
  129. * Close attached file.
  130. *
  131. *Entry:
  132. * None.
  133. *Exit:
  134. * Returns NULL if error, otherwise returns "this" pointer.
  135. *
  136. *******************************************************************************/
  137. filebuf* filebuf::close()
  138. {
  139. int retval;
  140. if (x_fd==-1)
  141. return NULL;
  142. lock();
  143. retval = sync();
  144. if ((_close(x_fd)==-1) || (retval==EOF))
  145. {
  146. unlock();
  147. return NULL;
  148. }
  149. x_fd = -1;
  150. unlock();
  151. return this;
  152. }
  153. /***
  154. *virtual int filebuf::overflow(int c) - overflow virtual function
  155. *
  156. *Purpose:
  157. * flush any characters in the reserve area and handle 'c'.
  158. *
  159. *Entry:
  160. * c = character to output (if not EOF)
  161. *
  162. *Exit:
  163. * Returns EOF if error, otherwise returns something else.
  164. *
  165. *Exceptions:
  166. * Returns EOF if error.
  167. *
  168. *******************************************************************************/
  169. int filebuf::overflow(int c)
  170. {
  171. if (allocate()==EOF) // make sure there is a reserve area
  172. return EOF;
  173. if (filebuf::sync()==EOF) // sync before new buffer created below
  174. return EOF;
  175. if (!unbuffered())
  176. setp(base(),ebuf());
  177. if (c!=EOF)
  178. {
  179. if ((!unbuffered()) && (pptr() < epptr())) // guard against recursion
  180. sputc(c);
  181. else
  182. {
  183. if (_write(x_fd,&c,1)!=1)
  184. return(EOF);
  185. }
  186. }
  187. return(1); // return something other than EOF if successful
  188. }
  189. /***
  190. *virtual int filebuf::underflow() - underflow virtual function
  191. *
  192. *Purpose:
  193. * return next character in get area, or get more characters from source.
  194. *
  195. *Entry:
  196. * None.
  197. *
  198. *Exit:
  199. * Returns current character in file. Does not advance get pointer.
  200. *
  201. *Exceptions:
  202. * Returns EOF if error.
  203. *
  204. *******************************************************************************/
  205. int filebuf::underflow()
  206. {
  207. int count;
  208. unsigned char tbuf;
  209. if (in_avail())
  210. return (int)(unsigned char) *gptr();
  211. if (allocate()==EOF) // make sure there is a reserve area
  212. return EOF;
  213. if (filebuf::sync()==EOF)
  214. return EOF;
  215. if (unbuffered())
  216. {
  217. if (_read(x_fd,(void *)&tbuf,1)<=0)
  218. return EOF;
  219. return (int)tbuf;
  220. }
  221. if ((count=_read(x_fd,(void *)base(),blen())) <= 0)
  222. return EOF; // reached EOF
  223. setg(base(),base(),base()+count);
  224. return (int)(unsigned char) *gptr();
  225. }
  226. /***
  227. *virtual streampos filebuf::seekoff() - seekoff virtual function
  228. *
  229. *Purpose:
  230. * Seeks to given absolute or relative file offset.
  231. *
  232. *Entry:
  233. * off = offset to seek to relative to beginning, end or current
  234. * position in the file.
  235. * dir = one of ios::beg, ios::cur, or ios::end
  236. *
  237. *Exit:
  238. * Returns current file position after seek.
  239. *
  240. *Exceptions:
  241. * Returns EOF if error.
  242. *
  243. *******************************************************************************/
  244. streampos filebuf::seekoff(streamoff off, ios::seek_dir dir, int)
  245. {
  246. int fdir;
  247. long retpos;
  248. switch (dir) {
  249. case ios::beg :
  250. fdir = SEEK_SET;
  251. break;
  252. case ios::cur :
  253. fdir = SEEK_CUR;
  254. break;
  255. case ios::end :
  256. fdir = SEEK_END;
  257. break;
  258. default:
  259. // error
  260. return(EOF);
  261. }
  262. if (filebuf::sync()==EOF)
  263. return EOF;
  264. if ((retpos=_lseek(x_fd, off, fdir))==-1L)
  265. return (EOF);
  266. return((streampos)retpos);
  267. }
  268. /***
  269. *virtual int filebuf::sync() - synchronize buffers with external file postion.
  270. *
  271. *Purpose:
  272. * Synchronizes buffer with external file, by flushing any output and/or
  273. * discarding any unread input data. Discards any get or put area(s).
  274. *
  275. *Entry:
  276. * None.
  277. *
  278. *Exit:
  279. * Returns EOF if error, else 0.
  280. *
  281. *Exceptions:
  282. * Returns EOF if error.
  283. *
  284. *******************************************************************************/
  285. int filebuf::sync()
  286. {
  287. long count, nout;
  288. char * p;
  289. if (x_fd==-1)
  290. return(EOF);
  291. if (!unbuffered())
  292. {
  293. if ((count=out_waiting())!=0)
  294. {
  295. if ((nout =_write(x_fd,(void *) pbase(),(unsigned int)count)) != count)
  296. {
  297. if (nout > 0) {
  298. // should set _pptr -= nout
  299. pbump(-(int)nout);
  300. memmove(pbase(), pbase()+nout, (int)(count-nout));
  301. }
  302. return(EOF);
  303. }
  304. }
  305. setp(0,0); // empty put area
  306. if ((count=in_avail()) > 0)
  307. {
  308. // can't use seekoff here!!
  309. if (_osfile(x_fd) & FTEXT)
  310. {
  311. // If text mode, need to account for CR/LF etc.
  312. for (p = gptr(); p < egptr(); p++)
  313. if (*p == '\n')
  314. count++;
  315. // account for EOF if read, not counted by _read
  316. if ((_osfile(x_fd) & FEOFLAG))
  317. count++;
  318. }
  319. if (_lseek(x_fd, -count, SEEK_CUR)==-1L)
  320. {
  321. // unlock();
  322. return (EOF);
  323. }
  324. }
  325. setg(0,0,0); // empty get area
  326. }
  327. // unlock();
  328. return(0);
  329. }
  330. /***
  331. *virtual streambuf* filebuf::setbuf(char* ptr, int len) - set reserve area.
  332. *
  333. *Purpose:
  334. * Synchronizes buffer with external file, by flushing any output and/or
  335. * discarding any unread input data. Discards any get or put area(s).
  336. *
  337. *Entry:
  338. * ptr = requested reserve area. If NULL, request is for unbuffered.
  339. * len = size of reserve area. If <= 0, request is for unbuffered.
  340. *
  341. *Exit:
  342. * Returns this pointer if request is honored, else NULL.
  343. *
  344. *Exceptions:
  345. * Returns NULL if request is not honored.
  346. *
  347. *******************************************************************************/
  348. streambuf * filebuf::setbuf(char * ptr, int len)
  349. {
  350. if (is_open() && (ebuf()))
  351. return NULL;
  352. if ((!ptr) || (len <= 0))
  353. unbuffered(1);
  354. else
  355. {
  356. lock();
  357. setb(ptr, ptr+len, 0);
  358. unlock();
  359. }
  360. return this;
  361. }