blob: e6ff2ace57ea3fd56126cc8c1d484509fea75679 [file] [log] [blame]
/* 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)