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.

208 lines
6.1 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. *
  45. *******************************************************************************/
  46. #include <cruntime.h>
  47. #include <msdos.h>
  48. #include <stdio.h>
  49. #include <file2.h>
  50. #include <dbgint.h>
  51. #include <internal.h>
  52. #include <mtdll.h>
  53. #ifdef _POSIX_
  54. #include <limits.h>
  55. #endif
  56. #include <tchar.h>
  57. #include <errno.h>
  58. /***
  59. *FILE *_fdopen(filedes, mode) - open a file descriptor as a stream
  60. *
  61. *Purpose:
  62. * associates a stream with a file handle, thus allowing buffering, etc.
  63. * The mode must be specified and must be compatible with the mode
  64. * the file was opened with in the low level open.
  65. *
  66. *Entry:
  67. * int filedes - handle referring to open file
  68. * _TSCHAR *mode - file mode to use ("r", "w", "a", etc.)
  69. *
  70. *Exit:
  71. * returns stream pointer and sets FILE struct fields if successful
  72. * returns NULL if fails
  73. *
  74. *Exceptions:
  75. *
  76. *******************************************************************************/
  77. FILE * __cdecl _tfdopen (
  78. int filedes,
  79. REG2 const _TSCHAR *mode
  80. )
  81. {
  82. REG1 FILE *stream;
  83. int whileflag, tbflag, cnflag;
  84. _ASSERTE(mode != NULL);
  85. #if !defined(_POSIX_)
  86. _ASSERTE((unsigned)filedes < (unsigned)_nhandle);
  87. _ASSERTE(_osfile(filedes) & FOPEN);
  88. if ( ((unsigned)filedes >= (unsigned)_nhandle) ||
  89. !(_osfile(filedes) & FOPEN) )
  90. return(NULL);
  91. #else
  92. _ASSERTE((unsigned)filedes < OPEN_MAX);
  93. if ((unsigned)filedes >= OPEN_MAX)
  94. return(NULL);
  95. #endif /* !_POSIX_ */
  96. /* Find a free stream; stream is returned 'locked'. */
  97. if ((stream = _getstream()) == NULL) {
  98. errno = EMFILE;
  99. return(NULL);
  100. }
  101. #ifdef _MT
  102. __try {
  103. #endif
  104. /* First character must be 'r', 'w', or 'a'. */
  105. switch (*mode) {
  106. case _T('r'):
  107. stream->_flag = _IOREAD;
  108. break;
  109. case _T('w'):
  110. case _T('a'):
  111. stream->_flag = _IOWRT;
  112. break;
  113. default:
  114. stream = NULL; /* error */
  115. goto done;
  116. break;
  117. }
  118. /* There can be up to three more optional characters:
  119. (1) A single '+' character,
  120. (2) One of 'b' and 't' and
  121. (3) One of 'c' and 'n'.
  122. Note that currently, the 't' and 'b' flags are syntax checked
  123. but ignored. 'c' and 'n', however, are correctly supported.
  124. */
  125. whileflag=1;
  126. tbflag=cnflag=0;
  127. stream->_flag |= _commode;
  128. while(*++mode && whileflag)
  129. switch(*mode) {
  130. case _T('+'):
  131. if (stream->_flag & _IORW)
  132. whileflag=0;
  133. else {
  134. stream->_flag |= _IORW;
  135. stream->_flag &= ~(_IOREAD | _IOWRT);
  136. }
  137. break;
  138. case _T('b'):
  139. case _T('t'):
  140. if (tbflag)
  141. whileflag=0;
  142. else
  143. tbflag=1;
  144. break;
  145. case _T('c'):
  146. if (cnflag)
  147. whileflag = 0;
  148. else {
  149. cnflag = 1;
  150. stream->_flag |= _IOCOMMIT;
  151. }
  152. break;
  153. case _T('n'):
  154. if (cnflag)
  155. whileflag = 0;
  156. else {
  157. cnflag = 1;
  158. stream->_flag &= ~_IOCOMMIT;
  159. }
  160. break;
  161. default:
  162. whileflag=0;
  163. break;
  164. }
  165. #ifndef CRTDLL
  166. _cflush++; /* force library pre-termination procedure */
  167. #endif /* CRTDLL */
  168. stream->_file = filedes;
  169. /* Common return */
  170. done:
  171. #ifdef _MT
  172. ; }
  173. __finally {
  174. _unlock_str(stream);
  175. }
  176. #endif
  177. return(stream);
  178. }