diff options
Diffstat (limited to 'src/system')
-rw-r--r-- | src/system/ByteOrder.hxx | 44 | ||||
-rw-r--r-- | src/system/Clock.cxx | 2 | ||||
-rw-r--r-- | src/system/Clock.hxx | 2 | ||||
-rw-r--r-- | src/system/EPollFD.cxx | 2 | ||||
-rw-r--r-- | src/system/EPollFD.hxx | 2 | ||||
-rw-r--r-- | src/system/EventFD.cxx | 23 | ||||
-rw-r--r-- | src/system/EventFD.hxx | 11 | ||||
-rw-r--r-- | src/system/EventPipe.cxx | 2 | ||||
-rw-r--r-- | src/system/EventPipe.hxx | 2 | ||||
-rw-r--r-- | src/system/FatalError.cxx | 29 | ||||
-rw-r--r-- | src/system/FatalError.hxx | 14 | ||||
-rw-r--r-- | src/system/FileDescriptor.cxx | 215 | ||||
-rw-r--r-- | src/system/FileDescriptor.hxx | 176 | ||||
-rw-r--r-- | src/system/PeriodClock.hxx | 2 | ||||
-rw-r--r-- | src/system/Resolver.cxx | 161 | ||||
-rw-r--r-- | src/system/Resolver.hxx | 62 | ||||
-rw-r--r-- | src/system/SignalFD.cxx | 16 | ||||
-rw-r--r-- | src/system/SignalFD.hxx | 7 | ||||
-rw-r--r-- | src/system/SocketError.cxx | 46 | ||||
-rw-r--r-- | src/system/SocketError.hxx | 139 | ||||
-rw-r--r-- | src/system/SocketUtil.cxx | 93 | ||||
-rw-r--r-- | src/system/SocketUtil.hxx | 57 | ||||
-rw-r--r-- | src/system/fd_util.c | 146 | ||||
-rw-r--r-- | src/system/fd_util.h | 72 |
24 files changed, 494 insertions, 831 deletions
diff --git a/src/system/ByteOrder.hxx b/src/system/ByteOrder.hxx index 42181fe2c..babc503a9 100644 --- a/src/system/ByteOrder.hxx +++ b/src/system/ByteOrder.hxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2013 Max Kellermann <max@duempel.org>, + * Copyright (C) 2011-2015 Max Kellermann <max@duempel.org>, * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,6 +30,8 @@ #ifndef BYTE_ORDER_HXX #define BYTE_ORDER_HXX +#include "Compiler.h" + #include <stdint.h> #if defined(__i386__) || defined(__x86_64__) || defined(__ARMEL__) @@ -75,23 +77,53 @@ IsBigEndian() } static inline constexpr uint16_t +GenericByteSwap16(uint16_t value) +{ + return (value >> 8) | (value << 8); +} + +static inline constexpr uint32_t +GenericByteSwap32(uint32_t value) +{ + return (value >> 24) | ((value >> 8) & 0x0000ff00) | + ((value << 8) & 0x00ff0000) | (value << 24); +} + +static inline constexpr uint64_t +GenericByteSwap64(uint64_t value) +{ + return uint64_t(GenericByteSwap32(uint32_t(value >> 32))) + | (uint64_t(GenericByteSwap32(value)) << 32); +} + +static inline constexpr uint16_t ByteSwap16(uint16_t value) { - return (value >> 8) | (value << 8); +#if CLANG_OR_GCC_VERSION(4,8) + return __builtin_bswap16(value); +#else + return GenericByteSwap16(value); +#endif } static inline constexpr uint32_t ByteSwap32(uint32_t value) { - return (value >> 24) | ((value >> 8) & 0x0000ff00) | - ((value << 8) & 0x00ff0000) | (value << 24); +#if CLANG_OR_GCC_VERSION(4,3) + return __builtin_bswap32(value); +#else + return GenericByteSwap32(value); +#endif } static inline constexpr uint64_t ByteSwap64(uint64_t value) { - return uint64_t(ByteSwap32(uint32_t(value >> 32))) - | (uint64_t(ByteSwap32(value)) << 32); +#if CLANG_OR_GCC_VERSION(4,3) + return __builtin_bswap64(value); +#else + return GenericByteSwap64(value); +#endif } /** diff --git a/src/system/Clock.cxx b/src/system/Clock.cxx index c2f5e5087..161525fe1 100644 --- a/src/system/Clock.cxx +++ b/src/system/Clock.cxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright (C) 2003-2015 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff --git a/src/system/Clock.hxx b/src/system/Clock.hxx index 333a41000..7a710477e 100644 --- a/src/system/Clock.hxx +++ b/src/system/Clock.hxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright (C) 2003-2015 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff --git a/src/system/EPollFD.cxx b/src/system/EPollFD.cxx index 43e74712f..08051cf06 100644 --- a/src/system/EPollFD.cxx +++ b/src/system/EPollFD.cxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright (C) 2003-2015 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff --git a/src/system/EPollFD.hxx b/src/system/EPollFD.hxx index 8b9d7d2ba..d12561b5d 100644 --- a/src/system/EPollFD.hxx +++ b/src/system/EPollFD.hxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright (C) 2003-2015 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff --git a/src/system/EventFD.cxx b/src/system/EventFD.cxx index 9ac4c1d94..016dd372c 100644 --- a/src/system/EventFD.cxx +++ b/src/system/EventFD.cxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright (C) 2003-2015 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,46 +20,35 @@ #include "config.h" #ifdef USE_EVENTFD #include "EventFD.hxx" -#include "system/fd_util.h" #include "system/FatalError.hxx" #include "Compiler.h" #include <assert.h> -#include <unistd.h> - #include <sys/eventfd.h> EventFD::EventFD() - :fd(eventfd_cloexec_nonblock(0, 0)) { - if (fd < 0) + if (!fd.CreateEventFD(0)) FatalSystemError("eventfd() failed"); } -EventFD::~EventFD() -{ - assert(fd >= 0); - - close(fd); -} - bool EventFD::Read() { - assert(fd >= 0); + assert(fd.IsDefined()); eventfd_t value; - return read(fd, &value, sizeof(value)) == (ssize_t)sizeof(value); + return fd.Read(&value, sizeof(value)) == (ssize_t)sizeof(value); } void EventFD::Write() { - assert(fd >= 0); + assert(fd.IsDefined()); static constexpr eventfd_t value = 1; gcc_unused ssize_t nbytes = - write(fd, &value, sizeof(value)); + fd.Write(&value, sizeof(value)); } #endif /* USE_EVENTFD */ diff --git a/src/system/EventFD.hxx b/src/system/EventFD.hxx index 2a70461d9..616877f4a 100644 --- a/src/system/EventFD.hxx +++ b/src/system/EventFD.hxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright (C) 2003-2015 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,6 +21,7 @@ #define MPD_EVENT_FD_HXX #include "check.h" +#include "FileDescriptor.hxx" /** * A class that wraps eventfd(). @@ -28,17 +29,19 @@ * Errors in the constructor are fatal. */ class EventFD { - int fd; + FileDescriptor fd; public: EventFD(); - ~EventFD(); + ~EventFD() { + fd.Close(); + } EventFD(const EventFD &other) = delete; EventFD &operator=(const EventFD &other) = delete; int Get() const { - return fd; + return fd.Get(); } /** diff --git a/src/system/EventPipe.cxx b/src/system/EventPipe.cxx index b8fc85aed..8b3141492 100644 --- a/src/system/EventPipe.cxx +++ b/src/system/EventPipe.cxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright (C) 2003-2015 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff --git a/src/system/EventPipe.hxx b/src/system/EventPipe.hxx index 42b3bb93d..229d5633e 100644 --- a/src/system/EventPipe.hxx +++ b/src/system/EventPipe.hxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright (C) 2003-2015 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff --git a/src/system/FatalError.cxx b/src/system/FatalError.cxx index 35e94f169..664b96a6c 100644 --- a/src/system/FatalError.cxx +++ b/src/system/FatalError.cxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright (C) 2003-2015 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,10 +23,6 @@ #include "util/Domain.hxx" #include "LogV.hxx" -#ifdef HAVE_GLIB -#include <glib.h> -#endif - #include <unistd.h> #include <stdarg.h> #include <stdio.h> @@ -78,18 +74,31 @@ FatalError(const char *msg, const Error &error) FormatFatalError("%s: %s", msg, error.GetMessage()); } +#ifdef WIN32 + +void +FatalSystemError(const char *msg, DWORD code) +{ + char buffer[256]; + FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + nullptr, code, 0, + buffer, sizeof(buffer), nullptr); + FormatFatalError("%s: %s", msg, buffer); +} + +#endif + void FatalSystemError(const char *msg) { - const char *system_error; #ifdef WIN32 - system_error = g_win32_error_message(GetLastError()); + FatalSystemError(msg, GetLastError()); #else - system_error = strerror(errno); -#endif - + const char *system_error = strerror(errno); FormatError(fatal_error_domain, "%s: %s", msg, system_error); Abort(); +#endif } void diff --git a/src/system/FatalError.hxx b/src/system/FatalError.hxx index d4698b3d9..89363feeb 100644 --- a/src/system/FatalError.hxx +++ b/src/system/FatalError.hxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright (C) 2003-2015 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,6 +23,10 @@ #include "check.h" #include "Compiler.h" +#ifdef WIN32 +#include <windef.h> +#endif + class Error; /** @@ -53,6 +57,14 @@ gcc_noreturn void FatalSystemError(const char *msg); +#ifdef WIN32 + +gcc_noreturn +void +FatalSystemError(const char *msg, DWORD code); + +#endif + gcc_noreturn void FormatFatalSystemError(const char *fmt, ...); diff --git a/src/system/FileDescriptor.cxx b/src/system/FileDescriptor.cxx new file mode 100644 index 000000000..db258e107 --- /dev/null +++ b/src/system/FileDescriptor.cxx @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2012-2015 Max Kellermann <max@duempel.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "FileDescriptor.hxx" + +#include <sys/stat.h> +#include <fcntl.h> + +#ifndef WIN32 +#include <poll.h> +#endif + +#ifdef USE_EVENTFD +#include <sys/eventfd.h> +#endif + +#ifdef USE_SIGNALFD +#include <sys/signalfd.h> +#endif + +#ifdef HAVE_INOTIFY_INIT +#include <sys/inotify.h> +#endif + +#ifndef O_NOCTTY +#define O_NOCTTY 0 +#endif + +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif + +bool +FileDescriptor::Open(const char *pathname, int flags, mode_t mode) +{ + fd = ::open(pathname, flags | O_NOCTTY | O_CLOEXEC, mode); + return IsDefined(); +} + +bool +FileDescriptor::OpenReadOnly(const char *pathname) +{ + return Open(pathname, O_RDONLY); +} + +#ifndef WIN32 + +bool +FileDescriptor::OpenNonBlocking(const char *pathname) +{ + return Open(pathname, O_RDWR | O_NONBLOCK); +} + +bool +FileDescriptor::CreatePipe(FileDescriptor &r, FileDescriptor &w) +{ + int fds[2]; + +#ifdef HAVE_PIPE2 + const int flags = O_CLOEXEC; + const int result = pipe2(fds, flags); +#else + const int result = pipe(fds); +#endif + + if (result < 0) + return false; + + r = FileDescriptor(fds[0]); + w = FileDescriptor(fds[1]); + return true; +} + +void +FileDescriptor::SetNonBlocking() +{ + assert(IsDefined()); + + int flags = fcntl(fd, F_GETFL); + fcntl(fd, F_SETFL, flags | O_NONBLOCK); +} + +void +FileDescriptor::SetBlocking() +{ + assert(IsDefined()); + + int flags = fcntl(fd, F_GETFL); + fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); +} + +#endif + +#ifdef USE_EVENTFD + +bool +FileDescriptor::CreateEventFD(unsigned initval) +{ + fd = ::eventfd(initval, EFD_NONBLOCK|EFD_CLOEXEC); + return fd >= 0; +} + +#endif + +#ifdef USE_SIGNALFD + +bool +FileDescriptor::CreateSignalFD(const sigset_t *mask) +{ + int new_fd = ::signalfd(fd, mask, SFD_NONBLOCK|SFD_CLOEXEC); + if (new_fd < 0) + return false; + + fd = new_fd; + return true; +} + +#endif + +#ifdef HAVE_INOTIFY_INIT + +bool +FileDescriptor::CreateInotify() +{ +#ifdef HAVE_INOTIFY_INIT1 + int new_fd = inotify_init1(IN_CLOEXEC|IN_NONBLOCK); +#else + int new_fd = inotify_init(); +#endif + if (new_fd < 0) + return false; + +#ifndef HAVE_INOTIFY_INIT1 + SetNonBlocking(); +#endif + + fd = new_fd; + return true; +} + +#endif + +bool +FileDescriptor::Rewind() +{ + assert(IsDefined()); + + return lseek(fd, 0, SEEK_SET) == 0; +} + +off_t +FileDescriptor::GetSize() const +{ + struct stat st; + return ::fstat(fd, &st) >= 0 + ? (long)st.st_size + : -1; +} + +#ifndef WIN32 + +int +FileDescriptor::Poll(short events, int timeout) const +{ + assert(IsDefined()); + + struct pollfd pfd; + pfd.fd = fd; + pfd.events = events; + int result = poll(&pfd, 1, timeout); + return result > 0 + ? pfd.revents + : result; +} + +int +FileDescriptor::WaitReadable(int timeout) const +{ + return Poll(POLLIN, timeout); +} + +int +FileDescriptor::WaitWritable(int timeout) const +{ + return Poll(POLLOUT, timeout); +} + +#endif diff --git a/src/system/FileDescriptor.hxx b/src/system/FileDescriptor.hxx new file mode 100644 index 000000000..75a76844c --- /dev/null +++ b/src/system/FileDescriptor.hxx @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2012-2015 Max Kellermann <max@duempel.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef FILE_DESCRIPTOR_HXX +#define FILE_DESCRIPTOR_HXX + +#include "check.h" +#include "Compiler.h" + +#include <assert.h> +#include <unistd.h> +#include <sys/types.h> + +#ifdef USE_SIGNALFD +#include <signal.h> +#endif + +/** + * An OO wrapper for a UNIX file descriptor. + * + * This class is unmanaged and trivial. + */ +class FileDescriptor { +protected: + int fd; + +public: + FileDescriptor() = default; + explicit constexpr FileDescriptor(int _fd):fd(_fd) {} + + constexpr bool operator==(FileDescriptor other) const { + return fd == other.fd; + } + + constexpr bool IsDefined() const { + return fd >= 0; + } + + /** + * Returns the file descriptor. This may only be called if + * IsDefined() returns true. + */ + constexpr int Get() const { + return fd; + } + + void Set(int _fd) { + fd = _fd; + } + + int Steal() { + assert(IsDefined()); + + int _fd = fd; + fd = -1; + return _fd; + } + + void SetUndefined() { + fd = -1; + } + + static constexpr FileDescriptor Undefined() { + return FileDescriptor(-1); + } + + bool Open(const char *pathname, int flags, mode_t mode=0666); + bool OpenReadOnly(const char *pathname); + +#ifndef WIN32 + bool OpenNonBlocking(const char *pathname); + + static bool CreatePipe(FileDescriptor &r, FileDescriptor &w); + + /** + * Enable non-blocking mode on this file descriptor. + */ + void SetNonBlocking(); + + /** + * Enable blocking mode on this file descriptor. + */ + void SetBlocking(); + + /** + * Duplicate the file descriptor onto the given file descriptor. + */ + bool Duplicate(int new_fd) const { + return ::dup2(Get(), new_fd) == 0; + } +#endif + +#ifdef USE_EVENTFD + bool CreateEventFD(unsigned initval=0); +#endif + +#ifdef USE_SIGNALFD + bool CreateSignalFD(const sigset_t *mask); +#endif + +#ifdef HAVE_INOTIFY_INIT + bool CreateInotify(); +#endif + + /** + * Close the file descriptor. It is legal to call it on an + * "undefined" object. After this call, IsDefined() is guaranteed + * to return false, and this object may be reused. + */ + bool Close() { + return ::close(Steal()) == 0; + } + + /** + * Rewind the pointer to the beginning of the file. + */ + bool Rewind(); + + off_t Seek(off_t offset) { + return lseek(Get(), offset, SEEK_SET); + } + + gcc_pure + off_t Tell() const { + return lseek(Get(), 0, SEEK_CUR); + } + + /** + * Returns the size of the file in bytes, or -1 on error. + */ + gcc_pure + off_t GetSize() const; + + ssize_t Read(void *buffer, size_t length) { + return ::read(fd, buffer, length); + } + + ssize_t Write(const void *buffer, size_t length) { + return ::write(fd, buffer, length); + } + +#ifndef WIN32 + int Poll(short events, int timeout) const; + + int WaitReadable(int timeout) const; + int WaitWritable(int timeout) const; +#endif +}; + +#endif diff --git a/src/system/PeriodClock.hxx b/src/system/PeriodClock.hxx index 2c535fee9..a9db4cea0 100644 --- a/src/system/PeriodClock.hxx +++ b/src/system/PeriodClock.hxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright (C) 2003-2015 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff --git a/src/system/Resolver.cxx b/src/system/Resolver.cxx deleted file mode 100644 index a94217bac..000000000 --- a/src/system/Resolver.cxx +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "config.h" -#include "Resolver.hxx" -#include "util/Error.hxx" -#include "util/Domain.hxx" - -#ifndef WIN32 -#include <sys/socket.h> -#include <netdb.h> -#ifdef HAVE_TCP -#include <netinet/in.h> -#endif -#else -#include <ws2tcpip.h> -#include <winsock.h> -#endif - -#ifdef HAVE_UN -#include <sys/un.h> -#endif - -#include <string.h> -#include <stdio.h> - -const Domain resolver_domain("resolver"); - -std::string -sockaddr_to_string(const struct sockaddr *sa, size_t length) -{ -#ifdef HAVE_UN - if (sa->sa_family == AF_UNIX) { - /* return path of UNIX domain sockets */ - const sockaddr_un &s_un = *(const sockaddr_un *)sa; - if (length < sizeof(s_un) || s_un.sun_path[0] == 0) - return "local"; - - return s_un.sun_path; - } -#endif - -#if defined(HAVE_IPV6) && defined(IN6_IS_ADDR_V4MAPPED) - const struct sockaddr_in6 *a6 = (const struct sockaddr_in6 *)sa; - struct sockaddr_in a4; -#endif - int ret; - char host[NI_MAXHOST], serv[NI_MAXSERV]; - -#if defined(HAVE_IPV6) && defined(IN6_IS_ADDR_V4MAPPED) - if (sa->sa_family == AF_INET6 && - IN6_IS_ADDR_V4MAPPED(&a6->sin6_addr)) { - /* convert "::ffff:127.0.0.1" to "127.0.0.1" */ - - memset(&a4, 0, sizeof(a4)); - a4.sin_family = AF_INET; - memcpy(&a4.sin_addr, ((const char *)&a6->sin6_addr) + 12, - sizeof(a4.sin_addr)); - a4.sin_port = a6->sin6_port; - - sa = (const struct sockaddr *)&a4; - length = sizeof(a4); - } -#endif - - ret = getnameinfo(sa, length, host, sizeof(host), serv, sizeof(serv), - NI_NUMERICHOST|NI_NUMERICSERV); - if (ret != 0) - return "unknown"; - -#ifdef HAVE_IPV6 - if (strchr(host, ':') != nullptr) { - std::string result("["); - result.append(host); - result.append("]:"); - result.append(serv); - return result; - } -#endif - - std::string result(host); - result.push_back(':'); - result.append(serv); - return result; -} - -struct addrinfo * -resolve_host_port(const char *host_port, unsigned default_port, - int flags, int socktype, - Error &error) -{ - std::string p(host_port); - const char *host = p.c_str(), *port = nullptr; - - if (host_port[0] == '[') { - /* IPv6 needs enclosing square braces, to - differentiate between IP colons and the port - separator */ - - size_t q = p.find(']', 1); - if (q != p.npos && p[q + 1] == ':' && p[q + 2] != 0) { - p[q] = 0; - port = host + q + 2; - ++host; - } - } - - if (port == nullptr) { - /* port is after the colon, but only if it's the only - colon (don't split IPv6 addresses) */ - - auto q = p.find(':'); - if (q != p.npos && p[q + 1] != 0 && - p.find(':', q + 1) == p.npos) { - p[q] = 0; - port = host + q + 1; - } - } - - char buffer[32]; - if (port == nullptr && default_port != 0) { - snprintf(buffer, sizeof(buffer), "%u", default_port); - port = buffer; - } - - if ((flags & AI_PASSIVE) != 0 && strcmp(host, "*") == 0) - host = nullptr; - - addrinfo hints; - memset(&hints, 0, sizeof(hints)); - hints.ai_flags = flags; - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = socktype; - - struct addrinfo *ai; - int ret = getaddrinfo(host, port, &hints, &ai); - if (ret != 0) { - error.Format(resolver_domain, ret, - "Failed to look up '%s': %s", - host_port, gai_strerror(ret)); - return nullptr; - } - - return ai; -} diff --git a/src/system/Resolver.hxx b/src/system/Resolver.hxx deleted file mode 100644 index 54922d98f..000000000 --- a/src/system/Resolver.hxx +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef MPD_RESOLVER_HXX -#define MPD_RESOLVER_HXX - -#include "Compiler.h" - -#include <string> - -#include <stddef.h> - -struct sockaddr; -struct addrinfo; -class Error; -class Domain; - -extern const Domain resolver_domain; - -/** - * Converts the specified socket address into a string in the form - * "IP:PORT". - * - * @param sa the sockaddr struct - * @param length the length of #sa in bytes - */ -gcc_pure -std::string -sockaddr_to_string(const sockaddr *sa, size_t length); - -/** - * Resolve a specification in the form "host", "host:port", - * "[host]:port". This is a convenience wrapper for getaddrinfo(). - * - * @param default_port a default port number that will be used if none - * is given in the string (if applicable); pass 0 to go without a - * default - * @return an #addrinfo linked list that must be freed with - * freeaddrinfo(), or NULL on error - */ -addrinfo * -resolve_host_port(const char *host_port, unsigned default_port, - int flags, int socktype, - Error &error); - -#endif diff --git a/src/system/SignalFD.cxx b/src/system/SignalFD.cxx index 173a0cc8c..14193c893 100644 --- a/src/system/SignalFD.cxx +++ b/src/system/SignalFD.cxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright (C) 2003-2015 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -23,33 +23,29 @@ #include "FatalError.hxx" #include <assert.h> -#include <unistd.h> #include <sys/signalfd.h> void SignalFD::Create(const sigset_t &mask) { - fd = ::signalfd(fd, &mask, SFD_NONBLOCK|SFD_CLOEXEC); - if (fd < 0) + if (!fd.CreateSignalFD(&mask)) FatalSystemError("signalfd() failed"); } void SignalFD::Close() { - if (fd >= 0) { - ::close(fd); - fd = -1; - } + if (fd.IsDefined()) + fd.Close(); } int SignalFD::Read() { - assert(fd >= 0); + assert(fd.IsDefined()); signalfd_siginfo info; - return read(fd, &info, sizeof(info)) > 0 + return fd.Read(&info, sizeof(info)) > 0 ? info.ssi_signo : -1; } diff --git a/src/system/SignalFD.hxx b/src/system/SignalFD.hxx index 11bf30f74..dae150fea 100644 --- a/src/system/SignalFD.hxx +++ b/src/system/SignalFD.hxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright (C) 2003-2015 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,6 +21,7 @@ #define MPD_SIGNAL_FD_HXX #include "check.h" +#include "FileDescriptor.hxx" #include <signal.h> @@ -28,7 +29,7 @@ * A class that wraps signalfd(). */ class SignalFD { - int fd; + FileDescriptor fd; public: SignalFD():fd(-1) {} @@ -48,7 +49,7 @@ public: void Close(); int Get() const { - return fd; + return fd.Get(); } /** diff --git a/src/system/SocketError.cxx b/src/system/SocketError.cxx deleted file mode 100644 index e138f4dd3..000000000 --- a/src/system/SocketError.cxx +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "config.h" -#include "SocketError.hxx" -#include "util/Domain.hxx" - -#include <string.h> - -const Domain socket_domain("socket"); - -#ifdef WIN32 - -SocketErrorMessage::SocketErrorMessage(socket_error_t code) -{ - DWORD nbytes = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS | - FORMAT_MESSAGE_MAX_WIDTH_MASK, - NULL, code, 0, - (LPSTR)msg, sizeof(msg), NULL); - if (nbytes == 0) - strcpy(msg, "Unknown error"); -} - -#else - -SocketErrorMessage::SocketErrorMessage(socket_error_t code) - :msg(strerror(code)) {} - -#endif diff --git a/src/system/SocketError.hxx b/src/system/SocketError.hxx deleted file mode 100644 index 01abc9884..000000000 --- a/src/system/SocketError.hxx +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef MPD_SOCKET_ERROR_HXX -#define MPD_SOCKET_ERROR_HXX - -#include "Compiler.h" -#include "util/Error.hxx" // IWYU pragma: export - -#ifdef WIN32 -#include <winsock2.h> -typedef DWORD socket_error_t; -#else -#include <errno.h> -typedef int socket_error_t; -#endif - -class Domain; - -/** - * A #Domain for #Error for socket I/O errors. The code is an errno - * value (or WSAGetLastError() on Windows). - */ -extern const Domain socket_domain; - -gcc_pure -static inline socket_error_t -GetSocketError() -{ -#ifdef WIN32 - return WSAGetLastError(); -#else - return errno; -#endif -} - -gcc_const -static inline bool -IsSocketErrorAgain(socket_error_t code) -{ -#ifdef WIN32 - return code == WSAEINPROGRESS; -#else - return code == EAGAIN; -#endif -} - -gcc_const -static inline bool -IsSocketErrorInterruped(socket_error_t code) -{ -#ifdef WIN32 - return code == WSAEINTR; -#else - return code == EINTR; -#endif -} - -gcc_const -static inline bool -IsSocketErrorClosed(socket_error_t code) -{ -#ifdef WIN32 - return code == WSAECONNRESET; -#else - return code == EPIPE || code == ECONNRESET; -#endif -} - -/** - * Helper class that formats a socket error message into a - * human-readable string. On Windows, a buffer is necessary for this, - * and this class hosts the buffer. - */ -class SocketErrorMessage { -#ifdef WIN32 - char msg[256]; -#else - const char *const msg; -#endif - -public: -#ifdef WIN32 - explicit SocketErrorMessage(socket_error_t code=GetSocketError()); -#else - explicit SocketErrorMessage(socket_error_t code=GetSocketError()); -#endif - - operator const char *() const { - return msg; - } -}; - -static inline void -SetSocketError(Error &error, socket_error_t code) -{ - const SocketErrorMessage msg(code); - error.Set(socket_domain, code, msg); -} - -static inline void -SetSocketError(Error &error) -{ - SetSocketError(error, GetSocketError()); -} - -gcc_const -static inline Error -NewSocketError(socket_error_t code) -{ - Error error; - SetSocketError(error, code); - return error; -} - -gcc_pure -static inline Error -NewSocketError() -{ - return NewSocketError(GetSocketError()); -} - -#endif diff --git a/src/system/SocketUtil.cxx b/src/system/SocketUtil.cxx deleted file mode 100644 index b9df0d59d..000000000 --- a/src/system/SocketUtil.cxx +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "config.h" -#include "SocketUtil.hxx" -#include "SocketError.hxx" -#include "fd_util.h" - -#include <unistd.h> - -#ifndef WIN32 -#include <sys/socket.h> -#else -#include <ws2tcpip.h> -#include <winsock.h> -#endif - -#ifdef HAVE_IPV6 -#include <string.h> -#endif - -int -socket_bind_listen(int domain, int type, int protocol, - const struct sockaddr *address, size_t address_length, - int backlog, - Error &error) -{ - int fd, ret; - const int reuse = 1; - - fd = socket_cloexec_nonblock(domain, type, protocol); - if (fd < 0) { - SetSocketError(error); - error.AddPrefix("Failed to create socket: "); - return -1; - } - - ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, - (const char *) &reuse, sizeof(reuse)); - if (ret < 0) { - SetSocketError(error); - error.AddPrefix("setsockopt() failed: "); - close_socket(fd); - return -1; - } - - ret = bind(fd, address, address_length); - if (ret < 0) { - SetSocketError(error); - close_socket(fd); - return -1; - } - - ret = listen(fd, backlog); - if (ret < 0) { - SetSocketError(error); - error.AddPrefix("listen() failed: "); - close_socket(fd); - return -1; - } - -#ifdef HAVE_STRUCT_UCRED - setsockopt(fd, SOL_SOCKET, SO_PASSCRED, - (const char *) &reuse, sizeof(reuse)); -#endif - - return fd; -} - -int -socket_keepalive(int fd) -{ - const int reuse = 1; - - return setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, - (const char *)&reuse, sizeof(reuse)); -} diff --git a/src/system/SocketUtil.hxx b/src/system/SocketUtil.hxx deleted file mode 100644 index 652788759..000000000 --- a/src/system/SocketUtil.hxx +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -/* - * This library provides easy helper functions for working with - * sockets. - * - */ - -#ifndef MPD_SOCKET_UTIL_HXX -#define MPD_SOCKET_UTIL_HXX - -#include <stddef.h> - -struct sockaddr; -class Error; - -/** - * Creates a socket listening on the specified address. This is a - * shortcut for socket(), bind() and listen(). - * - * @param domain the socket domain, e.g. PF_INET6 - * @param type the socket type, e.g. SOCK_STREAM - * @param protocol the protocol, usually 0 to let the kernel choose - * @param address the address to listen on - * @param address_length the size of #address - * @param backlog the backlog parameter for the listen() system call - * @param error location to store the error occurring, or NULL to - * ignore errors - * @return the socket file descriptor or -1 on error - */ -int -socket_bind_listen(int domain, int type, int protocol, - const struct sockaddr *address, size_t address_length, - int backlog, - Error &error); - -int -socket_keepalive(int fd); - -#endif diff --git a/src/system/fd_util.c b/src/system/fd_util.c index b53ecda00..5763ede90 100644 --- a/src/system/fd_util.c +++ b/src/system/fd_util.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright (C) 2003-2015 The Music Player Daemon Project * http://www.musicpd.org * * Redistribution and use in source and binary forms, with or without @@ -41,10 +41,6 @@ #include <sys/socket.h> #endif -#ifdef HAVE_INOTIFY_INIT -#include <sys/inotify.h> -#endif - #ifdef USE_EVENTFD #include <sys/eventfd.h> #endif @@ -106,16 +102,6 @@ fd_set_nonblock(int fd) } int -dup_cloexec(int oldfd) -{ - int newfd = dup(oldfd); - if (newfd >= 0) - fd_set_nonblock(newfd); - - return newfd; -} - -int open_cloexec(const char *path_fs, int flags, int mode) { int fd; @@ -136,30 +122,6 @@ open_cloexec(const char *path_fs, int flags, int mode) } int -pipe_cloexec(int fd[2]) -{ -#ifdef WIN32 - return _pipe(fd, 512, _O_BINARY); -#else - int ret; - -#ifdef HAVE_PIPE2 - ret = pipe2(fd, O_CLOEXEC); - if (ret >= 0 || errno != ENOSYS) - return ret; -#endif - - ret = pipe(fd); - if (ret >= 0) { - fd_set_cloexec(fd[0], true); - fd_set_cloexec(fd[1], true); - } - - return ret; -#endif -} - -int pipe_cloexec_nonblock(int fd[2]) { #ifdef WIN32 @@ -186,53 +148,6 @@ pipe_cloexec_nonblock(int fd[2]) #endif } -#ifndef WIN32 - -int -socketpair_cloexec(int domain, int type, int protocol, int sv[2]) -{ - int ret; - -#ifdef SOCK_CLOEXEC - ret = socketpair(domain, type | SOCK_CLOEXEC, protocol, sv); - if (ret >= 0 || errno != EINVAL) - return ret; -#endif - - ret = socketpair(domain, type, protocol, sv); - if (ret >= 0) { - fd_set_cloexec(sv[0], true); - fd_set_cloexec(sv[1], true); - } - - return ret; -} - -int -socketpair_cloexec_nonblock(int domain, int type, int protocol, int sv[2]) -{ - int ret; - -#if defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK) - ret = socketpair(domain, type | SOCK_CLOEXEC | SOCK_NONBLOCK, protocol, - sv); - if (ret >= 0 || errno != EINVAL) - return ret; -#endif - - ret = socketpair(domain, type, protocol, sv); - if (ret >= 0) { - fd_set_cloexec(sv[0], true); - fd_set_nonblock(sv[0]); - fd_set_cloexec(sv[1], true); - fd_set_nonblock(sv[1]); - } - - return ret; -} - -#endif - int socket_cloexec_nonblock(int domain, int type, int protocol) { @@ -281,65 +196,6 @@ accept_cloexec_nonblock(int fd, struct sockaddr *address, return ret; } -#ifndef WIN32 - -ssize_t -recvmsg_cloexec(int sockfd, struct msghdr *msg, int flags) -{ -#ifdef MSG_CMSG_CLOEXEC - flags |= MSG_CMSG_CLOEXEC; -#endif - - ssize_t result = recvmsg(sockfd, msg, flags); - if (result >= 0) { - struct cmsghdr *cmsg = CMSG_FIRSTHDR(msg); - while (cmsg != NULL) { - if (cmsg->cmsg_type == SCM_RIGHTS) { - const int *fd_p = (const int *)CMSG_DATA(cmsg); - fd_set_cloexec(*fd_p, true); - } - - cmsg = CMSG_NXTHDR(msg, cmsg); - } - } - - return result; -} - -#endif - -#ifdef HAVE_INOTIFY_INIT - -int -inotify_init_cloexec(void) -{ - int fd; - -#ifdef HAVE_INOTIFY_INIT1 - fd = inotify_init1(IN_CLOEXEC); - if (fd >= 0 || errno != ENOSYS) - return fd; -#endif - - fd = inotify_init(); - if (fd >= 0) - fd_set_cloexec(fd, true); - - return fd; -} - -#endif - -#ifdef USE_EVENTFD - -int -eventfd_cloexec_nonblock(unsigned initval, int flags) -{ - return eventfd(initval, flags | EFD_CLOEXEC | EFD_NONBLOCK); -} - -#endif - int close_socket(int fd) { diff --git a/src/system/fd_util.h b/src/system/fd_util.h index f4a940e91..172b1ade3 100644 --- a/src/system/fd_util.h +++ b/src/system/fd_util.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright (C) 2003-2015 The Music Player Daemon Project * http://www.musicpd.org * * Redistribution and use in source and binary forms, with or without @@ -55,13 +55,6 @@ int fd_set_cloexec(int fd, bool enable); /** - * Wrapper for dup(), which sets the CLOEXEC flag on the new - * descriptor. - */ -int -dup_cloexec(int oldfd); - -/** * Wrapper for open(), which sets the CLOEXEC flag (atomically if * supported by the OS). */ @@ -71,13 +64,6 @@ open_cloexec(const char *path_fs, int flags, int mode); /** * Wrapper for pipe(), which sets the CLOEXEC flag (atomically if * supported by the OS). - */ -int -pipe_cloexec(int fd[2]); - -/** - * Wrapper for pipe(), which sets the CLOEXEC flag (atomically if - * supported by the OS). * * On systems that supports it (everybody except for Windows), it also * sets the NONBLOCK flag. @@ -85,25 +71,7 @@ pipe_cloexec(int fd[2]); int pipe_cloexec_nonblock(int fd[2]); -#ifndef WIN32 - -/** - * Wrapper for socketpair(), which sets the CLOEXEC flag (atomically - * if supported by the OS). - */ -int -socketpair_cloexec(int domain, int type, int protocol, int sv[2]); - -/** - * Wrapper for socketpair(), which sets the flags CLOEXEC and NONBLOCK - * (atomically if supported by the OS). - */ -int -socketpair_cloexec_nonblock(int domain, int type, int protocol, int sv[2]); - -#endif - -#ifdef HAVE_LIBMPDCLIENT +#ifdef ENABLE_LIBMPDCLIENT /* Avoid symbol conflict with statically linked libmpdclient */ #define socket_cloexec_nonblock socket_cloexec_nonblock_noconflict #endif @@ -123,42 +91,6 @@ int accept_cloexec_nonblock(int fd, struct sockaddr *address, size_t *address_length_r); - -#ifndef WIN32 - -struct msghdr; - -/** - * Wrapper for recvmsg(), which sets the CLOEXEC flag (atomically if - * supported by the OS). - */ -ssize_t -recvmsg_cloexec(int sockfd, struct msghdr *msg, int flags); - -#endif - -#ifdef HAVE_INOTIFY_INIT - -/** - * Wrapper for inotify_init(), which sets the CLOEXEC flag (atomically - * if supported by the OS). - */ -int -inotify_init_cloexec(void); - -#endif - -#ifdef USE_EVENTFD - -/** - * Wrapper for eventfd() which sets the flags CLOEXEC and NONBLOCK - * flag (atomically if supported by the OS). - */ -int -eventfd_cloexec_nonblock(unsigned initval, int flags); - -#endif - /** * Portable wrapper for close(); use closesocket() on WIN32/WinSock. */ |