1 /* $Id: open.c,v 1.13 2002/12/05 15:30:44 robd Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/msvcrt/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>
34 #define STD_AUX_HANDLE 3
35 #define STD_PRINTER_HANDLE 4
37 typedef struct _fileno_modes_type
44 static fileno_modes_type
* fileno_modes
= NULL
;
48 char __is_text_file(FILE* p
)
50 if ( p
== NULL
|| fileno_modes
== NULL
)
52 return (!((p
)->_flag
&_IOSTRG
) && (fileno_modes
[(p
)->_file
].mode
&O_TEXT
));
55 int _open(const char* _path
, int _oflag
,...)
57 #if !defined(NDEBUG) && defined(DBG)
62 DWORD dwDesiredAccess
= 0;
63 DWORD dwShareMode
= 0;
64 DWORD dwCreationDistribution
= 0;
65 DWORD dwFlagsAndAttributes
= 0;
67 SECURITY_ATTRIBUTES sa
= {sizeof(SECURITY_ATTRIBUTES
), NULL
, TRUE
};
69 #if !defined(NDEBUG) && defined(DBG)
70 va_start(arg
, _oflag
);
71 pmode
= va_arg(arg
, int);
74 // DPRINT("_open('%s', %x, (%x))\n", _path, _oflag, pmode);
76 if ((_oflag
& S_IREAD
) == S_IREAD
)
77 dwShareMode
= FILE_SHARE_READ
;
78 else if ((_oflag
& S_IWRITE
) == S_IWRITE
) {
79 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.
89 if ((_oflag
& _O_RDWR
) == _O_RDWR
)
90 dwDesiredAccess
|= GENERIC_WRITE
|GENERIC_READ
;
91 else if ((_oflag
& O_RDONLY
) == O_RDONLY
)
92 dwDesiredAccess
|= GENERIC_READ
;
93 else if ((_oflag
& _O_WRONLY
) == _O_WRONLY
)
94 dwDesiredAccess
|= GENERIC_WRITE
;
96 if ((_oflag
& _O_WRONLY
) == _O_WRONLY
)
97 dwDesiredAccess
|= GENERIC_WRITE
;
98 else if ((_oflag
& _O_RDWR
) == _O_RDWR
)
99 dwDesiredAccess
|= GENERIC_WRITE
|GENERIC_READ
;
100 else //if ((_oflag & O_RDONLY) == O_RDONLY)
101 dwDesiredAccess
|= GENERIC_READ
;
103 if (( _oflag
& S_IREAD
) == S_IREAD
)
104 dwShareMode
|= FILE_SHARE_READ
;
106 if (( _oflag
& S_IWRITE
) == S_IWRITE
)
107 dwShareMode
|= FILE_SHARE_WRITE
;
109 if (( _oflag
& (_O_CREAT
| _O_EXCL
)) == (_O_CREAT
| _O_EXCL
))
110 dwCreationDistribution
|= CREATE_NEW
;
112 else if ((_oflag
& O_TRUNC
) == O_TRUNC
) {
113 if ((_oflag
& O_CREAT
) == O_CREAT
)
114 dwCreationDistribution
|= CREATE_ALWAYS
;
115 else if ((_oflag
& O_RDONLY
) != O_RDONLY
)
116 dwCreationDistribution
|= TRUNCATE_EXISTING
;
118 else if ((_oflag
& _O_APPEND
) == _O_APPEND
)
119 dwCreationDistribution
|= OPEN_EXISTING
;
120 else if ((_oflag
& _O_CREAT
) == _O_CREAT
)
121 dwCreationDistribution
|= OPEN_ALWAYS
;
123 dwCreationDistribution
|= OPEN_EXISTING
;
125 if ((_oflag
& _O_RANDOM
) == _O_RANDOM
)
126 dwFlagsAndAttributes
|= FILE_FLAG_RANDOM_ACCESS
;
127 if ((_oflag
& _O_SEQUENTIAL
) == _O_SEQUENTIAL
)
128 dwFlagsAndAttributes
|= FILE_FLAG_SEQUENTIAL_SCAN
;
129 if ((_oflag
& _O_TEMPORARY
) == _O_TEMPORARY
) {
130 dwFlagsAndAttributes
|= FILE_FLAG_DELETE_ON_CLOSE
;
131 DPRINT("FILE_FLAG_DELETE_ON_CLOSE\n");
133 if ((_oflag
& _O_SHORT_LIVED
) == _O_SHORT_LIVED
) {
134 dwFlagsAndAttributes
|= FILE_FLAG_DELETE_ON_CLOSE
;
135 DPRINT("FILE_FLAG_DELETE_ON_CLOSE\n");
137 if (_oflag
& _O_NOINHERIT
)
138 sa
.bInheritHandle
= FALSE
;
139 hFile
= CreateFileA(_path
,
143 dwCreationDistribution
,
144 dwFlagsAndAttributes
,
146 if (hFile
== (HANDLE
)-1) {
147 dwLastError
= GetLastError();
148 if (dwLastError
== ERROR_ALREADY_EXISTS
) {
149 DPRINT("ERROR_ALREADY_EXISTS\n");
152 DPRINT("%x\n", dwLastError
);
153 __set_errno(ENOFILE
);
158 if (!(_oflag
& (_O_TEXT
|_O_BINARY
))) {
161 return __fileno_alloc(hFile
,_oflag
);
165 int __fileno_alloc(HANDLE hFile
, int mode
)
168 /* Check for bogus values */
172 for (i
= 5; i
< maxfno
; i
++) {
173 if (fileno_modes
[i
].fd
== -1 ) {
174 fileno_modes
[i
].fd
= i
;
175 fileno_modes
[i
].mode
= mode
;
176 fileno_modes
[i
].hFile
= hFile
;
181 /* See if we need to expand the tables. Check this BEFORE it might fail,
182 so that when we hit the count'th request, we've already up'd it. */
184 int oldcount
= maxfno
;
185 fileno_modes_type
* old_fileno_modes
= fileno_modes
;
187 fileno_modes
= (fileno_modes_type
*)malloc(maxfno
* sizeof(fileno_modes_type
));
188 if (old_fileno_modes
!= NULL
) {
189 memcpy(fileno_modes
, old_fileno_modes
, oldcount
* sizeof(fileno_modes_type
));
190 free(old_fileno_modes
);
192 memset(fileno_modes
+ oldcount
, -1, (maxfno
-oldcount
)*sizeof(fileno_modes_type
));
195 /* Fill in the value */
196 fileno_modes
[i
].fd
= i
;
197 fileno_modes
[i
].mode
= mode
;
198 fileno_modes
[i
].hFile
= hFile
;
202 void* filehnd(int fileno
)
204 if (fileno
< 0 || fileno
>= maxfno
|| fileno_modes
[fileno
].fd
== -1) {
207 return fileno_modes
[fileno
].hFile
;
210 int __fileno_setmode(int _fd
, int _newmode
)
213 if (_fd
< 0 || _fd
>= maxfno
) {
217 m
= fileno_modes
[_fd
].mode
;
218 fileno_modes
[_fd
].mode
= _newmode
;
222 int __fileno_getmode(int _fd
)
224 if (_fd
< 0 || _fd
>= maxfno
) {
228 return fileno_modes
[_fd
].mode
;
232 int __fileno_close(int _fd
)
234 if (_fd
< 0 || _fd
>= maxfno
) {
238 fileno_modes
[_fd
].fd
= -1;
239 fileno_modes
[_fd
].hFile
= (HANDLE
)-1;
243 int _open_osfhandle(void* osfhandle
, int flags
)
245 return __fileno_alloc((HANDLE
)osfhandle
, flags
);
248 void* _get_osfhandle( int fileno
)
250 return filehnd(fileno
);
253 int __fileno_dup2(int handle1
, int handle2
)
257 if (handle1
>= maxfno
|| handle1
< 0 || handle2
>= maxfno
|| handle2
< 0) {
261 if (fileno_modes
[handle1
].fd
== -1) {
265 if (handle1
== handle2
)
267 if (fileno_modes
[handle2
].fd
!= -1) {
270 hProcess
= GetCurrentProcess();
271 result
= DuplicateHandle(hProcess
,
272 fileno_modes
[handle1
].hFile
,
274 &fileno_modes
[handle2
].hFile
,
277 DUPLICATE_SAME_ACCESS
);
279 fileno_modes
[handle2
].fd
= handle2
;
280 fileno_modes
[handle2
].mode
= fileno_modes
[handle1
].mode
;
283 SetStdHandle(STD_INPUT_HANDLE
, fileno_modes
[handle2
].hFile
);
286 SetStdHandle(STD_OUTPUT_HANDLE
, fileno_modes
[handle2
].hFile
);
289 SetStdHandle(STD_ERROR_HANDLE
, fileno_modes
[handle2
].hFile
);
292 SetStdHandle(STD_AUX_HANDLE
, fileno_modes
[handle2
].hFile
);
295 SetStdHandle(STD_AUX_HANDLE
, fileno_modes
[handle2
].hFile
);
300 __set_errno(EMFILE
); // Is this the correct error no.?
306 void* malloc(size_t sizeObject
);
308 BOOL
__fileno_init(void)
315 GetStartupInfoA(&StInfo
);
316 if (StInfo
.lpReserved2
&& StInfo
.cbReserved2
>= sizeof(ULONG
)) {
317 count
= *(ULONG
*)StInfo
.lpReserved2
;
319 if (sizeof(ULONG) + count * (sizeof(HANDLE) + sizeof(char)) != StInfo.cbReserved2)
326 while(count
>= maxfno
)
331 // why was this here ???? - robd.
336 //fileno_modes = (fileno_modes_type*)malloc(sizeof(fileno_modes_type) * maxfno);
337 fileno_modes
= malloc(sizeof(fileno_modes_type
) * maxfno
);
338 if (fileno_modes
== NULL
) {
341 memset(fileno_modes
, -1, sizeof(fileno_modes_type
) * maxfno
);
343 pFile
= (HANDLE
*)(StInfo
.lpReserved2
+ sizeof(ULONG
) + count
* sizeof(char));
344 pmode
= (char*)(StInfo
.lpReserved2
+ sizeof(ULONG
));
345 for (i
= 0; i
< count
; i
++) {
346 if (*pFile
!= INVALID_HANDLE_VALUE
) {
347 fileno_modes
[i
].fd
= i
;
348 fileno_modes
[i
].mode
= ((*pmode
<< 8) & (_O_TEXT
|_O_BINARY
)) | (*pmode
& _O_ACCMODE
);
349 fileno_modes
[i
].hFile
= *pFile
;
355 if (fileno_modes
[0].fd
== -1) {
356 fileno_modes
[0].fd
= 0;
357 fileno_modes
[0].hFile
= GetStdHandle(STD_INPUT_HANDLE
);
358 fileno_modes
[0].mode
= _O_RDONLY
|_O_TEXT
;
360 if (fileno_modes
[1].fd
== -1) {
361 fileno_modes
[1].fd
= 1;
362 fileno_modes
[1].hFile
= GetStdHandle(STD_OUTPUT_HANDLE
);
363 fileno_modes
[1].mode
= _O_WRONLY
|_O_TEXT
;
365 if (fileno_modes
[2].fd
== -1) {
366 fileno_modes
[2].fd
= 2;
367 fileno_modes
[2].hFile
= GetStdHandle(STD_ERROR_HANDLE
);
368 fileno_modes
[2].mode
= _O_WRONLY
|_O_TEXT
;
370 if (fileno_modes
[3].fd
== -1) {
371 fileno_modes
[3].fd
= 3;
372 fileno_modes
[3].hFile
= GetStdHandle(STD_AUX_HANDLE
);
373 fileno_modes
[3].mode
= _O_WRONLY
|_O_TEXT
;
375 if (fileno_modes
[4].fd
== -1) {
376 fileno_modes
[4].fd
= 4;
377 fileno_modes
[4].hFile
= GetStdHandle(STD_PRINTER_HANDLE
);
378 fileno_modes
[4].mode
= _O_WRONLY
|_O_TEXT
;