diff --git a/lib/libsys/Symbol.sys.map b/lib/libsys/Symbol.sys.map index 36f79d6d0b72..64f0117b55e2 100644 --- a/lib/libsys/Symbol.sys.map +++ b/lib/libsys/Symbol.sys.map @@ -383,7 +383,8 @@ FBSD_1.7 { }; FBSD_1.8 { - kcmp; + kcmp; + vfcntl; }; FBSDprivate_1.0 { diff --git a/lib/libsys/fcntl.2 b/lib/libsys/fcntl.2 index b5d4abe35aeb..9a1202721f0c 100644 --- a/lib/libsys/fcntl.2 +++ b/lib/libsys/fcntl.2 @@ -37,6 +37,9 @@ .In fcntl.h .Ft int .Fn fcntl "int fd" "int cmd" "..." +.In stdarg.h +.Ft int +.Fn vfcntl "int fd" "int cmd" "va_list ap" .Sh DESCRIPTION The .Fn fcntl diff --git a/lib/libsys/fcntl.c b/lib/libsys/fcntl.c index b8d837889613..e2047339bb9f 100644 --- a/lib/libsys/fcntl.c +++ b/lib/libsys/fcntl.c @@ -43,26 +43,27 @@ * CHERI CHANGES END */ -#include -#include #include #include + +#include +#include + #include "libc_private.h" -#pragma weak fcntl -int -fcntl(int fd, int cmd, ...) +typedef int (*fcntl_func)(int, int, intptr_t); + +static int +call_fcntl(fcntl_func fn, int fd, int cmd, va_list ap) { - va_list args; intptr_t arg; - va_start(args, cmd); switch (cmd) { case F_GETLK: case F_SETLK: case F_SETLKW: case F_KINFO: - arg = va_arg(args, intptr_t); + arg = va_arg(ap, intptr_t); break; case F_GETFD: @@ -74,13 +75,34 @@ fcntl(int fd, int cmd, ...) break; default: - arg = va_arg(args, int); + arg = va_arg(ap, int); break; } + + return (fn(fd, cmd, arg)); +} + +#pragma weak fcntl +int +vfcntl(int fd, int cmd, va_list ap) +{ + fcntl_func fn = (fcntl_func)*__libsys_interposing_slot(INTERPOS_fcntl); + + return (call_fcntl(fn, fd, cmd, ap)); +} + +#pragma weak fcntl +int +fcntl(int fd, int cmd, ...) +{ + va_list args; + int result; + + va_start(args, cmd); + result = vfcntl(fd, cmd, args); va_end(args); - return (((int (*)(int, int, intptr_t)) - *(__libc_interposing_slot(INTERPOS_fcntl)))(fd, cmd, arg)); + return (result); } #ifdef __CHERI_PURE_CAPABILITY__ @@ -90,31 +112,12 @@ int _fcntl(int fd, int cmd, ...) { va_list args; - intptr_t arg; + int result; va_start(args, cmd); - switch (cmd) { - case F_GETLK: - case F_SETLK: - case F_SETLKW: - case F_KINFO: - arg = va_arg(args, intptr_t); - break; - - case F_GETFD: - case F_GETFL: - case F_GETOWN: - case F_GET_SEALS: - case F_ISUNIONSTACK: - arg = 0; - break; - - default: - arg = va_arg(args, int); - break; - } + result = call_fcntl(__sys_fcntl, fd, cmd, args); va_end(args); - return (__sys_fcntl(fd, cmd, arg)); + return (result); } #endif diff --git a/sys/sys/fcntl.h b/sys/sys/fcntl.h index 143824558fc2..3e1b2b38e6e1 100644 --- a/sys/sys/fcntl.h +++ b/sys/sys/fcntl.h @@ -376,6 +376,7 @@ int open(const char *, int, ...); int creat(const char *, mode_t); int fcntl(int, int, ...); #if __BSD_VISIBLE +int vfcntl(int, int, __va_list); int flock(int, int); int fspacectl(int, int, const struct spacectl_range *, int, struct spacectl_range *);