| /* Copyright (c) 2015 Google, Inc. |
| * Barret Rhoden <brho@cs.berkeley.edu> |
| * See LICENSE for details. */ |
| |
| #include <errno.h> |
| #include <fcntl.h> |
| #include <stdarg.h> |
| #include <stdlib.h> |
| #include <ros/syscall.h> |
| |
| /* This is overridden when we're building with sockets. We need to go through |
| * these hoops since fnctl is a lower-level glibc function and is included in |
| * code that can't use sockets/rocks/stdio. */ |
| static void __weak_sock_mirror_fcntl(int sock_fd, int cmd, long arg) |
| { |
| } |
| weak_alias(__weak_sock_mirror_fcntl, _sock_mirror_fcntl); |
| |
| int __vfcntl(int fd, int cmd, va_list vl) |
| { |
| int ret, arg, advise; |
| __off64_t offset, len; |
| long a1, a2, a3, a4; |
| |
| switch (cmd) { |
| case F_GETFD: |
| case F_SYNC: |
| ret = ros_syscall(SYS_fcntl, fd, cmd, 0, 0, 0, 0); |
| break; |
| case F_DUPFD: |
| case F_SETFD: |
| case F_GETFL: |
| arg = va_arg(vl, int); |
| ret = ros_syscall(SYS_fcntl, fd, cmd, arg, 0, 0, 0); |
| break; |
| case F_SETFL: |
| arg = va_arg(vl, int); |
| ret = ros_syscall(SYS_fcntl, fd, cmd, arg, 0, 0, 0); |
| /* For SETFL, we mirror the operation on all of the Rocks FDs. |
| * If the others fail, we won't hear about it. Similarly, we |
| * only GETFL for the data FD. */ |
| _sock_mirror_fcntl(fd, cmd, arg); |
| break; |
| case F_ADVISE: |
| offset = va_arg(vl, __off64_t); |
| len = va_arg(vl, __off64_t); |
| advise = va_arg(vl, int); |
| ret = ros_syscall(SYS_fcntl, fd, cmd, offset, len, advise, 0); |
| break; |
| default: |
| /* We don't know the number of arguments for generic calls. |
| * We'll just yank whatever arguments there could be from the |
| * ABI and send them along. */ |
| a1 = va_arg(vl, long); |
| a2 = va_arg(vl, long); |
| a3 = va_arg(vl, long); |
| a4 = va_arg(vl, long); |
| ret = ros_syscall(SYS_fcntl, fd, cmd, a1, a2, a3, a4); |
| break; |
| } |
| return ret; |
| } |
| |
| /* We used to override fcntl() with some Rock processing from within Glibc. It |
| * might be useful to override fcntl() in the future. */ |
| int __fcntl(int fd, int cmd, ...) |
| { |
| int ret; |
| va_list vl; |
| |
| va_start(vl, cmd); |
| ret = __vfcntl(fd, cmd, vl); |
| va_end(vl); |
| return ret; |
| } |
| libc_hidden_def(__fcntl) |
| weak_alias(__fcntl, fcntl) |