diff options
Diffstat (limited to 'src/common/compat.h')
-rw-r--r-- | src/common/compat.h | 199 |
1 files changed, 71 insertions, 128 deletions
diff --git a/src/common/compat.h b/src/common/compat.h index 531e88f1bd..8cf84580c6 100644 --- a/src/common/compat.h +++ b/src/common/compat.h @@ -1,26 +1,18 @@ /* Copyright (c) 2003-2004, Roger Dingledine * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2013, The Tor Project, Inc. */ + * Copyright (c) 2007-2016, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #ifndef TOR_COMPAT_H #define TOR_COMPAT_H #include "orconfig.h" -#include "torint.h" -#include "testsupport.h" #ifdef _WIN32 -#ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x0501 -#endif -#define WIN32_LEAN_AND_MEAN -#if defined(_MSC_VER) && (_MSC_VER < 1300) -#include <winsock.h> -#else #include <winsock2.h> #include <ws2tcpip.h> #endif -#endif +#include "torint.h" +#include "testsupport.h" #ifdef HAVE_SYS_PARAM_H #include <sys/param.h> #endif @@ -36,9 +28,6 @@ #ifdef HAVE_STRING_H #include <string.h> #endif -#if defined(HAVE_PTHREAD_H) && !defined(_WIN32) -#include <pthread.h> -#endif #include <stdarg.h> #ifdef HAVE_SYS_RESOURCE_H #include <sys/resource.h> @@ -53,24 +42,18 @@ #include <netinet6/in6.h> #endif +#if defined(__has_feature) +# if __has_feature(address_sanitizer) +/* Some of the fancy glibc strcmp() macros include references to memory that + * clang rejects because it is off the end of a less-than-3. Clang hates this, + * even though those references never actually happen. */ +# undef strcmp +# endif +#endif + #include <stdio.h> #include <errno.h> -#if defined (WINCE) -#include <fcntl.h> -#include <io.h> -#include <math.h> -#include <projects.h> -/* this is not exported as W .... */ -#define SHGetPathFromIDListW SHGetPathFromIDList -/* wcecompat has vasprintf */ -#define HAVE_VASPRINTF -/* no service here */ -#ifdef NT_SERVICE -#undef NT_SERVICE -#endif -#endif // WINCE - #ifndef NULL_REP_IS_ZERO_BYTES #error "It seems your platform does not represent NULL as zero. We can't cope." #endif @@ -101,20 +84,13 @@ /* inline is __inline on windows. */ #ifdef _WIN32 -#define INLINE __inline -#else -#define INLINE inline +#define inline __inline #endif /* Try to get a reasonable __func__ substitute in place. */ #if defined(_MSC_VER) -/* MSVC compilers before VC7 don't have __func__ at all; later ones call it - * __FUNCTION__. */ -#if _MSC_VER < 1300 -#define __func__ "???" -#else + #define __func__ __FUNCTION__ -#endif #else /* For platforms where autoconf works, make sure __func__ is defined @@ -130,18 +106,8 @@ #endif /* ifndef MAVE_MACRO__func__ */ #endif /* if not windows */ -#if defined(_MSC_VER) && (_MSC_VER < 1300) -/* MSVC versions before 7 apparently don't believe that you can cast uint64_t - * to double and really mean it. */ -extern INLINE double U64_TO_DBL(uint64_t x) { - int64_t i = (int64_t) x; - return (i < 0) ? ((double) INT64_MAX) : (double) i; -} -#define DBL_TO_U64(x) ((uint64_t)(int64_t) (x)) -#else #define U64_TO_DBL(x) ((double) (x)) #define DBL_TO_U64(x) ((uint64_t) (x)) -#endif #ifdef ENUM_VALS_ARE_SIGNED #define ENUM_BF(t) unsigned @@ -159,6 +125,7 @@ extern INLINE double U64_TO_DBL(uint64_t x) { #define ATTR_CONST __attribute__((const)) #define ATTR_MALLOC __attribute__((malloc)) #define ATTR_NORETURN __attribute__((noreturn)) +#define ATTR_WUR __attribute__((warn_unused_result)) /* Alas, nonnull is not at present a good idea for us. We'd like to get * warnings when we pass NULL where we shouldn't (which nonnull does, albeit * spottily), but we don't want to tell the compiler to make optimizations @@ -194,6 +161,7 @@ extern INLINE double U64_TO_DBL(uint64_t x) { #define ATTR_NORETURN #define ATTR_NONNULL(x) #define ATTR_UNUSED +#define ATTR_WUR #define PREDICT_LIKELY(exp) (exp) #define PREDICT_UNLIKELY(exp) (exp) #endif @@ -218,6 +186,15 @@ extern INLINE double U64_TO_DBL(uint64_t x) { #define STMT_END } while (0) #endif +/* Some tools (like coccinelle) don't like to see operators as macro + * arguments. */ +#define OP_LT < +#define OP_GT > +#define OP_GE >= +#define OP_LE <= +#define OP_EQ == +#define OP_NE != + /* ===== String compatibility */ #ifdef _WIN32 /* Windows names string functions differently from most other platforms. */ @@ -320,7 +297,7 @@ const void *tor_memmem(const void *haystack, size_t hlen, const void *needle, size_t nlen) ATTR_NONNULL((1,3)); static const void *tor_memstr(const void *haystack, size_t hlen, const char *needle) ATTR_NONNULL((1,3)); -static INLINE const void * +static inline const void * tor_memstr(const void *haystack, size_t hlen, const char *needle) { return tor_memmem(haystack, hlen, needle, strlen(needle)); @@ -331,7 +308,7 @@ tor_memstr(const void *haystack, size_t hlen, const char *needle) #define DECLARE_CTYPE_FN(name) \ static int TOR_##name(char c); \ extern const uint32_t TOR_##name##_TABLE[]; \ - static INLINE int TOR_##name(char c) { \ + static inline int TOR_##name(char c) { \ uint8_t u = c; \ return !!(TOR_##name##_TABLE[(u >> 5) & 7] & (1u << (u & 31))); \ } @@ -435,6 +412,9 @@ void tor_lockfile_unlock(tor_lockfile_t *lockfile); off_t tor_fd_getpos(int fd); int tor_fd_setpos(int fd, off_t pos); int tor_fd_seekend(int fd); +int tor_ftruncate(int fd); + +int64_t tor_get_avail_disk_space(const char *path); #ifdef _WIN32 #define PATH_SEPARATOR "\\" @@ -471,7 +451,8 @@ int tor_close_socket(tor_socket_t s); tor_socket_t tor_open_socket_with_extensions( int domain, int type, int protocol, int cloexec, int nonblock); -tor_socket_t tor_open_socket(int domain, int type, int protocol); +MOCK_DECL(tor_socket_t, +tor_open_socket,(int domain, int type, int protocol)); tor_socket_t tor_open_socket_nonblocking(int domain, int type, int protocol); tor_socket_t tor_accept_socket(tor_socket_t sockfd, struct sockaddr *addr, socklen_t *len); @@ -482,8 +463,15 @@ tor_socket_t tor_accept_socket_with_extensions(tor_socket_t sockfd, struct sockaddr *addr, socklen_t *len, int cloexec, int nonblock); +MOCK_DECL(tor_socket_t, +tor_connect_socket,(tor_socket_t socket,const struct sockaddr *address, + socklen_t address_len)); int get_n_open_sockets(void); +MOCK_DECL(int, +tor_getsockname,(tor_socket_t socket, struct sockaddr *address, + socklen_t *address_len)); + #define tor_socket_send(s, buf, len, flags) send(s, buf, len, flags) #define tor_socket_recv(s, buf, len, flags) recv(s, buf, len, flags) @@ -549,10 +537,11 @@ struct sockaddr_in6 { }; #endif +MOCK_DECL(int,tor_gethostname,(char *name, size_t namelen)); int tor_inet_aton(const char *cp, struct in_addr *addr) ATTR_NONNULL((1,2)); const char *tor_inet_ntop(int af, const void *src, char *dst, size_t len); int tor_inet_pton(int af, const char *src, void *dst); -int tor_lookup_hostname(const char *name, uint32_t *addr) ATTR_NONNULL((1,2)); +MOCK_DECL(int,tor_lookup_hostname,(const char *name, uint32_t *addr)); int set_socket_nonblocking(tor_socket_t socket); int tor_socketpair(int family, int type, int protocol, tor_socket_t fd[2]); int network_init(void); @@ -579,26 +568,30 @@ int network_init(void); #define ERRNO_IS_ACCEPT_EAGAIN(e) ERRNO_IS_EAGAIN(e) /** Return true if e is EMFILE or another error indicating that a call to * accept() has failed because we're out of fds or something. */ -#define ERRNO_IS_ACCEPT_RESOURCE_LIMIT(e) \ +#define ERRNO_IS_RESOURCE_LIMIT(e) \ ((e) == WSAEMFILE || (e) == WSAENOBUFS) /** Return true if e is EADDRINUSE or the local equivalent. */ #define ERRNO_IS_EADDRINUSE(e) ((e) == WSAEADDRINUSE) +/** Return true if e is EINTR or the local equivalent */ +#define ERRNO_IS_EINTR(e) ((e) == WSAEINTR || 0) int tor_socket_errno(tor_socket_t sock); const char *tor_socket_strerror(int e); #else #define SOCK_ERRNO(e) e #if EAGAIN == EWOULDBLOCK -#define ERRNO_IS_EAGAIN(e) ((e) == EAGAIN) +/* || 0 is for -Wparentheses-equality (-Wall?) appeasement under clang */ +#define ERRNO_IS_EAGAIN(e) ((e) == EAGAIN || 0) #else #define ERRNO_IS_EAGAIN(e) ((e) == EAGAIN || (e) == EWOULDBLOCK) #endif -#define ERRNO_IS_EINPROGRESS(e) ((e) == EINPROGRESS) -#define ERRNO_IS_CONN_EINPROGRESS(e) ((e) == EINPROGRESS) +#define ERRNO_IS_EINTR(e) ((e) == EINTR || 0) +#define ERRNO_IS_EINPROGRESS(e) ((e) == EINPROGRESS || 0) +#define ERRNO_IS_CONN_EINPROGRESS(e) ((e) == EINPROGRESS || 0) #define ERRNO_IS_ACCEPT_EAGAIN(e) \ (ERRNO_IS_EAGAIN(e) || (e) == ECONNABORTED) -#define ERRNO_IS_ACCEPT_RESOURCE_LIMIT(e) \ +#define ERRNO_IS_RESOURCE_LIMIT(e) \ ((e) == EMFILE || (e) == ENFILE || (e) == ENOBUFS || (e) == ENOMEM) -#define ERRNO_IS_EADDRINUSE(e) ((e) == EADDRINUSE) +#define ERRNO_IS_EADDRINUSE(e) (((e) == EADDRINUSE) || 0) #define tor_socket_errno(sock) (errno) #define tor_socket_strerror(e) strerror(e) #endif @@ -617,7 +610,7 @@ typedef enum { } socks5_reply_status_t; /* ===== OS compatibility */ -const char *get_uname(void); +MOCK_DECL(const char *, get_uname, (void)); uint16_t get_uint16(const void *cp) ATTR_NONNULL((1)); uint32_t get_uint32(const void *cp) ATTR_NONNULL((1)); @@ -629,7 +622,7 @@ void set_uint64(void *cp, uint64_t v) ATTR_NONNULL((1)); /* These uint8 variants are defined to make the code more uniform. */ #define get_uint8(cp) (*(const uint8_t*)(cp)) static void set_uint8(void *cp, uint8_t v); -static INLINE void +static inline void set_uint8(void *cp, uint8_t v) { *(uint8_t*)cp = v; @@ -638,9 +631,21 @@ set_uint8(void *cp, uint8_t v) #if !defined(HAVE_RLIM_T) typedef unsigned long rlim_t; #endif +int get_max_sockets(void); int set_max_file_descriptors(rlim_t limit, int *max); int tor_disable_debugger_attach(void); -int switch_id(const char *user); + +#if defined(HAVE_SYS_CAPABILITY_H) && defined(HAVE_CAP_SET_PROC) +#define HAVE_LINUX_CAPABILITIES +#endif + +int have_capability_support(void); + +/** Flag for switch_id; see switch_id() for documentation */ +#define SWITCH_ID_KEEP_BINDLOW (1<<0) +/** Flag for switch_id; see switch_id() for documentation */ +#define SWITCH_ID_WARN_IF_NO_CAPS (1<<1) +int switch_id(const char *user, unsigned flags); #ifdef HAVE_PWD_H char *get_user_homedir(const char *username); #endif @@ -657,77 +662,10 @@ char **get_environment(void); int get_total_system_memory(size_t *mem_out); -int spawn_func(void (*func)(void *), void *data); -void spawn_exit(void) ATTR_NORETURN; - -#if defined(ENABLE_THREADS) && defined(_WIN32) -#define USE_WIN32_THREADS -#define TOR_IS_MULTITHREADED 1 -#elif (defined(ENABLE_THREADS) && defined(HAVE_PTHREAD_H) && \ - defined(HAVE_PTHREAD_CREATE)) -#define USE_PTHREADS -#define TOR_IS_MULTITHREADED 1 -#else -#undef TOR_IS_MULTITHREADED -#endif - int compute_num_cpus(void); -/* Because we use threads instead of processes on most platforms (Windows, - * Linux, etc), we need locking for them. On platforms with poor thread - * support or broken gethostbyname_r, these functions are no-ops. */ - -/** A generic lock structure for multithreaded builds. */ -typedef struct tor_mutex_t { -#if defined(USE_WIN32_THREADS) - /** Windows-only: on windows, we implement locks with CRITICAL_SECTIONS. */ - CRITICAL_SECTION mutex; -#elif defined(USE_PTHREADS) - /** Pthreads-only: with pthreads, we implement locks with - * pthread_mutex_t. */ - pthread_mutex_t mutex; -#else - /** No-threads only: Dummy variable so that tor_mutex_t takes up space. */ - int _unused; -#endif -} tor_mutex_t; - int tor_mlockall(void); -#ifdef TOR_IS_MULTITHREADED -tor_mutex_t *tor_mutex_new(void); -void tor_mutex_init(tor_mutex_t *m); -void tor_mutex_acquire(tor_mutex_t *m); -void tor_mutex_release(tor_mutex_t *m); -void tor_mutex_free(tor_mutex_t *m); -void tor_mutex_uninit(tor_mutex_t *m); -unsigned long tor_get_thread_id(void); -void tor_threads_init(void); -#else -#define tor_mutex_new() ((tor_mutex_t*)tor_malloc(sizeof(int))) -#define tor_mutex_init(m) STMT_NIL -#define tor_mutex_acquire(m) STMT_VOID(m) -#define tor_mutex_release(m) STMT_NIL -#define tor_mutex_free(m) STMT_BEGIN tor_free(m); STMT_END -#define tor_mutex_uninit(m) STMT_NIL -#define tor_get_thread_id() (1UL) -#define tor_threads_init() STMT_NIL -#endif - -void set_main_thread(void); -int in_main_thread(void); - -#ifdef TOR_IS_MULTITHREADED -#if 0 -typedef struct tor_cond_t tor_cond_t; -tor_cond_t *tor_cond_new(void); -void tor_cond_free(tor_cond_t *cond); -int tor_cond_wait(tor_cond_t *cond, tor_mutex_t *mutex); -void tor_cond_signal_one(tor_cond_t *cond); -void tor_cond_signal_all(tor_cond_t *cond); -#endif -#endif - /** Macros for MIN/MAX. Never use these when the arguments could have * side-effects. * {With GCC extensions we could probably define a safer MIN/MAX. But @@ -773,5 +711,10 @@ STATIC int tor_ersatz_socketpair(int family, int type, int protocol, #endif #endif +ssize_t tor_getpass(const char *prompt, char *output, size_t buflen); + +/* This needs some of the declarations above so we include it here. */ +#include "compat_threads.h" + #endif |