diff options
Diffstat (limited to 'src/common/compat.h')
-rw-r--r-- | src/common/compat.h | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/src/common/compat.h b/src/common/compat.h new file mode 100644 index 000000000..afc8af41f --- /dev/null +++ b/src/common/compat.h @@ -0,0 +1,168 @@ +/* Copyright 2003-2004 Roger Dingledine; Copyright 2004 Nick Mathewson */ +/* See LICENSE for licensing information */ +/* $Id$ */ + +#ifndef __COMPAT_H +#define __COMPAT_H + +#include "orconfig.h" +#include "torint.h" +#ifdef MS_WINDOWS +#define WIN32_WINNT 0x400 +#define _WIN32_WINNT 0x400 +#define WIN32_LEAN_AND_MEAN +#if (_MSC_VER <= 1300) +#include <winsock.h> +#else +#include <winsock2.h> +#include <ws2tcpip.h> +#endif +#endif +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#include <stdarg.h> + +#ifndef NULL_REP_IS_ZERO_BYTES +#error "It seems your platform does not represent NULL as zero. We can't cope." +#endif + +/* ===== Compiler compatibility */ + +/* GCC can check printf types on arbitrary functions. */ +#ifdef __GNUC__ +#define CHECK_PRINTF(formatIdx, firstArg) \ + __attribute__ ((format (printf, formatIdx, firstArg))) +#else +#define CHECK_PRINTF(formatIdx, firstArg) +#endif + +/* inline is __inline on windows. */ +#ifdef MS_WINDOWS +#define INLINE __inline +#else +#define INLINE inline +#endif + +/* Windows compilers before VC7 don't have __FUNCTION__. */ +#if defined(_MSC_VER) && _MSC_VER < 1300 +#define __FUNCTION__ "???" +#endif + +/* ===== String compatibility */ +#ifdef MS_WINDOWS +/* Windows names string functions differently from most other platforms. */ +#define strncasecmp strnicmp +#define strcasecmp stricmp +#endif + +int tor_snprintf(char *str, size_t size, const char *format, ...) + CHECK_PRINTF(3,4); +int tor_vsnprintf(char *str, size_t size, const char *format, va_list args); + +/* ===== Time compatibility */ +#if !defined(HAVE_GETTIMEOFDAY) && !defined(HAVE_STRUCT_TIMEVAL_TV_SEC) +struct timeval { + time_t tv_sec; + unsigned int tv_usec; +}; +#endif + +void tor_gettimeofday(struct timeval *timeval); + +/* ===== File compatibility */ +int replace_file(const char *from, const char *to); + +/* ===== Net compatibility */ +#ifdef MS_WINDOWS +/** On windows, you have to call close() on fds returned by open(), + * and closesocket() on fds returned by socket(). On Unix, everything + * gets close()'d. We abstract this difference by always using + * tor_close_socket to close sockets, and always using close() on + * files. + */ +#define tor_close_socket(s) closesocket(s) +#else +#define tor_close_socket(s) close(s) +#endif + +struct in_addr; +int tor_inet_aton(const char *cp, struct in_addr *addr); +void set_socket_nonblocking(int socket); +int tor_socketpair(int family, int type, int protocol, int fd[2]); +/* For stupid historical reasons, windows sockets have an independent + * set of errnos, and an independent way to get them. Also, you can't + * always believe WSAEWOULDBLOCK. Use the macros below to compare + * errnos against expected values, and use tor_socket_errno to find + * the actual errno after a socket operation fails. + */ +#ifdef MS_WINDOWS +/** Return true if e is EAGAIN or the local equivalent. */ +#define ERRNO_IS_EAGAIN(e) ((e) == EAGAIN || (e) == WSAEWOULDBLOCK) +/** Return true if e is EINPROGRESS or the local equivalent. */ +#define ERRNO_IS_EINPROGRESS(e) ((e) == WSAEINPROGRESS) +/** Return true if e is EINPROGRESS or the local equivalent as returned by + * a call to connect(). */ +#define ERRNO_IS_CONN_EINPROGRESS(e) ((e) == WSAEINPROGRESS || (e)== WSAEINVAL) +/** Return true if e is EAGAIN or another error indicating that a call to + * accept() has no pending connections to return. */ +#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) \ + ((e) == WSAEMFILE || (e) == WSAENOBUFS) +int tor_socket_errno(int sock); +const char *tor_socket_strerror(int e); +#else +#define ERRNO_IS_EAGAIN(e) ((e) == EAGAIN) +#define ERRNO_IS_EINPROGRESS(e) ((e) == EINPROGRESS) +#define ERRNO_IS_CONN_EINPROGRESS(e) ((e) == EINPROGRESS) +#define ERRNO_IS_ACCEPT_EAGAIN(e) ((e) == EAGAIN || (e) == ECONNABORTED) +#define ERRNO_IS_ACCEPT_RESOURCE_LIMIT(e) \ + ((e) == EMFILE || (e) == ENFILE || (e) == ENOBUFS || (e) == ENOMEM) +#define tor_socket_errno(sock) (errno) +#define tor_socket_strerror(e) strerror(e) +#endif + +/* ===== OS compatibility */ +const char *get_uname(void); + +/* Some platforms segfault when you try to access a multi-byte type + * that isn't aligned to a word boundary. The macros and/or functions + * below can be used to access unaligned data on any platform. + */ +#ifdef UNALIGNED_INT_ACCESS_OK +#define get_uint16(cp) (*(uint16_t*)(cp)) +#define get_uint32(cp) (*(uint32_t*)(cp)) +#define set_uint16(cp,v) do { *(uint16_t*)(cp) = (v); } while (0) +#define set_uint32(cp,v) do { *(uint32_t*)(cp) = (v); } while (0) +#else +uint16_t get_uint16(const char *cp); +uint32_t get_uint32(const char *cp); +void set_uint16(char *cp, uint16_t v); +void set_uint32(char *cp, uint32_t v); +#endif + +int set_max_file_descriptors(int required_min); +int switch_id(char *user, char *group); + +int spawn_func(int (*func)(void *), void *data); +void spawn_exit(void); + +/* Because we use threads instead of processes on Windows, we need locking on + * Windows. On Unixy platforms, these functions are no-ops. */ +typedef struct tor_mutex_t tor_mutex_t; +tor_mutex_t *tor_mutex_new(void); +void tor_mutex_acquire(tor_mutex_t *m); +void tor_mutex_release(tor_mutex_t *m); +void tor_mutex_free(tor_mutex_t *m); + +#endif + +/* + Local Variables: + mode:c + indent-tabs-mode:nil + c-basic-offset:2 + End: +*/ |