| /* 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; | 
 | 	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: | 
 | 			errno = ENOSYS; | 
 | 			ret = -1; | 
 | 	} | 
 | 	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) |