Forward port changelog
[tor.git] / src / common / compat.c
blobc4e949a6e71cf4aa07e4f92a4f9438b843a3a3a1
1 /* Copyright 2003-2004 Roger Dingledine; Copyright 2004 Nick Mathewson */
2 /* See LICENSE for licensing information */
3 /* $Id$ */
4 const char compat_c_id[] = "$Id$";
6 /* This is required on rh7 to make strptime not complain.
7 */
8 #define _GNU_SOURCE
10 #include "orconfig.h"
11 #include "compat.h"
13 #ifdef MS_WINDOWS
14 #include <process.h>
15 #endif
16 #ifdef HAVE_UNAME
17 #include <sys/utsname.h>
18 #endif
19 #ifdef HAVE_SYS_TIME_H
20 #include <sys/time.h>
21 #endif
22 #ifdef HAVE_UNISTD_H
23 #include <unistd.h>
24 #endif
25 #ifdef HAVE_SYS_FCNTL_H
26 #include <sys/fcntl.h>
27 #endif
28 #ifdef HAVE_PWD_H
29 #include <pwd.h>
30 #endif
31 #ifdef HAVE_GRP_H
32 #include <grp.h>
33 #endif
34 #ifdef HAVE_FCNTL_H
35 #include <fcntl.h>
36 #endif
37 #ifdef HAVE_SYS_RESOURCE_H
38 #include <sys/resource.h>
39 #endif
40 #ifdef HAVE_ERRNO_H
41 #include <errno.h>
42 #endif
43 #ifdef HAVE_NETINET_IN_H
44 #include <netinet/in.h>
45 #endif
46 #ifdef HAVE_ARPA_INET_H
47 #include <arpa/inet.h>
48 #endif
49 #ifndef HAVE_GETTIMEOFDAY
50 #ifdef HAVE_FTIME
51 #include <sys/timeb.h>
52 #endif
53 #endif
54 #ifdef HAVE_SYS_SOCKET_H
55 #include <sys/socket.h>
56 #endif
57 #ifdef HAVE_NETDB_H
58 #include <netdb.h>
59 #endif
60 #ifdef HAVE_SYS_PARAM_H
61 #include <sys/param.h> /* FreeBSD needs this to know what version it is */
62 #endif
63 #include <stdarg.h>
64 #include <stdio.h>
65 #include <stdlib.h>
66 #include <string.h>
67 #include <assert.h>
68 #ifdef HAVE_PTHREAD_H
69 #include <pthread.h>
70 #endif
72 #include "log.h"
73 #include "util.h"
75 /* Inline the strl functions if the platform doesn't have them. */
76 #ifndef HAVE_STRLCPY
77 #include "strlcpy.c"
78 #endif
79 #ifndef HAVE_STRLCAT
80 #include "strlcat.c"
81 #endif
83 /* used by inet_addr, not defined on solaris anywhere!? */
84 #ifndef INADDR_NONE
85 #define INADDR_NONE ((unsigned long) -1)
86 #endif
88 /** Replacement for snprintf. Differs from platform snprintf in two
89 * ways: First, always NUL-terminates its output. Second, always
90 * returns -1 if the result is truncated. (Note that this return
91 * behavior does <i>not</i> conform to C99; it just happens to be the
92 * easiest to emulate "return -1" with conformant implementations than
93 * it is to emulate "return number that would be written" with
94 * non-conformant implementations.) */
95 int tor_snprintf(char *str, size_t size, const char *format, ...)
97 va_list ap;
98 int r;
99 va_start(ap,format);
100 r = tor_vsnprintf(str,size,format,ap);
101 va_end(ap);
102 return r;
105 /** Replacement for vsnprintf; behavior differs as tor_snprintf differs from
106 * snprintf.
108 int tor_vsnprintf(char *str, size_t size, const char *format, va_list args)
110 int r;
111 if (size == 0)
112 return -1; /* no place for the NUL */
113 if (size > SIZE_T_CEILING)
114 return -1;
115 #ifdef MS_WINDOWS
116 r = _vsnprintf(str, size, format, args);
117 #else
118 r = vsnprintf(str, size, format, args);
119 #endif
120 str[size-1] = '\0';
121 if (r < 0 || ((size_t)r) >= size)
122 return -1;
123 return r;
126 /** Take a filename and return a pointer to its final element. This
127 * function is called on __FILE__ to fix a MSVC nit where __FILE__
128 * contains the full path to the file. This is bad, because it
129 * confuses users to find the home directory of the person who
130 * compiled the binary in their warrning messages.
132 const char *
133 _tor_fix_source_file(const char *fname)
135 const char *cp1, *cp2, *r;
136 cp1 = strrchr(fname, '/');
137 cp2 = strrchr(fname, '\\');
138 if (cp1 && cp2) {
139 r = (cp1<cp2)?(cp2+1):(cp1+1);
140 } else if (cp1) {
141 r = cp1+1;
142 } else if (cp2) {
143 r = cp2+1;
144 } else {
145 r = fname;
147 return r;
150 #ifndef UNALIGNED_INT_ACCESS_OK
152 * Read a 16-bit value beginning at <b>cp</b>. Equivalent to
153 * *(uint16_t*)(cp), but will not cause segfaults on platforms that forbid
154 * unaligned memory access.
156 uint16_t get_uint16(const char *cp)
158 uint16_t v;
159 memcpy(&v,cp,2);
160 return v;
163 * Read a 32-bit value beginning at <b>cp</b>. Equivalent to
164 * *(uint32_t*)(cp), but will not cause segfaults on platforms that forbid
165 * unaligned memory access.
167 uint32_t get_uint32(const char *cp)
169 uint32_t v;
170 memcpy(&v,cp,4);
171 return v;
174 * Set a 16-bit value beginning at <b>cp</b> to <b>v</b>. Equivalent to
175 * *(uint16_t)(cp) = v, but will not cause segfaults on platforms that forbid
176 * unaligned memory access. */
177 void set_uint16(char *cp, uint16_t v)
179 memcpy(cp,&v,2);
182 * Set a 32-bit value beginning at <b>cp</b> to <b>v</b>. Equivalent to
183 * *(uint32_t)(cp) = v, but will not cause segfaults on platforms that forbid
184 * unaligned memory access. */
185 void set_uint32(char *cp, uint32_t v)
187 memcpy(cp,&v,4);
189 #endif
192 * Rename the file 'from' to the file 'to'. On unix, this is the same as
193 * rename(2). On windows, this removes 'to' first if it already exists.
194 * Returns 0 on success. Returns -1 and sets errno on failure.
196 int replace_file(const char *from, const char *to)
198 #ifndef MS_WINDOWS
199 return rename(from,to);
200 #else
201 switch (file_status(to))
203 case FN_NOENT:
204 break;
205 case FN_FILE:
206 if (unlink(to)) return -1;
207 break;
208 case FN_ERROR:
209 return -1;
210 case FN_DIR:
211 errno = EISDIR;
212 return -1;
214 return rename(from,to);
215 #endif
218 /** Turn <b>socket</b> into a nonblocking socket.
220 void set_socket_nonblocking(int socket)
222 #ifdef MS_WINDOWS
223 int nonblocking = 1;
224 ioctlsocket(socket, FIONBIO, (unsigned long*) &nonblocking);
225 #else
226 fcntl(socket, F_SETFL, O_NONBLOCK);
227 #endif
231 * Allocate a pair of connected sockets. (Like socketpair(family,
232 * type,protocol,fd), but works on systems that don't have
233 * socketpair.)
235 * Currently, only (AF_UNIX, SOCK_STREAM, 0 ) sockets are supported.
237 * Note that on systems without socketpair, this call will fail if
238 * localhost is inaccessible (for example, if the networking
239 * stack is down). And even if it succeeds, the socket pair will not
240 * be able to read while localhost is down later (the socket pair may
241 * even close, depending on OS-specific timeouts).
244 tor_socketpair(int family, int type, int protocol, int fd[2])
246 #ifdef HAVE_SOCKETPAIR
247 return socketpair(family, type, protocol, fd);
248 #else
249 /* This socketpair does not work when localhost is down. So
250 * it's really not the same thing at all. But it's close enough
251 * for now, and really, when localhost is down sometimes, we
252 * have other problems too.
254 int listener = -1;
255 int connector = -1;
256 int acceptor = -1;
257 struct sockaddr_in listen_addr;
258 struct sockaddr_in connect_addr;
259 int size;
261 if (protocol
262 #ifdef AF_UNIX
263 || family != AF_UNIX
264 #endif
266 #ifdef MS_WINDOWS
267 errno = WSAEAFNOSUPPORT;
268 #else
269 errno = EAFNOSUPPORT;
270 #endif
271 return -1;
273 if (!fd) {
274 errno = EINVAL;
275 return -1;
278 listener = socket(AF_INET, type, 0);
279 if (listener == -1)
280 return -1;
281 if (!SOCKET_IS_POLLABLE(listener)) {
282 log_fn(LOG_WARN, "Too many connections; can't open socketpair");
283 tor_close_socket(listener);
284 return -1;
286 memset(&listen_addr, 0, sizeof(listen_addr));
287 listen_addr.sin_family = AF_INET;
288 listen_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
289 listen_addr.sin_port = 0; /* kernel chooses port. */
290 if (bind(listener, (struct sockaddr *) &listen_addr, sizeof (listen_addr))
291 == -1)
292 goto tidy_up_and_fail;
293 if (listen(listener, 1) == -1)
294 goto tidy_up_and_fail;
296 connector = socket(AF_INET, type, 0);
297 if (connector == -1)
298 goto tidy_up_and_fail;
299 if (!SOCKET_IS_POLLABLE(connector)) {
300 log_fn(LOG_WARN, "Too many connections; can't open socketpair");
301 goto tidy_up_and_fail;
303 /* We want to find out the port number to connect to. */
304 size = sizeof(connect_addr);
305 if (getsockname(listener, (struct sockaddr *) &connect_addr, &size) == -1)
306 goto tidy_up_and_fail;
307 if (size != sizeof (connect_addr))
308 goto abort_tidy_up_and_fail;
309 if (connect(connector, (struct sockaddr *) &connect_addr,
310 sizeof(connect_addr)) == -1)
311 goto tidy_up_and_fail;
313 size = sizeof(listen_addr);
314 acceptor = accept(listener, (struct sockaddr *) &listen_addr, &size);
315 if (acceptor == -1)
316 goto tidy_up_and_fail;
317 if (!SOCKET_IS_POLLABLE(acceptor)) {
318 log_fn(LOG_WARN, "Too many connections; can't open socketpair");
319 goto tidy_up_and_fail;
321 if (size != sizeof(listen_addr))
322 goto abort_tidy_up_and_fail;
323 tor_close_socket(listener);
324 /* Now check we are talking to ourself by matching port and host on the
325 two sockets. */
326 if (getsockname(connector, (struct sockaddr *) &connect_addr, &size) == -1)
327 goto tidy_up_and_fail;
328 if (size != sizeof (connect_addr)
329 || listen_addr.sin_family != connect_addr.sin_family
330 || listen_addr.sin_addr.s_addr != connect_addr.sin_addr.s_addr
331 || listen_addr.sin_port != connect_addr.sin_port) {
332 goto abort_tidy_up_and_fail;
334 fd[0] = connector;
335 fd[1] = acceptor;
337 return 0;
339 abort_tidy_up_and_fail:
340 #ifdef MS_WINDOWS
341 errno = WSAECONNABORTED;
342 #else
343 errno = ECONNABORTED; /* I hope this is portable and appropriate. */
344 #endif
345 tidy_up_and_fail:
347 int save_errno = errno;
348 if (listener != -1)
349 tor_close_socket(listener);
350 if (connector != -1)
351 tor_close_socket(connector);
352 if (acceptor != -1)
353 tor_close_socket(acceptor);
354 errno = save_errno;
355 return -1;
357 #endif
360 /** Get the maximum allowed number of file descriptors. (Some systems
361 * have a low soft limit.) Make sure we set it to at least
362 * <b>required_min</b>. Return 0 if we can, or -1 if we fail. */
363 int set_max_file_descriptors(unsigned int required_min) {
364 #ifndef HAVE_GETRLIMIT
365 log_fn(LOG_INFO,"This platform is missing getrlimit(). Proceeding.");
366 return 0; /* hope we'll be ok */
367 #else
368 struct rlimit rlim;
370 if (getrlimit(RLIMIT_NOFILE, &rlim) != 0) {
371 log_fn(LOG_WARN, "Could not get maximum number of file descriptors: %s",
372 strerror(errno));
373 return -1;
375 if (required_min > rlim.rlim_max) {
376 log_fn(LOG_WARN,"We need %u file descriptors available, and we're limited to %lu. Please change your ulimit.", required_min, (unsigned long int)rlim.rlim_max);
377 return -1;
379 if (required_min > rlim.rlim_cur) {
380 log_fn(LOG_INFO,"Raising max file descriptors from %lu to %lu.",
381 (unsigned long int)rlim.rlim_cur, (unsigned long int)rlim.rlim_max);
383 rlim.rlim_cur = rlim.rlim_max;
384 if (setrlimit(RLIMIT_NOFILE, &rlim) != 0) {
385 log_fn(LOG_WARN, "Could not set maximum number of file descriptors: %s",
386 strerror(errno));
387 return -1;
389 return 0;
390 #endif
393 /** Call setuid and setgid to run as <b>user</b>:<b>group</b>. Return 0 on
394 * success. On failure, log and return -1.
396 int switch_id(char *user, char *group) {
397 #ifndef MS_WINDOWS
398 struct passwd *pw = NULL;
399 struct group *gr = NULL;
401 if (user) {
402 pw = getpwnam(user);
403 if (pw == NULL) {
404 log_fn(LOG_ERR,"User '%s' not found.", user);
405 return -1;
409 /* switch the group first, while we still have the privileges to do so */
410 if (group) {
411 gr = getgrnam(group);
412 if (gr == NULL) {
413 log_fn(LOG_ERR,"Group '%s' not found.", group);
414 return -1;
417 if (setgid(gr->gr_gid) != 0) {
418 log_fn(LOG_ERR,"Error setting GID: %s", strerror(errno));
419 return -1;
421 } else if (user) {
422 if (setgid(pw->pw_gid) != 0) {
423 log_fn(LOG_ERR,"Error setting GID: %s", strerror(errno));
424 return -1;
428 /* now that the group is switched, we can switch users and lose
429 privileges */
430 if (user) {
431 if (setuid(pw->pw_uid) != 0) {
432 log_fn(LOG_ERR,"Error setting UID: %s", strerror(errno));
433 return -1;
437 return 0;
438 #endif
440 log_fn(LOG_ERR,
441 "User or group specified, but switching users is not supported.");
443 return -1;
446 #ifdef HAVE_PWD_H
447 /** Allocate and return a string containing the home directory for the
448 * user <b>username</b>. Only works on posix-like systems */
449 char *
450 get_user_homedir(const char *username)
452 struct passwd *pw;
453 tor_assert(username);
455 if (!(pw = getpwnam(username))) {
456 log_fn(LOG_ERR,"User '%s' not found.", username);
457 return NULL;
459 return tor_strdup(pw->pw_dir);
461 #endif
463 /** Set *addr to the IP address (in dotted-quad notation) stored in c.
464 * Return 1 on success, 0 if c is badly formatted. (Like inet_aton(c,addr),
465 * but works on Windows and Solaris.)
467 int tor_inet_aton(const char *c, struct in_addr* addr)
469 #ifdef HAVE_INET_ATON
470 return inet_aton(c, addr);
471 #else
472 uint32_t r;
473 tor_assert(c);
474 tor_assert(addr);
475 if (strcmp(c, "255.255.255.255") == 0) {
476 addr->s_addr = 0xFFFFFFFFu;
477 return 1;
479 r = inet_addr(c);
480 if (r == INADDR_NONE)
481 return 0;
482 addr->s_addr = r;
483 return 1;
484 #endif
487 /** Similar behavior to Unix gethostbyname: resolve <b>name</b>, and set
488 * *addr to the proper IP address, in network byte order. Returns 0
489 * on success, -1 on failure; 1 on transient failure.
491 * (This function exists because standard windows gethostbyname
492 * doesn't treat raw IP addresses properly.)
494 int tor_lookup_hostname(const char *name, uint32_t *addr)
496 /* Perhaps eventually this should be replaced by a tor_getaddrinfo or
497 * something.
499 struct in_addr iaddr;
500 tor_assert(addr);
501 if (!*name) {
502 /* Empty address is an error. */
503 return -1;
504 } else if (tor_inet_aton(name, &iaddr)) {
505 /* It's an IP. */
506 memcpy(addr, &iaddr.s_addr, 4);
507 return 0;
508 } else {
509 #ifdef HAVE_GETADDRINFO
510 int err;
511 struct addrinfo *res, *res_p;
512 struct addrinfo hints;
513 memset(&hints, 0, sizeof(hints));
514 hints.ai_family = PF_INET;
515 hints.ai_socktype = SOCK_STREAM;
516 err = getaddrinfo(name, NULL, NULL, &res);
517 if (!err) {
518 for (res_p = res; res_p; res_p = res_p->ai_next) {
519 if (res_p->ai_family == AF_INET) {
520 struct sockaddr_in *sin = (struct sockaddr_in *)res_p->ai_addr;
521 memcpy(addr, &sin->sin_addr, 4);
522 freeaddrinfo(res);
523 return 0;
524 } else {
527 return -1;
530 return (err == EAI_AGAIN) ? 1 : -1;
531 #else
532 struct hostent *ent;
533 #ifdef HAVE_GETHOSTBYNAME_R
534 ent = gethostbyname_r(name);
535 #else
536 struct hostent *ent;
537 #endif
538 if (ent) {
539 /* break to remind us if we move away from IPv4 */
540 tor_assert(ent->h_length == 4);
541 memcpy(addr, ent->h_addr, 4);
542 return 0;
544 memset(addr, 0, 4);
545 #ifdef MS_WINDOWS
546 return (WSAGetLastError() == WSATRY_AGAIN) ? 1 : -1;
547 #else
548 return (h_errno == TRY_AGAIN) ? 1 : -1;
549 #endif
550 #endif
554 /* Hold the result of our call to <b>uname</b>. */
555 static char uname_result[256];
556 /* True iff uname_result is set. */
557 static int uname_result_is_set = 0;
559 /* Return a pointer to a description of our platform.
561 const char *
562 get_uname(void)
564 #ifdef HAVE_UNAME
565 struct utsname u;
566 #endif
567 if (!uname_result_is_set) {
568 #ifdef HAVE_UNAME
569 if (uname(&u) != -1) {
570 /* (linux says 0 is success, solaris says 1 is success) */
571 tor_snprintf(uname_result, sizeof(uname_result), "%s %s %s",
572 u.sysname, u.nodename, u.machine);
573 } else
574 #endif
576 #ifdef MS_WINDOWS
577 OSVERSIONINFO info;
578 int i;
579 const char *plat = NULL;
580 static struct {
581 int major; int minor; const char *version;
582 } win_version_table[] = {
583 { 5, 2, "Windows Server 2003" },
584 { 5, 1, "Windows XP" },
585 { 5, 0, "Windows 2000" },
586 /* { 4, 0, "Windows NT 4.0" }, */
587 { 4, 90, "Windows Me" },
588 { 4, 10, "Windows 98" },
589 /* { 4, 0, "Windows 95" } */
590 { 3, 51, "Windows NT 3.51" },
591 { -1, -1, NULL }
593 info.dwOSVersionInfoSize = sizeof(info);
594 GetVersionEx(&info);
595 if (info.dwMajorVersion == 4 && info.dwMinorVersion == 0) {
596 if (info.dwPlatformId == VER_PLATFORM_WIN32_NT)
597 plat = "Windows NT 4.0";
598 else
599 plat = "Windows 95";
600 } else {
601 for (i=0; win_version_table[i].major>=0; ++i) {
602 if (win_version_table[i].major == info.dwMajorVersion &&
603 win_version_table[i].minor == info.dwMinorVersion) {
604 plat = win_version_table[i].version;
605 break;
609 if (plat) {
610 strlcpy(uname_result, plat, sizeof(uname_result));
611 } else {
612 if (info.dwMajorVersion > 5 ||
613 (info.dwMajorVersion==5 && info.dwMinorVersion>2))
614 tor_snprintf(uname_result, sizeof(uname_result),
615 "Very recent version of Windows [major=%d,minor=%d]",
616 (int)info.dwMajorVersion,(int)info.dwMinorVersion);
617 else
618 tor_snprintf(uname_result, sizeof(uname_result),
619 "Unrecognized version of Windows [major=%d,minor=%d]",
620 (int)info.dwMajorVersion,(int)info.dwMinorVersion);
622 #else
623 strlcpy(uname_result, "Unknown platform", sizeof(uname_result));
624 #endif
626 uname_result_is_set = 1;
628 return uname_result;
632 * Process control
635 #if defined(USE_PTHREADS)
636 struct tor_pthread_data_t {
637 int (*func)(void *);
638 void *data;
640 static void *
641 tor_pthread_helper_fn(void *_data)
643 struct tor_pthread_data_t *data = _data;
644 int (*func)(void*);
645 void *arg;
646 func = data->func;
647 arg = data->data;
648 tor_free(_data);
649 func(arg);
650 return NULL;
652 #endif
654 /** Minimalist interface to run a void function in the background. On
655 * unix calls fork, on win32 calls beginthread. Returns -1 on failure.
656 * func should not return, but rather should call spawn_exit.
658 * NOTE: if <b>data</b> is used, it should not be allocated on the stack,
659 * since in a multithreaded environment, there is no way to be sure that
660 * the caller's stack will still be around when the called function is
661 * running.
664 spawn_func(int (*func)(void *), void *data)
666 #if defined(USE_WIN32_THREADS)
667 int rv;
668 rv = _beginthread(func, 0, data);
669 if (rv == (unsigned long) -1)
670 return -1;
671 return 0;
672 #elif defined(USE_PTHREADS)
673 pthread_t thread;
674 struct tor_pthread_data_t *d;
675 d = tor_malloc(sizeof(struct tor_pthread_data_t));
676 d->data = data;
677 d->func = func;
678 if (pthread_create(&thread,NULL,tor_pthread_helper_fn,d))
679 return -1;
680 if (pthread_detach(thread))
681 return -1;
682 return 0;
683 #else
684 pid_t pid;
685 pid = fork();
686 if (pid<0)
687 return -1;
688 if (pid==0) {
689 /* Child */
690 func(data);
691 tor_assert(0); /* Should never reach here. */
692 return 0; /* suppress "control-reaches-end-of-non-void" warning. */
693 } else {
694 /* Parent */
695 return 0;
697 #endif
700 /** End the current thread/process.
702 void spawn_exit()
704 #if defined(USE_WIN32_THREADS)
705 _endthread();
706 #elif defined(USE_PTHREADS)
707 pthread_exit(NULL);
708 #else
709 /* http://www.erlenstar.demon.co.uk/unix/faq_2.html says we should
710 * call _exit, not exit, from child processes. */
711 _exit(0);
712 #endif
715 /** Set *timeval to the current time of day. On error, log and terminate.
716 * (Same as gettimeofday(timeval,NULL), but never returns -1.)
718 void tor_gettimeofday(struct timeval *timeval) {
719 #ifdef HAVE_GETTIMEOFDAY
720 if (gettimeofday(timeval, NULL)) {
721 log_fn(LOG_ERR, "gettimeofday failed.");
722 /* If gettimeofday dies, we have either given a bad timezone (we didn't),
723 or segfaulted.*/
724 exit(1);
726 #elif defined(HAVE_FTIME)
727 struct timeb tb;
728 ftime(&tb);
729 timeval->tv_sec = tb.time;
730 timeval->tv_usec = tb.millitm * 1000;
731 #else
732 #error "No way to get time."
733 #endif
734 return;
737 #ifdef USE_WIN32_THREADS
738 struct tor_mutex_t {
739 HANDLE handle;
741 tor_mutex_t *tor_mutex_new(void)
743 tor_mutex_t *m;
744 m = tor_malloc_zero(sizeof(tor_mutex_t));
745 m->handle = CreateMutex(NULL, FALSE, NULL);
746 tor_assert(m->handle != NULL);
747 return m;
749 void tor_mutex_free(tor_mutex_t *m)
751 CloseHandle(m->handle);
752 tor_free(m);
754 void tor_mutex_acquire(tor_mutex_t *m)
756 DWORD r;
757 r = WaitForSingleObject(m->handle, INFINITE);
758 switch (r) {
759 case WAIT_ABANDONED: /* holding thread exited. */
760 case WAIT_OBJECT_0: /* we got the mutex normally. */
761 break;
762 case WAIT_TIMEOUT: /* Should never happen. */
763 tor_assert(0);
764 break;
765 case WAIT_FAILED:
766 log_fn(LOG_WARN, "Failed to acquire mutex: %d", GetLastError());
769 void tor_mutex_release(tor_mutex_t *m)
771 BOOL r;
772 r = ReleaseMutex(m->handle);
773 if (!r) {
774 log_fn(LOG_WARN, "Failed to release mutex: %d", GetLastError());
777 #elif defined(USE_PTHREADS)
778 struct tor_mutex_t {
779 pthread_mutex_t mutex;
781 tor_mutex_t *tor_mutex_new(void)
783 tor_mutex_t *mutex = tor_malloc_zero(sizeof(tor_mutex_t));
784 pthread_mutex_init(&mutex->mutex, NULL);
785 return mutex;
787 void tor_mutex_acquire(tor_mutex_t *m)
789 tor_assert(m);
790 pthread_mutex_lock(&m->mutex);
792 void tor_mutex_release(tor_mutex_t *m)
794 tor_assert(m);
795 pthread_mutex_unlock(&m->mutex);
797 void tor_mutex_free(tor_mutex_t *m)
799 tor_assert(m);
800 pthread_mutex_destroy(&m->mutex);
801 tor_free(m);
803 #else
804 struct tor_mutex_t {
805 int _unused;
807 tor_mutex_t *tor_mutex_new(void) { return NULL; }
808 void tor_mutex_acquire(tor_mutex_t *m) { }
809 void tor_mutex_release(tor_mutex_t *m) { }
810 void tor_mutex_free(tor_mutex_t *m) { }
811 #endif
814 * On Windows, WSAEWOULDBLOCK is not always correct: when you see it,
815 * you need to ask the socket for its actual errno. Also, you need to
816 * get your errors from WSAGetLastError, not errno. (If you supply a
817 * socket of -1, we check WSAGetLastError, but don't correct
818 * WSAEWOULDBLOCKs.)
820 * The upshot of all of this is that when a socket call fails, you
821 * should call tor_socket_errno <em>at most once</em> on the failing
822 * socket to get the error.
824 #ifdef MS_WINDOWS
825 int tor_socket_errno(int sock)
827 int optval, optvallen=sizeof(optval);
828 int err = WSAGetLastError();
829 if (err == WSAEWOULDBLOCK && sock >= 0) {
830 if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*)&optval, &optvallen))
831 return err;
832 if (optval)
833 return optval;
835 return err;
837 #endif
839 #ifdef MS_WINDOWS
840 #define E(code, s) { code, (s " [" #code " ]") }
841 struct { int code; const char *msg; } windows_socket_errors[] = {
842 E(WSAEINTR, "Interrupted function call"),
843 E(WSAEACCES, "Permission denied"),
844 E(WSAEFAULT, "Bad address"),
845 E(WSAEINVAL, "Invalid argument"),
846 E(WSAEMFILE, "Too many open files"),
847 E(WSAEWOULDBLOCK, "Resource temporarily unavailable"),
848 E(WSAEINPROGRESS, "Operation now in progress"),
849 E(WSAEALREADY, "Operation already in progress"),
850 E(WSAENOTSOCK, "Socket operation on nonsocket"),
851 E(WSAEDESTADDRREQ, "Destination address required"),
852 E(WSAEMSGSIZE, "Message too long"),
853 E(WSAEPROTOTYPE, "Protocol wrong for socket"),
854 E(WSAENOPROTOOPT, "Bad protocol option"),
855 E(WSAEPROTONOSUPPORT, "Protocol not supported"),
856 E(WSAESOCKTNOSUPPORT, "Socket type not supported"),
857 /* What's the difference between NOTSUPP and NOSUPPORT? :) */
858 E(WSAEOPNOTSUPP, "Operation not supported"),
859 E(WSAEPFNOSUPPORT, "Protocol family not supported"),
860 E(WSAEAFNOSUPPORT, "Address family not supported by protocol family"),
861 E(WSAEADDRINUSE, "Address already in use"),
862 E(WSAEADDRNOTAVAIL, "Cannot assign requested address"),
863 E(WSAENETDOWN, "Network is down"),
864 E(WSAENETUNREACH, "Network is unreachable"),
865 E(WSAENETRESET, "Network dropped connection on reset"),
866 E(WSAECONNABORTED, "Software caused connection abort"),
867 E(WSAECONNRESET, "Connection reset by peer"),
868 E(WSAENOBUFS, "No buffer space available"),
869 E(WSAEISCONN, "Socket is already connected"),
870 E(WSAENOTCONN, "Socket is not connected"),
871 E(WSAESHUTDOWN, "Cannot send after socket shutdown"),
872 E(WSAETIMEDOUT, "Connection timed out"),
873 E(WSAECONNREFUSED, "Connection refused"),
874 E(WSAEHOSTDOWN, "Host is down"),
875 E(WSAEHOSTUNREACH, "No route to host"),
876 E(WSAEPROCLIM, "Too many processes"),
877 /* Yes, some of these start with WSA, not WSAE. No, I don't know why. */
878 E(WSASYSNOTREADY, "Network subsystem is unavailable"),
879 E(WSAVERNOTSUPPORTED, "Winsock.dll out of range"),
880 E(WSANOTINITIALISED, "Successful WSAStartup not yet performed"),
881 E(WSAEDISCON, "Graceful shutdown now in progress"),
882 #ifdef WSATYPE_NOT_FOUND
883 E(WSATYPE_NOT_FOUND, "Class type not found"),
884 #endif
885 E(WSAHOST_NOT_FOUND, "Host not found"),
886 E(WSATRY_AGAIN, "Nonauthoritative host not found"),
887 E(WSANO_RECOVERY, "This is a nonrecoverable error"),
888 E(WSANO_DATA, "Valid name, no data record of requested type)"),
890 /* There are some more error codes whose numeric values are marked
891 * <b>OS dependent</b>. They start with WSA_, apparently for the same
892 * reason that practitioners of some craft traditions deliberately
893 * introduce imperfections into their baskets and rugs "to allow the
894 * evil spirits to escape." If we catch them, then our binaries
895 * might not report consistent results across versions of Windows.
896 * Thus, I'm going to let them all fall through.
898 { -1, NULL },
900 /** There does not seem to be a strerror equivalent for winsock errors.
901 * Naturally, we have to roll our own.
903 const char *tor_socket_strerror(int e)
905 int i;
906 for (i=0; windows_socket_errors[i].code >= 0; ++i) {
907 if (e == windows_socket_errors[i].code)
908 return windows_socket_errors[i].msg;
910 return strerror(e);
912 #endif
914 /** Called before we make any calls to network-related functions.
915 * (Some operating systems require their network libraries to be
916 * initialized.) */
917 int network_init(void)
919 #ifdef MS_WINDOWS
920 /* This silly exercise is necessary before windows will allow gethostbyname to work.
922 WSADATA WSAData;
923 int r;
924 r = WSAStartup(0x101,&WSAData);
925 if (r) {
926 log_fn(LOG_WARN,"Error initializing windows network layer: code was %d",r);
927 return -1;
929 #endif
930 return 0;