features.h: support POSIX.1-2024
[newlib-cygwin.git] / winsup / cygwin / fcntl.cc
blob2bc52edb07eee1a32dc2498f850798f52bfb9ce6
1 /* fcntl.cc: fcntl syscall
3 This file is part of Cygwin.
5 This software is a copyrighted work licensed under the terms of the
6 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
7 details. */
9 #include "winsup.h"
10 #include <unistd.h>
11 #include "cygerrno.h"
12 #include "security.h"
13 #include "path.h"
14 #include "fhandler.h"
15 #include "dtable.h"
16 #include "cygheap.h"
17 #include "cygtls.h"
19 extern "C" int
20 fcntl (int fd, int cmd, ...)
22 int res = -1;
23 intptr_t arg = 0;
24 va_list args;
26 pthread_testcancel ();
28 __try
31 debug_printf ("fcntl(%d, %d, ...)", fd, cmd);
33 /* Don't lock the fd table when performing locking calls. */
34 cygheap_fdget cfd (fd, cmd < F_GETLK || cmd > F_SETLKW);
35 if (cfd < 0)
36 __leave;
38 /* FIXME? All numerical args to fcntl are defined as long on Linux.
39 This relies on a really dirty trick on x86_64: A 32 bit mov to
40 a register (e.g. mov $1, %edx) always sets the high 32 bit to 0.
41 We're following the Linux lead here since the third arg to any
42 function is in a register anyway (%r8 in MS ABI). That's the easy
43 case which is covered here by always reading the arg with
44 sizeof (intptr_t) == sizeof (long) == sizeof (void*) which matches
45 all targets.
47 However, the POSIX standard defines all numerical args as type int.
48 If we take that literally, we had a (small) problem on 64 bit, since
49 sizeof (void*) != sizeof (int). If we would like to follow POSIX more
50 closely than Linux, we'd have to call va_arg on a per cmd basis. */
52 va_start (args, cmd);
53 arg = va_arg (args, intptr_t);
54 va_end (args);
56 switch (cmd)
58 case F_DUPFD:
59 case F_DUPFD_CLOEXEC:
60 if (arg >= 0 && arg < OPEN_MAX)
62 int flags = cmd == F_DUPFD_CLOEXEC ? O_CLOEXEC : 0;
63 res = cygheap->fdtab.dup3 (fd, cygheap_fdnew ((arg) - 1), flags);
65 else
67 set_errno (EINVAL);
68 res = -1;
70 break;
71 default:
72 res = cfd->fcntl (cmd, arg);
73 break;
76 __except (EFAULT) {}
77 __endtry
78 syscall_printf ("%R = fcntl(%d, %d, %ly)", res, fd, cmd, arg);
79 return res;
82 EXPORT_ALIAS (fcntl, _fcntl)