diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/socket_wrapper/socket_wrapper.c | 122 | ||||
-rw-r--r-- | lib/socket_wrapper/socket_wrapper.h | 11 |
2 files changed, 131 insertions, 2 deletions
diff --git a/lib/socket_wrapper/socket_wrapper.c b/lib/socket_wrapper/socket_wrapper.c index 2b526262bd7..946980963ed 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 77af6feadd7..32c9de6b682 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__ */ |