//------------------------------------------------------------------------------ int CPosumStream::_close( int fh ) { int r = 0; //_CHECK_FH_CLEAR_OSSERR_RETURN( fh, EBADF, -1 ); //_VALIDATE_CLEAR_OSSERR_RETURN((fh >= 0 && (unsigned)fh < (unsigned)_nhandle), EBADF, -1); //_VALIDATE_CLEAR_OSSERR_RETURN((_osfile(fh) & FOPEN), EBADF, -1); flockfile(); __try { if ( m_chFlags & FOPEN ) { r = _close_nolock( fh ); } else { errno = EBADF; r = -1; //assert(("Invalid file descriptor. File possibly closed by a different thread",0)); } } __finally { funlockfile(); } return r; }
static int __cdecl dup2_nolock(int const source_fh, int const target_fh) throw() { if ((_osfile(source_fh) & FOPEN) == 0) { // If the source handle is not open, return an error. Noe that the // DuplicateHandle API will not detect this error, because it implies // that _osfhnd(source_fh) == INVALID_HANDLE_VALUE, and this is a // legal HANDLE value to be duplicated. errno = EBADF; _doserrno = 0; _ASSERTE(("Invalid file descriptor. File possibly closed by a different thread",0)); return -1; } // If the target is open, close it first. We ignore the possibility of an // error here: an error simply means that the OS handle value may remain // bound for the duration of the process. if (_osfile(target_fh) & FOPEN) { _close_nolock(target_fh); } // Duplicate the source file onto the target file: intptr_t new_osfhandle; BOOL const result = DuplicateHandle( GetCurrentProcess(), reinterpret_cast<HANDLE>(_get_osfhandle(source_fh)), GetCurrentProcess(), &reinterpret_cast<HANDLE&>(new_osfhandle), 0, TRUE, DUPLICATE_SAME_ACCESS); if (!result) { __acrt_errno_map_os_error(GetLastError()); return -1; } __acrt_lowio_set_os_handle(target_fh, new_osfhandle); // Copy the _osfile information, with the FNOINHERIT bit cleared: _osfile(target_fh) = _osfile(source_fh) & ~FNOINHERIT; _textmode(target_fh) = _textmode(source_fh); _tm_unicode(target_fh) = _tm_unicode(source_fh); return 0; }
// Closes the file associated with the given file handle. On success, returns 0. // On failure, returns -1 and sets errno. extern "C" int __cdecl _close(int const fh) { _CHECK_FH_CLEAR_OSSERR_RETURN(fh, EBADF, -1); _VALIDATE_CLEAR_OSSERR_RETURN((fh >= 0 && (unsigned)fh < (unsigned)_nhandle), EBADF, -1); _VALIDATE_CLEAR_OSSERR_RETURN((_osfile(fh) & FOPEN), EBADF, -1); return __acrt_lowio_lock_fh_and_call(fh, [&]() { if (_osfile(fh) & FOPEN) { return _close_nolock(fh); } else { errno = EBADF; _ASSERTE(("Invalid file descriptor. File possibly closed by a different thread",0)); return -1; } }); }
static int __cdecl _dup2_nolock ( int fh1, int fh2 ) { ULONG dosretval; /* o.s. return code */ intptr_t new_osfhandle; /* * Re-test and take care of case of unopened source handle. This is * necessary only in the multi-thread case where the file have been * closed by another thread before the lock was asserted, but after * the initial test above. */ if ( !(_osfile(fh1) & FOPEN) ) { /* * Source handle isn't open, bail out with an error. * Note that the DuplicateHandle API will not detect this * error since it implies that _osfhnd(fh1) == * INVALID_HANDLE_VALUE, and this is a legal HANDLE value * (it's the HANDLE for the current process). */ errno = EBADF; _doserrno = 0; /* not an OS error */ _ASSERTE(("Invalid file descriptor. File possibly closed by a different thread",0)); return -1; } /* * Take of the case of equal handles. */ if ( fh1 == fh2 ) /* * Since fh1 is known to be open, return 0 indicating success. * This is in conformance with the POSIX specification for * dup2. */ return 0; /* * if fh2 is open, close it. */ if ( _osfile(fh2) & FOPEN ) /* * close the handle. ignore the possibility of an error - an * error simply means that an OS handle value may remain bound * for the duration of the process. Use _close_nolock as we * already own lock */ (void) _close_nolock(fh2); /* Duplicate source file onto target file */ if ( !(DuplicateHandle(GetCurrentProcess(), (HANDLE)_get_osfhandle(fh1), GetCurrentProcess(), (PHANDLE)&new_osfhandle, 0L, TRUE, DUPLICATE_SAME_ACCESS)) ) { dosretval = GetLastError(); } else { _set_osfhnd(fh2, new_osfhandle); dosretval = 0; } if (dosretval) { _dosmaperr(dosretval); return -1; } /* copy the _osfile information, with the FNOINHERIT bit cleared */ _osfile(fh2) = _osfile(fh1) & ~FNOINHERIT; _textmode(fh2) = _textmode(fh1); _tm_unicode(fh2) = _tm_unicode(fh1); return 0; }