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.

206 lines
6.3 KiB

  1. /***
  2. *fdopen.c - open a file descriptor as stream
  3. *
  4. * Copyright (c) 1985-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * defines _fdopen() - opens a file descriptor as a stream, thus allowing
  8. * buffering, etc.
  9. *
  10. *Revision History:
  11. * 09-02-83 RN initial version
  12. * 03-02-87 JCR added support for 'b' and 't' embedded in mode strings
  13. * 09-28-87 JCR Corrected _iob2 indexing (now uses _iob_index() macro).
  14. * 11-03-87 JCR Multi-thread support
  15. * 12-11-87 JCR Added "_LOAD_DS" to declaration
  16. * 05-31-88 PHG Merged DLL and normal versions
  17. * 06-06-88 JCR Optimized _iob2 references
  18. * 11-20-89 GJF Fixed copyright, indents. Added const to type of mode.
  19. * 02-15-90 GJF _iob[], _iob2[] merge.
  20. * 03-16-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
  21. * <cruntime.h> and removed #include <register.h>.
  22. * 07-23-90 SBM Replaced <assertm.h> by <assert.h>
  23. * 08-24-90 SBM Added support for 'c' and 'n' flags
  24. * 10-02-90 GJF New-style function declarator.
  25. * 01-21-91 GJF ANSI naming.
  26. * 02-14-92 GJF Replaced _nfile with _nhandle for Win32.
  27. * 05-01-92 DJM Replaced _nfile with OPEN_MAX for POSIX.
  28. * 08-03-92 GJF Function name must be "fdopen" for POSIX.
  29. * 04-06-93 SKS Replace _CRTAPI* with __cdecl
  30. * 12-07-93 CFW Wide char enable.
  31. * 04-05-94 GJF #ifdef-ed out _cflush reference for msvcrt*.dll, it
  32. * is unnecessary.
  33. * 09-06-94 CFW Replace MTHREAD with _MT.
  34. * 01-04-95 GJF _WIN32_ -> _WIN32.
  35. * 02-06-94 CFW assert -> _ASSERTE.
  36. * 02-17-95 GJF Merged in Mac version.
  37. * 03-07-95 GJF _[un]lock_str macros now take FILE * arg.
  38. * 10-20-95 GJF Added checks to passed supplied handle is open (for
  39. * Win32 and Mac builds) (Olympus0 10153).
  40. * 09-26-97 BWT Fix POSIX
  41. * 02-26-98 GJF Exception-safe locking.
  42. * 05-17-99 PML Remove all Macintosh support.
  43. * 10-06-99 PML Set errno EMFILE when out of streams.
  44. * 04-26-02 PML Fix AV on bogus mode param (VS7#526205)
  45. *
  46. *******************************************************************************/
  47. #include <cruntime.h>
  48. #include <msdos.h>
  49. #include <stdio.h>
  50. #include <file2.h>
  51. #include <dbgint.h>
  52. #include <internal.h>
  53. #include <mtdll.h>
  54. #ifdef _POSIX_
  55. #include <limits.h>
  56. #endif
  57. #include <tchar.h>
  58. #include <errno.h>
  59. /***
  60. *FILE *_fdopen(filedes, mode) - open a file descriptor as a stream
  61. *
  62. *Purpose:
  63. * associates a stream with a file handle, thus allowing buffering, etc.
  64. * The mode must be specified and must be compatible with the mode
  65. * the file was opened with in the low level open.
  66. *
  67. *Entry:
  68. * int filedes - handle referring to open file
  69. * _TSCHAR *mode - file mode to use ("r", "w", "a", etc.)
  70. *
  71. *Exit:
  72. * returns stream pointer and sets FILE struct fields if successful
  73. * returns NULL if fails
  74. *
  75. *Exceptions:
  76. *
  77. *******************************************************************************/
  78. FILE * __cdecl _tfdopen (
  79. int filedes,
  80. REG2 const _TSCHAR *mode
  81. )
  82. {
  83. REG1 FILE *stream;
  84. int whileflag, tbflag, cnflag;
  85. int fileflag;
  86. _ASSERTE(mode != NULL);
  87. #if !defined(_POSIX_)
  88. _ASSERTE((unsigned)filedes < (unsigned)_nhandle);
  89. _ASSERTE(_osfile(filedes) & FOPEN);
  90. if ( ((unsigned)filedes >= (unsigned)_nhandle) ||
  91. !(_osfile(filedes) & FOPEN) )
  92. return(NULL);
  93. #else
  94. _ASSERTE((unsigned)filedes < OPEN_MAX);
  95. if ((unsigned)filedes >= OPEN_MAX)
  96. return(NULL);
  97. #endif /* !_POSIX_ */
  98. /* First character must be 'r', 'w', or 'a'. */
  99. switch (*mode) {
  100. case _T('r'):
  101. fileflag = _IOREAD;
  102. break;
  103. case _T('w'):
  104. case _T('a'):
  105. fileflag = _IOWRT;
  106. break;
  107. default:
  108. return(NULL); /* error */
  109. }
  110. /* There can be up to three more optional characters:
  111. (1) A single '+' character,
  112. (2) One of 'b' and 't' and
  113. (3) One of 'c' and 'n'.
  114. Note that currently, the 't' and 'b' flags are syntax checked
  115. but ignored. 'c' and 'n', however, are correctly supported.
  116. */
  117. whileflag=1;
  118. tbflag=cnflag=0;
  119. fileflag |= _commode;
  120. while(*++mode && whileflag)
  121. switch(*mode) {
  122. case _T('+'):
  123. if (fileflag & _IORW)
  124. whileflag=0;
  125. else {
  126. fileflag |= _IORW;
  127. fileflag &= ~(_IOREAD | _IOWRT);
  128. }
  129. break;
  130. case _T('b'):
  131. case _T('t'):
  132. if (tbflag)
  133. whileflag=0;
  134. else
  135. tbflag=1;
  136. break;
  137. case _T('c'):
  138. if (cnflag)
  139. whileflag = 0;
  140. else {
  141. cnflag = 1;
  142. fileflag |= _IOCOMMIT;
  143. }
  144. break;
  145. case _T('n'):
  146. if (cnflag)
  147. whileflag = 0;
  148. else {
  149. cnflag = 1;
  150. fileflag &= ~_IOCOMMIT;
  151. }
  152. break;
  153. default:
  154. whileflag=0;
  155. break;
  156. }
  157. /* Find a free stream; stream is returned 'locked'. */
  158. if ((stream = _getstream()) == NULL) {
  159. errno = EMFILE;
  160. return(NULL);
  161. }
  162. #ifdef _MT
  163. __try {
  164. #endif
  165. #ifndef CRTDLL
  166. _cflush++; /* force library pre-termination procedure */
  167. #endif /* CRTDLL */
  168. stream->_flag = fileflag;
  169. stream->_file = filedes;
  170. #ifdef _MT
  171. }
  172. __finally {
  173. _unlock_str(stream);
  174. }
  175. #endif
  176. return(stream);
  177. }