3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/crtdll/io/open.c
6 * PURPOSE: Opens a file and translates handles to fileno
7 * PROGRAMER: Boudewijn Dekker
12 // rember to interlock the allocation of fileno when making this thread safe
14 // possibly store extra information at the handle
17 #if !defined(NDEBUG) && defined(DBG)
18 #include <msvcrt/stdarg.h>
20 #include <msvcrt/io.h>
21 #include <msvcrt/fcntl.h>
22 #include <msvcrt/sys/stat.h>
23 #include <msvcrt/stdlib.h>
24 #include <msvcrt/internal/file.h>
25 #include <msvcrt/string.h>
26 #include <msvcrt/share.h>
27 #include <msvcrt/errno.h>
30 #include <msvcrt/msvcrtdbg.h>
32 #define STD_AUX_HANDLE 3
33 #define STD_PRINTER_HANDLE 4
35 typedef struct _fileno_modes_type
42 fileno_modes_type *fileno_modes = NULL;
46 char __is_text_file(FILE *p)
48 if ( p == NULL || fileno_modes == NULL )
50 return (!((p)->_flag&_IOSTRG) && (fileno_modes[(p)->_file].mode&O_TEXT));
54 int _open(const char *_path, int _oflag,...)
56 #if !defined(NDEBUG) && defined(DBG)
61 DWORD dwDesiredAccess = 0;
62 DWORD dwShareMode = 0;
63 DWORD dwCreationDistribution = 0;
64 DWORD dwFlagsAndAttributes = 0;
66 SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
68 #if !defined(NDEBUG) && defined(DBG)
69 va_start(arg, _oflag);
70 pmode = va_arg(arg, int);
73 DPRINT("_open('%s', %x, (%x))\n", _path, _oflag, pmode);
75 if (( _oflag & S_IREAD ) == S_IREAD)
76 dwShareMode = FILE_SHARE_READ;
77 else if ( ( _oflag & S_IWRITE) == S_IWRITE ) {
78 dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
83 * _O_BINARY Opens file in binary (untranslated) mode. (See fopen for a description of binary mode.)
84 * _O_TEXT Opens file in text (translated) mode. (For more information, see Text and Binary Mode File I/O and fopen.)
86 * _O_APPEND Moves file pointer to end of file before every write operation.
88 if (( _oflag & _O_RDWR ) == _O_RDWR )
89 dwDesiredAccess |= GENERIC_WRITE|GENERIC_READ ;
90 else if (( _oflag & O_RDONLY ) == O_RDONLY )
91 dwDesiredAccess |= GENERIC_READ ;
92 else if (( _oflag & _O_WRONLY ) == _O_WRONLY )
93 dwDesiredAccess |= GENERIC_WRITE ;
95 if (( _oflag & S_IREAD ) == S_IREAD )
96 dwShareMode |= FILE_SHARE_READ;
98 if (( _oflag & S_IWRITE ) == S_IWRITE )
99 dwShareMode |= FILE_SHARE_WRITE;
101 if (( _oflag & (_O_CREAT | _O_EXCL ) ) == (_O_CREAT | _O_EXCL) )
102 dwCreationDistribution |= CREATE_NEW;
104 else if (( _oflag & O_TRUNC ) == O_TRUNC ) {
105 if (( _oflag & O_CREAT ) == O_CREAT )
106 dwCreationDistribution |= CREATE_ALWAYS;
107 else if (( _oflag & O_RDONLY ) != O_RDONLY )
108 dwCreationDistribution |= TRUNCATE_EXISTING;
110 else if (( _oflag & _O_APPEND ) == _O_APPEND )
111 dwCreationDistribution |= OPEN_EXISTING;
112 else if (( _oflag & _O_CREAT ) == _O_CREAT )
113 dwCreationDistribution |= OPEN_ALWAYS;
115 dwCreationDistribution |= OPEN_EXISTING;
117 if (( _oflag & _O_RANDOM ) == _O_RANDOM )
118 dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
119 if (( _oflag & _O_SEQUENTIAL ) == _O_SEQUENTIAL )
120 dwFlagsAndAttributes |= FILE_FLAG_SEQUENTIAL_SCAN;
122 if (( _oflag & _O_TEMPORARY ) == _O_TEMPORARY )
124 dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE;
125 DPRINT("FILE_FLAG_DELETE_ON_CLOSE\n");
128 if (( _oflag & _O_SHORT_LIVED ) == _O_SHORT_LIVED )
130 dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE;
131 DPRINT("FILE_FLAG_DELETE_ON_CLOSE\n");
134 if (_oflag & _O_NOINHERIT)
135 sa.bInheritHandle = FALSE;
137 hFile = CreateFileA(_path,
141 dwCreationDistribution,
142 dwFlagsAndAttributes,
144 if (hFile == (HANDLE)-1)
146 dwLastError = GetLastError();
147 if (dwLastError == ERROR_ALREADY_EXISTS)
149 DPRINT("ERROR_ALREADY_EXISTS\n");
154 DPRINT("%x\n", dwLastError);
155 __set_errno(ENOFILE);
160 if (!(_oflag & (_O_TEXT|_O_BINARY)))
164 return __fileno_alloc(hFile,_oflag);
168 int _wopen(const wchar_t *_path, int _oflag,...)
170 #if !defined(NDEBUG) && defined(DBG)
175 DWORD dwDesiredAccess = 0;
176 DWORD dwShareMode = 0;
177 DWORD dwCreationDistribution = 0;
178 DWORD dwFlagsAndAttributes = 0;
179 SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
181 #if !defined(NDEBUG) && defined(DBG)
182 va_start(arg, _oflag);
183 pmode = va_arg(arg, int);
186 DPRINT("_wopen('%S', %x, (%x))\n", _path, _oflag, pmode);
188 if (( _oflag & S_IREAD ) == S_IREAD)
189 dwShareMode = FILE_SHARE_READ;
190 else if ( ( _oflag & S_IWRITE) == S_IWRITE ) {
191 dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
196 * _O_BINARY Opens file in binary (untranslated) mode. (See fopen for a description of binary mode.)
197 * _O_TEXT Opens file in text (translated) mode. (For more information, see Text and Binary Mode File I/O and fopen.)
199 * _O_APPEND Moves file pointer to end of file before every write operation.
201 if (( _oflag & _O_RDWR ) == _O_RDWR )
202 dwDesiredAccess |= GENERIC_WRITE|GENERIC_READ | FILE_READ_DATA |
203 FILE_WRITE_DATA | FILE_READ_ATTRIBUTES |
204 FILE_WRITE_ATTRIBUTES;
205 else if (( _oflag & O_RDONLY ) == O_RDONLY )
206 dwDesiredAccess |= GENERIC_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES
207 | FILE_WRITE_ATTRIBUTES;
208 else if (( _oflag & _O_WRONLY ) == _O_WRONLY )
209 dwDesiredAccess |= GENERIC_WRITE | FILE_WRITE_DATA |
210 FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES;
212 if (( _oflag & S_IREAD ) == S_IREAD )
213 dwShareMode |= FILE_SHARE_READ;
215 if (( _oflag & S_IWRITE ) == S_IWRITE )
216 dwShareMode |= FILE_SHARE_WRITE;
218 if (( _oflag & (_O_CREAT | _O_EXCL ) ) == (_O_CREAT | _O_EXCL) )
219 dwCreationDistribution |= CREATE_NEW;
221 else if (( _oflag & O_TRUNC ) == O_TRUNC ) {
222 if (( _oflag & O_CREAT ) == O_CREAT )
223 dwCreationDistribution |= CREATE_ALWAYS;
224 else if (( _oflag & O_RDONLY ) != O_RDONLY )
225 dwCreationDistribution |= TRUNCATE_EXISTING;
227 else if (( _oflag & _O_APPEND ) == _O_APPEND )
228 dwCreationDistribution |= OPEN_EXISTING;
229 else if (( _oflag & _O_CREAT ) == _O_CREAT )
230 dwCreationDistribution |= OPEN_ALWAYS;
232 dwCreationDistribution |= OPEN_EXISTING;
234 if (( _oflag & _O_RANDOM ) == _O_RANDOM )
235 dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
236 if (( _oflag & _O_SEQUENTIAL ) == _O_SEQUENTIAL )
237 dwFlagsAndAttributes |= FILE_FLAG_SEQUENTIAL_SCAN;
239 if (( _oflag & _O_TEMPORARY ) == _O_TEMPORARY )
240 dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE;
242 if (( _oflag & _O_SHORT_LIVED ) == _O_SHORT_LIVED )
243 dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE;
245 if (_oflag & _O_NOINHERIT)
246 sa.bInheritHandle = FALSE;
248 hFile = CreateFileW(_path,
252 dwCreationDistribution,
253 dwFlagsAndAttributes,
255 if (hFile == (HANDLE)-1)
257 return __fileno_alloc(hFile,_oflag);
262 __fileno_alloc(HANDLE hFile, int mode)
265 /* Check for bogus values */
269 for(i=5;i<maxfno;i++) {
270 if (fileno_modes[i].fd == -1 ) {
271 fileno_modes[i].fd = i;
272 fileno_modes[i].mode = mode;
273 fileno_modes[i].hFile = hFile;
278 /* See if we need to expand the tables. Check this BEFORE it might fail,
279 so that when we hit the count'th request, we've already up'd it. */
282 int oldcount = maxfno;
283 fileno_modes_type *old_fileno_modes = fileno_modes;
285 fileno_modes = (fileno_modes_type *)malloc(maxfno * sizeof(fileno_modes_type));
286 if ( old_fileno_modes != NULL )
288 memcpy(fileno_modes, old_fileno_modes, oldcount * sizeof(fileno_modes_type));
289 free ( old_fileno_modes );
291 memset(fileno_modes + oldcount, -1, (maxfno-oldcount)*sizeof(fileno_modes_type));
294 /* Fill in the value */
295 fileno_modes[i].fd = i;
296 fileno_modes[i].mode = mode;
297 fileno_modes[i].hFile = hFile;
301 void *filehnd(int fileno)
303 if ( fileno < 0 || fileno>= maxfno || fileno_modes[fileno].fd == -1)
307 return fileno_modes[fileno].hFile;
310 int __fileno_dup2( int handle1, int handle2 )
314 if (handle1 >= maxfno || handle1 < 0 || handle2 >= maxfno || handle2 < 0 )
319 if (fileno_modes[handle1].fd == -1)
324 if (handle1 == handle2)
326 if (fileno_modes[handle2].fd != -1)
330 hProcess = GetCurrentProcess();
331 result = DuplicateHandle(hProcess,
332 fileno_modes[handle1].hFile,
334 &fileno_modes[handle2].hFile,
337 DUPLICATE_SAME_ACCESS);
340 fileno_modes[handle2].fd = handle2;
341 fileno_modes[handle2].mode = fileno_modes[handle1].mode;
345 SetStdHandle(STD_INPUT_HANDLE, fileno_modes[handle2].hFile);
348 SetStdHandle(STD_OUTPUT_HANDLE, fileno_modes[handle2].hFile);
351 SetStdHandle(STD_ERROR_HANDLE, fileno_modes[handle2].hFile);
354 SetStdHandle(STD_AUX_HANDLE, fileno_modes[handle2].hFile);
357 SetStdHandle(STD_AUX_HANDLE, fileno_modes[handle2].hFile);
364 __set_errno(EMFILE); // Is this the correct error no.?
369 int __fileno_setmode(int _fd, int _newmode)
372 if ( _fd < 0 || _fd >= maxfno )
378 m = fileno_modes[_fd].mode;
379 fileno_modes[_fd].mode = _newmode;
383 int __fileno_getmode(int _fd)
385 if ( _fd < 0 || _fd >= maxfno )
390 return fileno_modes[_fd].mode;
394 int __fileno_close(int _fd)
396 if ( _fd < 0 || _fd >= maxfno )
402 fileno_modes[_fd].fd = -1;
403 fileno_modes[_fd].hFile = (HANDLE)-1;
407 int _open_osfhandle (void *osfhandle, int flags )
409 return __fileno_alloc((HANDLE)osfhandle, flags);
412 void *_get_osfhandle( int fileno )
414 return filehnd(fileno);
417 void __fileno_init(void)
424 GetStartupInfoA(&StInfo);
426 if (StInfo.lpReserved2 && StInfo.cbReserved2 >= sizeof(ULONG))
428 count = *(ULONG*)StInfo.lpReserved2;
430 if (sizeof(ULONG) + count * (sizeof(HANDLE) + sizeof(char)) != StInfo.cbReserved2)
437 while(count >= maxfno)
440 fileno_modes = (fileno_modes_type*)malloc(sizeof(fileno_modes_type) * maxfno);
441 memset(fileno_modes, -1, sizeof(fileno_modes_type) * maxfno);
445 pFile = (HANDLE*)(StInfo.lpReserved2 + sizeof(ULONG) + count * sizeof(char));
446 pmode = (char*)(StInfo.lpReserved2 + sizeof(ULONG));
447 for (i = 0; i < count; i++)
449 if (*pFile != INVALID_HANDLE_VALUE)
451 fileno_modes[i].fd = i;
452 fileno_modes[i].mode = ((*pmode << 8) & (_O_TEXT|_O_BINARY)) | (*pmode & _O_ACCMODE);
453 fileno_modes[i].hFile = *pFile;
460 if (fileno_modes[0].fd == -1)
462 fileno_modes[0].fd = 0;
463 fileno_modes[0].hFile = GetStdHandle(STD_INPUT_HANDLE);
464 fileno_modes[0].mode = _O_RDONLY|_O_TEXT;
466 if (fileno_modes[1].fd == -1)
468 fileno_modes[1].fd = 1;
469 fileno_modes[1].hFile = GetStdHandle(STD_OUTPUT_HANDLE);
470 fileno_modes[1].mode = _O_WRONLY|_O_TEXT;
472 if (fileno_modes[2].fd == -1)
474 fileno_modes[2].fd = 2;
475 fileno_modes[2].hFile = GetStdHandle(STD_ERROR_HANDLE);
476 fileno_modes[2].mode = _O_WRONLY|_O_TEXT;
478 if (fileno_modes[3].fd == -1)
480 fileno_modes[3].fd = 3;
481 fileno_modes[3].hFile = GetStdHandle(STD_AUX_HANDLE);
482 fileno_modes[3].mode = _O_WRONLY|_O_TEXT;
484 if (fileno_modes[4].fd == -1)
486 fileno_modes[4].fd = 4;
487 fileno_modes[4].hFile = GetStdHandle(STD_PRINTER_HANDLE);
488 fileno_modes[4].mode = _O_WRONLY|_O_TEXT;