summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/socket_wrapper/socket_wrapper.c122
-rw-r--r--lib/socket_wrapper/socket_wrapper.h11
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__ */