diff options
author | Andreas Schneider <asn@samba.org> | 2014-09-11 10:17:06 +0200 |
---|---|---|
committer | Andreas Schneider <asn@samba.org> | 2014-10-01 14:06:27 +0200 |
commit | 045689644b87a3f6a3f4c2baeb70d22d3f6c441c (patch) | |
tree | eb22899966706593d27f2c7280b34d9c57c26b60 | |
parent | 7dad23ab56c707a0c5e3780436259781375be0e0 (diff) | |
download | socket_wrapper-045689644b87a3f6a3f4c2baeb70d22d3f6c441c.tar.gz socket_wrapper-045689644b87a3f6a3f4c2baeb70d22d3f6c441c.tar.xz socket_wrapper-045689644b87a3f6a3f4c2baeb70d22d3f6c441c.zip |
swrap: Implement fcntl() to catch F_DUPFD.
Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
-rw-r--r-- | src/socket_wrapper.c | 87 |
1 files changed, 86 insertions, 1 deletions
diff --git a/src/socket_wrapper.c b/src/socket_wrapper.c index e0942ed..8a7b572 100644 --- a/src/socket_wrapper.c +++ b/src/socket_wrapper.c @@ -339,6 +339,7 @@ struct swrap_libc_fns { socklen_t addrlen); int (*libc_dup)(int fd); int (*libc_dup2)(int oldfd, int newfd); + int (*libc_fcntl)(int fd, int cmd, ...); FILE *(*libc_fopen)(const char *name, const char *mode); #ifdef HAVE_EVENTFD int (*libc_eventfd)(int count, int flags); @@ -591,6 +592,28 @@ static int libc_eventfd(int count, int flags) } #endif +static int libc_vfcntl(int fd, int cmd, va_list ap) +{ + long int args[4]; + int rc; + int i; + + swrap_load_lib_function(SWRAP_LIBC, fcntl); + + for (i = 0; i < 4; i++) { + args[i] = va_arg(ap, long int); + } + + rc = swrap.fns.libc_fcntl(fd, + cmd, + args[0], + args[1], + args[2], + args[3]); + + return rc; +} + static int libc_getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen) @@ -4918,7 +4941,69 @@ int dup2(int fd, int newfd) } /**************************** - * DUP2 + * FCNTL + ***************************/ + +static int swrap_vfcntl(int fd, int cmd, va_list va) +{ + struct socket_info_fd *fi; + struct socket_info *si; + int rc; + + si = find_socket_info(fd); + if (si == NULL) { + rc = libc_vfcntl(fd, cmd, va); + + return rc; + } + + switch (cmd) { + case F_DUPFD: + fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd)); + if (fi == NULL) { + errno = ENOMEM; + return -1; + } + + fi->fd = libc_vfcntl(fd, cmd, va); + if (fi->fd == -1) { + int saved_errno = errno; + free(fi); + errno = saved_errno; + return -1; + } + + /* Make sure we don't have an entry for the fd */ + swrap_remove_stale(fi->fd); + + SWRAP_DLIST_ADD(si->fds, fi); + + rc = fi->fd; + break; + default: + rc = libc_vfcntl(fd, cmd, va); + break; + } + + return rc; +} + +int fcntl(int fd, int cmd, ...) +{ + va_list va; + int rc; + + va_start(va, cmd); + + rc = swrap_vfcntl(fd, cmd, va); + + va_end(va); + + return rc; +} + +/**************************** + * EVENTFD ***************************/ #ifdef HAVE_EVENTFD |