Back to index

tor  0.2.3.18-rc
Classes | Defines | Functions | Variables
compat.c File Reference

Wrappers to make calls more portable. More...

#include "compat.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "torlog.h"
#include "util.h"
#include "container.h"
#include "address.h"
#include "strlcpy.c"
#include "strlcat.c"

Go to the source code of this file.

Classes

struct  tor_lockfile_t
 Represents a lockfile on which we hold the lock. More...

Defines

#define _GNU_SOURCE
#define ULIMIT_BUFFER   32 /* keep 32 extra fd's beyond _ConnLimit */
 Number of extra file descriptors to keep in reserve beyond those that we tell Tor it's allowed to use.
#define CREDENTIAL_LOG_LEVEL   LOG_INFO
#define START_PATH_LENGTH   128
#define MAX_SANE_PATH_LENGTH   4096
#define MAX_DETECTABLE_CPUS   16
#define SEEK_CUR   1
 Some old versions of Unix didn't define constants for these values, and instead expect you to say 0, 1, or 2.
#define SEEK_END   2
#define mark_socket_open(s)   STMT_NIL

Functions

int tor_open_cloexec (const char *path, int flags, unsigned mode)
 As open(path, flags, mode), but return an fd with the close-on-exec mode set.
FILE * tor_fopen_cloexec (const char *path, const char *mode)
 As fopen(path,mode), but ensures that the O_CLOEXEC bit is set on the underlying file handle.
tor_mmap_ttor_mmap_file (const char *filename)
void tor_munmap_file (tor_mmap_t *handle)
int tor_snprintf (char *str, size_t size, const char *format,...)
 Replacement for snprintf.
int tor_vsnprintf (char *str, size_t size, const char *format, va_list args)
 Replacement for vsnprintf; behavior differs as tor_snprintf differs from snprintf.
int tor_asprintf (char **strp, const char *fmt,...)
 Portable asprintf implementation.
int tor_vasprintf (char **strp, const char *fmt, va_list args)
 Portable vasprintf implementation.
const void * tor_memmem (const void *_haystack, size_t hlen, const void *_needle, size_t nlen)
 Given hlen bytes at haystack and nlen bytes at needle, return a pointer to the first occurrence of the needle within the haystack, or NULL if there is no such occurrence.
static char * strtok_helper (char *cp, const char *sep)
 Helper for tor_strtok_r_impl: Advances cp past all characters in sep, and returns its new value.
char * tor_strtok_r_impl (char *str, const char *sep, char **lasts)
 Implementation of strtok_r for platforms whose coders haven't figured out how to write one.
uint16_t get_uint16 (const void *cp)
 Read a 16-bit value beginning at cp.
uint32_t get_uint32 (const void *cp)
 Read a 32-bit value beginning at cp.
uint64_t get_uint64 (const void *cp)
 Read a 64-bit value beginning at cp.
void set_uint16 (void *cp, uint16_t v)
 Set a 16-bit value beginning at cp to v.
void set_uint32 (void *cp, uint32_t v)
 Set a 32-bit value beginning at cp to v.
void set_uint64 (void *cp, uint64_t v)
 Set a 64-bit value beginning at cp to v.
int replace_file (const char *from, const char *to)
 Rename the file from to the file to.
int touch_file (const char *fname)
 Change fname's modification time to now.
tor_lockfile_ttor_lockfile_lock (const char *filename, int blocking, int *locked_out)
 Try to get a lock on the lockfile filename, creating it as necessary.
void tor_lockfile_unlock (tor_lockfile_t *lockfile)
 Release the lock held as lockfile.
off_t tor_fd_getpos (int fd)
 Return the position of fd with respect to the start of the file.
int tor_fd_seekend (int fd)
 Move fd to the end of the file.
static INLINE void socket_accounting_lock (void)
 Helper: acquire the socket accounting lock.
static INLINE void socket_accounting_unlock (void)
 Helper: release the socket accounting lock.
