Leaked source code of windows server 2003
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.

229 lines
8.2 KiB

  1. /***
  2. *ftelli64.c - get current file position
  3. *
  4. * Copyright (c) 1994-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * defines _ftelli64() - find current current position of file pointer
  8. *
  9. *Revision History:
  10. * 12-22-94 GJF Module created. Derived from ftell.c
  11. * 02-06-94 CFW assert -> _ASSERTE.
  12. * 03-07-95 GJF _[un]lock_str macros now take FILE * arg.
  13. * 06-23-95 GJF Replaced _osfile[] with _osfile() (macro referencing
  14. * field in ioinfo struct).
  15. * 03-02-98 GJF Exception-safe locking.
  16. * 03-04-98 RKP Added 64 bit support.
  17. *
  18. *******************************************************************************/
  19. #include <cruntime.h>
  20. #include <stdio.h>
  21. #include <file2.h>
  22. #include <dbgint.h>
  23. #include <errno.h>
  24. #include <msdos.h>
  25. #include <stddef.h>
  26. #include <io.h>
  27. #include <internal.h>
  28. #include <mtdll.h>
  29. /***
  30. *__int64 _ftelli64(stream) - query stream file pointer
  31. *
  32. *Purpose:
  33. * Find out what stream's position is. coordinate with buffering; adjust
  34. * backward for read-ahead and forward for write-behind. This is NOT
  35. * equivalent to fseek(stream,0L,1), because fseek will remove an ungetc,
  36. * may flush buffers, etc.
  37. *
  38. *Entry:
  39. * FILE *stream - stream to query for position
  40. *
  41. *Exit:
  42. * return present file position if succeeds
  43. * returns -1i64 and sets errno if fails
  44. *
  45. *Exceptions:
  46. *
  47. *******************************************************************************/
  48. #ifdef _MT
  49. __int64 __cdecl _ftelli64 (
  50. FILE *stream
  51. )
  52. {
  53. __int64 retval;
  54. _ASSERTE(stream != NULL);
  55. _lock_str(stream);
  56. __try {
  57. retval = _ftelli64_lk (stream);
  58. }
  59. __finally {
  60. _unlock_str(stream);
  61. }
  62. return(retval);
  63. }
  64. /***
  65. *_ftelli64_lk() - _ftelli64() core routine (assumes stream is locked).
  66. *
  67. *Purpose:
  68. * Core _ftelli64() routine (assumes caller has aquired stream lock).
  69. *
  70. *Entry:
  71. *
  72. *Exit:
  73. *
  74. *Exceptions:
  75. *
  76. *******************************************************************************/
  77. __int64 __cdecl _ftelli64_lk (
  78. #else /* mdef _MT */
  79. __int64 __cdecl _ftelli64 (
  80. #endif /* _MT */
  81. FILE *str
  82. )
  83. {
  84. REG1 FILE *stream;
  85. size_t offset;
  86. __int64 filepos;
  87. REG2 char *p;
  88. char *max;
  89. int fd;
  90. size_t rdcnt;
  91. _ASSERTE(str != NULL);
  92. /* Init stream pointer and file descriptor */
  93. stream = str;
  94. fd = _fileno(stream);
  95. if (stream->_cnt < 0)
  96. stream->_cnt = 0;
  97. if ((filepos = _lseeki64(fd, 0i64, SEEK_CUR)) < 0L)
  98. return(-1i64);
  99. if (!bigbuf(stream)) /* _IONBF or no buffering designated */
  100. return(filepos - stream->_cnt);
  101. offset = (size_t)(stream->_ptr - stream->_base);
  102. if (stream->_flag & (_IOWRT|_IOREAD)) {
  103. if (_osfile(fd) & FTEXT)
  104. for (p = stream->_base; p < stream->_ptr; p++)
  105. if (*p == '\n') /* adjust for '\r' */
  106. offset++;
  107. }
  108. else if (!(stream->_flag & _IORW)) {
  109. errno=EINVAL;
  110. return(-1i64);
  111. }
  112. if (filepos == 0i64)
  113. return((__int64)offset);
  114. if (stream->_flag & _IOREAD) /* go to preceding sector */
  115. if (stream->_cnt == 0) /* filepos holds correct location */
  116. offset = 0;
  117. else {
  118. /* Subtract out the number of unread bytes left in the
  119. buffer. [We can't simply use _iob[]._bufsiz because
  120. the last read may have hit EOF and, thus, the buffer
  121. was not completely filled.] */
  122. rdcnt = stream->_cnt + (size_t)(stream->_ptr - stream->_base);
  123. /* If text mode, adjust for the cr/lf substitution. If
  124. binary mode, we're outta here. */
  125. if (_osfile(fd) & FTEXT) {
  126. /* (1) If we're not at eof, simply copy _bufsiz
  127. onto rdcnt to get the # of untranslated
  128. chars read. (2) If we're at eof, we must
  129. look through the buffer expanding the '\n'
  130. chars one at a time. */
  131. /* [NOTE: Performance issue -- it is faster to
  132. do the two _lseek() calls than to blindly go
  133. through and expand the '\n' chars regardless
  134. of whether we're at eof or not.] */
  135. if (_lseeki64(fd, 0i64, SEEK_END) == filepos) {
  136. max = stream->_base + rdcnt;
  137. for (p = stream->_base; p < max; p++)
  138. if (*p == '\n')
  139. /* adjust for '\r' */
  140. rdcnt++;
  141. /* If last byte was ^Z, the lowio read
  142. didn't tell us about it. Check flag
  143. and bump count, if necessary. */
  144. if (stream->_flag & _IOCTRLZ)
  145. ++rdcnt;
  146. }
  147. else {
  148. if (_lseeki64(fd, filepos, SEEK_SET) < 0)
  149. return (-1);
  150. /* We want to set rdcnt to the number
  151. of bytes originally read into the
  152. stream buffer (before crlf->lf
  153. translation). In most cases, this
  154. will just be _bufsiz. However, the
  155. buffer size may have been changed,
  156. due to fseek optimization, at the
  157. END of the last _filbuf call. */
  158. if ( (rdcnt <= _SMALL_BUFSIZ) &&
  159. (stream->_flag & _IOMYBUF) &&
  160. !(stream->_flag & _IOSETVBUF) )
  161. {
  162. /* The translated contents of
  163. the buffer is small and we
  164. are not at eof. The buffer
  165. size must have been set to
  166. _SMALL_BUFSIZ during the
  167. last _filbuf call. */
  168. rdcnt = _SMALL_BUFSIZ;
  169. }
  170. else
  171. rdcnt = stream->_bufsiz;
  172. /* If first byte in untranslated buffer
  173. was a '\n', assume it was preceeded
  174. by a '\r' which was discarded by the
  175. previous read operation and count
  176. the '\n'. */
  177. if (_osfile(fd) & FCRLF)
  178. ++rdcnt;
  179. }
  180. } /* end if FTEXT */
  181. filepos -= (__int64)rdcnt;
  182. } /* end else stream->_cnt != 0 */
  183. return(filepos + (__int64)offset);
  184. }