feat(fcntl): fcntl/open flag handling

This commit is contained in:
2026-09-05 16:46:34 -04:00
parent 6eaacd4448
commit c9e9676d38
7 changed files with 857 additions and 0 deletions
+55
View File
@@ -0,0 +1,55 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdarg.h>
#include <fcntl.h>
#include "../internal/syscall.h"
/*
* fcntl over SYS_fcntl (72). The third argument is read from the varargs
* only for the commands POSIX defines one for (F_DUPFD, F_DUPFD_CLOEXEC,
* F_SETFD, F_SETFL, the lock commands, and the owner/signal commands);
* every other command passes 0, which the kernel ignores. Pointers (the
* struct flock * of F_GETLK/F_SETLK/F_SETLKW/F_OFD_*) ride the varargs
* slot as a long — on x86_64 long and void * share one GPR slot, so the
* read is ABI-exact.
*
* F_DUPFD_CLOEXEC passes straight through: the x86_64 kernel has supported
* it as a single native operation since 2.6.24, so no F_DUPFD + F_SETFD
* fallback is needed. F_SETFL needs no O_LARGEFILE massaging on x86_64
* (that is a 32-bit compat concern only).
*/
int
fcntl(int fildes, int cmd, ...)
{
long arg = 0;
va_list ap;
switch (cmd)
{
case F_DUPFD:
case F_DUPFD_CLOEXEC:
case F_SETFD:
case F_SETFL:
case F_GETLK:
case F_SETLK:
case F_SETLKW:
case F_SETOWN:
case F_SETSIG:
case F_GETOWN_EX:
case F_SETOWN_EX:
case F_OFD_GETLK:
case F_OFD_SETLK:
case F_OFD_SETLKW:
va_start(ap, cmd);
arg = va_arg(ap, long);
va_end(ap);
break;
default:
break;
}
return syscall_ret(__syscall3(SYS_fcntl, fildes, cmd, arg));
}