From 63e5b395d00535c88274bafb9d5e4b0e9d753b36 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 12 Aug 2011 14:28:03 +1000 Subject: socket-wrapped: added wrappers for dup() and dup2() The Samba4 standard process model uses dup() on incoming sockets as an optimisation (it makes select() a tiny bit faster when used). Adding dup() to socket wrapper allows us to use the standard process model in selftest Pair-Programmed-With: Andrew Bartlett --- lib/socket_wrapper/socket_wrapper.c | 122 +++++++++++++++++++++++++++++++++++- lib/socket_wrapper/socket_wrapper.h | 11 ++++ 2 files changed, 131 insertions(+), 2 deletions(-) (limited to 'lib/socket_wrapper') diff --git a/lib/socket_wrapper/socket_wrapper.c b/lib/socket_wrapper/socket_wrapper.c index 2b526262bd..946980963e 100644 --- a/lib/socket_wrapper/socket_wrapper.c +++ b/lib/socket_wrapper/socket_wrapper.c @@ -127,6 +127,8 @@ #define real_writev writev #define real_socket socket #define real_close close +#define real_dup dup +#define real_dup2 dup2 #endif #ifdef HAVE_GETTIMEOFDAY_TZ @@ -225,7 +227,6 @@ struct socket_info int connected; int defer_connect; - char *path; char *tmp_path; struct sockaddr *myname; @@ -2523,7 +2524,6 @@ _PUBLIC_ int swrap_close(int fd) swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0); } - if (si->path) free(si->path); if (si->myname) free(si->myname); if (si->peername) free(si->peername); if (si->tmp_path) { @@ -2534,3 +2534,121 @@ _PUBLIC_ int swrap_close(int fd) return ret; } + +_PUBLIC_ int swrap_dup(int fd) +{ + struct socket_info *si, *si2; + int fd2; + + si = find_socket_info(fd); + + if (!si) { + return real_dup(fd); + } + + if (si->tmp_path) { + /* we would need reference counting to handle this */ + errno = EINVAL; + return -1; + } + + fd2 = real_dup(fd); + if (fd2 == -1) { + return -1; + } + + si2 = (struct socket_info *)malloc(sizeof(struct socket_info)); + if (si2 == NULL) { + real_close(fd2); + errno = ENOMEM; + return -1; + } + + /* copy the whole structure, then duplicate pointer elements */ + *si2 = *si; + + si2->fd = fd2; + + if (si2->myname) { + si2->myname = sockaddr_dup(si2->myname, si2->myname_len); + if (si2->myname == NULL) { + real_close(fd2); + errno = ENOMEM; + return -1; + } + } + + if (si2->peername) { + si2->peername = sockaddr_dup(si2->peername, si2->peername_len); + if (si2->peername == NULL) { + real_close(fd2); + errno = ENOMEM; + return -1; + } + } + + SWRAP_DLIST_ADD(sockets, si2); + return fd2; +} + +_PUBLIC_ int swrap_dup2(int fd, int newfd) +{ + struct socket_info *si, *si2; + int fd2; + + si = find_socket_info(fd); + + if (!si) { + return real_dup2(fd, newfd); + } + + if (si->tmp_path) { + /* we would need reference counting to handle this */ + errno = EINVAL; + return -1; + } + + if (find_socket_info(newfd)) { + /* dup2() does an implicit close of newfd, which we + * need to emulate */ + swrap_close(newfd); + } + + fd2 = real_dup2(fd, newfd); + if (fd2 == -1) { + return -1; + } + + si2 = (struct socket_info *)malloc(sizeof(struct socket_info)); + if (si2 == NULL) { + real_close(fd2); + errno = ENOMEM; + return -1; + } + + /* copy the whole structure, then duplicate pointer elements */ + *si2 = *si; + + si2->fd = fd2; + + if (si2->myname) { + si2->myname = sockaddr_dup(si2->myname, si2->myname_len); + if (si2->myname == NULL) { + real_close(fd2); + errno = ENOMEM; + return -1; + } + } + + if (si2->peername) { + si2->peername = sockaddr_dup(si2->peername, si2->peername_len); + if (si2->peername == NULL) { + real_close(fd2); + errno = ENOMEM; + return -1; + } + } + + SWRAP_DLIST_ADD(sockets, si2); + return fd2; +} diff --git a/lib/socket_wrapper/socket_wrapper.h b/lib/socket_wrapper/socket_wrapper.h index 77af6feadd..32c9de6b68 100644 --- a/lib/socket_wrapper/socket_wrapper.h +++ b/lib/socket_wrapper/socket_wrapper.h @@ -58,6 +58,8 @@ ssize_t swrap_send(int s, const void *buf, size_t len, int flags); int swrap_readv(int s, const struct iovec *vector, size_t count); int swrap_writev(int s, const struct iovec *vector, size_t count); int swrap_close(int); +int swrap_dup(int oldfd); +int swrap_dup2(int oldfd, int newfd); #ifdef SOCKET_WRAPPER_REPLACE @@ -160,7 +162,16 @@ int swrap_close(int); #undef close #endif #define close(s) swrap_close(s) + +#ifdef dup +#undef dup #endif +#define dup(s) swrap_dup(s) +#ifdef dup2 +#undef dup2 +#endif +#define dup2(s, s2) swrap_dup2(s, s2) +#endif /* SOCKET_WRAPPER_REPLACE */ #endif /* __SOCKET_WRAPPER_H__ */ -- cgit