update for HEAD-2003021201
[reactos.git] / lib / crtdll / io / open.c
1 /* $Id$
2  *
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
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 #include <stdarg.h>
18 #include <msvcrt/io.h>
19 #include <msvcrt/fcntl.h>
20 #include <msvcrt/sys/stat.h>
21 #include <msvcrt/stdlib.h>
22 #include <msvcrt/internal/file.h>
23 #include <msvcrt/string.h>
24 #include <msvcrt/share.h>
25
26 #define STD_AUX_HANDLE 3
27 #define STD_PRINTER_HANDLE 4
28
29 typedef struct _fileno_modes_type
30 {
31     HANDLE hFile;
32     int mode;
33     int fd;
34 } fileno_modes_type;
35
36 int __fileno_alloc(HANDLE hFile, int mode);
37
38 fileno_modes_type *fileno_modes = NULL;
39
40 int maxfno = 5;
41 int minfno = 5;
42
43 char __is_text_file(FILE* p)
44 {
45    if (p == NULL || fileno_modes == NULL)
46      return FALSE;
47    return (!((p)->_flag&_IOSTRG) && (fileno_modes[(p)->_file].mode&O_TEXT));
48 }
49
50 int _open(const char* _path, int _oflag,...)
51 {
52     HANDLE hFile;
53     DWORD dwDesiredAccess = 0;
54     DWORD dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
55     DWORD dwCreationDistribution = 0;
56     DWORD dwFlagsAndAttributes = 0;
57     int mode;
58     va_list arg;
59
60     va_start(arg, _oflag);
61     mode = va_arg(arg,int);
62     va_end (arg);
63     if ((mode == S_IWRITE) || (mode == 0))
64         dwFlagsAndAttributes = FILE_ATTRIBUTE_READONLY;
65     /*
66      *
67      * _O_BINARY   Opens file in binary (untranslated) mode. (See fopen for a description of binary mode.)
68      * _O_TEXT   Opens file in text (translated) mode. (For more information, see Text and Binary Mode File I/O and fopen.)
69      * 
70      */
71     if (( _oflag & _O_RDWR ) == _O_RDWR ) 
72         dwDesiredAccess |= GENERIC_WRITE|GENERIC_READ ;
73     else if (( _oflag & _O_WRONLY ) == _O_WRONLY )
74         dwDesiredAccess |= GENERIC_WRITE ;
75     else 
76         dwDesiredAccess |= GENERIC_READ ;
77
78     if ((_oflag & (_O_CREAT | _O_EXCL ) ) == (_O_CREAT | _O_EXCL))
79         dwCreationDistribution |= CREATE_NEW;
80
81     else if ((_oflag &  O_TRUNC) == O_TRUNC) {
82         if ((_oflag &  O_CREAT) ==  O_CREAT)
83             dwCreationDistribution |= CREATE_ALWAYS;
84         else if ((_oflag & O_RDONLY ) != O_RDONLY)
85             dwCreationDistribution |= TRUNCATE_EXISTING;
86     }
87     else if ((_oflag & _O_APPEND) == _O_APPEND)
88         dwCreationDistribution |= OPEN_EXISTING;
89     else if ((_oflag &  _O_CREAT) == _O_CREAT)
90         dwCreationDistribution |= OPEN_ALWAYS;
91     else
92         dwCreationDistribution |= OPEN_EXISTING;
93
94     if ((_oflag &  _O_RANDOM) == _O_RANDOM)
95         dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
96     if ((_oflag &  _O_SEQUENTIAL) == _O_SEQUENTIAL)
97         dwFlagsAndAttributes |= FILE_FLAG_SEQUENTIAL_SCAN;
98
99     if ((_oflag &  _O_TEMPORARY) == _O_TEMPORARY)
100         dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE;
101
102     if ((_oflag &  _O_SHORT_LIVED) == _O_SHORT_LIVED)
103         dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE;
104
105     hFile = CreateFileA(_path,
106                dwDesiredAccess,
107                dwShareMode, 
108                NULL, 
109                dwCreationDistribution,  
110                dwFlagsAndAttributes,
111                NULL);
112     if (hFile == (HANDLE)-1)
113         return -1;
114     return  __fileno_alloc(hFile,_oflag);
115
116 //  _O_APPEND   Moves file pointer to end of file before every write operation.
117
118 }
119
120
121 int
122 __fileno_alloc(HANDLE hFile, int mode)
123 {
124   int i;
125   /* Check for bogus values */
126   if (hFile < 0)
127     return -1;
128
129   for(i=minfno;i<maxfno;i++) {
130     if (fileno_modes[i].fd == -1 ) {
131         fileno_modes[i].fd = i;
132         fileno_modes[i].mode = mode;
133         fileno_modes[i].hFile = hFile;
134         return i;
135     }
136   }
137
138   /* See if we need to expand the tables.  Check this BEFORE it might fail,
139      so that when we hit the count'th request, we've already up'd it. */
140   if ( i == maxfno)
141   {
142     int oldcount = maxfno;
143     fileno_modes_type *old_fileno_modes = fileno_modes;
144     maxfno += 255;
145     fileno_modes = (fileno_modes_type *)malloc(maxfno * sizeof(fileno_modes_type));
146     if ( old_fileno_modes != NULL )
147     {
148         memcpy(fileno_modes, old_fileno_modes, oldcount * sizeof(fileno_modes_type));
149         free ( old_fileno_modes );
150     }
151     memset(fileno_modes + oldcount, 0, (maxfno-oldcount)*sizeof(fileno_modes));
152   }
153
154   /* Fill in the value */
155   fileno_modes[i].fd = i;
156   fileno_modes[i].mode = mode;
157   fileno_modes[i].hFile = hFile;
158   return i;
159 }
160
161 void *filehnd(int fileno)
162 {
163     if (fileno < 0)
164         return (void*)-1;
165     switch (fileno) {
166     case 0:
167         return GetStdHandle(STD_INPUT_HANDLE);
168     case 1:
169         return GetStdHandle(STD_OUTPUT_HANDLE);
170     case 2:
171         return GetStdHandle(STD_ERROR_HANDLE);
172     case 3:
173         return GetStdHandle(STD_AUX_HANDLE);
174     case 4:
175         return GetStdHandle(STD_PRINTER_HANDLE);
176     default:
177         break;
178     }
179     if (fileno >= maxfno)
180         return (void*)-1;
181     if (fileno_modes[fileno].fd == -1)
182         return (void*)-1;
183     return fileno_modes[fileno].hFile;
184 }
185
186 int __fileno_setmode(int _fd, int _newmode)
187 {
188     int m;
189
190     if (_fd < minfno) {
191         return -1;
192     }
193     if (_fd >= maxfno)
194         return -1;
195     m = fileno_modes[_fd].mode;
196     fileno_modes[_fd].mode = _newmode;
197     return m;
198 }
199
200 int __fileno_getmode(int _fd)
201 {
202     if (_fd < minfno) {
203         return -1;
204     }
205     if (_fd >= maxfno)
206         return -1;
207     return fileno_modes[_fd].mode;
208 }
209
210 int __fileno_close(int _fd)
211 {
212     if (_fd < 0) {
213         return -1;
214     }
215     if (_fd >= maxfno)
216         return -1;
217     fileno_modes[_fd].fd = -1;
218     fileno_modes[_fd].hFile = (HANDLE)-1;
219     return 0;
220 }
221
222 int _open_osfhandle(void *osfhandle, int flags)
223 {
224     return __fileno_alloc((HANDLE)osfhandle, flags);
225 }
226
227 void *_get_osfhandle(int fileno)
228 {
229     return filehnd(fileno);
230 }
231
232 int __fileno_dup2(int handle1, int handle2)
233 {
234     if (handle1 >= maxfno) {
235         return -1;
236     }
237     if (handle1 < 0)
238         return -1;
239     if (handle2 >= maxfno)
240         return -1;
241     if (handle2 < 0)
242         return -1;
243     memcpy(&fileno_modes[handle1],&fileno_modes[handle2],sizeof(fileno_modes));
244     return handle1;
245 }