d3866eb815c62980b6cf28e56acc4adb6b9f6b48
[reactos.git] / reactos / lib / msvcrt / io / open.c
1 /* $Id: open.c,v 1.12 2002/11/24 18:42:22 robd Exp $
2 *
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
8 * UPDATE HISTORY:
9 * 28/12/98: Created
10 */
11
12 // rember to interlock the allocation of fileno when making this thread safe
13
14 // possibly store extra information at the handle
15
16 #include <windows.h>
17 #if !defined(NDEBUG) && defined(DBG)
18 #include <msvcrt/stdarg.h>
19 #endif
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>
28
29 #define NDEBUG
30 #include <msvcrt/msvcrtdbg.h>
31
32 #define STD_AUX_HANDLE 3
33 #define STD_PRINTER_HANDLE 4
34
35 typedef struct _fileno_modes_type
36 {
37 HANDLE hFile;
38 int mode;
39 int fd;
40 } fileno_modes_type;
41
42 static fileno_modes_type *fileno_modes = NULL;
43
44 int maxfno = 0;
45
46 char __is_text_file(FILE *p)
47 {
48 if ( p == NULL || fileno_modes == NULL )
49 return FALSE;
50 return (!((p)->_flag&_IOSTRG) && (fileno_modes[(p)->_file].mode&O_TEXT));
51 }
52
53 int _open(const char* _path, int _oflag,...)
54 {
55 #if !defined(NDEBUG) && defined(DBG)
56 va_list arg;
57 int pmode;
58 #endif
59 HANDLE hFile;
60 DWORD dwDesiredAccess = 0;
61 DWORD dwShareMode = 0;
62 DWORD dwCreationDistribution = 0;
63 DWORD dwFlagsAndAttributes = 0;
64 DWORD dwLastError;
65 SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
66
67 #if !defined(NDEBUG) && defined(DBG)
68 va_start(arg, _oflag);
69 pmode = va_arg(arg, int);
70 #endif
71
72 // DPRINT("_open('%s', %x, (%x))\n", _path, _oflag, pmode);
73
74 if (( _oflag & S_IREAD ) == S_IREAD)
75 dwShareMode = FILE_SHARE_READ;
76 else if ( ( _oflag & S_IWRITE) == S_IWRITE ) {
77 dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
78 }
79
80 /*
81 *
82 * _O_BINARY Opens file in binary (untranslated) mode. (See fopen for a description of binary mode.)
83 * _O_TEXT Opens file in text (translated) mode. (For more information, see Text and Binary Mode File I/O and fopen.)
84 *
85 * _O_APPEND Moves file pointer to end of file before every write operation.
86 */
87 if (( _oflag & _O_RDWR ) == _O_RDWR )
88 dwDesiredAccess |= GENERIC_WRITE|GENERIC_READ ;
89 else if (( _oflag & O_RDONLY ) == O_RDONLY )
90 dwDesiredAccess |= GENERIC_READ ;
91 else if (( _oflag & _O_WRONLY ) == _O_WRONLY )
92 dwDesiredAccess |= GENERIC_WRITE ;
93
94 if (( _oflag & S_IREAD ) == S_IREAD )
95 dwShareMode |= FILE_SHARE_READ;
96
97 if (( _oflag & S_IWRITE ) == S_IWRITE )
98 dwShareMode |= FILE_SHARE_WRITE;
99
100 if (( _oflag & (_O_CREAT | _O_EXCL ) ) == (_O_CREAT | _O_EXCL) )
101 dwCreationDistribution |= CREATE_NEW;
102
103 else if (( _oflag & O_TRUNC ) == O_TRUNC ) {
104 if (( _oflag & O_CREAT ) == O_CREAT )
105 dwCreationDistribution |= CREATE_ALWAYS;
106 else if (( _oflag & O_RDONLY ) != O_RDONLY )
107 dwCreationDistribution |= TRUNCATE_EXISTING;
108 }
109 else if (( _oflag & _O_APPEND ) == _O_APPEND )
110 dwCreationDistribution |= OPEN_EXISTING;
111 else if (( _oflag & _O_CREAT ) == _O_CREAT )
112 dwCreationDistribution |= OPEN_ALWAYS;
113 else
114 dwCreationDistribution |= OPEN_EXISTING;
115
116 if (( _oflag & _O_RANDOM ) == _O_RANDOM )
117 dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
118 if (( _oflag & _O_SEQUENTIAL ) == _O_SEQUENTIAL )
119 dwFlagsAndAttributes |= FILE_FLAG_SEQUENTIAL_SCAN;
120
121 if (( _oflag & _O_TEMPORARY ) == _O_TEMPORARY )
122 {
123 dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE;
124 DPRINT("FILE_FLAG_DELETE_ON_CLOSE\n");
125 }
126
127 if (( _oflag & _O_SHORT_LIVED ) == _O_SHORT_LIVED )
128 {
129 dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE;
130 DPRINT("FILE_FLAG_DELETE_ON_CLOSE\n");
131 }
132
133 if (_oflag & _O_NOINHERIT)
134 sa.bInheritHandle = FALSE;
135
136 hFile = CreateFileA(_path,
137 dwDesiredAccess,
138 dwShareMode,
139 &sa,
140 dwCreationDistribution,
141 dwFlagsAndAttributes,
142 NULL);
143 if (hFile == (HANDLE)-1)
144 {
145 dwLastError = GetLastError();
146 if (dwLastError == ERROR_ALREADY_EXISTS)
147 {
148 DPRINT("ERROR_ALREADY_EXISTS\n");
149 __set_errno(EEXIST);
150 }
151 else
152 {
153 DPRINT("%x\n", dwLastError);
154 __set_errno(ENOFILE);
155 }
156 return -1;
157 }
158 DPRINT("OK\n");
159 if (!(_oflag & (_O_TEXT|_O_BINARY)))
160 {
161 _oflag |= _fmode;
162 }
163 return __fileno_alloc(hFile,_oflag);
164 }
165
166
167 int
168 __fileno_alloc(HANDLE hFile, int mode)
169 {
170 int i;
171 /* Check for bogus values */
172 if (hFile < 0)
173 return -1;
174
175 for(i=5;i<maxfno;i++) {
176 if (fileno_modes[i].fd == -1 ) {
177 fileno_modes[i].fd = i;
178 fileno_modes[i].mode = mode;
179 fileno_modes[i].hFile = hFile;
180 return i;
181 }
182 }
183
184 /* See if we need to expand the tables. Check this BEFORE it might fail,
185 so that when we hit the count'th request, we've already up'd it. */
186 if ( i == maxfno)
187 {
188 int oldcount = maxfno;
189 fileno_modes_type *old_fileno_modes = fileno_modes;
190 maxfno += 255;
191 fileno_modes = (fileno_modes_type *)malloc(maxfno * sizeof(fileno_modes_type));
192 if ( old_fileno_modes != NULL )
193 {
194 memcpy(fileno_modes, old_fileno_modes, oldcount * sizeof(fileno_modes_type));
195 free ( old_fileno_modes );
196 }
197 memset(fileno_modes + oldcount, -1, (maxfno-oldcount)*sizeof(fileno_modes_type));
198 }
199
200 /* Fill in the value */
201 fileno_modes[i].fd = i;
202 fileno_modes[i].mode = mode;
203 fileno_modes[i].hFile = hFile;
204 return i;
205 }
206
207 void *filehnd(int fileno)
208 {
209 if ( fileno < 0 || fileno>= maxfno || fileno_modes[fileno].fd == -1)
210 {
211 return (void *)-1;
212 }
213 return fileno_modes[fileno].hFile;
214 }
215
216 int __fileno_setmode(int _fd, int _newmode)
217 {
218 int m;
219 if ( _fd < 0 || _fd >= maxfno )
220 {
221 __set_errno(EBADF);
222 return -1;
223 }
224
225 m = fileno_modes[_fd].mode;
226 fileno_modes[_fd].mode = _newmode;
227 return m;
228 }
229
230 int __fileno_getmode(int _fd)
231 {
232 if ( _fd < 0 || _fd >= maxfno )
233 {
234 __set_errno(EBADF);
235 return -1;
236 }
237 return fileno_modes[_fd].mode;
238
239 }
240
241 int __fileno_close(int _fd)
242 {
243 if ( _fd < 0 || _fd >= maxfno )
244 {
245 __set_errno(EBADF);
246 return -1;
247 }
248
249 fileno_modes[_fd].fd = -1;
250 fileno_modes[_fd].hFile = (HANDLE)-1;
251 return 0;
252 }
253
254 int _open_osfhandle (void *osfhandle, int flags )
255 {
256 return __fileno_alloc((HANDLE)osfhandle, flags);
257 }
258
259 void *_get_osfhandle( int fileno )
260 {
261 return filehnd(fileno);
262 }
263
264 int __fileno_dup2( int handle1, int handle2 )
265 {
266 HANDLE hProcess;
267 BOOL result;
268 if (handle1 >= maxfno || handle1 < 0 || handle2 >= maxfno || handle2 < 0 )
269 {
270 __set_errno(EBADF);
271 return -1;
272 }
273 if (fileno_modes[handle1].fd == -1)
274 {
275 __set_errno(EBADF);
276 return -1;
277 }
278 if (handle1 == handle2)
279 return handle1;
280 if (fileno_modes[handle2].fd != -1)
281 {
282 _close(handle2);
283 }
284 hProcess = GetCurrentProcess();
285 result = DuplicateHandle(hProcess,
286 fileno_modes[handle1].hFile,
287 hProcess,
288 &fileno_modes[handle2].hFile,
289 0,
290 TRUE,
291 DUPLICATE_SAME_ACCESS);
292 if (result)
293 {
294 fileno_modes[handle2].fd = handle2;
295 fileno_modes[handle2].mode = fileno_modes[handle1].mode;
296 switch (handle2)
297 {
298 case 0:
299 SetStdHandle(STD_INPUT_HANDLE, fileno_modes[handle2].hFile);
300 break;
301 case 1:
302 SetStdHandle(STD_OUTPUT_HANDLE, fileno_modes[handle2].hFile);
303 break;
304 case 2:
305 SetStdHandle(STD_ERROR_HANDLE, fileno_modes[handle2].hFile);
306 break;
307 case 3:
308 SetStdHandle(STD_AUX_HANDLE, fileno_modes[handle2].hFile);
309 break;
310 case 4:
311 SetStdHandle(STD_AUX_HANDLE, fileno_modes[handle2].hFile);
312 break;
313 }
314 return handle1;
315 }
316 else
317 {
318 __set_errno(EMFILE); // Is this the correct error no.?
319 return -1;
320 }
321 }
322
323
324 void* malloc(size_t sizeObject);
325
326 BOOL __fileno_init(void)
327 {
328 ULONG count = 0, i;
329 HANDLE *pFile;
330 char* pmode;
331 STARTUPINFO StInfo;
332
333 GetStartupInfoA(&StInfo);
334
335 if (StInfo.lpReserved2 && StInfo.cbReserved2 >= sizeof(ULONG))
336 {
337 count = *(ULONG*)StInfo.lpReserved2;
338 /*
339 if (sizeof(ULONG) + count * (sizeof(HANDLE) + sizeof(char)) != StInfo.cbReserved2)
340 {
341 count = 0;
342 }
343 */
344 }
345 maxfno = 255;
346 while(count >= maxfno)
347 maxfno += 255;
348
349 {
350 // why was this here ???? - robd.
351 //int result;
352 //result = malloc(50);
353
354 }
355 //fileno_modes = (fileno_modes_type*)malloc(sizeof(fileno_modes_type) * maxfno);
356 fileno_modes = malloc(sizeof(fileno_modes_type) * maxfno);
357 if (fileno_modes == NULL) {
358 return FALSE;
359 }
360 memset(fileno_modes, -1, sizeof(fileno_modes_type) * maxfno);
361
362 if (count)
363 {
364 pFile = (HANDLE*)(StInfo.lpReserved2 + sizeof(ULONG) + count * sizeof(char));
365 pmode = (char*)(StInfo.lpReserved2 + sizeof(ULONG));
366 for (i = 0; i < count; i++)
367 {
368 if (*pFile != INVALID_HANDLE_VALUE)
369 {
370 fileno_modes[i].fd = i;
371 fileno_modes[i].mode = ((*pmode << 8) & (_O_TEXT|_O_BINARY)) | (*pmode & _O_ACCMODE);
372 fileno_modes[i].hFile = *pFile;
373 }
374 pFile++;
375 pmode++;
376 }
377 }
378
379 if (fileno_modes[0].fd == -1)
380 {
381 fileno_modes[0].fd = 0;
382 fileno_modes[0].hFile = GetStdHandle(STD_INPUT_HANDLE);
383 fileno_modes[0].mode = _O_RDONLY|_O_TEXT;
384 }
385 if (fileno_modes[1].fd == -1)
386 {
387 fileno_modes[1].fd = 1;
388 fileno_modes[1].hFile = GetStdHandle(STD_OUTPUT_HANDLE);
389 fileno_modes[1].mode = _O_WRONLY|_O_TEXT;
390 }
391 if (fileno_modes[2].fd == -1)
392 {
393 fileno_modes[2].fd = 2;
394 fileno_modes[2].hFile = GetStdHandle(STD_ERROR_HANDLE);
395 fileno_modes[2].mode = _O_WRONLY|_O_TEXT;
396 }
397 if (fileno_modes[3].fd == -1)
398 {
399 fileno_modes[3].fd = 3;
400 fileno_modes[3].hFile = GetStdHandle(STD_AUX_HANDLE);
401 fileno_modes[3].mode = _O_WRONLY|_O_TEXT;
402 }
403 if (fileno_modes[4].fd == -1)
404 {
405 fileno_modes[4].fd = 4;
406 fileno_modes[4].hFile = GetStdHandle(STD_PRINTER_HANDLE);
407 fileno_modes[4].mode = _O_WRONLY|_O_TEXT;
408 }
409 return TRUE;
410 }