ReactOS 0.4.16-dev-822-gbcedb53
dup2.cpp
Go to the documentation of this file.
1//
2// dup2.cpp
3//
4// Copyright (c) Microsoft Corporation. All rights reserved.
5//
6// Defines _dup2() and _dup2_nolock, which duplicate lowio file handles
7//
10
11static int __cdecl _dup2_nolock_internal(int const source_fh, int const target_fh, __crt_cached_ptd_host& ptd) throw()
12{
13 if ((_osfile(source_fh) & FOPEN) == 0)
14 {
15 // If the source handle is not open, return an error. Noe that the
16 // DuplicateHandle API will not detect this error, because it implies
17 // that _osfhnd(source_fh) == INVALID_HANDLE_VALUE, and this is a
18 // legal HANDLE value to be duplicated.
19 ptd.get_errno().set(EBADF);
20 ptd.get_doserrno().set(0);
21 _ASSERTE(("Invalid file descriptor. File possibly closed by a different thread",0));
22 return -1;
23 }
24
25 // Duplicate the source file onto the target file:
26 intptr_t new_osfhandle;
27
30 reinterpret_cast<HANDLE>(_get_osfhandle(source_fh)),
32 &reinterpret_cast<HANDLE&>(new_osfhandle),
33 0,
34 TRUE,
36
37 if (!result)
38 {
40 return -1;
41 }
42
43 // If the target is open, close it once we know the OS handle was duplicated successfully.
44 // We ignore the possibility of an error here: an error simply means that the OS handle
45 // value may remain bound for the duration of the process.
46 if (_osfile(target_fh) & FOPEN)
47 {
48 _close_nolock_internal(target_fh, ptd);
49 }
50
51 __acrt_lowio_set_os_handle(target_fh, new_osfhandle);
52
53 // Copy the _osfile information, with the FNOINHERIT bit cleared:
54 _osfile(target_fh) = _osfile(source_fh) & ~FNOINHERIT;
55 _textmode(target_fh) = _textmode(source_fh);
56 _tm_unicode(target_fh) = _tm_unicode(source_fh);
57
58 return 0;
59}
60
61static int __cdecl _dup2_internal(int const source_fh, int const target_fh, __crt_cached_ptd_host& ptd) throw()
62{
64 _UCRT_VALIDATE_CLEAR_OSSERR_RETURN(ptd, (source_fh >= 0 && (unsigned)source_fh < (unsigned)_nhandle), EBADF, -1);
67 _UCRT_VALIDATE_CLEAR_OSSERR_RETURN(ptd, ((unsigned)target_fh < _NHANDLE_), EBADF, -1);
68
69 // Make sure there is an __crt_lowio_handle_data struct corresponding to the target_fh:
70 if (target_fh >= _nhandle && __acrt_lowio_ensure_fh_exists(target_fh) != 0)
71 {
72 return -1;
73 }
74
75 // If the source and target are the same, return success (we've already
76 // verified that the file handle is open, above). This is for conformance
77 // with the POSIX specification for dup2.
78 if (source_fh == target_fh)
79 {
80 return 0;
81 }
82
83 // Obtain the two file handle locks. In order to prevent deadlock, we
84 // always obtain the lock for the lower-numbered file handle first:
85 if (source_fh < target_fh)
86 {
87 __acrt_lowio_lock_fh(source_fh);
88 __acrt_lowio_lock_fh(target_fh);
89 }
90 else if (source_fh > target_fh)
91 {
92 __acrt_lowio_lock_fh(target_fh);
93 __acrt_lowio_lock_fh(source_fh);
94 }
95
96 int result = 0;
97
98 __try
99 {
100 result = _dup2_nolock_internal(source_fh, target_fh, ptd);
101 }
103 {
104 // The order in which we unlock the file handles does not matter:
105 __acrt_lowio_unlock_fh(source_fh);
106 __acrt_lowio_unlock_fh(target_fh);
107 }
109 return result;
110}
111
112// _dup2() makes the target file handle a duplicate of the source file handle,
113// so that both handles refer to the same file. If the target handle is open
114// upon entry, it is closed so that it is not leaked.
115//
116// Returns 0 if successful; returns -1 and sets errno on failure.
117extern "C" int __cdecl _dup2(int const source_fh, int const target_fh)
118{
119 __crt_cached_ptd_host ptd;
120 return _dup2_internal(source_fh, target_fh, ptd);
121}
#define EBADF
Definition: acclib.h:82
#define __cdecl
Definition: accygwin.h:79
int _nhandle
Definition: ioinit.cpp:34
_Check_return_opt_ int __cdecl _close_nolock_internal(_In_ int _FileHandle, _Inout_ __crt_cached_ptd_host &_Ptd)
int __cdecl __acrt_lowio_set_os_handle(int, intptr_t)
Definition: osfinfo.cpp:195
_Check_return_opt_ errno_t __cdecl __acrt_lowio_ensure_fh_exists(_In_ int _FileHandle)
#define _NHANDLE_
void __cdecl __acrt_lowio_lock_fh(_In_ int _FileHandle)
void __cdecl __acrt_lowio_unlock_fh(_In_ int _FileHandle)
#define _UCRT_VALIDATE_CLEAR_OSSERR_RETURN(ptd, expr, errorcode, retexpr)
#define _UCRT_CHECK_FH_CLEAR_OSSERR_RETURN(ptd, handle, errorcode, retexpr)
#define _ASSERTE(expr)
Definition: crtdbg.h:114
_In_ size_t const _In_ int _In_ bool const _In_ unsigned const _In_ __acrt_rounding_mode const _Inout_ __crt_cached_ptd_host & ptd
Definition: cvt.cpp:355
#define TRUE
Definition: types.h:120
#define GetCurrentProcess()
Definition: compat.h:759
BOOL WINAPI DuplicateHandle(IN HANDLE hSourceProcessHandle, IN HANDLE hSourceHandle, IN HANDLE hTargetProcessHandle, OUT LPHANDLE lpTargetHandle, IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN DWORD dwOptions)
Definition: handle.c:149
int __cdecl _dup2(int const source_fh, int const target_fh)
Definition: dup2.cpp:117
static int __cdecl _dup2_internal(int const source_fh, int const target_fh, __crt_cached_ptd_host &ptd)
Definition: dup2.cpp:61
static int __cdecl _dup2_nolock_internal(int const source_fh, int const target_fh, __crt_cached_ptd_host &ptd)
Definition: dup2.cpp:11
void __cdecl __acrt_errno_map_os_error_ptd(unsigned long const oserrno, __crt_cached_ptd_host &ptd)
Definition: errno.cpp:97
unsigned int BOOL
Definition: ntddk_ex.h:94
#define FOPEN
GLuint64EXT * result
Definition: glext.h:11304
#define __try
Definition: pseh2_64.h:172
#define __endtry
Definition: pseh2_64.h:175
#define __finally
Definition: pseh2_64.h:174
_CRTIMP intptr_t __cdecl _get_osfhandle(_In_ int _FileHandle)
#define _osfile(i)
Definition: internal.h:72
#define _tm_unicode(i)
Definition: internal.h:75
#define _textmode(i)
Definition: internal.h:74
int intptr_t
Definition: vcruntime.h:134
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define DUPLICATE_SAME_ACCESS