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