| /* 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) |