1#define _GNU_SOURCE 2#include <fcntl.h> 3#include <stdarg.h> 4#include <errno.h> 5#include "syscall.h" 6#include "libc.h" 7 8int fcntl(int fd, int cmd, ...) 9{ 10 unsigned long arg; 11 va_list ap; 12 va_start(ap, cmd); 13 arg = va_arg(ap, unsigned long); 14 va_end(ap); 15 if (cmd == F_SETFL) arg |= O_LARGEFILE; 16 if (cmd == F_SETLKW) return syscall_cp(SYS_fcntl, fd, cmd, (void *)arg); 17 if (cmd == F_GETOWN) { 18 struct f_owner_ex ex; 19 int ret = __syscall(SYS_fcntl, fd, F_GETOWN_EX, &ex); 20 if (ret == -EINVAL) return __syscall(SYS_fcntl, fd, cmd, (void *)arg); 21 if (ret) return __syscall_ret(ret); 22 return ex.type == F_OWNER_PGRP ? -ex.pid : ex.pid; 23 } 24 if (cmd == F_DUPFD_CLOEXEC) { 25 int ret = __syscall(SYS_fcntl, fd, F_DUPFD_CLOEXEC, arg); 26 if (ret != -EINVAL) { 27 if (ret >= 0) 28 __syscall(SYS_fcntl, ret, F_SETFD, FD_CLOEXEC); 29 return __syscall_ret(ret); 30 } 31 ret = __syscall(SYS_fcntl, fd, F_DUPFD_CLOEXEC, 0); 32 if (ret != -EINVAL) { 33 if (ret >= 0) __syscall(SYS_close, ret); 34 return __syscall_ret(-EINVAL); 35 } 36 ret = __syscall(SYS_fcntl, fd, F_DUPFD, arg); 37 if (ret >= 0) __syscall(SYS_fcntl, ret, F_SETFD, FD_CLOEXEC); 38 return __syscall_ret(ret); 39 } 40 switch (cmd) { 41 case F_SETLK: 42 case F_GETLK: 43 case F_GETOWN_EX: 44 case F_SETOWN_EX: 45 return syscall(SYS_fcntl, fd, cmd, (void *)arg); 46 default: 47 return syscall(SYS_fcntl, fd, cmd, arg); 48 } 49} 50