int tor_close_socket (tor_socket_t s)
 As close(), but guaranteed to work for sockets across platforms (including Windows, where close()ing a socket doesn't work.
tor_socket_t tor_open_socket (int domain, int type, int protocol)
 As socket(), but counts the number of open sockets.
tor_socket_t tor_accept_socket (tor_socket_t sockfd, struct sockaddr *addr, socklen_t *len)
 As socket(), but counts the number of open sockets.
int get_n_open_sockets (void)
 Return the number of sockets we currently have opened.
void set_socket_nonblocking (tor_socket_t socket)
 Turn socket into a nonblocking socket.
int tor_socketpair (int family, int type, int protocol, tor_socket_t fd[2])
 Allocate a pair of connected sockets.
int set_max_file_descriptors (rlim_t limit, int *max_out)
 Learn the maximum allowed number of file descriptors, and tell the system we want to use up to that number.
static int log_credential_status (void)
 Log details of current user and group credentials.
int switch_id (const char *user)
 Call setuid and setgid to run as user and switch to their primary group.
int tor_disable_debugger_attach (void)
 Attempt to disable debugger attachment: return 1 on success, -1 on failure, and 0 if we don't know how to try on this platform.
int get_parent_directory (char *fname)
 Modify fname to contain the name of its parent directory.
static char * alloc_getcwd (void)
 Return a newly allocated string containing the output of getcwd().
char * make_path_absolute (char *fname)
 Expand possibly relative path fname to an absolute path.
char ** get_environment (void)
 Return the current environment.
int tor_inet_aton (const char *str, struct in_addr *addr)
 Set *addr to the IP address (in dotted-quad notation) stored in c.
const char * tor_inet_ntop (int af, const void *src, char *dst, size_t len)
 Given af==AF_INET and src a struct in_addr, or af==AF_INET6 and src a struct in6_addr, try to format the address and store it in the len-byte buffer dst.
int tor_inet_pton (int af, const char *src, void *dst)
 Given af==AF_INET or af==AF_INET6, and a string src encoding an IPv4 address or IPv6 address correspondingly, try to parse the address and store the result in dst (which must have space for a struct in_addr or a struct in6_addr, as appropriate).
int tor_lookup_hostname (const char *name, uint32_t *addr)
 Similar behavior to Unix gethostbyname: resolve name, and set *addr to the proper IP address, in host byte order.
void tor_init_weak_random (unsigned seed)
 Initialize the insecure libc RNG.
long tor_weak_random (void)
 Return a randomly chosen value in the range 0..TOR_RAND_MAX.
const char * get_uname (void)
 Return a pointer to a description of our platform.
int spawn_func (void(*func)(void *), void *data)
 Minimalist interface to run a void function in the background.
void spawn_exit (void)
 End the current thread/process.
static int compute_num_cpus_impl (void)
 Implementation logic for compute_num_cpus().
int compute_num_cpus (void)
 Return how many CPUs we are running with.
void tor_gettimeofday (struct timeval *timeval)
 Set *timeval to the current time of day.
static struct tm * correct_tm (int islocal, const time_t *timep, struct tm *resultbuf, struct tm *r)
 Helper: Deal with confused or out-of-bounds values from localtime_r and friends.
struct tm * tor_localtime_r (const time_t *timep, struct tm *result)
 As localtime_r, but defined for platforms that don't have it:

Variables

static int n_sockets_open = 0
 Count of number of sockets currently open.
static tor_mutex_tsocket_accounting_mutex = NULL
 Mutex to protect open_sockets, max_socket, and n_sockets_open.
char ** environ
static char uname_result [256]
 Hold the result of our call to uname.
static int uname_result_is_set = 0
 True iff uname_result is set.
const uint32_t TOR_ISALPHA_TABLE [8]
 Tables to implement ctypes-replacement TOR_IS*() functions.
const uint32_t TOR_ISALNUM_TABLE [8]
const uint32_t TOR_ISSPACE_TABLE [8] = { 0x3e00, 0x1, 0, 0, 0, 0, 0, 0 }
const uint32_t TOR_ISXDIGIT_TABLE [8]
const uint32_t TOR_ISDIGIT_TABLE [8] = { 0, 0x3ff0000, 0, 0, 0, 0, 0, 0 }
const uint32_t TOR_ISPRINT_TABLE [8]
const uint32_t TOR_ISUPPER_TABLE [8] = { 0, 0, 0x7fffffe, 0, 0, 0, 0, 0 }
const uint32_t TOR_ISLOWER_TABLE [8] = { 0, 0, 0, 0x7fffffe, 0, 0, 0, 0 }
const char TOR_TOUPPER_TABLE [256]
 Upper-casing and lowercasing tables to map characters to upper/lowercase equivalents.
const char TOR_TOLOWER_TABLE [256]
static unsigned long main_thread_id = -1
 Identity of the "main" thread.
struct tm * tor_gmtime_r (const time_t *timep, struct tm *result)
 As gmtimee_r, but defined for platforms that don't have it:
int tor_mlockall (void)
 Attempt to lock all current and all future memory pages.
void set_main_thread (void)
 Start considering the current thread to be the 'main thread'.
int in_main_thread (void)
 Return true iff called from the main thread.
int network_init (void)
 On Windows, WSAEWOULDBLOCK is not always correct: when you see it, you need to ask the socket for its actual errno.

Detailed Description

Wrappers to make calls more portable.

This code defines functions such as tor_malloc, tor_snprintf, get/set various data types, renaming, setting socket options, switching user IDs. It is basically where the non-portable items are conditionally included depending on the platform.

Definition in file compat.c.


Class Documentation

struct tor_lockfile_t

Represents a lockfile on which we hold the lock.

Definition at line 752 of file compat.c.

Class Members
int fd File descriptor used to hold the file open.
char * filename Name of the file.

Define Documentation

#define _GNU_SOURCE

Definition at line 24 of file compat.c.

#define mark_socket_open (   s)    STMT_NIL

Definition at line 1003 of file compat.c.

#define MAX_DETECTABLE_CPUS   16

Definition at line 2304 of file compat.c.

#define MAX_SANE_PATH_LENGTH   4096
#define SEEK_CUR   1

Some old versions of Unix didn't define constants for these values, and instead expect you to say 0, 1, or 2.

Definition at line 865 of file compat.c.

#define SEEK_END   2

Definition at line 868 of file compat.c.

#define START_PATH_LENGTH   128
#define ULIMIT_BUFFER   32 /* keep 32 extra fd's beyond _ConnLimit */

Number of extra file descriptors to keep in reserve beyond those that we tell Tor it's allowed to use.

Definition at line 1259 of file compat.c.


Function Documentation

static char* alloc_getcwd ( void  ) [static]

Return a newly allocated string containing the output of getcwd().

Return NULL on failure. (We can't just use getcwd() into a PATH_MAX buffer, since Hurd hasn't got a PATH_MAX.)

Definition at line 1737 of file compat.c.

{
    int saved_errno = errno;
/* We use this as a starting path length. Not too large seems sane. */
#define START_PATH_LENGTH 128
/* Nobody has a maxpath longer than this, as far as I know.  And if they
 * do, they shouldn't. */
#define MAX_SANE_PATH_LENGTH 4096
    size_t path_length = START_PATH_LENGTH;
    char *path = tor_malloc(path_length);

    errno = 0;
    while (getcwd(path, path_length) == NULL) {
      if (errno == ERANGE && path_length < MAX_SANE_PATH_LENGTH) {
        path_length*=2;
        path = tor_realloc(path, path_length);
      } else {
        tor_free(path);
        path = NULL;
        break;
      }
    }
    errno = saved_errno;
    return path;
}

Here is the caller graph for this function:

int compute_num_cpus ( void  )

Return how many CPUs we are running with.

We assume that nobody is using hot-swappable CPUs, so we don't recompute this after the first time. Return -1 if we don't know how to tell the number of CPUs on this system.

Definition at line 2312 of file compat.c.

{
  static int num_cpus = -2;
  if (num_cpus == -2) {
    num_cpus = compute_num_cpus_impl();
    tor_assert(num_cpus != -2);
    if (num_cpus > MAX_DETECTABLE_CPUS)
      log_notice(LD_GENERAL, "Wow!  I detected that you have %d CPUs. I "
                 "will not autodetect any more than %d, though.  If you "
                 "want to configure more, set NumCPUs in your torrc",
                 num_cpus, MAX_DETECTABLE_CPUS);
  }
  return num_cpus;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int compute_num_cpus_impl ( void  ) [static]

Implementation logic for compute_num_cpus().

Definition at line 2283 of file compat.c.

{
#ifdef _WIN32
  SYSTEM_INFO info;
  memset(&info, 0, sizeof(info));
  GetSystemInfo(&info);
  if (info.dwNumberOfProcessors >= 1 && info.dwNumberOfProcessors < INT_MAX)
    return (int)info.dwNumberOfProcessors;
  else
    return -1;
#elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_CONF)
  long cpus = sysconf(_SC_NPROCESSORS_CONF);
  if (cpus >= 1 && cpus < INT_MAX)
    return (int)cpus;
  else
    return -1;
#else
  return -1;
#endif
}

Here is the caller graph for this function:

static struct tm* correct_tm ( int  islocal,
const time_t *  timep,
struct tm *  resultbuf,
struct tm *  r 
) [static, read]

Helper: Deal with confused or out-of-bounds values from localtime_r and friends.

(On some platforms, they can give out-of-bounds values or can return NULL.) If islocal, this is a localtime result; otherwise it's from gmtime. The function returned r, when given timep as its input. If we need to store new results, store them in resultbuf.

Definition at line 2391 of file compat.c.

{
  const char *outcome;

  if (PREDICT_LIKELY(r)) {
    if (r->tm_year > 8099) { /* We can't strftime dates after 9999 CE. */
      r->tm_year = 8099;
      r->tm_mon = 11;
      r->tm_mday = 31;
      r->tm_yday = 365;
      r->tm_hour = 23;
      r->tm_min = 59;
      r->tm_sec = 59;
    }
    return r;
  }

  /* If we get here, gmtime or localtime returned NULL. It might have done
   * this because of overrun or underrun, or it might have done it because of
   * some other weird issue. */
  if (timep) {
    if (*timep < 0) {
      r = resultbuf;
      r->tm_year = 70; /* 1970 CE */
      r->tm_mon = 0;
      r->tm_mday = 1;
      r->tm_yday = 1;
      r->tm_hour = 0;
      r->tm_min = 0 ;
      r->tm_sec = 0;
      outcome = "Rounding up to 1970";
      goto done;
    } else if (*timep >= INT32_MAX) {
      /* Rounding down to INT32_MAX isn't so great, but keep in mind that we
       * only do it if gmtime/localtime tells us NULL. */
      r = resultbuf;
      r->tm_year = 137; /* 2037 CE */
      r->tm_mon = 11;
      r->tm_mday = 31;
      r->tm_yday = 365;
      r->tm_hour = 23;
      r->tm_min = 59;
      r->tm_sec = 59;
      outcome = "Rounding down to 2037";
      goto done;
    }
  }

  /* If we get here, then gmtime/localtime failed without getting an extreme
   * value for *timep */

  tor_fragile_assert();
  r = resultbuf;
  memset(resultbuf, 0, sizeof(struct tm));
  outcome="can't recover";
 done:
  log_warn(LD_BUG, "%s("I64_FORMAT") failed with error %s: %s",
           islocal?"localtime":"gmtime",
           timep?I64_PRINTF_ARG(*timep):0,
           strerror(errno),
           outcome);
  return r;
}

Here is the caller graph for this function:

char** get_environment ( void  )

Return the current environment.

This is a portable replacement for 'environ'.

Definition at line 1814 of file compat.c.

{
#ifdef HAVE__NSGETENVIRON
  /* This is for compatibility between OSX versions.  Otherwise (for example)
   * when we do a mostly-static build on OSX 10.7, the resulting binary won't
   * work on OSX 10.6. */
  return *_NSGetEnviron();
#else
  return environ;
#endif
}

Here is the caller graph for this function:

int get_n_open_sockets ( void  )

Return the number of sockets we currently have opened.

Definition at line 1078 of file compat.c.

Here is the call graph for this function:

Here is the caller graph for this function:

int get_parent_directory ( char *  fname)

Modify fname to contain the name of its parent directory.

Doesn't actually examine the filesystem; does a purely syntactic modification.

The parent of the root director is considered to be iteself.

Definition at line 1689 of file compat.c.

{
  char *cp;
  int at_end = 1;
  tor_assert(fname);
#ifdef _WIN32
  /* If we start with, say, c:, then don't consider that the start of the path
   */
  if (fname[0] && fname[1] == ':') {
    fname += 2;
  }
#endif
  /* Now we want to remove all path-separators at the end of the string,
   * and to remove the end of the string starting with the path separator
   * before the last non-path-separator.  In perl, this would be
   *   s#[/]*$##; s#/[^/]*$##;
   * on a unixy platform.
   */
  cp = fname + strlen(fname);
  at_end = 1;
  while (--cp >= fname) {
    int is_sep = (*cp == '/'
#ifdef _WIN32
                  || *cp == '\\'
#endif
                  );
    if (is_sep) {
      if (cp == fname) {
        /* This is the first separator in the file name; don't remove it! */
        cp[1] = '\0';
        return 0;
      }
      *cp = '\0';
      if (! at_end)
        return 0;
    } else {
      at_end = 0;
    }
  }
  return -1;
}
uint16_t get_uint16 ( const void *  cp)

Read a 16-bit value beginning at cp.

Equivalent to *(uint16_t*)(cp), but will not cause segfaults on platforms that forbid unaligned memory access.

Definition at line 654 of file compat.c.

{
  uint16_t v;
  memcpy(&v,cp,2);
  return v;
}

Here is the caller graph for this function:

uint32_t get_uint32 ( const void *  cp)

Read a 32-bit value beginning at cp.

Equivalent to *(uint32_t*)(cp), but will not cause segfaults on platforms that forbid unaligned memory access.

Definition at line 666 of file compat.c.

{
  uint32_t v;
  memcpy(&v,cp,4);
  return v;
}

Here is the caller graph for this function:

uint64_t get_uint64 ( const void *  cp)

Read a 64-bit value beginning at cp.

Equivalent to *(uint64_t*)(cp), but will not cause segfaults on platforms that forbid unaligned memory access.

Definition at line 678 of file compat.c.

{
  uint64_t v;
  memcpy(&v,cp,8);
  return v;
}

Here is the caller graph for this function:

const char* get_uname ( void  )

Return a pointer to a description of our platform.

Definition at line 2095 of file compat.c.

{
#ifdef HAVE_UNAME
  struct utsname u;
#endif
  if (!uname_result_is_set) {
#ifdef HAVE_UNAME
    if (uname(&u) != -1) {
      /* (Linux says 0 is success, Solaris says 1 is success) */
      strlcpy(uname_result, u.sysname, sizeof(uname_result));
    } else
#endif
      {
#ifdef _WIN32
        OSVERSIONINFOEX info;
        int i;
        const char *plat = NULL;
        static struct {
          unsigned major; unsigned minor; const char *version;
        } win_version_table[] = {
          { 6, 2, "Windows 8" },
          { 6, 1, "Windows 7" },
          { 6, 0, "Windows Vista" },
          { 5, 2, "Windows Server 2003" },
          { 5, 1, "Windows XP" },
          { 5, 0, "Windows 2000" },
          /* { 4, 0, "Windows NT 4.0" }, */
          { 4, 90, "Windows Me" },
          { 4, 10, "Windows 98" },
          /* { 4, 0, "Windows 95" } */
          { 3, 51, "Windows NT 3.51" },
          { 0, 0, NULL }
        };
        memset(&info, 0, sizeof(info));
        info.dwOSVersionInfoSize = sizeof(info);
        if (! GetVersionEx((LPOSVERSIONINFO)&info)) {
          strlcpy(uname_result, "Bizarre version of Windows where GetVersionEx"
                  " doesn't work.", sizeof(uname_result));
          uname_result_is_set = 1;
          return uname_result;
        }
        if (info.dwMajorVersion == 4 && info.dwMinorVersion == 0) {
          if (info.dwPlatformId == VER_PLATFORM_WIN32_NT)
            plat = "Windows NT 4.0";
          else
            plat = "Windows 95";
        } else {
          for (i=0; win_version_table[i].major>0; ++i) {
            if (win_version_table[i].major == info.dwMajorVersion &&
                win_version_table[i].minor == info.dwMinorVersion) {
              plat = win_version_table[i].version;
              break;
            }
          }
        }
        if (plat) {
          strlcpy(uname_result, plat, sizeof(uname_result));
        } else {
          if (info.dwMajorVersion > 6 ||
              (info.dwMajorVersion==6 && info.dwMinorVersion>2))
            tor_snprintf(uname_result, sizeof(uname_result),
                         "Very recent version of Windows [major=%d,minor=%d]",
                         (int)info.dwMajorVersion,(int)info.dwMinorVersion);
          else
            tor_snprintf(uname_result, sizeof(uname_result),
                         "Unrecognized version of Windows [major=%d,minor=%d]",
                         (int)info.dwMajorVersion,(int)info.dwMinorVersion);
        }
#if !defined (WINCE)
#ifdef VER_NT_SERVER
      if (info.wProductType == VER_NT_SERVER ||
          info.wProductType == VER_NT_DOMAIN_CONTROLLER) {
        strlcat(uname_result, " [server]", sizeof(uname_result));
      }
#endif
#endif
#else
        strlcpy(uname_result, "Unknown platform", sizeof(uname_result));
#endif
      }
    uname_result_is_set = 1;
  }
  return uname_result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int in_main_thread ( void  )

Return true iff called from the main thread.

Definition at line 2912 of file compat.c.

Here is the caller graph for this function:

static int log_credential_status ( void  ) [static]

Log details of current user and group credentials.

Return 0 on success. Logs and return -1 on failure.

Log level to use when describing non-error UID/GID status.

Definition at line 1378 of file compat.c.

{
#define CREDENTIAL_LOG_LEVEL LOG_INFO
  /* Real, effective and saved UIDs */
  uid_t ruid, euid, suid;
  /* Read, effective and saved GIDs */
  gid_t rgid, egid, sgid;
  /* Supplementary groups */
  gid_t *sup_gids = NULL;
  int sup_gids_size;
  /* Number of supplementary groups */
  int ngids;

  /* log UIDs */
#ifdef HAVE_GETRESUID
  if (getresuid(&ruid, &euid, &suid) != 0 ) {
    log_warn(LD_GENERAL, "Error getting changed UIDs: %s", strerror(errno));
    return -1;
  } else {
    log_fn(CREDENTIAL_LOG_LEVEL, LD_GENERAL,
           "UID is %u (real), %u (effective), %u (saved)",
           (unsigned)ruid, (unsigned)euid, (unsigned)suid);
  }
#else
  /* getresuid is not present on MacOS X, so we can't get the saved (E)UID */
  ruid = getuid();
  euid = geteuid();
  (void)suid;

  log_fn(CREDENTIAL_LOG_LEVEL, LD_GENERAL,
         "UID is %u (real), %u (effective), unknown (saved)",
         (unsigned)ruid, (unsigned)euid);
#endif

  /* log GIDs */
#ifdef HAVE_GETRESGID
  if (getresgid(&rgid, &egid, &sgid) != 0 ) {
    log_warn(LD_GENERAL, "Error getting changed GIDs: %s", strerror(errno));
    return -1;
  } else {
    log_fn(CREDENTIAL_LOG_LEVEL, LD_GENERAL,
           "GID is %u (real), %u (effective), %u (saved)",
           (unsigned)rgid, (unsigned)egid, (unsigned)sgid);
  }
#else
  /* getresgid is not present on MacOS X, so we can't get the saved (E)GID */
  rgid = getgid();
  egid = getegid();
  (void)sgid;
  log_fn(CREDENTIAL_LOG_LEVEL, LD_GENERAL,
         "GID is %u (real), %u (effective), unknown (saved)",
         (unsigned)rgid, (unsigned)egid);
#endif

  /* log supplementary groups */
  sup_gids_size = 64;
  sup_gids = tor_malloc(sizeof(gid_t) * 64);
  while ((ngids = getgroups(sup_gids_size, sup_gids)) < 0 &&
         errno == EINVAL &&
         sup_gids_size < NGROUPS_MAX) {
    sup_gids_size *= 2;
    sup_gids = tor_realloc(sup_gids, sizeof(gid_t) * sup_gids_size);
  }

  if (ngids < 0) {
    log_warn(LD_GENERAL, "Error getting supplementary GIDs: %s",
             strerror(errno));
    tor_free(sup_gids);
    return -1;
  } else {
    int i, retval = 0;
    char *s = NULL;
    smartlist_t *elts = smartlist_new();

    for (i = 0; i<ngids; i++) {
      smartlist_add_asprintf(elts, "%u", (unsigned)sup_gids[i]);
    }

    s = smartlist_join_strings(elts, " ", 0, NULL);

    log_fn(CREDENTIAL_LOG_LEVEL, LD_GENERAL, "Supplementary groups are: %s",s);

    tor_free(s);
    SMARTLIST_FOREACH(elts, char *, cp, tor_free(cp));
    smartlist_free(elts);
    tor_free(sup_gids);

    return retval;
  }

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* make_path_absolute ( char *  fname)

Expand possibly relative path fname to an absolute path.

Return a newly allocated string, possibly equal to fname.

Definition at line 1767 of file compat.c.

{
#ifdef _WIN32
  char *absfname_malloced = _fullpath(NULL, fname, 1);

  /* We don't want to assume that tor_free can free a string allocated
   * with malloc.  On failure, return fname (it's better than nothing). */
  char *absfname = tor_strdup(absfname_malloced ? absfname_malloced : fname);
  if (absfname_malloced) free(absfname_malloced);

  return absfname;
#else
  char *absfname = NULL, *path = NULL;

  tor_assert(fname);

  if (fname[0] == '/') {
    absfname = tor_strdup(fname);
  } else {
    path = alloc_getcwd();
    if (path) {
      tor_asprintf(&absfname, "%s/%s", path, fname);
      tor_free(path);
    } else {
      /* If getcwd failed, the best we can do here is keep using the
       * relative path.  (Perhaps / isn't readable by this UID/GID.) */
      log_warn(LD_GENERAL, "Unable to find current working directory: %s",
               strerror(errno));
      absfname = tor_strdup(fname);
    }
  }
  return absfname;
#endif
}

Here is the call graph for this function:

Here is the caller graph for this function:

int network_init ( void  )

On Windows, WSAEWOULDBLOCK is not always correct: when you see it, you need to ask the socket for its actual errno.

Also, you need to get your errors from WSAGetLastError, not errno. (If you supply a socket of -1, we check WSAGetLastError, but don't correct WSAEWOULDBLOCKs.)

The upshot of all of this is that when a socket call fails, you should call tor_socket_errno at most once on the failing socket to get the error. Called before we make any calls to network-related functions. (Some operating systems require their network libraries to be initialized.)

Definition at line 3024 of file compat.c.

{
#ifdef _WIN32
  /* This silly exercise is necessary before windows will allow
   * gethostbyname to work. */
  WSADATA WSAData;
  int r;
  r = WSAStartup(0x101,&WSAData);
  if (r) {
    log_warn(LD_NET,"Error initializing windows network layer: code was %d",r);
    return -1;
  }
  if (sizeof(SOCKET) != sizeof(tor_socket_t)) {
    log_warn(LD_BUG,"The tor_socket_t type does not match SOCKET in size; Tor "
             "might not work. (Sizes are %d and %d respectively.)",
             (int)sizeof(tor_socket_t), (int)sizeof(SOCKET));
  }
  /* WSAData.iMaxSockets might show the max sockets we're allowed to use.
   * We might use it to complain if we're trying to be a server but have
   * too few sockets available. */
#endif
  return 0;
}

Here is the caller graph for this function:

int replace_file ( const char *  from,
const char *  to 
)

Rename the file from to the file to.

On Unix, this is the same as rename(2). On windows, this removes to first if it already exists. Returns 0 on success. Returns -1 and sets errno on failure.

Definition at line 720 of file compat.c.

{
#ifndef _WIN32
  return rename(from,to);
#else
  switch (file_status(to))
    {
    case FN_NOENT:
      break;
    case FN_FILE:
      if (unlink(to)) return -1;
      break;
    case FN_ERROR:
      return -1;
    case FN_DIR:
      errno = EISDIR;
      return -1;
    }
  return rename(from,to);
#endif
}

Here is the call graph for this function:

Here is the caller graph for this function:

void set_main_thread ( void  )

Start considering the current thread to be the 'main thread'.

This has no effect on anything besides in_main_thread().

Definition at line 2906 of file compat.c.

Here is the caller graph for this function:

int set_max_file_descriptors ( rlim_t  limit,
int *  max_out 
)

Learn the maximum allowed number of file descriptors, and tell the system we want to use up to that number.

(Some systems have a low soft limit, and let us set it higher.)

We compute this by finding the largest number that we can use. If we can't find a number greater than or equal to limit, then we fail: return -1.

If limit is 0, then do not adjust the current maximum.

Otherwise, return 0 and store the maximum we found inside max_out.

Definition at line 1273 of file compat.c.

{
  /* Define some maximum connections values for systems where we cannot
   * automatically determine a limit. Re Cygwin, see
   * http://archives.seul.org/or/talk/Aug-2006/msg00210.html
   * For an iPhone, 9999 should work. For Windows and all other unknown
   * systems we use 15000 as the default. */
#ifndef HAVE_GETRLIMIT
#if defined(CYGWIN) || defined(__CYGWIN__)
  const char *platform = "Cygwin";
  const unsigned long MAX_CONNECTIONS = 3200;
#elif defined(_WIN32)
  const char *platform = "Windows";
  const unsigned long MAX_CONNECTIONS = 15000;
#else
  const char *platform = "unknown platforms with no getrlimit()";
  const unsigned long MAX_CONNECTIONS = 15000;
#endif
  log_fn(LOG_INFO, LD_NET,
         "This platform is missing getrlimit(). Proceeding.");
  if (limit > MAX_CONNECTIONS) {
    log_warn(LD_CONFIG,
             "We do not support more than %lu file descriptors "
             "on %s. Tried to raise to %lu.",
             (unsigned long)MAX_CONNECTIONS, platform, (unsigned long)limit);
    return -1;
  }
  limit = MAX_CONNECTIONS;
#else /* HAVE_GETRLIMIT */
  struct rlimit rlim;

  if (getrlimit(RLIMIT_NOFILE, &rlim) != 0) {
    log_warn(LD_NET, "Could not get maximum number of file descriptors: %s",
             strerror(errno));
    return -1;
  }
  if (limit == 0) {
    /* If limit == 0, return the maximum value without setting it. */
    limit = rlim.rlim_max;
    if (limit > INT_MAX)
      limit = INT_MAX;
    *max_out = (int)limit - ULIMIT_BUFFER;
    return 0;
  }
  if (rlim.rlim_max < limit) {
    log_warn(LD_CONFIG,"We need %lu file descriptors available, and we're "
             "limited to %lu. Please change your ulimit -n.",
             (unsigned long)limit, (unsigned long)rlim.rlim_max);
    return -1;
  }

  if (rlim.rlim_max > rlim.rlim_cur) {
    log_info(LD_NET,"Raising max file descriptors from %lu to %lu.",
             (unsigned long)rlim.rlim_cur, (unsigned long)rlim.rlim_max);
  }
  rlim.rlim_cur = rlim.rlim_max;

  if (setrlimit(RLIMIT_NOFILE, &rlim) != 0) {
    int bad = 1;
#ifdef OPEN_MAX
    if (errno == EINVAL && OPEN_MAX < rlim.rlim_cur) {
      /* On some platforms, OPEN_MAX is the real limit, and getrlimit() is
       * full of nasty lies.  I'm looking at you, OSX 10.5.... */
      rlim.rlim_cur = OPEN_MAX;
      if (setrlimit(RLIMIT_NOFILE, &rlim) == 0) {
        if (rlim.rlim_cur < (rlim_t)limit) {
          log_warn(LD_CONFIG, "We are limited to %lu file descriptors by "
                 "OPEN_MAX, and ConnLimit is %lu.  Changing ConnLimit; sorry.",
                   (unsigned long)OPEN_MAX, (unsigned long)limit);
        } else {
          log_info(LD_CONFIG, "Dropped connection limit to OPEN_MAX (%lu); "
                   "Apparently, %lu was too high and rlimit lied to us.",
                   (unsigned long)OPEN_MAX, (unsigned long)rlim.rlim_max);
        }
        bad = 0;
      }
    }
#endif /* OPEN_MAX */
    if (bad) {
      log_warn(LD_CONFIG,"Couldn't set maximum number of file descriptors: %s",
               strerror(errno));
      return -1;
    }
  }
  /* leave some overhead for logs, etc, */
  limit = rlim.rlim_cur;
#endif /* HAVE_GETRLIMIT */

  if (limit < ULIMIT_BUFFER) {
    log_warn(LD_CONFIG,
             "ConnLimit must be at least %d. Failing.", ULIMIT_BUFFER);
    return -1;
  }
  if (limit > INT_MAX)
    limit = INT_MAX;
  tor_assert(max_out);
  *max_out = (int)limit - ULIMIT_BUFFER;
  return 0;
}

Here is the caller graph for this function:

Turn socket into a nonblocking socket.

Definition at line 1090 of file compat.c.

{
#if defined(_WIN32)
  unsigned long nonblocking = 1;
  ioctlsocket(socket, FIONBIO, (unsigned long*) &nonblocking);
#else
  fcntl(socket, F_SETFL, O_NONBLOCK);
#endif
}

Here is the caller graph for this function:

void set_uint16 ( void *  cp,
uint16_t  v 
)

Set a 16-bit value beginning at cp to v.

Equivalent to *(uint16_t*)(cp) = v, but will not cause segfaults on platforms that forbid unaligned memory access.

Definition at line 690 of file compat.c.

{
  memcpy(cp,&v,2);
}

Here is the caller graph for this function:

void set_uint32 ( void *  cp,
uint32_t  v 
)

Set a 32-bit value beginning at cp to v.

Equivalent to *(uint32_t*)(cp) = v, but will not cause segfaults on platforms that forbid unaligned memory access.

Definition at line 699 of file compat.c.

{
  memcpy(cp,&v,4);
}

Here is the caller graph for this function:

void set_uint64 ( void *  cp,
uint64_t  v 
)

Set a 64-bit value beginning at cp to v.

Equivalent to *(uint64_t*)(cp) = v, but will not cause segfaults on platforms that forbid unaligned memory access.

Definition at line 708 of file compat.c.

{
  memcpy(cp,&v,8);
}

Here is the caller graph for this function:

static INLINE void socket_accounting_lock ( void  ) [static]

Helper: acquire the socket accounting lock.

Definition at line 912 of file compat.c.

Here is the caller graph for this function:

static INLINE void socket_accounting_unlock ( void  ) [static]

Helper: release the socket accounting lock.

Definition at line 921 of file compat.c.

Here is the caller graph for this function:

void spawn_exit ( void  )

End the current thread/process.

Definition at line 2264 of file compat.c.

{
#if defined(USE_WIN32_THREADS)
  _endthread();
  //we should never get here. my compiler thinks that _endthread returns, this
  //is an attempt to fool it.
  tor_assert(0);
  _exit(0);
#elif defined(USE_PTHREADS)
  pthread_exit(NULL);
#else
  /* http://www.erlenstar.demon.co.uk/unix/faq_2.html says we should
   * call _exit, not exit, from child processes. */
  _exit(0);
#endif
}

Here is the caller graph for this function:

int spawn_func ( void(*)(void *)  func,
void *  data 
)

Minimalist interface to run a void function in the background.

On Unix calls fork, on win32 calls beginthread. Returns -1 on failure. func should not return, but rather should call spawn_exit.

NOTE: if data is used, it should not be allocated on the stack, since in a multithreaded environment, there is no way to be sure that the caller's stack will still be around when the called function is running.

Definition at line 2225 of file compat.c.

{
#if defined(USE_WIN32_THREADS)
  int rv;
  rv = (int)_beginthread(func, 0, data);
  if (rv == (int)-1)
    return -1;
  return 0;
#elif defined(USE_PTHREADS)
  pthread_t thread;
  tor_pthread_data_t *d;
  d = tor_malloc(sizeof(tor_pthread_data_t));
  d->data = data;
  d->func = func;
  if (pthread_create(&thread,NULL,tor_pthread_helper_fn,d))
    return -1;
  if (pthread_detach(thread))
    return -1;
  return 0;
#else
  pid_t pid;
  pid = fork();
  if (pid<0)
    return -1;
  if (pid==0) {
    /* Child */
    func(data);
    tor_assert(0); /* Should never reach here. */
    return 0; /* suppress "control-reaches-end-of-non-void" warning. */
  } else {
    /* Parent */
    return 0;
  }
#endif
}

Here is the caller graph for this function:

static char* strtok_helper ( char *  cp,
const char *  sep 
) [static]

Helper for tor_strtok_r_impl: Advances cp past all characters in sep, and returns its new value.

Definition at line 576 of file compat.c.

{
  if (sep[1]) {
    while (*cp && strchr(sep, *cp))
      ++cp;
  } else {
    while (*cp && *cp == *sep)
      ++cp;
  }
  return cp;
}

Here is the caller graph for this function:

int switch_id ( const char *  user)

Call setuid and setgid to run as user and switch to their primary group.

Return 0 on success. On failure, log and return -1.

Definition at line 1477 of file compat.c.

{
#ifndef _WIN32
  struct passwd *pw = NULL;
  uid_t old_uid;
  gid_t old_gid;
  static int have_already_switched_id = 0;

  tor_assert(user);

  if (have_already_switched_id)
    return 0;

  /* Log the initial credential state */
  if (log_credential_status())
    return -1;

  log_fn(CREDENTIAL_LOG_LEVEL, LD_GENERAL, "Changing user and groups");

  /* Get old UID/GID to check if we changed correctly */
  old_uid = getuid();
  old_gid = getgid();

  /* Lookup the user and group information, if we have a problem, bail out. */
  pw = getpwnam(user);
  if (pw == NULL) {
    log_warn(LD_CONFIG, "Error setting configured user: %s not found", user);
    return -1;
  }

  /* Properly switch egid,gid,euid,uid here or bail out */
  if (setgroups(1, &pw->pw_gid)) {
    log_warn(LD_GENERAL, "Error setting groups to gid %d: \"%s\".",
             (int)pw->pw_gid, strerror(errno));
    if (old_uid == pw->pw_uid) {
      log_warn(LD_GENERAL, "Tor is already running as %s.  You do not need "
               "the \"User\" option if you are already running as the user "
               "you want to be.  (If you did not set the User option in your "
               "torrc, check whether it was specified on the command line "
               "by a startup script.)", user);
    } else {
      log_warn(LD_GENERAL, "If you set the \"User\" option, you must start Tor"
               " as root.");
    }
    return -1;
  }

  if (setegid(pw->pw_gid)) {
    log_warn(LD_GENERAL, "Error setting egid to %d: %s",
             (int)pw->pw_gid, strerror(errno));
    return -1;
  }

  if (setgid(pw->pw_gid)) {
    log_warn(LD_GENERAL, "Error setting gid to %d: %s",
             (int)pw->pw_gid, strerror(errno));
    return -1;
  }

  if (setuid(pw->pw_uid)) {
    log_warn(LD_GENERAL, "Error setting configured uid to %s (%d): %s",
             user, (int)pw->pw_uid, strerror(errno));
    return -1;
  }

  if (seteuid(pw->pw_uid)) {
    log_warn(LD_GENERAL, "Error setting configured euid to %s (%d): %s",
             user, (int)pw->pw_uid, strerror(errno));
    return -1;
  }

  /* This is how OpenBSD rolls:
  if (setgroups(1, &pw->pw_gid) || setegid(pw->pw_gid) ||
      setgid(pw->pw_gid) || setuid(pw->pw_uid) || seteuid(pw->pw_uid)) {
      setgid(pw->pw_gid) || seteuid(pw->pw_uid) || setuid(pw->pw_uid)) {
    log_warn(LD_GENERAL, "Error setting configured UID/GID: %s",
    strerror(errno));
    return -1;
  }
  */

  /* We've properly switched egid, gid, euid, uid, and supplementary groups if
   * we're here. */

#if !defined(CYGWIN) && !defined(__CYGWIN__)
  /* If we tried to drop privilege to a group/user other than root, attempt to
   * restore root (E)(U|G)ID, and abort if the operation succeeds */

  /* Only check for privilege dropping if we were asked to be non-root */
  if (pw->pw_uid) {
    /* Try changing GID/EGID */
    if (pw->pw_gid != old_gid &&
        (setgid(old_gid) != -1 || setegid(old_gid) != -1)) {
      log_warn(LD_GENERAL, "Was able to restore group credentials even after "
               "switching GID: this means that the setgid code didn't work.");
      return -1;
    }

    /* Try changing UID/EUID */
    if (pw->pw_uid != old_uid &&
        (setuid(old_uid) != -1 || seteuid(old_uid) != -1)) {
      log_warn(LD_GENERAL, "Was able to restore user credentials even after "
               "switching UID: this means that the setuid code didn't work.");
      return -1;
    }
  }
#endif

  /* Check what really happened */
  if (log_credential_status()) {
    return -1;
  }

  have_already_switched_id = 1; /* mark success so we never try again */

#if defined(__linux__) && defined(HAVE_SYS_PRCTL_H) && defined(HAVE_PRCTL)
#ifdef PR_SET_DUMPABLE
  if (pw->pw_uid) {
    /* Re-enable core dumps if we're not running as root. */
    log_info(LD_CONFIG, "Re-enabling coredumps");
    if (prctl(PR_SET_DUMPABLE, 1)) {
      log_warn(LD_CONFIG, "Unable to re-enable coredumps: %s",strerror(errno));
    }
  }
#endif
#endif
  return 0;

#else
  (void)user;

  log_warn(LD_CONFIG,
           "User specified but switching users is unsupported on your OS.");
  return -1;
#endif
}

Here is the call graph for this function:

Here is the caller graph for this function:

tor_socket_t tor_accept_socket ( tor_socket_t  sockfd,
struct sockaddr *  addr,
socklen_t len 
)

As socket(), but counts the number of open sockets.

Definition at line 1043 of file compat.c.

{
  tor_socket_t s;
#if defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC)
  s = accept4(sockfd, addr, len, SOCK_CLOEXEC);
  if (SOCKET_OK(s))
    goto socket_ok;
  /* If we got an error, see if it is ENOSYS. ENOSYS indicates that,
   * even though we were built on a system with accept4 support, we
   * are running on one without. Also, check for EINVAL, which indicates that
   * we are missing SOCK_CLOEXEC support. */
  if (errno != EINVAL && errno != ENOSYS)
    return s;
#endif

  s = accept(sockfd, addr, len);
  if (!SOCKET_OK(s))
    return s;

#if defined(FD_CLOEXEC)
  fcntl(s, F_SETFD, FD_CLOEXEC);
#endif

  goto socket_ok; /* So that socket_ok will not be unused. */

 socket_ok:
  socket_accounting_lock();
  ++n_sockets_open;
  mark_socket_open(s);
  socket_accounting_unlock();
  return s;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int tor_asprintf ( char **  strp,
const char *  fmt,
  ... 
)

Portable asprintf implementation.

Does a printf() into a newly malloc'd string. Sets *strp to this string, and returns its length (not including the terminating NUL character).

You can treat this function as if its implementation were something like

     char buf[_INFINITY_];
     tor_snprintf(buf, sizeof(buf), fmt, args);
     *strp = tor_strdup(buf);
     return strlen(*strp):
   

Where INFINITY is an imaginary constant so big that any string can fit into it.

Definition at line 396 of file compat.c.

{
  int r;
  va_list args;
  va_start(args, fmt);
  r = tor_vasprintf(strp, fmt, args);
  va_end(args);
  if (!*strp || r < 0) {
    log_err(LD_BUG, "Internal error in asprintf");
    tor_assert(0);
  }
  return r;
}

Here is the call graph for this function:

As close(), but guaranteed to work for sockets across platforms (including Windows, where close()ing a socket doesn't work.

Returns 0 on success, -1 on failure.

Definition at line 930 of file compat.c.

{
  int r = 0;

  /* 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.
   */
#if defined(_WIN32)
  r = closesocket(s);
#else
  r = close(s);
#endif

  socket_accounting_lock();
#ifdef DEBUG_SOCKET_COUNTING
  if (s > max_socket || ! bitarray_is_set(open_sockets, s)) {
    log_warn(LD_BUG, "Closing a socket (%d) that wasn't returned by tor_open_"
             "socket(), or that was already closed or something.", s);
  } else {
    tor_assert(open_sockets && s <= max_socket);
    bitarray_clear(open_sockets, s);
  }
#endif
  if (r == 0) {
    --n_sockets_open;
  } else {
    int err = tor_socket_errno(-1);
    log_info(LD_NET, "Close returned an error: %s", tor_socket_strerror(err));
#ifdef _WIN32
    if (err != WSAENOTSOCK)
      --n_sockets_open;
#else
    if (err != EBADF)
      --n_sockets_open;
#endif
    r = -1;
  }

  if (n_sockets_open < 0)
    log_warn(LD_BUG, "Our socket count is below zero: %d. Please submit a "
             "bug report.", n_sockets_open);
  socket_accounting_unlock();
  return r;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Attempt to disable debugger attachment: return 1 on success, -1 on failure, and 0 if we don't know how to try on this platform.

Definition at line 1632 of file compat.c.

{
  int r, attempted;
  r = -1;
  attempted = 0;
  log_debug(LD_CONFIG,
            "Attemping to disable debugger attachment to Tor for "
            "unprivileged users.");
#if defined(__linux__) && defined(HAVE_SYS_PRCTL_H) && defined(HAVE_PRCTL)
#ifdef PR_SET_DUMPABLE
  attempted = 1;
  r = prctl(PR_SET_DUMPABLE, 0);
#endif
#endif
#if defined(__APPLE__) && defined(PT_DENY_ATTACH)
  if (r < 0) {
    attempted = 1;
    r = ptrace(PT_DENY_ATTACH, 0, 0, 0);
  }
#endif

  // XXX: TODO - Mac OS X has dtrace and this may be disabled.
  // XXX: TODO - Windows probably has something similar
  if (r == 0 && attempted) {
    log_debug(LD_CONFIG,"Debugger attachment disabled for "
              "unprivileged users.");
    return 1;
  } else if (attempted) {
    log_warn(LD_CONFIG, "Unable to disable debugger attaching: %s",
             strerror(errno));
  }
  return r;
}

Here is the caller graph for this function:

off_t tor_fd_getpos ( int  fd)

Return the position of fd with respect to the start of the file.

Definition at line 874 of file compat.c.

{
#ifdef _WIN32
  return (off_t) _lseek(fd, 0, SEEK_CUR);
#else
  return (off_t) lseek(fd, 0, SEEK_CUR);
#endif
}

Here is the caller graph for this function:

int tor_fd_seekend ( int  fd)

Move fd to the end of the file.

Return -1 on error, 0 on success.

Definition at line 885 of file compat.c.

{
#ifdef _WIN32
  return _lseek(fd, 0, SEEK_END) < 0 ? -1 : 0;
#else
  return lseek(fd, 0, SEEK_END) < 0 ? -1 : 0;
#endif
}

Here is the caller graph for this function:

FILE* tor_fopen_cloexec ( const char *  path,
const char *  mode 
)

As fopen(path,mode), but ensures that the O_CLOEXEC bit is set on the underlying file handle.

Definition at line 149 of file compat.c.

{
  FILE *result = fopen(path, mode);
#ifdef FD_CLOEXEC
  if (result != NULL)
    fcntl(fileno(result), F_SETFD, FD_CLOEXEC);
#endif
  return result;
}

Here is the caller graph for this function:

void tor_gettimeofday ( struct timeval timeval)

Set *timeval to the current time of day.

On error, log and terminate. (Same as gettimeofday(timeval,NULL), but never returns -1.)

Definition at line 2331 of file compat.c.

{
#ifdef _WIN32
  /* Epoch bias copied from perl: number of units between windows epoch and
   * Unix epoch. */
#define EPOCH_BIAS U64_LITERAL(116444736000000000)
#define UNITS_PER_SEC U64_LITERAL(10000000)
#define USEC_PER_SEC U64_LITERAL(1000000)
#define UNITS_PER_USEC U64_LITERAL(10)
  union {
    uint64_t ft_64;
    FILETIME ft_ft;
  } ft;
#if defined (WINCE)
  /* wince do not have GetSystemTimeAsFileTime */
  SYSTEMTIME stime;
  GetSystemTime(&stime);
  SystemTimeToFileTime(&stime,&ft.ft_ft);
#else
  /* number of 100-nsec units since Jan 1, 1601 */
  GetSystemTimeAsFileTime(&ft.ft_ft);
#endif
  if (ft.ft_64 < EPOCH_BIAS) {
    log_err(LD_GENERAL,"System time is before 1970; failing.");
    exit(1);
  }
  ft.ft_64 -= EPOCH_BIAS;
  timeval->tv_sec = (unsigned) (ft.ft_64 / UNITS_PER_SEC);
  timeval->tv_usec = (unsigned) ((ft.ft_64 / UNITS_PER_USEC) % USEC_PER_SEC);
#elif defined(HAVE_GETTIMEOFDAY)
  if (gettimeofday(timeval, NULL)) {
    log_err(LD_GENERAL,"gettimeofday failed.");
    /* If gettimeofday dies, we have either given a bad timezone (we didn't),
       or segfaulted.*/
    exit(1);
  }
#elif defined(HAVE_FTIME)
  struct timeb tb;
  ftime(&tb);
  timeval->tv_sec = tb.time;
  timeval->tv_usec = tb.millitm * 1000;
#else
#error "No way to get time."
#endif
  return;
}

Here is the caller graph for this function:

struct tm* tor_gmtime_r ( const time_t *  timep,
struct tm *  result 
) [read]

As gmtimee_r, but defined for platforms that don't have it:

Convert *timep to a struct tm in UTC, and store the value in *result. Return the result on success, or NULL on failure.

Definition at line 2530 of file compat.c.

{
  struct tm *r;
  tor_assert(result);
  r = gmtime(timep);
  if (r)
    memcpy(result, r, sizeof(struct tm));
  return correct_tm(0, timep, result, r);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int tor_inet_aton ( const char *  str,
struct in_addr *  addr 
)

Set *addr to the IP address (in dotted-quad notation) stored in c.

Return 1 on success, 0 if c is badly formatted. (Like inet_aton(c,addr), but works on Windows and Solaris.)

Definition at line 1831 of file compat.c.

{
  unsigned a,b,c,d;
  char more;
  if (tor_sscanf(str, "%3u.%3u.%3u.%3u%c", &a,&b,&c,&d,&more) != 4)
    return 0;
  if (a > 255) return 0;
  if (b > 255) return 0;
  if (c > 255) return 0;
  if (d > 255) return 0;
  addr->s_addr = htonl((a<<24) | (b<<16) | (c<<8) | d);
  return 1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

const char* tor_inet_ntop ( int  af,
const void *  src,
char *  dst,
size_t  len 
)

Given af==AF_INET and src a struct in_addr, or af==AF_INET6 and src a struct in6_addr, try to format the address and store it in the len-byte buffer dst.

Returns dst on success, NULL on failure.

(Like inet_ntop(af,src,dst,len), but works on platforms that don't have it: Tor sometimes needs to format ipv6 addresses even on platforms without ipv6 support.)

Definition at line 1854 of file compat.c.

{
  if (af == AF_INET) {
    if (tor_inet_ntoa(src, dst, len) < 0)
      return NULL;
    else
      return dst;
  } else if (af == AF_INET6) {
    const struct in6_addr *addr = src;
    char buf[64], *cp;
    int longestGapLen = 0, longestGapPos = -1, i,
      curGapPos = -1, curGapLen = 0;
    uint16_t words[8];
    for (i = 0; i < 8; ++i) {
      words[i] = (((uint16_t)addr->s6_addr[2*i])<<8) + addr->s6_addr[2*i+1];
    }
    if (words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 &&
        words[4] == 0 && ((words[5] == 0 && words[6] && words[7]) ||
                          (words[5] == 0xffff))) {
      /* This is an IPv4 address. */
      if (words[5] == 0) {
        tor_snprintf(buf, sizeof(buf), "::%d.%d.%d.%d",
                     addr->s6_addr[12], addr->s6_addr[13],
                     addr->s6_addr[14], addr->s6_addr[15]);
      } else {
        tor_snprintf(buf, sizeof(buf), "::%x:%d.%d.%d.%d", words[5],
                     addr->s6_addr[12], addr->s6_addr[13],
                     addr->s6_addr[14], addr->s6_addr[15]);
      }
      if ((strlen(buf) + 1) > len) /* +1 for \0 */
        return NULL;
      strlcpy(dst, buf, len);
      return dst;
    }
    i = 0;
    while (i < 8) {
      if (words[i] == 0) {
        curGapPos = i++;
        curGapLen = 1;
        while (i<8 && words[i] == 0) {
          ++i; ++curGapLen;
        }
        if (curGapLen > longestGapLen) {
          longestGapPos = curGapPos;
          longestGapLen = curGapLen;
        }
      } else {
        ++i;
      }
    }
    if (longestGapLen<=1)
      longestGapPos = -1;

    cp = buf;
    for (i = 0; i < 8; ++i) {
      if (words[i] == 0 && longestGapPos == i) {
        if (i == 0)
          *cp++ = ':';
        *cp++ = ':';
        while (i < 8 && words[i] == 0)
          ++i;
        --i; /* to compensate for loop increment. */
      } else {
        tor_snprintf(cp, sizeof(buf)-(cp-buf), "%x", (unsigned)words[i]);
        cp += strlen(cp);
        if (i != 7)
          *cp++ = ':';
      }
    }
    *cp = '\0';
    if ((strlen(buf) + 1) > len) /* +1 for \0 */
      return NULL;
    strlcpy(dst, buf, len);
    return dst;
  } else {
    return NULL;
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

int tor_inet_pton ( int  af,
const char *  src,
void *  dst 
)

Given af==AF_INET or af==AF_INET6, and a string src encoding an IPv4 address or IPv6 address correspondingly, try to parse the address and store the result in dst (which must have space for a struct in_addr or a struct in6_addr, as appropriate).

Return 1 on success, 0 on a bad parse, and -1 on a bad af.

(Like inet_pton(af,src,dst) but works on platforms that don't have it: Tor sometimes needs to format ipv6 addresses even on platforms without ipv6 support.)

Definition at line 1943 of file compat.c.

{
  if (af == AF_INET) {
    return tor_inet_aton(src, dst);
  } else if (af == AF_INET6) {
    struct in6_addr *out = dst;
    uint16_t words[8];
    int gapPos = -1, i, setWords=0;
    const char *dot = strchr(src, '.');
    const char *eow; /* end of words. */
    if (dot == src)
      return 0;
    else if (!dot)
      eow = src+strlen(src);
    else {
      unsigned byte1,byte2,byte3,byte4;
      char more;
      for (eow = dot-1; eow >= src && TOR_ISDIGIT(*eow); --eow)
        ;
      ++eow;

      /* We use "scanf" because some platform inet_aton()s are too lax
       * about IPv4 addresses of the form "1.2.3" */
      if (tor_sscanf(eow, "%3u.%3u.%3u.%3u%c",
                     &byte1,&byte2,&byte3,&byte4,&more) != 4)
        return 0;

      if (byte1 > 255 || byte2 > 255 || byte3 > 255 || byte4 > 255)
        return 0;

      words[6] = (byte1<<8) | byte2;
      words[7] = (byte3<<8) | byte4;
      setWords += 2;
    }

    i = 0;
    while (src < eow) {
      if (i > 7)
        return 0;
      if (TOR_ISXDIGIT(*src)) {
        char *next;
        ssize_t len;
        long r = strtol(src, &next, 16);
        tor_assert(next != NULL);
        tor_assert(next != src);

        len = *next == '\0' ? eow - src : next - src;
        if (len > 4)
          return 0;
        if (len > 1 && !TOR_ISXDIGIT(src[1]))
          return 0; /* 0x is not valid */

        tor_assert(r >= 0);
        tor_assert(r < 65536);
        words[i++] = (uint16_t)r;
        setWords++;
        src = next;
        if (*src != ':' && src != eow)
          return 0;
        ++src;
      } else if (*src == ':' && i > 0 && gapPos == -1) {
        gapPos = i;
        ++src;
      } else if (*src == ':' && i == 0 && src+1 < eow && src[1] == ':' &&
                 gapPos == -1) {
        gapPos = i;
        src += 2;
      } else {
        return 0;
      }
    }

    if (setWords > 8 ||
        (setWords == 8 && gapPos != -1) ||
        (setWords < 8 && gapPos == -1))
      return 0;

    if (gapPos >= 0) {
      int nToMove = setWords - (dot ? 2 : 0) - gapPos;
      int gapLen = 8 - setWords;
      tor_assert(nToMove >= 0);
      memmove(&words[gapPos+gapLen], &words[gapPos],
              sizeof(uint16_t)*nToMove);
      memset(&words[gapPos], 0, sizeof(uint16_t)*gapLen);
    }
    for (i = 0; i < 8; ++i) {
      out->s6_addr[2*i  ] = words[i] >> 8;
      out->s6_addr[2*i+1] = words[i] & 0xff;
    }

    return 1;
  } else {
    return -1;
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void tor_init_weak_random ( unsigned  seed)

Initialize the insecure libc RNG.

Definition at line 2065 of file compat.c.

{
#ifdef _WIN32
  srand(seed);
#else
  srandom(seed);
#endif
}

Here is the caller graph for this function:

struct tm* tor_localtime_r ( const time_t *  timep,
struct tm *  result 
) [read]

As localtime_r, but defined for platforms that don't have it:

Convert *timep to a struct tm in local time, and store the value in *result. Return the result on success, or NULL on failure.

Definition at line 2487 of file compat.c.

{
  struct tm *r;
  tor_assert(result);
  r = localtime(timep);
  if (r)
    memcpy(result, r, sizeof(struct tm));
  return correct_tm(1, timep, result, r);
}

Here is the call graph for this function:

Here is the caller graph for this function:

tor_lockfile_t* tor_lockfile_lock ( const char *  filename,
int  blocking,
int *  locked_out 
)

Try to get a lock on the lockfile filename, creating it as necessary.

If someone else has the lock and blocking is true, wait until the lock is available. Otherwise return immediately whether we succeeded or not.

Set *locked_out to true if somebody else had the lock, and to false otherwise.

Return a tor_lockfile_t on success, NULL on failure.

(Implementation note: because we need to fall back to fcntl on some platforms, these locks are per-process, not per-thread. If you want to do in-process locking, use tor_mutex_t like a normal person. On Windows, when blocking is true, the maximum time that is actually waited is 10 seconds, after which NULL is returned and locked_out is set to 1.)

Definition at line 777 of file compat.c.

{
  tor_lockfile_t *result;
  int fd;
  *locked_out = 0;

  log_info(LD_FS, "Locking \"%s\"", filename);
  fd = tor_open_cloexec(filename, O_RDWR|O_CREAT|O_TRUNC, 0600);
  if (fd < 0) {
    log_warn(LD_FS,"Couldn't open \"%s\" for locking: %s", filename,
             strerror(errno));
    return NULL;
  }

#ifdef _WIN32
  _lseek(fd, 0, SEEK_SET);
  if (_locking(fd, blocking ? _LK_LOCK : _LK_NBLCK, 1) < 0) {
    if (errno != EACCES && errno != EDEADLOCK)
      log_warn(LD_FS,"Couldn't lock \"%s\": %s", filename, strerror(errno));
    else
      *locked_out = 1;
    close(fd);
    return NULL;
  }
#elif defined(HAVE_FLOCK)
  if (flock(fd, LOCK_EX|(blocking ? 0 : LOCK_NB)) < 0) {
    if (errno != EWOULDBLOCK)
      log_warn(LD_FS,"Couldn't lock \"%s\": %s", filename, strerror(errno));
    else
      *locked_out = 1;
    close(fd);
    return NULL;
  }
#else
  {
    struct flock lock;
    memset(&lock, 0, sizeof(lock));
    lock.l_type = F_WRLCK;
    lock.l_whence = SEEK_SET;
    if (fcntl(fd, blocking ? F_SETLKW : F_SETLK, &lock) < 0) {
      if (errno != EACCES && errno != EAGAIN)
        log_warn(LD_FS, "Couldn't lock \"%s\": %s", filename, strerror(errno));
      else
        *locked_out = 1;
      close(fd);
      return NULL;
    }
  }
#endif

  result = tor_malloc(sizeof(tor_lockfile_t));
  result->filename = tor_strdup(filename);
  result->fd = fd;
  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void tor_lockfile_unlock ( tor_lockfile_t lockfile)

Release the lock held as lockfile.

Definition at line 835 of file compat.c.

{
  tor_assert(lockfile);

  log_info(LD_FS, "Unlocking \"%s\"", lockfile->filename);
#ifdef _WIN32
  _lseek(lockfile->fd, 0, SEEK_SET);
  if (_locking(lockfile->fd, _LK_UNLCK, 1) < 0) {
    log_warn(LD_FS,"Error unlocking \"%s\": %s", lockfile->filename,
             strerror(errno));
  }
#elif defined(HAVE_FLOCK)
  if (flock(lockfile->fd, LOCK_UN) < 0) {
    log_warn(LD_FS, "Error unlocking \"%s\": %s", lockfile->filename,
             strerror(errno));
  }
#else
  /* Closing the lockfile is sufficient. */
#endif

  close(lockfile->fd);
  lockfile->fd = -1;
  tor_free(lockfile->filename);
  tor_free(lockfile);
}

Here is the caller graph for this function:

int tor_lookup_hostname ( const char *  name,
uint32_t *  addr 
)

Similar behavior to Unix gethostbyname: resolve name, and set *addr to the proper IP address, in host byte order.

Returns 0 on success, -1 on failure; 1 on transient failure.

(This function exists because standard windows gethostbyname doesn't treat raw IP addresses properly.)

Definition at line 2047 of file compat.c.

{
  tor_addr_t myaddr;
  int ret;

  if ((ret = tor_addr_lookup(name, AF_INET, &myaddr)))
    return ret;

  if (tor_addr_family(&myaddr) == AF_INET) {
    *addr = tor_addr_to_ipv4h(&myaddr);
    return ret;
  }

  return -1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

const void* tor_memmem ( const void *  _haystack,
size_t  hlen,
const void *  _needle,
size_t  nlen 
)

Given hlen bytes at haystack and nlen bytes at needle, return a pointer to the first occurrence of the needle within the haystack, or NULL if there is no such occurrence.

This function is not timing-safe.

Requires that nlen be greater than zero.

Definition at line 483 of file compat.c.

{
#if defined(HAVE_MEMMEM) && (!defined(__GNUC__) || __GNUC__ >= 2)
  tor_assert(nlen);
  return memmem(_haystack, hlen, _needle, nlen);
#else
  /* This isn't as fast as the GLIBC implementation, but it doesn't need to
   * be. */
  const char *p, *end;
  const char *haystack = (const char*)_haystack;
  const char *needle = (const char*)_needle;
  char first;
  tor_assert(nlen);

  p = haystack;
  end = haystack + hlen;
  first = *(const char*)needle;
  while ((p = memchr(p, first, end-p))) {
    if (p+nlen > end)
      return NULL;
    if (fast_memeq(p, needle, nlen))
      return p;
    ++p;
  }
  return NULL;
#endif
}

Here is the caller graph for this function:

int tor_mlockall ( void  )

Attempt to lock all current and all future memory pages.

This should only be called once and while we're privileged. Like mlockall() we return 0 when we're successful and -1 when we're not. Unlike mlockall() we return 1 if we've already attempted to lock memory.

Definition at line 2856 of file compat.c.

{
  static int memory_lock_attempted = 0;

  if (memory_lock_attempted) {
    return 1;
  }

  memory_lock_attempted = 1;

  /*
   * Future consideration for Windows may be VirtualLock
   * VirtualLock appears to implement mlock() but not mlockall()
   *
   * http://msdn.microsoft.com/en-us/library/aa366895(VS.85).aspx
   */

#if defined(HAVE_MLOCKALL) && HAVE_DECL_MLOCKALL && defined(RLIMIT_MEMLOCK)
  if (tor_set_max_memlock() == 0) {
    log_debug(LD_GENERAL, "RLIMIT_MEMLOCK is now set to RLIM_INFINITY.");
  }

  if (mlockall(MCL_CURRENT|MCL_FUTURE) == 0) {
    log_info(LD_GENERAL, "Insecure OS paging is effectively disabled.");
    return 0;
  } else {
    if (errno == ENOSYS) {
      /* Apple - it's 2009! I'm looking at you. Grrr. */
      log_notice(LD_GENERAL, "It appears that mlockall() is not available on "
                             "your platform.");
    } else if (errno == EPERM) {
      log_notice(LD_GENERAL, "It appears that you lack the permissions to "
                             "lock memory. Are you root?");
    }
    log_notice(LD_GENERAL, "Unable to lock all current and future memory "
                           "pages: %s", strerror(errno));
    return -1;
  }
#else
  log_warn(LD_GENERAL, "Unable to lock memory pages. mlockall() unsupported?");
  return -1;
#endif
}

Here is the caller graph for this function:

tor_mmap_t* tor_mmap_file ( const char *  filename)

Definition at line 318 of file compat.c.

{
  struct stat st;
  char *res = read_file_to_str(filename, RFTS_BIN|RFTS_IGNORE_MISSING, &st);
  tor_mmap_t *handle;
  if (! res)
    return NULL;
  handle = tor_malloc_zero(sizeof(tor_mmap_t));
  handle->data = res;
  handle->size = st.st_size;
  return handle;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void tor_munmap_file ( tor_mmap_t handle)

Definition at line 331 of file compat.c.

{
  char *d = (char*)handle->data;
  tor_free(d);
  memset(handle, 0, sizeof(tor_mmap_t));
  tor_free(handle);
}

Here is the caller graph for this function:

int tor_open_cloexec ( const char *  path,
int  flags,
unsigned  mode 
)

As open(path, flags, mode), but return an fd with the close-on-exec mode set.

Definition at line 124 of file compat.c.

{
  int fd;
#ifdef O_CLOEXEC
  fd = open(path, flags|O_CLOEXEC, mode);
  if (fd >= 0)
    return fd;
  /* If we got an error, see if it is EINVAL. EINVAL might indicate that,
   * even though we were built on a system with O_CLOEXEC support, we
   * are running on one without. */
  if (errno != EINVAL)
    return -1;
#endif

  fd = open(path, flags, mode);
#ifdef FD_CLOEXEC
  if (fd >= 0)
        fcntl(fd, F_SETFD, FD_CLOEXEC);
#endif
  return fd;
}

Here is the caller graph for this function:

tor_socket_t tor_open_socket ( int  domain,
int  type,
int  protocol 
)

As socket(), but counts the number of open sockets.

Definition at line 1009 of file compat.c.

{
  tor_socket_t s;
#ifdef SOCK_CLOEXEC
  s = socket(domain, type|SOCK_CLOEXEC, protocol);
  if (SOCKET_OK(s))
    goto socket_ok;
  /* If we got an error, see if it is EINVAL. EINVAL might indicate that,
   * even though we were built on a system with SOCK_CLOEXEC support, we
   * are running on one without. */
  if (errno != EINVAL)
    return s;
#endif /* SOCK_CLOEXEC */

  s = socket(domain, type, protocol);
  if (! SOCKET_OK(s))
    return s;

#if defined(FD_CLOEXEC)
  fcntl(s, F_SETFD, FD_CLOEXEC);
#endif

  goto socket_ok; /* So that socket_ok will not be unused. */

 socket_ok:
  socket_accounting_lock();
  ++n_sockets_open;
  mark_socket_open(s);
  socket_accounting_unlock();
  return s;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int tor_snprintf ( char *  str,
size_t  size,
const char *  format,
  ... 
)

Replacement for snprintf.

Differs from platform snprintf in two ways: First, always NUL-terminates its output. Second, always returns -1 if the result is truncated. (Note that this return behavior does not conform to C99; it just happens to be easier to emulate "return -1" with conformant implementations than it is to emulate "return number that would be written" with non-conformant implementations.)

Definition at line 348 of file compat.c.

{
  va_list ap;
  int r;
  va_start(ap,format);
  r = tor_vsnprintf(str,size,format,ap);
  va_end(ap);
  return r;
}

Here is the call graph for this function:

int tor_socketpair ( int  family,
int  type,
int  protocol,
tor_socket_t  fd[2] 
)

Allocate a pair of connected sockets.

(Like socketpair(family, type,protocol,fd), but works on systems that don't have socketpair.)

Currently, only (AF_UNIX, SOCK_STREAM, 0) sockets are supported.

Note that on systems without socketpair, this call will fail if localhost is inaccessible (for example, if the networking stack is down). And even if it succeeds, the socket pair will not be able to read while localhost is down later (the socket pair may even close, depending on OS-specific timeouts).

Returns 0 on success and -errno on failure; do not rely on the value of errno or WSAGetLastError().

Definition at line 1118 of file compat.c.

{
//don't use win32 socketpairs (they are always bad)
#if defined(HAVE_SOCKETPAIR) && !defined(_WIN32)
  int r;

#ifdef SOCK_CLOEXEC
  r = socketpair(family, type|SOCK_CLOEXEC, protocol, fd);
  if (r == 0)
    goto sockets_ok;
  /* If we got an error, see if it is EINVAL. EINVAL might indicate that,
   * even though we were built on a system with SOCK_CLOEXEC support, we
   * are running on one without. */
  if (errno != EINVAL)
    return -errno;
#endif

  r = socketpair(family, type, protocol, fd);
  if (r < 0)
    return -errno;

#if defined(FD_CLOEXEC)
  if (SOCKET_OK(fd[0]))
    fcntl(fd[0], F_SETFD, FD_CLOEXEC);
  if (SOCKET_OK(fd[1]))
    fcntl(fd[1], F_SETFD, FD_CLOEXEC);
#endif
  goto sockets_ok; /* So that sockets_ok will not be unused. */

 sockets_ok:
  socket_accounting_lock();
  if (SOCKET_OK(fd[0])) {
    ++n_sockets_open;
    mark_socket_open(fd[0]);
  }
  if (SOCKET_OK(fd[1])) {
    ++n_sockets_open;
    mark_socket_open(fd[1]);
  }
  socket_accounting_unlock();

  return 0;
#else
    /* This socketpair does not work when localhost is down. So
     * it's really not the same thing at all. But it's close enough
     * for now, and really, when localhost is down sometimes, we
     * have other problems too.
     */
    tor_socket_t listener = -1;
    tor_socket_t connector = -1;
    tor_socket_t acceptor = -1;
    struct sockaddr_in listen_addr;
    struct sockaddr_in connect_addr;
    int size;
    int saved_errno = -1;

    if (protocol
#ifdef AF_UNIX
        || family != AF_UNIX
#endif
        ) {
#ifdef _WIN32
      return -WSAEAFNOSUPPORT;
#else
      return -EAFNOSUPPORT;
#endif
    }
    if (!fd) {
      return -EINVAL;
    }

    listener = tor_open_socket(AF_INET, type, 0);
    if (!SOCKET_OK(listener))
      return -tor_socket_errno(-1);
    memset(&listen_addr, 0, sizeof(listen_addr));
    listen_addr.sin_family = AF_INET;
    listen_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    listen_addr.sin_port = 0;   /* kernel chooses port.  */
    if (bind(listener, (struct sockaddr *) &listen_addr, sizeof (listen_addr))
        == -1)
      goto tidy_up_and_fail;
    if (listen(listener, 1) == -1)
      goto tidy_up_and_fail;

    connector = tor_open_socket(AF_INET, type, 0);
    if (!SOCKET_OK(connector))
      goto tidy_up_and_fail;
    /* We want to find out the port number to connect to.  */
    size = sizeof(connect_addr);
    if (getsockname(listener, (struct sockaddr *) &connect_addr, &size) == -1)
      goto tidy_up_and_fail;
    if (size != sizeof (connect_addr))
      goto abort_tidy_up_and_fail;
    if (connect(connector, (struct sockaddr *) &connect_addr,
                sizeof(connect_addr)) == -1)
      goto tidy_up_and_fail;

    size = sizeof(listen_addr);
    acceptor = tor_accept_socket(listener,
                                 (struct sockaddr *) &listen_addr, &size);
    if (!SOCKET_OK(acceptor))
      goto tidy_up_and_fail;
    if (size != sizeof(listen_addr))
      goto abort_tidy_up_and_fail;
    tor_close_socket(listener);
    /* Now check we are talking to ourself by matching port and host on the
       two sockets.  */
    if (getsockname(connector, (struct sockaddr *) &connect_addr, &size) == -1)
      goto tidy_up_and_fail;
    if (size != sizeof (connect_addr)
        || listen_addr.sin_family != connect_addr.sin_family
        || listen_addr.sin_addr.s_addr != connect_addr.sin_addr.s_addr
        || listen_addr.sin_port != connect_addr.sin_port) {
      goto abort_tidy_up_and_fail;
    }
    fd[0] = connector;
    fd[1] = acceptor;

    return 0;

  abort_tidy_up_and_fail:
#ifdef _WIN32
    saved_errno = WSAECONNABORTED;
#else
    saved_errno = ECONNABORTED; /* I hope this is portable and appropriate.  */
#endif
  tidy_up_and_fail:
    if (saved_errno < 0)
      saved_errno = errno;
    if (listener != -1)
      tor_close_socket(listener);
    if (connector != -1)
      tor_close_socket(connector);
    if (acceptor != -1)
      tor_close_socket(acceptor);
    return -saved_errno;
#endif
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* tor_strtok_r_impl ( char *  str,
const char *  sep,
char **  lasts 
)

Implementation of strtok_r for platforms whose coders haven't figured out how to write one.

Hey guys! You can use this code here for free!

Definition at line 591 of file compat.c.

{
  char *cp, *start;
  tor_assert(*sep);
  if (str) {
    str = strtok_helper(str, sep);
    if (!*str)
      return NULL;
    start = cp = *lasts = str;
  } else if (!*lasts || !**lasts) {
    return NULL;
  } else {
    start = cp = *lasts;
  }

  if (sep[1]) {
    while (*cp && !strchr(sep, *cp))
      ++cp;
  } else {
    cp = strchr(cp, *sep);
  }

  if (!cp || !*cp) {
    *lasts = NULL;
  } else {
    *cp++ = '\0';
    *lasts = strtok_helper(cp, sep);
  }
  return start;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int tor_vasprintf ( char **  strp,
const char *  fmt,
va_list  args 
)

Portable vasprintf implementation.

Does a printf() into a newly malloc'd string. Differs from regular vasprintf in the same ways that tor_asprintf() differs from regular asprintf.

Definition at line 416 of file compat.c.

{
  /* use a temporary variable in case *strp is in args. */
  char *strp_tmp=NULL;
#ifdef HAVE_VASPRINTF
  /* If the platform gives us one, use it. */
  int r = vasprintf(&strp_tmp, fmt, args);
  if (r < 0)
    *strp = NULL;
  else
    *strp = strp_tmp;
  return r;
#elif defined(_MSC_VER)
  /* On Windows, _vsnprintf won't tell us the length of the string if it
   * overflows, so we need to use _vcsprintf to tell how much to allocate */
  int len, r;
  char *res;
  len = _vscprintf(fmt, args);
  if (len < 0) {
    *strp = NULL;
    return -1;
  }
  strp_tmp = tor_malloc(len + 1);
  r = _vsnprintf(strp_tmp, len+1, fmt, args);
  if (r != len) {
    tor_free(strp_tmp);
    *strp = NULL;
    return -1;
  }
  *strp = strp_tmp;
  return len;
#else
  /* Everywhere else, we have a decent vsnprintf that tells us how many
   * characters we need.  We give it a try on a short buffer first, since
   * it might be nice to avoid the second vsnprintf call.
   */
  char buf[128];
  int len, r;
  va_list tmp_args;
  va_copy(tmp_args, args);
  len = vsnprintf(buf, sizeof(buf), fmt, tmp_args);
  va_end(tmp_args);
  if (len < (int)sizeof(buf)) {
    *strp = tor_strdup(buf);
    return len;
  }
  strp_tmp = tor_malloc(len+1);
  r = vsnprintf(strp_tmp, len+1, fmt, args);
  if (r != len) {
    tor_free(strp_tmp);
    *strp = NULL;
    return -1;
  }
  *strp = strp_tmp;
  return len;
#endif
}

Here is the caller graph for this function:

int tor_vsnprintf ( char *  str,
size_t  size,
const char *  format,
va_list  args 
)

Replacement for vsnprintf; behavior differs as tor_snprintf differs from snprintf.

Definition at line 362 of file compat.c.

{
  int r;
  if (size == 0)
    return -1; /* no place for the NUL */
  if (size > SIZE_T_CEILING)
    return -1;
#ifdef _WIN32
  r = _vsnprintf(str, size, format, args);
#else
  r = vsnprintf(str, size, format, args);
#endif
  str[size-1] = '\0';
  if (r < 0 || r >= (ssize_t)size)
    return -1;
  return r;
}

Here is the caller graph for this function:

long tor_weak_random ( void  )

Return a randomly chosen value in the range 0..TOR_RAND_MAX.

This entropy will not be cryptographically strong; do not rely on it for anything an adversary should not be able to predict.

Definition at line 2078 of file compat.c.

{
#ifdef _WIN32
  return rand();
#else
  return random();
#endif
}

Here is the caller graph for this function:

int touch_file ( const char *  fname)

Change fname's modification time to now.

Definition at line 744 of file compat.c.

{
  if (utime(fname, NULL)!=0)
    return -1;
  return 0;
}

Here is the caller graph for this function:


Variable Documentation

char** environ
unsigned long main_thread_id = -1 [static]

Identity of the "main" thread.

Definition at line 2901 of file compat.c.

int n_sockets_open = 0 [static]

Count of number of sockets currently open.

(Undercounts sockets opened by eventdns and libevent.)

Definition at line 905 of file compat.c.

Mutex to protect open_sockets, max_socket, and n_sockets_open.

Definition at line 908 of file compat.c.

const uint32_t TOR_ISALNUM_TABLE[8]
Initial value:
  { 0, 0x3ff0000, 0x7fffffe, 0x7fffffe, 0, 0, 0, 0 }

Definition at line 521 of file compat.c.

const uint32_t TOR_ISALPHA_TABLE[8]
Initial value:
  { 0, 0, 0x7fffffe, 0x7fffffe, 0, 0, 0, 0 }

Tables to implement ctypes-replacement TOR_IS*() functions.

Each table has 256 bits to look up whether a character is in some set or not. This fails on non-ASCII platforms, but it is hard to find a platform whose character set is not a superset of ASCII nowadays.

Definition at line 519 of file compat.c.

const uint32_t TOR_ISDIGIT_TABLE[8] = { 0, 0x3ff0000, 0, 0, 0, 0, 0, 0 }

Definition at line 526 of file compat.c.

const uint32_t TOR_ISLOWER_TABLE[8] = { 0, 0, 0, 0x7fffffe, 0, 0, 0, 0 }

Definition at line 530 of file compat.c.

const uint32_t TOR_ISPRINT_TABLE[8]
Initial value:
  { 0, 0xffffffff, 0xffffffff, 0x7fffffff, 0, 0, 0, 0x0 }

Definition at line 527 of file compat.c.

const uint32_t TOR_ISSPACE_TABLE[8] = { 0x3e00, 0x1, 0, 0, 0, 0, 0, 0 }

Definition at line 523 of file compat.c.

const uint32_t TOR_ISUPPER_TABLE[8] = { 0, 0, 0x7fffffe, 0, 0, 0, 0, 0 }

Definition at line 529 of file compat.c.

const uint32_t TOR_ISXDIGIT_TABLE[8]
Initial value:
  { 0, 0x3ff0000, 0x7e, 0x7e, 0, 0, 0, 0 }

Definition at line 524 of file compat.c.

const char TOR_TOLOWER_TABLE[256]
Initial value:
 {
  0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
  16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
  32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,
  48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,
  64,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,
  112,113,114,115,116,117,118,119,120,121,122,91,92,93,94,95,
  96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,
  112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
  128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
  144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
  160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
  176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
  192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
  208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
  224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
  240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,
}

Definition at line 553 of file compat.c.

const char TOR_TOUPPER_TABLE[256]
Initial value:
 {
  0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
  16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
  32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,
  48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,
  64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,
  80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,
  96,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,
  80,81,82,83,84,85,86,87,88,89,90,123,124,125,126,127,
  128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
  144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
  160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
  176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
  192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
  208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
  224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
  240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,
}

Upper-casing and lowercasing tables to map characters to upper/lowercase equivalents.

Used by tor_toupper() and tor_tolower().

Definition at line 535 of file compat.c.

char uname_result[256] [static]

Hold the result of our call to uname.

Definition at line 2088 of file compat.c.

int uname_result_is_set = 0 [static]

True iff uname_result is set.

Definition at line 2090 of file compat.c.