r12001@catbus: nickm | 2007-02-28 15:24:12 -0500
[tor.git] / src / common / compat.c
blobce7e00babc98da1e299d20c4fe68c9e7e338ea85
1 /* Copyright 2003-2004 Roger Dingledine
2 * Copyright 2004-2007 Roger Dingledine, Nick Mathewson */
3 /* See LICENSE for licensing information */
4 /* $Id$ */
5 const char compat_c_id[] =
6 "$Id$";
8 /**
9 * \file compat.c
10 * \brief Wrappers to make calls more portable. This code defines
11 * functions such as tor_malloc, tor_snprintf, get/set various data types,
12 * renaming, setting socket options, switching user IDs. It is basically
13 * where the non-portable items are conditionally included depending on
14 * the platform.
15 **/
17 /* This is required on rh7 to make strptime not complain.
18 * We also need it to make memmem get defined (where available)
20 #define _GNU_SOURCE
22 #include "orconfig.h"
23 #include "compat.h"
25 #ifdef MS_WINDOWS
26 #include <process.h>
27 #include <windows.h>
28 #endif
30 #ifdef HAVE_UNAME
31 #include <sys/utsname.h>
32 #endif
33 #ifdef HAVE_SYS_TIME_H
34 #include <sys/time.h>
35 #endif
36 #ifdef HAVE_UNISTD_H
37 #include <unistd.h>
38 #endif
39 #ifdef HAVE_SYS_FCNTL_H
40 #include <sys/fcntl.h>
41 #endif
42 #ifdef HAVE_PWD_H
43 #include <pwd.h>
44 #endif
45 #ifdef HAVE_GRP_H
46 #include <grp.h>
47 #endif
48 #ifdef HAVE_FCNTL_H
49 #include <fcntl.h>
50 #endif
51 #ifdef HAVE_SYS_RESOURCE_H
52 #include <sys/resource.h>
53 #endif
54 #ifdef HAVE_ERRNO_H
55 #include <errno.h>
56 #endif
57 #ifdef HAVE_NETINET_IN_H
58 #include <netinet/in.h>
59 #endif
60 #ifdef HAVE_ARPA_INET_H
61 #include <arpa/inet.h>
62 #endif
63 #ifndef HAVE_GETTIMEOFDAY
64 #ifdef HAVE_FTIME
65 #include <sys/timeb.h>
66 #endif
67 #endif
68 #ifdef HAVE_SYS_SOCKET_H
69 #include <sys/socket.h>
70 #endif
71 #ifdef HAVE_NETDB_H
72 #include <netdb.h>
73 #endif
74 #ifdef HAVE_SYS_PARAM_H
75 #include <sys/param.h> /* FreeBSD needs this to know what version it is */
76 #endif
77 #include <stdarg.h>
78 #include <stdio.h>
79 #include <stdlib.h>
80 #include <string.h>
81 #include <assert.h>
82 #ifdef HAVE_PTHREAD_H
83 #include <pthread.h>
84 #endif
85 #ifdef HAVE_SIGNAL_H
86 #include <signal.h>
87 #endif
88 #ifdef HAVE_UTIME_H
89 #include <utime.h>
90 #endif
91 #ifdef HAVE_SYS_UTIME_H
92 #include <sys/utime.h>
93 #endif
94 #ifdef HAVE_SYS_MMAN_H
95 #include <sys/mman.h>
96 #endif
98 #ifdef USE_BSOCKETS
99 #include <bsocket.h>
100 #endif
102 #include "log.h"
103 #include "util.h"
105 /* Inline the strl functions if the platform doesn't have them. */
106 #ifndef HAVE_STRLCPY
107 #include "strlcpy.c"
108 #endif
109 #ifndef HAVE_STRLCAT
110 #include "strlcat.c"
111 #endif
113 #ifndef INADDR_NONE
114 /* This is used by inet_addr, but apparently Solaris doesn't define it
115 * anyplace. */
116 #define INADDR_NONE ((unsigned long) -1)
117 #endif
119 #ifdef HAVE_SYS_MMAN_H
120 /** Implementation for tor_mmap_t: holds the regular tor_mmap_t, along
121 * with extra fields needed for mmap()-based memory mapping. */
122 typedef struct tor_mmap_impl_t {
123 tor_mmap_t base;
124 size_t mapping_size; /**< Size of the actual mapping. (This is this file
125 * size, rounded up to the nearest page.) */
126 } tor_mmap_impl_t;
127 /** Try to create a memory mapping for <b>filename</b> and return it. On
128 * failure, return NULL. */
129 tor_mmap_t *
130 tor_mmap_file(const char *filename)
132 int fd; /* router file */
133 char *string;
134 int page_size;
135 tor_mmap_impl_t *res;
136 size_t size, filesize;
138 tor_assert(filename);
140 fd = open(filename, O_RDONLY, 0);
141 if (fd<0) {
142 int severity = (errno == ENOENT) ? LOG_INFO : LOG_WARN;
143 log_fn(severity, LD_FS,"Could not open \"%s\" for mmap(): %s",filename,
144 strerror(errno));
145 return NULL;
148 size = filesize = (size_t) lseek(fd, 0, SEEK_END);
149 lseek(fd, 0, SEEK_SET);
150 /* ensure page alignment */
151 page_size = getpagesize();
152 size += (size%page_size) ? page_size-(size%page_size) : 0;
154 if (!size) {
155 /* Zero-length file. If we call mmap on it, it will succeed but
156 * return NULL, and bad things will happen. So just fail. */
157 log_info(LD_FS,"File \"%s\" is empty. Ignoring.",filename);
158 return NULL;
161 string = mmap(0, size, PROT_READ, MAP_PRIVATE, fd, 0);
162 if (string == MAP_FAILED) {
163 close(fd);
164 log_warn(LD_FS,"Could not mmap file \"%s\": %s", filename,
165 strerror(errno));
166 return NULL;
169 close(fd);
171 res = tor_malloc_zero(sizeof(tor_mmap_impl_t));
172 res->base.data = string;
173 res->base.size = filesize;
174 res->mapping_size = size;
176 return &(res->base);
178 /** Release storage held for a memory mapping. */
179 void
180 tor_munmap_file(tor_mmap_t *handle)
182 tor_mmap_impl_t *h = SUBTYPE_P(handle, tor_mmap_impl_t, base);
183 munmap((char*)h->base.data, h->mapping_size);
184 tor_free(h);
186 #elif defined(MS_WINDOWS)
187 /** Implementation for tor_mmap_t: holds the regular tor_mmap_t, along
188 * with extra fields needed for WIN32 memory mapping. */
189 typedef struct win_mmap_t {
190 tor_mmap_t base;
191 HANDLE file_handle;
192 HANDLE mmap_handle;
193 } win_mmap_t;
194 tor_mmap_t *
195 tor_mmap_file(const char *filename)
197 win_mmap_t *res = tor_malloc_zero(sizeof(win_mmap_t));
198 res->file_handle = INVALID_HANDLE_VALUE;
199 res->mmap_handle = NULL;
201 res->file_handle = CreateFile(filename,
202 GENERIC_READ,
203 0, NULL,
204 OPEN_EXISTING,
205 FILE_ATTRIBUTE_NORMAL,
208 if (res->file_handle == INVALID_HANDLE_VALUE)
209 goto win_err;
211 res->base.size = GetFileSize(res->file_handle, NULL);
213 if (res->base.size == 0) {
214 log_info(LD_FS,"File \"%s\" is empty. Ignoring.",filename);
215 goto err;
218 res->mmap_handle = CreateFileMapping(res->file_handle,
219 NULL,
220 PAGE_READONLY,
221 #if SIZEOF_SIZE_T > 4
222 (res->base.size >> 32),
223 #else
225 #endif
226 (res->base.size & 0xfffffffful),
227 NULL);
228 if (res->mmap_handle == NULL)
229 goto win_err;
230 res->base.data = (char*) MapViewOfFile(res->mmap_handle,
231 FILE_MAP_READ,
232 0, 0, 0);
233 if (!res->base.data)
234 goto win_err;
236 return &(res->base);
237 win_err: {
238 DWORD e = GetLastError();
239 int severity = (e == ERROR_FILE_NOT_FOUND || e == ERROR_PATH_NOT_FOUND) ?
240 LOG_INFO : LOG_WARN;
241 char *msg = format_win32_error(e);
242 log_fn(severity, LD_FS, "Couldn't mmap file \"%s\": %s", filename, msg);
243 tor_free(msg);
245 err:
246 tor_munmap_file(&res->base);
247 return NULL;
249 void
250 tor_munmap_file(tor_mmap_t *handle)
252 win_mmap_t *h = SUBTYPE_P(handle, win_mmap_t, base);
253 if (handle->data)
254 /* This is an ugly cast, but without it, "data" in struct tor_mmap_t would
255 have to be redefined as non-const. */
256 UnmapViewOfFile( (LPVOID) handle->data);
258 if (h->mmap_handle != NULL)
259 CloseHandle(h->mmap_handle);
260 if (h->file_handle != INVALID_HANDLE_VALUE)
261 CloseHandle(h->file_handle);
262 tor_free(h);
264 #else
265 tor_mmap_t *
266 tor_mmap_file(const char *filename)
268 struct stat st;
269 char *res = read_file_to_str(filename, RFTS_BIN|RFTS_IGNORE_MISSING, &st);
270 tor_mmap_t *handle;
271 if (! res)
272 return NULL;
273 handle = tor_malloc_zero(sizeof(tor_mmap_t));
274 handle->data = res;
275 handle->size = st.st_size;
276 return handle;
278 void
279 tor_munmap_file(tor_mmap_t *handle)
281 char *d = (char*)handle->data;
282 tor_free(d);
283 memset(handle, 0, sizeof(tor_mmap_t));
284 tor_free(handle);
286 #endif
288 /** Replacement for snprintf. Differs from platform snprintf in two
289 * ways: First, always NUL-terminates its output. Second, always
290 * returns -1 if the result is truncated. (Note that this return
291 * behavior does <i>not</i> conform to C99; it just happens to be
292 * easier to emulate "return -1" with conformant implementations than
293 * it is to emulate "return number that would be written" with
294 * non-conformant implementations.) */
296 tor_snprintf(char *str, size_t size, const char *format, ...)
298 va_list ap;
299 int r;
300 va_start(ap,format);
301 r = tor_vsnprintf(str,size,format,ap);
302 va_end(ap);
303 return r;
306 /** Replacement for vsnprintf; behavior differs as tor_snprintf differs from
307 * snprintf.
310 tor_vsnprintf(char *str, size_t size, const char *format, va_list args)
312 int r;
313 if (size == 0)
314 return -1; /* no place for the NUL */
315 if (size > SIZE_T_CEILING)
316 return -1;
317 #ifdef MS_WINDOWS
318 r = _vsnprintf(str, size, format, args);
319 #else
320 r = vsnprintf(str, size, format, args);
321 #endif
322 str[size-1] = '\0';
323 if (r < 0 || ((size_t)r) >= size)
324 return -1;
325 return r;
328 /** Given <b>hlen</b> bytes at <b>haystack</b> and <b>nlen</b> bytes at
329 * <b>needle</b>, return a pointer to the first occurrence of the needle
330 * within the haystack, or NULL if there is no such occurrence.
332 * Requires that nlen be greater than zero.
334 const void *
335 tor_memmem(const void *_haystack, size_t hlen,
336 const void *_needle, size_t nlen)
338 #if defined(HAVE_MEMMEM) && (!defined(__GNUC__) || __GNUC__ >= 2)
339 tor_assert(nlen);
340 return memmem(_haystack, hlen, _needle, nlen);
341 #else
342 /* This isn't as fast as the GLIBC implementation, but it doesn't need to
343 * be. */
344 const char *p, *end;
345 const char *haystack = (const char*)_haystack;
346 const char *needle = (const char*)_needle;
347 char first;
348 tor_assert(nlen);
350 p = haystack;
351 end = haystack + hlen;
352 first = *(const char*)needle;
353 while ((p = memchr(p, first, end-p))) {
354 if (p+nlen > end)
355 return NULL;
356 if (!memcmp(p, needle, nlen))
357 return p;
358 ++p;
360 return NULL;
361 #endif
364 #ifdef MS_WINDOWS
365 /** Take a filename and return a pointer to its final element. This
366 * function is called on __FILE__ to fix a MSVC nit where __FILE__
367 * contains the full path to the file. This is bad, because it
368 * confuses users to find the home directory of the person who
369 * compiled the binary in their warrning messages.
371 const char *
372 tor_fix_source_file(const char *fname)
374 const char *cp1, *cp2, *r;
375 cp1 = strrchr(fname, '/');
376 cp2 = strrchr(fname, '\\');
377 if (cp1 && cp2) {
378 r = (cp1<cp2)?(cp2+1):(cp1+1);
379 } else if (cp1) {
380 r = cp1+1;
381 } else if (cp2) {
382 r = cp2+1;
383 } else {
384 r = fname;
386 return r;
388 #endif
391 * Read a 16-bit value beginning at <b>cp</b>. Equivalent to
392 * *(uint16_t*)(cp), but will not cause segfaults on platforms that forbid
393 * unaligned memory access.
395 uint16_t
396 get_uint16(const char *cp)
398 uint16_t v;
399 memcpy(&v,cp,2);
400 return v;
403 * Read a 32-bit value beginning at <b>cp</b>. Equivalent to
404 * *(uint32_t*)(cp), but will not cause segfaults on platforms that forbid
405 * unaligned memory access.
407 uint32_t
408 get_uint32(const char *cp)
410 uint32_t v;
411 memcpy(&v,cp,4);
412 return v;
415 * Set a 16-bit value beginning at <b>cp</b> to <b>v</b>. Equivalent to
416 * *(uint16_t)(cp) = v, but will not cause segfaults on platforms that forbid
417 * unaligned memory access. */
418 void
419 set_uint16(char *cp, uint16_t v)
421 memcpy(cp,&v,2);
424 * Set a 32-bit value beginning at <b>cp</b> to <b>v</b>. Equivalent to
425 * *(uint32_t)(cp) = v, but will not cause segfaults on platforms that forbid
426 * unaligned memory access. */
427 void
428 set_uint32(char *cp, uint32_t v)
430 memcpy(cp,&v,4);
434 * Rename the file <b>from</b> to the file <b>to</b>. On unix, this is
435 * the same as rename(2). On windows, this removes <b>to</b> first if
436 * it already exists.
437 * Returns 0 on success. Returns -1 and sets errno on failure.
440 replace_file(const char *from, const char *to)
442 #ifndef MS_WINDOWS
443 return rename(from,to);
444 #else
445 switch (file_status(to))
447 case FN_NOENT:
448 break;
449 case FN_FILE:
450 if (unlink(to)) return -1;
451 break;
452 case FN_ERROR:
453 return -1;
454 case FN_DIR:
455 errno = EISDIR;
456 return -1;
458 return rename(from,to);
459 #endif
462 /** Change <b>fname</b>'s modification time to now. */
464 touch_file(const char *fname)
466 if (utime(fname, NULL)!=0)
467 return -1;
468 return 0;
471 /** Turn <b>socket</b> into a nonblocking socket.
473 void
474 set_socket_nonblocking(int socket)
476 #if defined(MS_WINDOWS) && !defined(USE_BSOCKETS)
477 unsigned long nonblocking = 1;
478 ioctlsocket(socket, FIONBIO, (unsigned long*) &nonblocking);
479 #else
480 fcntl(socket, F_SETFL, O_NONBLOCK);
481 #endif
485 * Allocate a pair of connected sockets. (Like socketpair(family,
486 * type,protocol,fd), but works on systems that don't have
487 * socketpair.)
489 * Currently, only (AF_UNIX, SOCK_STREAM, 0 ) sockets are supported.
491 * Note that on systems without socketpair, this call will fail if
492 * localhost is inaccessible (for example, if the networking
493 * stack is down). And even if it succeeds, the socket pair will not
494 * be able to read while localhost is down later (the socket pair may
495 * even close, depending on OS-specific timeouts).
497 * Returns 0 on success and -errno on failure; do not rely on the value
498 * of errno or WSAGetLastError().
500 /* It would be nicer just to set errno, but that won't work for windows. */
502 tor_socketpair(int family, int type, int protocol, int fd[2])
504 //don't use win32 socketpairs (they are always bad)
505 #if defined(HAVE_SOCKETPAIR) && !defined(MS_WINDOWS)
506 int r;
507 r = socketpair(family, type, protocol, fd);
508 return r < 0 ? -errno : r;
509 #elif defined(USE_BSOCKETS)
510 return bsockepair(family, type, protocol, fd);
511 #else
512 /* This socketpair does not work when localhost is down. So
513 * it's really not the same thing at all. But it's close enough
514 * for now, and really, when localhost is down sometimes, we
515 * have other problems too.
517 int listener = -1;
518 int connector = -1;
519 int acceptor = -1;
520 struct sockaddr_in listen_addr;
521 struct sockaddr_in connect_addr;
522 int size;
523 int saved_errno = -1;
525 if (protocol
526 #ifdef AF_UNIX
527 || family != AF_UNIX
528 #endif
530 #ifdef MS_WINDOWS
531 return -WSAEAFNOSUPPORT;
532 #else
533 return -EAFNOSUPPORT;
534 #endif
536 if (!fd) {
537 return -EINVAL;
540 listener = socket(AF_INET, type, 0);
541 if (listener < 0)
542 return -tor_socket_errno(-1);
543 memset(&listen_addr, 0, sizeof(listen_addr));
544 listen_addr.sin_family = AF_INET;
545 listen_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
546 listen_addr.sin_port = 0; /* kernel chooses port. */
547 if (bind(listener, (struct sockaddr *) &listen_addr, sizeof (listen_addr))
548 == -1)
549 goto tidy_up_and_fail;
550 if (listen(listener, 1) == -1)
551 goto tidy_up_and_fail;
553 connector = socket(AF_INET, type, 0);
554 if (connector < 0)
555 goto tidy_up_and_fail;
556 /* We want to find out the port number to connect to. */
557 size = sizeof(connect_addr);
558 if (getsockname(listener, (struct sockaddr *) &connect_addr, &size) == -1)
559 goto tidy_up_and_fail;
560 if (size != sizeof (connect_addr))
561 goto abort_tidy_up_and_fail;
562 if (connect(connector, (struct sockaddr *) &connect_addr,
563 sizeof(connect_addr)) == -1)
564 goto tidy_up_and_fail;
566 size = sizeof(listen_addr);
567 acceptor = accept(listener, (struct sockaddr *) &listen_addr, &size);
568 if (acceptor < 0)
569 goto tidy_up_and_fail;
570 if (size != sizeof(listen_addr))
571 goto abort_tidy_up_and_fail;
572 tor_close_socket(listener);
573 /* Now check we are talking to ourself by matching port and host on the
574 two sockets. */
575 if (getsockname(connector, (struct sockaddr *) &connect_addr, &size) == -1)
576 goto tidy_up_and_fail;
577 if (size != sizeof (connect_addr)
578 || listen_addr.sin_family != connect_addr.sin_family
579 || listen_addr.sin_addr.s_addr != connect_addr.sin_addr.s_addr
580 || listen_addr.sin_port != connect_addr.sin_port) {
581 goto abort_tidy_up_and_fail;
583 fd[0] = connector;
584 fd[1] = acceptor;
586 return 0;
588 abort_tidy_up_and_fail:
589 #ifdef MS_WINDOWS
590 saved_errno = WSAECONNABORTED;
591 #else
592 saved_errno = ECONNABORTED; /* I hope this is portable and appropriate. */
593 #endif
594 tidy_up_and_fail:
595 if (saved_errno < 0)
596 saved_errno = errno;
597 if (listener != -1)
598 tor_close_socket(listener);
599 if (connector != -1)
600 tor_close_socket(connector);
601 if (acceptor != -1)
602 tor_close_socket(acceptor);
603 return -saved_errno;
604 #endif
607 #define ULIMIT_BUFFER 32 /* keep 32 extra fd's beyond _ConnLimit */
609 /** Learn the maximum allowed number of file descriptors. (Some systems
610 * have a low soft limit.
612 * We compute this by finding the largest number between <b>limit</b>
613 * and <b>cap</b> that we can use. If we can't find a number greater
614 * than or equal to <b>limit</b>, then we fail: return -1.
616 * Otherwise, return the number minus some buffer to allow for other
617 * file descriptors we'll want available for ordinary use. */
619 set_max_file_descriptors(unsigned long limit, unsigned long cap)
621 #ifndef HAVE_GETRLIMIT
622 log_fn(LOG_INFO, LD_NET,
623 "This platform is missing getrlimit(). Proceeding.");
624 if (limit < cap) {
625 log_info(LD_CONFIG, "ConnLimit must be at most %d. Using that.", (int)cap);
626 limit = cap;
628 #else
629 struct rlimit rlim;
630 unsigned long most;
631 tor_assert(limit > 0);
632 tor_assert(cap > 0);
634 if (getrlimit(RLIMIT_NOFILE, &rlim) != 0) {
635 log_warn(LD_NET, "Could not get maximum number of file descriptors: %s",
636 strerror(errno));
637 return -1;
639 if (rlim.rlim_max < limit) {
640 log_warn(LD_CONFIG,"We need %lu file descriptors available, and we're "
641 "limited to %lu. Please change your ulimit -n.",
642 limit, (unsigned long)rlim.rlim_max);
643 return -1;
645 most = (rlim.rlim_max > cap) ? cap : (unsigned) rlim.rlim_max;
646 if (most > rlim.rlim_cur) {
647 log_info(LD_NET,"Raising max file descriptors from %lu to %lu.",
648 (unsigned long)rlim.rlim_cur, most);
650 rlim.rlim_cur = most;
651 if (setrlimit(RLIMIT_NOFILE, &rlim) != 0) {
652 log_warn(LD_CONFIG, "Could not set maximum number of file descriptors: %s",
653 strerror(errno));
654 return -1;
656 /* leave some overhead for logs, etc, */
657 limit = most;
658 #endif
660 if (limit < ULIMIT_BUFFER) {
661 log_warn(LD_CONFIG,
662 "ConnLimit must be at least %d. Failing.", ULIMIT_BUFFER);
663 return -1;
665 return limit - ULIMIT_BUFFER;
668 /** Call setuid and setgid to run as <b>user</b>:<b>group</b>. Return 0 on
669 * success. On failure, log and return -1.
672 switch_id(const char *user, const char *group)
674 #ifndef MS_WINDOWS
675 struct passwd *pw = NULL;
676 struct group *gr = NULL;
678 if (user) {
679 pw = getpwnam(user);
680 if (pw == NULL) {
681 log_warn(LD_CONFIG,"User '%s' not found.", user);
682 return -1;
686 /* switch the group first, while we still have the privileges to do so */
687 if (group) {
688 gr = getgrnam(group);
689 if (gr == NULL) {
690 log_warn(LD_CONFIG,"Group '%s' not found.", group);
691 return -1;
694 if (setgid(gr->gr_gid) != 0) {
695 log_warn(LD_GENERAL,"Error setting to configured GID: %s",
696 strerror(errno));
697 return -1;
699 } else if (user) {
700 if (setgid(pw->pw_gid) != 0) {
701 log_warn(LD_GENERAL,"Error setting to user GID: %s", strerror(errno));
702 return -1;
706 /* now that the group is switched, we can switch users and lose
707 privileges */
708 if (user) {
709 if (setuid(pw->pw_uid) != 0) {
710 log_warn(LD_GENERAL,"Error setting UID: %s", strerror(errno));
711 return -1;
715 return 0;
716 #else
717 (void)user;
718 (void)group;
719 #endif
721 log_warn(LD_CONFIG,
722 "User or group specified, but switching users is not supported.");
723 return -1;
726 #ifdef HAVE_PWD_H
727 /** Allocate and return a string containing the home directory for the
728 * user <b>username</b>. Only works on posix-like systems */
729 char *
730 get_user_homedir(const char *username)
732 struct passwd *pw;
733 tor_assert(username);
735 if (!(pw = getpwnam(username))) {
736 log_err(LD_CONFIG,"User \"%s\" not found.", username);
737 return NULL;
739 return tor_strdup(pw->pw_dir);
741 #endif
743 /** Set *addr to the IP address (in dotted-quad notation) stored in c.
744 * Return 1 on success, 0 if c is badly formatted. (Like inet_aton(c,addr),
745 * but works on Windows and Solaris.)
748 tor_inet_aton(const char *c, struct in_addr* addr)
750 #ifdef HAVE_INET_ATON
751 return inet_aton(c, addr);
752 #else
753 uint32_t r;
754 tor_assert(c);
755 tor_assert(addr);
756 if (strcmp(c, "255.255.255.255") == 0) {
757 addr->s_addr = 0xFFFFFFFFu;
758 return 1;
760 r = inet_addr(c);
761 if (r == INADDR_NONE)
762 return 0;
763 addr->s_addr = r;
764 return 1;
765 #endif
768 /** Similar behavior to Unix gethostbyname: resolve <b>name</b>, and set
769 * *addr to the proper IP address, in network byte order. Returns 0
770 * on success, -1 on failure; 1 on transient failure.
772 * (This function exists because standard windows gethostbyname
773 * doesn't treat raw IP addresses properly.)
776 tor_lookup_hostname(const char *name, uint32_t *addr)
778 /* Perhaps eventually this should be replaced by a tor_getaddrinfo or
779 * something.
781 struct in_addr iaddr;
782 tor_assert(name);
783 tor_assert(addr);
784 if (!*name) {
785 /* Empty address is an error. */
786 return -1;
787 } else if (tor_inet_aton(name, &iaddr)) {
788 /* It's an IP. */
789 memcpy(addr, &iaddr.s_addr, 4);
790 return 0;
791 } else {
792 #ifdef HAVE_GETADDRINFO
793 int err;
794 struct addrinfo *res=NULL, *res_p;
795 struct addrinfo hints;
796 int result = -1;
797 memset(&hints, 0, sizeof(hints));
798 hints.ai_family = PF_INET;
799 hints.ai_socktype = SOCK_STREAM;
800 err = getaddrinfo(name, NULL, &hints, &res);
801 if (!err) {
802 for (res_p = res; res_p; res_p = res_p->ai_next) {
803 if (res_p->ai_family == AF_INET) {
804 struct sockaddr_in *sin = (struct sockaddr_in *)res_p->ai_addr;
805 memcpy(addr, &sin->sin_addr, 4);
806 result = 0;
807 break;
810 freeaddrinfo(res);
811 return result;
813 return (err == EAI_AGAIN) ? 1 : -1;
814 #else
815 struct hostent *ent;
816 int err;
817 #ifdef HAVE_GETHOSTBYNAME_R_6_ARG
818 char buf[2048];
819 struct hostent hostent;
820 int r;
821 r = gethostbyname_r(name, &hostent, buf, sizeof(buf), &ent, &err);
822 #elif defined(HAVE_GETHOSTBYNAME_R_5_ARG)
823 char buf[2048];
824 struct hostent hostent;
825 ent = gethostbyname_r(name, &hostent, buf, sizeof(buf), &err);
826 #elif defined(HAVE_GETHOSTBYNAME_R_3_ARG)
827 struct hostent_data data;
828 struct hostent hent;
829 memset(&data, 0, sizeof(data));
830 err = gethostbyname_r(name, &hent, &data);
831 ent = err ? NULL : &hent;
832 #else
833 ent = gethostbyname(name);
834 #ifdef MS_WINDOWS
835 err = WSAGetLastError();
836 #else
837 err = h_errno;
838 #endif
839 #endif
840 if (ent) {
841 /* break to remind us if we move away from IPv4 */
842 tor_assert(ent->h_length == 4);
843 memcpy(addr, ent->h_addr, 4);
844 return 0;
846 memset(addr, 0, 4);
847 #ifdef MS_WINDOWS
848 return (err == WSATRY_AGAIN) ? 1 : -1;
849 #else
850 return (err == TRY_AGAIN) ? 1 : -1;
851 #endif
852 #endif
856 /** Hold the result of our call to <b>uname</b>. */
857 static char uname_result[256];
858 /** True iff uname_result is set. */
859 static int uname_result_is_set = 0;
861 /** Return a pointer to a description of our platform.
863 const char *
864 get_uname(void)
866 #ifdef HAVE_UNAME
867 struct utsname u;
868 #endif
869 if (!uname_result_is_set) {
870 #ifdef HAVE_UNAME
871 if (uname(&u) != -1) {
872 /* (linux says 0 is success, solaris says 1 is success) */
873 tor_snprintf(uname_result, sizeof(uname_result), "%s %s",
874 u.sysname, u.machine);
875 } else
876 #endif
878 #ifdef MS_WINDOWS
879 OSVERSIONINFOEX info;
880 int i;
881 unsigned int leftover_mask;
882 const char *plat = NULL;
883 static struct {
884 unsigned major; unsigned minor; const char *version;
885 } win_version_table[] = {
886 { 6, 0, "Windows \"Longhorn\"" },
887 { 5, 2, "Windows Server 2003" },
888 { 5, 1, "Windows XP" },
889 { 5, 0, "Windows 2000" },
890 /* { 4, 0, "Windows NT 4.0" }, */
891 { 4, 90, "Windows Me" },
892 { 4, 10, "Windows 98" },
893 /* { 4, 0, "Windows 95" } */
894 { 3, 51, "Windows NT 3.51" },
895 { 0, 0, NULL }
897 #ifdef VER_SUITE_BACKOFFICE
898 static struct {
899 unsigned int mask; const char *str;
900 } win_mask_table[] = {
901 { VER_SUITE_BACKOFFICE, " {backoffice}" },
902 { VER_SUITE_BLADE, " {\"blade\" (2003, web edition)}" },
903 { VER_SUITE_DATACENTER, " {datacenter}" },
904 { VER_SUITE_ENTERPRISE, " {enterprise}" },
905 { VER_SUITE_EMBEDDEDNT, " {embedded}" },
906 { VER_SUITE_PERSONAL, " {personal}" },
907 { VER_SUITE_SINGLEUSERTS,
908 " {terminal services, single user}" },
909 { VER_SUITE_SMALLBUSINESS, " {small business}" },
910 { VER_SUITE_SMALLBUSINESS_RESTRICTED,
911 " {small business, restricted}" },
912 { VER_SUITE_TERMINAL, " {terminal services}" },
913 { 0, NULL },
915 #endif
916 memset(&info, 0, sizeof(info));
917 info.dwOSVersionInfoSize = sizeof(info);
918 if (! GetVersionEx((LPOSVERSIONINFO)&info)) {
919 strlcpy(uname_result, "Bizarre version of Windows where GetVersionEx"
920 " doesn't work.", sizeof(uname_result));
921 uname_result_is_set = 1;
922 return uname_result;
924 if (info.dwMajorVersion == 4 && info.dwMinorVersion == 0) {
925 if (info.dwPlatformId == VER_PLATFORM_WIN32_NT)
926 plat = "Windows NT 4.0";
927 else
928 plat = "Windows 95";
929 } else {
930 for (i=0; win_version_table[i].major>0; ++i) {
931 if (win_version_table[i].major == info.dwMajorVersion &&
932 win_version_table[i].minor == info.dwMinorVersion) {
933 plat = win_version_table[i].version;
934 break;
938 if (plat) {
939 tor_snprintf(uname_result, sizeof(uname_result), "%s %s",
940 plat, info.szCSDVersion);
941 } else {
942 if (info.dwMajorVersion > 6 ||
943 (info.dwMajorVersion==6 && info.dwMinorVersion>0))
944 tor_snprintf(uname_result, sizeof(uname_result),
945 "Very recent version of Windows [major=%d,minor=%d] %s",
946 (int)info.dwMajorVersion,(int)info.dwMinorVersion,
947 info.szCSDVersion);
948 else
949 tor_snprintf(uname_result, sizeof(uname_result),
950 "Unrecognized version of Windows [major=%d,minor=%d] %s",
951 (int)info.dwMajorVersion,(int)info.dwMinorVersion,
952 info.szCSDVersion);
954 #ifdef VER_SUITE_BACKOFFICE
955 if (info.wProductType == VER_NT_DOMAIN_CONTROLLER) {
956 strlcat(uname_result, " [domain controller]", sizeof(uname_result));
957 } else if (info.wProductType == VER_NT_SERVER) {
958 strlcat(uname_result, " [server]", sizeof(uname_result));
959 } else if (info.wProductType == VER_NT_WORKSTATION) {
960 strlcat(uname_result, " [workstation]", sizeof(uname_result));
962 leftover_mask = info.wSuiteMask;
963 for (i = 0; win_mask_table[i].mask; ++i) {
964 if (info.wSuiteMask & win_mask_table[i].mask) {
965 strlcat(uname_result, win_mask_table[i].str, sizeof(uname_result));
966 leftover_mask &= ~win_mask_table[i].mask;
969 if (leftover_mask) {
970 size_t len = strlen(uname_result);
971 tor_snprintf(uname_result+len, sizeof(uname_result)-len,
972 " {0x%x}", info.wSuiteMask);
974 #endif
975 #else
976 strlcpy(uname_result, "Unknown platform", sizeof(uname_result));
977 #endif
979 uname_result_is_set = 1;
981 return uname_result;
985 * Process control
988 #if defined(USE_PTHREADS)
989 /** Wraps a void (*)(void*) function and its argument so we can
990 * invoke them in a way pthreads would expect.
992 typedef struct tor_pthread_data_t {
993 void (*func)(void *);
994 void *data;
995 } tor_pthread_data_t;
996 /** Given a tor_pthread_data_t <b>_data</b>, call _data-&gt;func(d-&gt;data)
997 * and free _data. Used to make sure we can call functions the way pthread
998 * expects. */
999 static void *
1000 tor_pthread_helper_fn(void *_data)
1002 tor_pthread_data_t *data = _data;
1003 void (*func)(void*);
1004 void *arg;
1005 /* mask signals to worker threads to avoid SIGPIPE, etc */
1006 sigset_t sigs;
1007 /* We're in a subthread; don't handle any signals here. */
1008 sigfillset(&sigs);
1009 pthread_sigmask(SIG_SETMASK, &sigs, NULL);
1011 func = data->func;
1012 arg = data->data;
1013 tor_free(_data);
1014 func(arg);
1015 return NULL;
1017 #endif
1019 /** Minimalist interface to run a void function in the background. On
1020 * unix calls fork, on win32 calls beginthread. Returns -1 on failure.
1021 * func should not return, but rather should call spawn_exit.
1023 * NOTE: if <b>data</b> is used, it should not be allocated on the stack,
1024 * since in a multithreaded environment, there is no way to be sure that
1025 * the caller's stack will still be around when the called function is
1026 * running.
1029 spawn_func(void (*func)(void *), void *data)
1031 #if defined(USE_WIN32_THREADS)
1032 int rv;
1033 rv = (int)_beginthread(func, 0, data);
1034 if (rv == (int)-1)
1035 return -1;
1036 return 0;
1037 #elif defined(USE_PTHREADS)
1038 pthread_t thread;
1039 tor_pthread_data_t *d;
1040 d = tor_malloc(sizeof(tor_pthread_data_t));
1041 d->data = data;
1042 d->func = func;
1043 if (pthread_create(&thread,NULL,tor_pthread_helper_fn,d))
1044 return -1;
1045 if (pthread_detach(thread))
1046 return -1;
1047 return 0;
1048 #else
1049 pid_t pid;
1050 pid = fork();
1051 if (pid<0)
1052 return -1;
1053 if (pid==0) {
1054 /* Child */
1055 func(data);
1056 tor_assert(0); /* Should never reach here. */
1057 return 0; /* suppress "control-reaches-end-of-non-void" warning. */
1058 } else {
1059 /* Parent */
1060 return 0;
1062 #endif
1065 /** End the current thread/process.
1067 void
1068 spawn_exit(void)
1070 #if defined(USE_WIN32_THREADS)
1071 _endthread();
1072 //we should never get here. my compiler thinks that _endthread returns, this
1073 //is an attempt to fool it.
1074 tor_assert(0);
1075 _exit(0);
1076 #elif defined(USE_PTHREADS)
1077 pthread_exit(NULL);
1078 #else
1079 /* http://www.erlenstar.demon.co.uk/unix/faq_2.html says we should
1080 * call _exit, not exit, from child processes. */
1081 _exit(0);
1082 #endif
1086 /** Set *timeval to the current time of day. On error, log and terminate.
1087 * (Same as gettimeofday(timeval,NULL), but never returns -1.)
1089 void
1090 tor_gettimeofday(struct timeval *timeval)
1092 #ifdef MS_WINDOWS
1093 /* Epoch bias copied from perl: number of units between windows epoch and
1094 * unix epoch. */
1095 #define EPOCH_BIAS U64_LITERAL(116444736000000000)
1096 #define UNITS_PER_SEC U64_LITERAL(10000000)
1097 #define USEC_PER_SEC U64_LITERAL(1000000)
1098 #define UNITS_PER_USEC U64_LITERAL(10)
1099 union {
1100 uint64_t ft_64;
1101 FILETIME ft_ft;
1102 } ft;
1103 /* number of 100-nsec units since Jan 1, 1601 */
1104 GetSystemTimeAsFileTime(&ft.ft_ft);
1105 if (ft.ft_64 < EPOCH_BIAS) {
1106 log_err(LD_GENERAL,"System time is before 1970; failing.");
1107 exit(1);
1109 ft.ft_64 -= EPOCH_BIAS;
1110 timeval->tv_sec = (unsigned) (ft.ft_64 / UNITS_PER_SEC);
1111 timeval->tv_usec = (unsigned) ((ft.ft_64 / UNITS_PER_USEC) % USEC_PER_SEC);
1112 #elif defined(HAVE_GETTIMEOFDAY)
1113 if (gettimeofday(timeval, NULL)) {
1114 log_err(LD_GENERAL,"gettimeofday failed.");
1115 /* If gettimeofday dies, we have either given a bad timezone (we didn't),
1116 or segfaulted.*/
1117 exit(1);
1119 #elif defined(HAVE_FTIME)
1120 struct timeb tb;
1121 ftime(&tb);
1122 timeval->tv_sec = tb.time;
1123 timeval->tv_usec = tb.millitm * 1000;
1124 #else
1125 #error "No way to get time."
1126 #endif
1127 return;
1130 #if defined(TOR_IS_MULTITHREADED) && !defined(MS_WINDOWS)
1131 /** Defined iff we need to add locks when defining fake versions of reentrant
1132 * versions of time-related functions. */
1133 #define TIME_FNS_NEED_LOCKS
1134 #endif
1136 #ifndef HAVE_LOCALTIME_R
1137 #ifdef TIME_FNS_NEED_LOCKS
1138 struct tm *
1139 tor_localtime_r(const time_t *timep, struct tm *result)
1141 struct tm *r;
1142 static tor_mutex_t *m=NULL;
1143 if (!m) { m=tor_mutex_new(); }
1144 tor_assert(result);
1145 tor_mutex_acquire(m);
1146 r = localtime(timep);
1147 memcpy(result, r, sizeof(struct tm));
1148 tor_mutex_release(m);
1149 return result;
1151 #else
1152 struct tm *
1153 tor_localtime_r(const time_t *timep, struct tm *result)
1155 struct tm *r;
1156 tor_assert(result);
1157 r = localtime(timep);
1158 memcpy(result, r, sizeof(struct tm));
1159 return result;
1161 #endif
1162 #endif
1164 #ifndef HAVE_GMTIME_R
1165 #ifdef TIME_FNS_NEED_LOCKS
1166 struct tm *
1167 tor_gmtime_r(const time_t *timep, struct tm *result)
1169 struct tm *r;
1170 static tor_mutex_t *m=NULL;
1171 if (!m) { m=tor_mutex_new(); }
1172 tor_assert(result);
1173 tor_mutex_acquire(m);
1174 r = gmtime(timep);
1175 memcpy(result, r, sizeof(struct tm));
1176 tor_mutex_release(m);
1177 return result;
1179 #else
1180 struct tm *
1181 tor_gmtime_r(const time_t *timep, struct tm *result)
1183 struct tm *r;
1184 tor_assert(result);
1185 r = gmtime(timep);
1186 memcpy(result, r, sizeof(struct tm));
1187 return result;
1189 #endif
1190 #endif
1192 #ifdef USE_WIN32_THREADS
1193 /** A generic lock structure for multithreaded builds. */
1194 struct tor_mutex_t {
1195 HANDLE handle;
1197 tor_mutex_t *
1198 tor_mutex_new(void)
1200 tor_mutex_t *m;
1201 m = tor_malloc_zero(sizeof(tor_mutex_t));
1202 m->handle = CreateMutex(NULL, FALSE, NULL);
1203 tor_assert(m->handle != NULL);
1204 return m;
1206 void
1207 tor_mutex_free(tor_mutex_t *m)
1209 CloseHandle(m->handle);
1210 tor_free(m);
1212 void
1213 tor_mutex_acquire(tor_mutex_t *m)
1215 DWORD r;
1216 r = WaitForSingleObject(m->handle, INFINITE);
1217 switch (r) {
1218 case WAIT_ABANDONED: /* holding thread exited. */
1219 case WAIT_OBJECT_0: /* we got the mutex normally. */
1220 break;
1221 case WAIT_TIMEOUT: /* Should never happen. */
1222 tor_assert(0);
1223 break;
1224 case WAIT_FAILED:
1225 log_warn(LD_GENERAL, "Failed to acquire mutex: %d",(int) GetLastError());
1228 void
1229 tor_mutex_release(tor_mutex_t *m)
1231 BOOL r;
1232 r = ReleaseMutex(m->handle);
1233 if (!r) {
1234 log_warn(LD_GENERAL, "Failed to release mutex: %d", (int) GetLastError());
1237 unsigned long
1238 tor_get_thread_id(void)
1240 return (unsigned long)GetCurrentThreadId();
1242 #elif defined(USE_PTHREADS)
1243 /** A generic lock structure for multithreaded builds. */
1244 struct tor_mutex_t {
1245 pthread_mutex_t mutex;
1247 /** Allocate and return new lock. */
1248 tor_mutex_t *
1249 tor_mutex_new(void)
1251 tor_mutex_t *mutex = tor_malloc_zero(sizeof(tor_mutex_t));
1252 pthread_mutex_init(&mutex->mutex, NULL);
1253 return mutex;
1255 /** Wait until <b>m</b> is free, then acquire it. */
1256 void
1257 tor_mutex_acquire(tor_mutex_t *m)
1259 tor_assert(m);
1260 pthread_mutex_lock(&m->mutex);
1262 /** Release the lock <b>m</b> so another thread can have it. */
1263 void
1264 tor_mutex_release(tor_mutex_t *m)
1266 tor_assert(m);
1267 pthread_mutex_unlock(&m->mutex);
1269 /** Free all storage held by the lock <b>m</b>. */
1270 void
1271 tor_mutex_free(tor_mutex_t *m)
1273 tor_assert(m);
1274 pthread_mutex_destroy(&m->mutex);
1275 tor_free(m);
1277 /** Return an integer representing this thread. */
1278 unsigned long
1279 tor_get_thread_id(void)
1281 union {
1282 pthread_t thr;
1283 unsigned long id;
1284 } r;
1285 r.thr = pthread_self();
1286 return r.id;
1288 #else
1289 /** A generic lock structure for multithreaded builds. */
1290 struct tor_mutex_t {
1291 int _unused;
1293 #endif
1296 * On Windows, WSAEWOULDBLOCK is not always correct: when you see it,
1297 * you need to ask the socket for its actual errno. Also, you need to
1298 * get your errors from WSAGetLastError, not errno. (If you supply a
1299 * socket of -1, we check WSAGetLastError, but don't correct
1300 * WSAEWOULDBLOCKs.)
1302 * The upshot of all of this is that when a socket call fails, you
1303 * should call tor_socket_errno <em>at most once</em> on the failing
1304 * socket to get the error.
1306 #if defined(MS_WINDOWS) && !defined(USE_BSOCKETS)
1308 tor_socket_errno(int sock)
1310 int optval, optvallen=sizeof(optval);
1311 int err = WSAGetLastError();
1312 if (err == WSAEWOULDBLOCK && sock >= 0) {
1313 if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*)&optval, &optvallen))
1314 return err;
1315 if (optval)
1316 return optval;
1318 return err;
1320 #endif
1322 #if defined(MS_WINDOWS) && !defined(USE_BSOCKETS)
1323 #define E(code, s) { code, (s " [" #code " ]") }
1324 struct { int code; const char *msg; } windows_socket_errors[] = {
1325 E(WSAEINTR, "Interrupted function call"),
1326 E(WSAEACCES, "Permission denied"),
1327 E(WSAEFAULT, "Bad address"),
1328 E(WSAEINVAL, "Invalid argument"),
1329 E(WSAEMFILE, "Too many open files"),
1330 E(WSAEWOULDBLOCK, "Resource temporarily unavailable"),
1331 E(WSAEINPROGRESS, "Operation now in progress"),
1332 E(WSAEALREADY, "Operation already in progress"),
1333 E(WSAENOTSOCK, "Socket operation on nonsocket"),
1334 E(WSAEDESTADDRREQ, "Destination address required"),
1335 E(WSAEMSGSIZE, "Message too long"),
1336 E(WSAEPROTOTYPE, "Protocol wrong for socket"),
1337 E(WSAENOPROTOOPT, "Bad protocol option"),
1338 E(WSAEPROTONOSUPPORT, "Protocol not supported"),
1339 E(WSAESOCKTNOSUPPORT, "Socket type not supported"),
1340 /* What's the difference between NOTSUPP and NOSUPPORT? :) */
1341 E(WSAEOPNOTSUPP, "Operation not supported"),
1342 E(WSAEPFNOSUPPORT, "Protocol family not supported"),
1343 E(WSAEAFNOSUPPORT, "Address family not supported by protocol family"),
1344 E(WSAEADDRINUSE, "Address already in use"),
1345 E(WSAEADDRNOTAVAIL, "Cannot assign requested address"),
1346 E(WSAENETDOWN, "Network is down"),
1347 E(WSAENETUNREACH, "Network is unreachable"),
1348 E(WSAENETRESET, "Network dropped connection on reset"),
1349 E(WSAECONNABORTED, "Software caused connection abort"),
1350 E(WSAECONNRESET, "Connection reset by peer"),
1351 E(WSAENOBUFS, "No buffer space available"),
1352 E(WSAEISCONN, "Socket is already connected"),
1353 E(WSAENOTCONN, "Socket is not connected"),
1354 E(WSAESHUTDOWN, "Cannot send after socket shutdown"),
1355 E(WSAETIMEDOUT, "Connection timed out"),
1356 E(WSAECONNREFUSED, "Connection refused"),
1357 E(WSAEHOSTDOWN, "Host is down"),
1358 E(WSAEHOSTUNREACH, "No route to host"),
1359 E(WSAEPROCLIM, "Too many processes"),
1360 /* Yes, some of these start with WSA, not WSAE. No, I don't know why. */
1361 E(WSASYSNOTREADY, "Network subsystem is unavailable"),
1362 E(WSAVERNOTSUPPORTED, "Winsock.dll out of range"),
1363 E(WSANOTINITIALISED, "Successful WSAStartup not yet performed"),
1364 E(WSAEDISCON, "Graceful shutdown now in progress"),
1365 #ifdef WSATYPE_NOT_FOUND
1366 E(WSATYPE_NOT_FOUND, "Class type not found"),
1367 #endif
1368 E(WSAHOST_NOT_FOUND, "Host not found"),
1369 E(WSATRY_AGAIN, "Nonauthoritative host not found"),
1370 E(WSANO_RECOVERY, "This is a nonrecoverable error"),
1371 E(WSANO_DATA, "Valid name, no data record of requested type)"),
1373 /* There are some more error codes whose numeric values are marked
1374 * <b>OS dependent</b>. They start with WSA_, apparently for the same
1375 * reason that practitioners of some craft traditions deliberately
1376 * introduce imperfections into their baskets and rugs "to allow the
1377 * evil spirits to escape." If we catch them, then our binaries
1378 * might not report consistent results across versions of Windows.
1379 * Thus, I'm going to let them all fall through.
1381 { -1, NULL },
1383 /** There does not seem to be a strerror equivalent for winsock errors.
1384 * Naturally, we have to roll our own.
1386 const char *
1387 tor_socket_strerror(int e)
1389 int i;
1390 for (i=0; windows_socket_errors[i].code >= 0; ++i) {
1391 if (e == windows_socket_errors[i].code)
1392 return windows_socket_errors[i].msg;
1394 return strerror(e);
1396 #endif
1398 /** Called before we make any calls to network-related functions.
1399 * (Some operating systems require their network libraries to be
1400 * initialized.) */
1402 network_init(void)
1404 #ifdef MS_WINDOWS
1405 /* This silly exercise is necessary before windows will allow
1406 * gethostbyname to work. */
1407 WSADATA WSAData;
1408 int r;
1409 r = WSAStartup(0x101,&WSAData);
1410 if (r) {
1411 log_warn(LD_NET,"Error initializing windows network layer: code was %d",r);
1412 return -1;
1414 /* WSAData.iMaxSockets might show the max sockets we're allowed to use.
1415 * We might use it to complain if we're trying to be a server but have
1416 * too few sockets available. */
1417 #endif
1418 return 0;
1421 #ifdef MS_WINDOWS
1422 /** Return a newly allocated string describing the windows system error code
1423 * <b>err</b>. Note that error codes are different from errno. Error codes
1424 * come from GetLastError() when a winapi call fails. errno is set only when
1425 * ansi functions fail. Whee. */
1426 char *
1427 format_win32_error(DWORD err)
1429 LPVOID str = NULL;
1430 char *result;
1432 /* Somebody once decided that this interface was better than strerror(). */
1433 FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
1434 FORMAT_MESSAGE_FROM_SYSTEM |
1435 FORMAT_MESSAGE_IGNORE_INSERTS,
1436 NULL, err,
1437 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
1438 (LPTSTR) &str,
1439 0, NULL);
1441 if (str) {
1442 result = tor_strdup((char*)str);
1443 LocalFree(str); /* LocalFree != free() */
1444 } else {
1445 result = tor_strdup("<unformattable error>");
1447 return result;
1449 #endif