From bd4c2d60ba0f0db371f6dec519a48aa42e7cdadd Mon Sep 17 00:00:00 2001 From: Simon Giesecke Date: Fri, 6 Dec 2019 18:17:28 +0100 Subject: [PATCH] Problem: zmq::listener_t::create_wildcard_address not reusable in ip.cpp Solution: move to ip.hpp as zmq::create_ipc_wildcard_address --- src/ip.cpp | 92 ++++++++++++++++++++++++++++++++++++++++++++ src/ip.hpp | 5 +++ src/ipc_listener.cpp | 86 +---------------------------------------- src/ipc_listener.hpp | 6 --- 4 files changed, 98 insertions(+), 91 deletions(-) diff --git a/src/ip.cpp b/src/ip.cpp index 23243c6e..144f47ec 100644 --- a/src/ip.cpp +++ b/src/ip.cpp @@ -38,11 +38,18 @@ #include #include #include +#include #include #include #include +#include +#include + +#include #else #include "tcp.hpp" + +#include #endif #if defined ZMQ_HAVE_OPENVMS || defined ZMQ_HAVE_VXWORKS @@ -71,6 +78,14 @@ #include #endif +#ifndef ZMQ_HAVE_WINDOWS +// Acceptable temporary directory environment variables +static const char *tmp_env_vars[] = { + "TMPDIR", "TEMPDIR", "TMP", + 0 // Sentinel +}; +#endif + zmq::fd_t zmq::open_socket (int domain_, int type_, int protocol_) { int rc; @@ -730,3 +745,80 @@ void zmq::assert_success_or_recoverable (zmq::fd_t s_, int rc_) } #endif } + +#ifdef ZMQ_HAVE_IPC +int zmq::create_ipc_wildcard_address (std::string &path_, std::string &file_) +{ +#if defined ZMQ_HAVE_WINDOWS + char buffer[MAX_PATH]; + + { + const errno_t rc = tmpnam_s (buffer); + errno_assert (rc == 0); + } + + // TODO or use CreateDirectoryA and specify permissions? + const int rc = _mkdir (buffer); + if (rc != 0) { + return -1; + } + + path_.assign (buffer); + file_ = path_ + "/socket"; +#else + std::string tmp_path; + + // If TMPDIR, TEMPDIR, or TMP are available and are directories, create + // the socket directory there. + const char **tmp_env = tmp_env_vars; + while (tmp_path.empty () && *tmp_env != 0) { + char *tmpdir = getenv (*tmp_env); + struct stat statbuf; + + // Confirm it is actually a directory before trying to use + if (tmpdir != 0 && ::stat (tmpdir, &statbuf) == 0 + && S_ISDIR (statbuf.st_mode)) { + tmp_path.assign (tmpdir); + if (*(tmp_path.rbegin ()) != '/') { + tmp_path.push_back ('/'); + } + } + + // Try the next environment variable + ++tmp_env; + } + + // Append a directory name + tmp_path.append ("tmpXXXXXX"); + + // We need room for tmp_path + trailing NUL + std::vector buffer (tmp_path.length () + 1); + strcpy (&buffer[0], tmp_path.c_str ()); + +#if defined HAVE_MKDTEMP + // Create the directory. POSIX requires that mkdtemp() creates the + // directory with 0700 permissions, meaning the only possible race + // with socket creation could be the same user. However, since + // each socket is created in a directory created by mkdtemp(), and + // mkdtemp() guarantees a unique directory name, there will be no + // collision. + if (mkdtemp (&buffer[0]) == 0) { + return -1; + } + + path_.assign (&buffer[0]); + file_ = path_ + "/socket"; +#else + LIBZMQ_UNUSED (path_); + int fd = mkstemp (&buffer[0]); + if (fd == -1) + return -1; + ::close (fd); + + file_.assign (&buffer[0]); +#endif +#endif + + return 0; +} +#endif diff --git a/src/ip.hpp b/src/ip.hpp index 15e038c4..50ae7d64 100644 --- a/src/ip.hpp +++ b/src/ip.hpp @@ -76,6 +76,11 @@ void make_socket_noninheritable (fd_t sock_); // - an internal 0MQ error did not occur, // - and, if a socket error occured, it can be recovered from. void assert_success_or_recoverable (fd_t s_, int rc_); + +#ifdef ZMQ_HAVE_IPC +// Create an IPC wildcard path address +int create_ipc_wildcard_address (std::string &path_, std::string &file_); +#endif } #endif diff --git a/src/ipc_listener.cpp b/src/ipc_listener.cpp index df44eb5c..baffc373 100644 --- a/src/ipc_listener.cpp +++ b/src/ipc_listener.cpp @@ -52,8 +52,6 @@ #include #include -#define S_ISDIR(m) (((m) &S_IFMT) == S_IFDIR) - #define rmdir _rmdir #define unlink _unlink @@ -62,7 +60,6 @@ #include #include #include -#include #endif #ifdef ZMQ_HAVE_LOCAL_PEERCRED @@ -78,87 +75,6 @@ #endif #endif -const char *zmq::ipc_listener_t::tmp_env_vars[] = { - "TMPDIR", "TEMPDIR", "TMP", - 0 // Sentinel -}; - -int zmq::ipc_listener_t::create_wildcard_address (std::string &path_, - std::string &file_) -{ -#if defined ZMQ_HAVE_WINDOWS - char buffer[MAX_PATH]; - - { - const errno_t rc = tmpnam_s (buffer); - errno_assert (rc == 0); - } - - // TODO or use CreateDirectoryA and specify permissions? - const int rc = _mkdir (buffer); - if (rc != 0) { - return -1; - } - - path_.assign (buffer); - file_ = path_ + "/socket"; -#else - std::string tmp_path; - - // If TMPDIR, TEMPDIR, or TMP are available and are directories, create - // the socket directory there. - const char **tmp_env = tmp_env_vars; - while (tmp_path.empty () && *tmp_env != 0) { - char *tmpdir = getenv (*tmp_env); - struct stat statbuf; - - // Confirm it is actually a directory before trying to use - if (tmpdir != 0 && ::stat (tmpdir, &statbuf) == 0 - && S_ISDIR (statbuf.st_mode)) { - tmp_path.assign (tmpdir); - if (*(tmp_path.rbegin ()) != '/') { - tmp_path.push_back ('/'); - } - } - - // Try the next environment variable - ++tmp_env; - } - - // Append a directory name - tmp_path.append ("tmpXXXXXX"); - - // We need room for tmp_path + trailing NUL - std::vector buffer (tmp_path.length () + 1); - strcpy (&buffer[0], tmp_path.c_str ()); - -#if defined HAVE_MKDTEMP - // Create the directory. POSIX requires that mkdtemp() creates the - // directory with 0700 permissions, meaning the only possible race - // with socket creation could be the same user. However, since - // each socket is created in a directory created by mkdtemp(), and - // mkdtemp() guarantees a unique directory name, there will be no - // collision. - if (mkdtemp (&buffer[0]) == 0) { - return -1; - } - - path_.assign (&buffer[0]); - file_ = path_ + "/socket"; -#else - LIBZMQ_UNUSED (path_); - int fd = mkstemp (&buffer[0]); - if (fd == -1) - return -1; - ::close (fd); - - file_.assign (&buffer[0]); -#endif -#endif - - return 0; -} - zmq::ipc_listener_t::ipc_listener_t (io_thread_t *io_thread_, socket_base_t *socket_, const options_t &options_) : @@ -197,7 +113,7 @@ int zmq::ipc_listener_t::set_local_address (const char *addr_) // Allow wildcard file if (options.use_fd == -1 && addr[0] == '*') { - if (create_wildcard_address (_tmp_socket_dirname, addr) < 0) { + if (create_ipc_wildcard_address (_tmp_socket_dirname, addr) < 0) { return -1; } } diff --git a/src/ipc_listener.hpp b/src/ipc_listener.hpp index ddda500e..f1150364 100644 --- a/src/ipc_listener.hpp +++ b/src/ipc_listener.hpp @@ -56,9 +56,6 @@ class ipc_listener_t : public stream_listener_base_t // Handlers for I/O events. void in_event (); - // Create wildcard path address - static int create_wildcard_address (std::string &path_, std::string &file_); - // Filter new connections if the OS provides a mechanism to get // the credentials of the peer process. Called from accept(). #if defined ZMQ_HAVE_SO_PEERCRED || defined ZMQ_HAVE_LOCAL_PEERCRED @@ -82,9 +79,6 @@ class ipc_listener_t : public stream_listener_base_t // Name of the file associated with the UNIX domain address. std::string _filename; - // Acceptable temporary directory environment variables - static const char *tmp_env_vars[]; - ipc_listener_t (const ipc_listener_t &); const ipc_listener_t &operator= (const ipc_listener_t &); };