2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/crtdll/io/open.c
5 * PURPOSE: Opens a file and translates handles to fileno
6 * PROGRAMER: Boudewijn Dekker
11 // rember to interlock the allocation of fileno when making this thread safe
13 // possibly store extra information at the handle
16 #include <crtdll/io.h>
17 #include <crtdll/fcntl.h>
18 #include <crtdll/sys/stat.h>
19 #include <crtdll/stdlib.h>
20 #include <crtdll/internal/file.h>
21 #include <crtdll/string.h>
22 #include <crtdll/share.h>
24 typedef struct _fileno_modes_type
31 fileno_modes_type
*fileno_modes
= NULL
;
36 char __is_text_file(FILE *p
)
38 if ( p
== NULL
|| fileno_modes
== NULL
)
40 return (!((p
)->_flag
&_IOSTRG
) && (fileno_modes
[(p
)->_file
].mode
&O_TEXT
));
44 int __fileno_alloc(HANDLE hFile
, int mode
);
47 int _open(const char *_path
, int _oflag
,...)
50 DWORD dwDesiredAccess
= 0;
51 DWORD dwShareMode
= 0;
52 DWORD dwCreationDistribution
= 0;
53 DWORD dwFlagsAndAttributes
= 0;
55 if (( _oflag
& S_IREAD
) == S_IREAD
)
56 dwShareMode
= FILE_SHARE_READ
;
57 else if ( ( _oflag
& S_IWRITE
) == S_IWRITE
) {
58 dwShareMode
= FILE_SHARE_READ
| FILE_SHARE_WRITE
;
63 * _O_BINARY Opens file in binary (untranslated) mode. (See fopen for a description of binary mode.)
64 * _O_TEXT Opens file in text (translated) mode. (For more information, see Text and Binary Mode File I/O and fopen.)
66 * _O_APPEND Moves file pointer to end of file before every write operation.
68 if (( _oflag
& _O_RDWR
) == _O_RDWR
)
69 dwDesiredAccess
|= GENERIC_WRITE
|GENERIC_READ
;
70 else if (( _oflag
& O_RDONLY
) == O_RDONLY
)
71 dwDesiredAccess
|= GENERIC_READ
;
72 else if (( _oflag
& _O_WRONLY
) == _O_WRONLY
)
73 dwDesiredAccess
|= GENERIC_WRITE
;
75 if (( _oflag
& S_IREAD
) == S_IREAD
)
76 dwShareMode
|= FILE_SHARE_READ
;
78 if (( _oflag
& S_IWRITE
) == S_IWRITE
)
79 dwShareMode
|= FILE_SHARE_WRITE
;
81 if (( _oflag
& (_O_CREAT
| _O_EXCL
) ) == (_O_CREAT
| _O_EXCL
) )
82 dwCreationDistribution
|= CREATE_NEW
;
84 else if (( _oflag
& O_TRUNC
) == O_TRUNC
) {
85 if (( _oflag
& O_CREAT
) == O_CREAT
)
86 dwCreationDistribution
|= CREATE_ALWAYS
;
87 else if (( _oflag
& O_RDONLY
) != O_RDONLY
)
88 dwCreationDistribution
|= TRUNCATE_EXISTING
;
90 else if (( _oflag
& _O_APPEND
) == _O_APPEND
)
91 dwCreationDistribution
|= OPEN_EXISTING
;
92 else if (( _oflag
& _O_CREAT
) == _O_CREAT
)
93 dwCreationDistribution
|= OPEN_ALWAYS
;
95 dwCreationDistribution
|= OPEN_EXISTING
;
97 if (( _oflag
& _O_RANDOM
) == _O_RANDOM
)
98 dwFlagsAndAttributes
|= FILE_FLAG_RANDOM_ACCESS
;
99 if (( _oflag
& _O_SEQUENTIAL
) == _O_SEQUENTIAL
)
100 dwFlagsAndAttributes
|= FILE_FLAG_SEQUENTIAL_SCAN
;
102 if (( _oflag
& _O_TEMPORARY
) == _O_TEMPORARY
)
103 dwFlagsAndAttributes
|= FILE_FLAG_DELETE_ON_CLOSE
;
105 if (( _oflag
& _O_SHORT_LIVED
) == _O_SHORT_LIVED
)
106 dwFlagsAndAttributes
|= FILE_FLAG_DELETE_ON_CLOSE
;
108 hFile
= CreateFileA(_path
,
112 dwCreationDistribution
,
113 dwFlagsAndAttributes
,
115 if (hFile
== (HANDLE
)-1)
117 return __fileno_alloc(hFile
,_oflag
);
121 int _wopen(const wchar_t *_path
, int _oflag
,...)
124 DWORD dwDesiredAccess
= 0;
125 DWORD dwShareMode
= 0;
126 DWORD dwCreationDistribution
= 0;
127 DWORD dwFlagsAndAttributes
= 0;
129 if (( _oflag
& S_IREAD
) == S_IREAD
)
130 dwShareMode
= FILE_SHARE_READ
;
131 else if ( ( _oflag
& S_IWRITE
) == S_IWRITE
) {
132 dwShareMode
= FILE_SHARE_READ
| FILE_SHARE_WRITE
;
137 * _O_BINARY Opens file in binary (untranslated) mode. (See fopen for a description of binary mode.)
138 * _O_TEXT Opens file in text (translated) mode. (For more information, see Text and Binary Mode File I/O and fopen.)
140 * _O_APPEND Moves file pointer to end of file before every write operation.
142 if (( _oflag
& _O_RDWR
) == _O_RDWR
)
143 dwDesiredAccess
|= GENERIC_WRITE
|GENERIC_READ
| FILE_READ_DATA
|
144 FILE_WRITE_DATA
| FILE_READ_ATTRIBUTES
|
145 FILE_WRITE_ATTRIBUTES
;
146 else if (( _oflag
& O_RDONLY
) == O_RDONLY
)
147 dwDesiredAccess
|= GENERIC_READ
| FILE_READ_DATA
| FILE_READ_ATTRIBUTES
148 | FILE_WRITE_ATTRIBUTES
;
149 else if (( _oflag
& _O_WRONLY
) == _O_WRONLY
)
150 dwDesiredAccess
|= GENERIC_WRITE
| FILE_WRITE_DATA
|
151 FILE_READ_ATTRIBUTES
| FILE_WRITE_ATTRIBUTES
;
153 if (( _oflag
& S_IREAD
) == S_IREAD
)
154 dwShareMode
|= FILE_SHARE_READ
;
156 if (( _oflag
& S_IWRITE
) == S_IWRITE
)
157 dwShareMode
|= FILE_SHARE_WRITE
;
159 if (( _oflag
& (_O_CREAT
| _O_EXCL
) ) == (_O_CREAT
| _O_EXCL
) )
160 dwCreationDistribution
|= CREATE_NEW
;
162 else if (( _oflag
& O_TRUNC
) == O_TRUNC
) {
163 if (( _oflag
& O_CREAT
) == O_CREAT
)
164 dwCreationDistribution
|= CREATE_ALWAYS
;
165 else if (( _oflag
& O_RDONLY
) != O_RDONLY
)
166 dwCreationDistribution
|= TRUNCATE_EXISTING
;
168 else if (( _oflag
& _O_APPEND
) == _O_APPEND
)
169 dwCreationDistribution
|= OPEN_EXISTING
;
170 else if (( _oflag
& _O_CREAT
) == _O_CREAT
)
171 dwCreationDistribution
|= OPEN_ALWAYS
;
173 dwCreationDistribution
|= OPEN_EXISTING
;
175 if (( _oflag
& _O_RANDOM
) == _O_RANDOM
)
176 dwFlagsAndAttributes
|= FILE_FLAG_RANDOM_ACCESS
;
177 if (( _oflag
& _O_SEQUENTIAL
) == _O_SEQUENTIAL
)
178 dwFlagsAndAttributes
|= FILE_FLAG_SEQUENTIAL_SCAN
;
180 if (( _oflag
& _O_TEMPORARY
) == _O_TEMPORARY
)
181 dwFlagsAndAttributes
|= FILE_FLAG_DELETE_ON_CLOSE
;
183 if (( _oflag
& _O_SHORT_LIVED
) == _O_SHORT_LIVED
)
184 dwFlagsAndAttributes
|= FILE_FLAG_DELETE_ON_CLOSE
;
186 hFile
= CreateFileW(_path
,
190 dwCreationDistribution
,
191 dwFlagsAndAttributes
,
193 if (hFile
== (HANDLE
)-1)
195 return __fileno_alloc(hFile
,_oflag
);
200 __fileno_alloc(HANDLE hFile
, int mode
)
203 /* Check for bogus values */
207 for(i
=minfno
;i
<maxfno
;i
++) {
208 if (fileno_modes
[i
].fd
== -1 ) {
209 fileno_modes
[i
].fd
= i
;
210 fileno_modes
[i
].mode
= mode
;
211 fileno_modes
[i
].hFile
= hFile
;
216 /* See if we need to expand the tables. Check this BEFORE it might fail,
217 so that when we hit the count'th request, we've already up'd it. */
220 int oldcount
= maxfno
;
221 fileno_modes_type
*old_fileno_modes
= fileno_modes
;
223 fileno_modes
= (fileno_modes_type
*)malloc(maxfno
* sizeof(fileno_modes_type
));
224 if ( old_fileno_modes
!= NULL
)
225 memcpy(fileno_modes
, old_fileno_modes
, oldcount
* sizeof(fileno_modes_type
));
226 memset(fileno_modes
+ oldcount
, 0, (maxfno
-oldcount
)*sizeof(fileno_modes
));
227 free ( old_fileno_modes
);
230 /* Fill in the value */
231 fileno_modes
[i
].fd
= i
;
232 fileno_modes
[i
].mode
= mode
;
233 fileno_modes
[i
].hFile
= hFile
;
237 void *filehnd(int fileno
)
241 #define STD_AUX_HANDLE 3
242 #define STD_PRINTER_HANDLE 4
247 return GetStdHandle(STD_INPUT_HANDLE
);
249 return GetStdHandle(STD_OUTPUT_HANDLE
);
251 return GetStdHandle(STD_ERROR_HANDLE
);
253 return GetStdHandle(STD_AUX_HANDLE
);
255 return GetStdHandle(STD_PRINTER_HANDLE
);
260 if ( fileno
>= maxfno
)
263 if ( fileno_modes
[fileno
].fd
== -1 )
265 return fileno_modes
[fileno
].hFile
;
268 int __fileno_dup2( int handle1
, int handle2
)
270 if ( handle1
>= maxfno
)
275 if ( handle2
>= maxfno
)
281 memcpy(&fileno_modes
[handle1
],&fileno_modes
[handle2
],sizeof(fileno_modes
));
286 int __fileno_setmode(int _fd
, int _newmode
)
295 m
= fileno_modes
[_fd
].mode
;
296 fileno_modes
[_fd
].mode
= _newmode
;
300 int __fileno_getmode(int _fd
)
308 return fileno_modes
[_fd
].mode
;
313 int __fileno_close(int _fd
)
321 fileno_modes
[_fd
].fd
= -1;
322 fileno_modes
[_fd
].hFile
= (HANDLE
)-1;
326 int _open_osfhandle (void *osfhandle
, int flags
)
328 return __fileno_alloc((HANDLE
)osfhandle
, flags
);
331 void *_get_osfhandle( int fileno
)
333 return filehnd(fileno
);