430e0e2a8c940d779a1fc44fc96e04835b549ae8
[reactos.git] / posix / lib / psxdll / fcntl / fcntl.c
1 /* $Id: fcntl.c,v 1.3 2002/03/07 06:03:11 hyperion Exp $
2 */
3 /*
4 * COPYRIGHT: See COPYING in the top level directory
5 * PROJECT: ReactOS POSIX+ Subsystem
6 * FILE: subsys/psx/lib/psxdll/fcntl/fcntl.c
7 * PURPOSE: File control
8 * PROGRAMMER: KJK::Hyperion <noog@libero.it>
9 * UPDATE HISTORY:
10 * 13/02/2002: Created
11 * 15/02/2002: Implemented fcntl() (KJK::Hyperion)
12 */
13
14 #include <ddk/ntddk.h>
15 #include <sys/types.h>
16 #include <unistd.h>
17 #include <fcntl.h>
18 #include <stdarg.h>
19 #include <psx/errno.h>
20 #include <psx/stdlib.h>
21 #include <psx/fdtable.h>
22 #include <psx/pdata.h>
23 #include <psx/debug.h>
24
25 int fcntl(int fildes, int cmd, ...)
26 {
27 __fdtable_t *pftFdTable;
28 __fildes_t *pfdDescriptor;
29 NTSTATUS nErrCode;
30 int nRetVal;
31 int nThirdArg;
32 void *pThirdArg;
33 va_list vlArgs;
34
35 /* lock the environment */
36 __PdxAcquirePdataLock();
37
38 /* get the file descriptors table */
39 pftFdTable = &__PdxGetProcessData()->FdTable;
40
41 /* fildes is an invalid, closed or uninitialized descriptor */
42 if
43 (
44 fildes < 0 ||
45 fildes >= OPEN_MAX ||
46 __fdtable_entry_isavail(pftFdTable, fildes) == 0 ||
47 __fdtable_entry_get(pftFdTable, fildes) == 0
48 )
49 {
50 errno = EBADF;
51 __PdxReleasePdataLock();
52 return (-1);
53 }
54
55 /* get the file descriptor referenced by fildes */
56 pfdDescriptor = __fdtable_entry_get(pftFdTable, fildes);
57
58 /* get third argument as integer */
59 va_start(vlArgs, cmd);
60 nThirdArg = va_arg(vlArgs, int);
61 va_end(vlArgs);
62
63 /* get third argument as pointer */
64 va_start(vlArgs, cmd);
65 pThirdArg = va_arg(vlArgs, void *);
66 va_end(vlArgs);
67
68 /* initialize return value */
69 nRetVal = -1;
70
71 switch(cmd)
72 {
73 case F_DUPFD:
74 {
75 va_list vlArgs;
76 int nDupFileNo;
77 __fildes_t *pfdDupDescriptor;
78
79 /* allocate the duplicated descriptor */
80 nDupFileNo = __fdtable_entry_add(pftFdTable, nThirdArg, 0, &pfdDupDescriptor);
81
82 if(nDupFileNo)
83 break;
84
85 /* copy the open flags */
86 pfdDupDescriptor->OpenFlags = pfdDescriptor->OpenFlags;
87
88 /* clear the FD_CLOEXEC flag */
89 pfdDupDescriptor->FdFlags = pfdDescriptor->FdFlags & ~FD_CLOEXEC;
90
91 /* duplicate the extra data */
92 if(pfdDescriptor->ExtraDataSize != 0 && pfdDescriptor->ExtraData != 0)
93 {
94 /* allocate space for the duplicated extra data */
95 pfdDupDescriptor->ExtraDataSize = pfdDescriptor->ExtraDataSize;
96 pfdDupDescriptor->ExtraData = __malloc(pfdDupDescriptor->ExtraDataSize);
97
98 /* failure */
99 if(pfdDupDescriptor->ExtraData == 0)
100 {
101 errno = ENOMEM;
102 break;
103 }
104
105 /* copy the extra data */
106 memcpy(pfdDupDescriptor->ExtraData, pfdDescriptor->ExtraData, pfdDupDescriptor->ExtraDataSize);
107 INFO
108 (
109 "copied %u bytes from 0x%08X into 0x%08X",
110 pfdDupDescriptor->ExtraDataSize,
111 pfdDescriptor->ExtraData,
112 pfdDupDescriptor->ExtraData
113 );
114 }
115
116 /* duplicate the handle */
117 nErrCode = NtDuplicateObject
118 (
119 NtCurrentProcess(),
120 pfdDescriptor->FileHandle,
121 NtCurrentProcess(),
122 &pfdDupDescriptor->FileHandle,
123 0,
124 0,
125 DUPLICATE_SAME_ACCESS /* | DUPLICATE_SAME_ATTRIBUTES */
126 );
127
128 /* failure */
129 if(!NT_SUCCESS(nErrCode))
130 {
131 __free(pfdDupDescriptor->ExtraData);
132 errno = __status_to_errno(nErrCode);
133 break;
134 }
135
136 INFO
137 (
138 "duplicated handle 0x%08X into handle 0x%08X",
139 pfdDescriptor->FileHandle,
140 pfdDupDescriptor->FileHandle
141 );
142
143 /* return the duplicated file number */
144 nRetVal = nDupFileNo;
145 break;
146 }
147
148 case F_GETFD:
149 {
150 nRetVal = pfdDescriptor->FdFlags;
151 break;
152 }
153
154 case F_SETFD:
155 {
156 pfdDescriptor->FdFlags = nThirdArg;
157 nRetVal = 0;
158 break;
159 }
160
161 case F_GETFL:
162 {
163 nRetVal = pfdDescriptor->OpenFlags;
164 break;
165 }
166
167 case F_SETFL:
168 {
169 pfdDescriptor->OpenFlags = nThirdArg;
170 nRetVal = 0;
171 break;
172 }
173
174 case F_GETLK:
175 {
176 errno = EINVAL;
177 break;
178 }
179
180 case F_SETLK:
181 {
182 errno = EINVAL;
183 break;
184 }
185
186 case F_SETLKW:
187 {
188 errno = EINVAL;
189 break;
190 }
191
192 case F_NEWFD:
193 {
194 /* allocate a new descriptor */
195 nRetVal = __fdtable_entry_add(pftFdTable, fildes, (__fildes_t *)pThirdArg, 0);
196 break;
197 }
198
199 case F_DELFD:
200 {
201 /* invalid return pointer */
202 if(pThirdArg == 0)
203 {
204 errno = EINVAL;
205 break;
206 }
207
208 memcpy((__fildes_t *)pThirdArg, pfdDescriptor, sizeof(*pfdDescriptor));
209
210 /* remove file descriptor */
211 nRetVal = __fdtable_entry_remove(pftFdTable, fildes);
212
213 }
214
215 case F_GETALL:
216 {
217 /* invalid return pointer */
218 if(pThirdArg == 0)
219 {
220 errno = EINVAL;
221 break;
222 }
223
224 /* return a copy of the file descriptor */
225 memcpy((__fildes_t *)pThirdArg, pfdDescriptor, sizeof(*pfdDescriptor));
226 nRetVal = 0;
227 }
228
229 case F_SETALL:
230 {
231 /* invalid file descriptor to copy attributes from */
232 if(pThirdArg == 0)
233 {
234 errno = EINVAL;
235 break;
236 }
237
238 /* copy the attributes of file descriptor from the provided descriptor */
239 memcpy(pfdDescriptor, pThirdArg, sizeof(*pfdDescriptor));
240 nRetVal = 0;
241 }
242
243 case F_GETXP:
244 {
245 /* invalid return pointer */
246 if(pThirdArg == 0)
247 {
248 errno = EINVAL;
249 break;
250 }
251
252 /* return a pointer to the extra data associated to the descriptor */
253 *((void **)pThirdArg) = pfdDescriptor->ExtraData;
254 nRetVal = 0;
255 break;
256 }
257
258 case F_SETXP:
259 {
260 /* set the pointer to the extra data associated */
261 pfdDescriptor->ExtraData = pThirdArg;
262 nRetVal = 0;
263 break;
264 }
265
266 case F_GETXS:
267 {
268 nRetVal = pfdDescriptor->ExtraDataSize;
269 break;
270 }
271
272 case F_SETXS:
273 {
274 pfdDescriptor->ExtraDataSize = nThirdArg;
275 nRetVal = 0;
276 break;
277 }
278
279 case F_GETFH:
280 {
281 /* invalid return pointer */
282 if(pThirdArg == 0)
283 {
284 errno = EINVAL;
285 break;
286 }
287
288 /* return the handle associated to the descriptor */
289 *((void **)pThirdArg) = pfdDescriptor->FileHandle;
290 nRetVal = 0;
291 break;
292 }
293
294 case F_SETFH:
295 {
296 pfdDescriptor->FileHandle = pThirdArg;
297 nRetVal = 0;
298 break;
299 }
300
301 default:
302 errno = EINVAL;
303 }
304
305 /* unlock the environment */
306 __PdxReleasePdataLock();
307
308 return (nRetVal);
309 }
310
311 /* EOF */