#define _GNU_SOURCE #include #include #include #include "syscall.h" #include "libc.h" int fcntl(int fd, int cmd, ...) { va_list ap; int arg, ret; void *ptrarg; struct f_owner_ex ex; switch (cmd) { case F_GETFD: case F_GETFL: case F_GETSIG: case F_GETLEASE: case F_GETPIPE_SZ: return syscall(SYS_fcntl, fd, cmd); case F_GETOWN: ret = __syscall(SYS_fcntl, fd, F_GETOWN_EX, &ex); if (ret == -EINVAL) return __syscall(SYS_fcntl, fd, cmd); if (ret) return __syscall_ret(ret); return ex.type == F_OWNER_PGRP ? -ex.pid : ex.pid; case F_DUPFD: case F_SETFD: case F_SETOWN: case F_SETSIG: va_start(ap, cmd); arg = va_arg(ap, int); va_end(ap); return syscall(SYS_fcntl, fd, cmd, arg); case F_SETFL: va_start(ap, cmd); arg = va_arg(ap, int) | O_LARGEFILE; va_end(ap); return syscall(SYS_fcntl, fd, cmd, arg); case F_DUPFD_CLOEXEC: va_start(ap, cmd); arg = va_arg(ap, int); va_end(ap); ret = __syscall(SYS_fcntl, fd, F_DUPFD_CLOEXEC, arg); if (ret != -EINVAL) { if (ret >= 0) __syscall(SYS_fcntl, ret, F_SETFD, FD_CLOEXEC); return __syscall_ret(ret); } ret = __syscall(SYS_fcntl, fd, F_DUPFD_CLOEXEC, 0); if (ret != -EINVAL) { if (ret >= 0) __syscall(SYS_close, ret); return __syscall_ret(-EINVAL); } ret = __syscall(SYS_fcntl, fd, F_DUPFD, arg); if (ret >= 0) __syscall(SYS_fcntl, ret, F_SETFD, FD_CLOEXEC); return __syscall_ret(ret); case F_SETLKW: va_start(ap, cmd); ptrarg = va_arg(ap, void *); va_end(ap); return syscall_cp(SYS_fcntl, fd, cmd, ptrarg); default: va_start(ap, cmd); ptrarg = va_arg(ap, void *); va_end(ap); return syscall(SYS_fcntl, fd, cmd, ptrarg); } }