[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[or-cvs] [tor/release-0.2.2] Merge remote branch 'origin/maint-0.2.1' into maint-0.2.2
commit f089804332c0289159ec432d8ce82bb1ed6316aa
Merge: cee433d e365aee
Author: Nick Mathewson <nickm@xxxxxxxxxxxxxx>
Date: Mon Jan 3 15:31:19 2011 -0500
Merge remote branch 'origin/maint-0.2.1' into maint-0.2.2
changes/bug2326 | 6 ++++++
src/common/util.c | 2 +-
2 files changed, 7 insertions(+), 1 deletions(-)
diff --combined src/common/util.c
index c7282e7,f206d00..abd87ea
--- a/src/common/util.c
+++ b/src/common/util.c
@@@ -15,8 -15,7 +15,8 @@@
#include "orconfig.h"
#include "util.h"
-#include "log.h"
+#include "torlog.h"
+#undef log
#include "crypto.h"
#include "torint.h"
#include "container.h"
@@@ -26,17 -25,11 +26,17 @@@
#include <io.h>
#include <direct.h>
#include <process.h>
+#include <tchar.h>
#else
#include <dirent.h>
#include <pwd.h>
#endif
+/* math.h needs this on Linux */
+#ifndef __USE_ISOC99
+#define __USE_ISOC99 1
+#endif
+#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@@ -294,7 -287,7 +294,7 @@@ tor_log_mallinfo(int severity
struct mallinfo mi;
memset(&mi, 0, sizeof(mi));
mi = mallinfo();
- log(severity, LD_MM,
+ tor_log(severity, LD_MM,
"mallinfo() said: arena=%d, ordblks=%d, smblks=%d, hblks=%d, "
"hblkhd=%d, usmblks=%d, fsmblks=%d, uordblks=%d, fordblks=%d, "
"keepcost=%d",
@@@ -317,25 -310,6 +317,25 @@@
* Math
* ===== */
+/**
+ * Returns the natural logarithm of d base 2. We define this wrapper here so
+ * as to make it easier not to conflict with Tor's log() macro.
+ */
+double
+tor_mathlog(double d)
+{
+ return log(d);
+}
+
+/** Return the long integer closest to d. We define this wrapper here so
+ * that not all users of math.h need to use the right incancations to get
+ * the c99 functions. */
+long
+tor_lround(double d)
+{
+ return lround(d);
+}
+
/** Returns floor(log2(u64)). If u64 is 0, (incorrectly) returns 0. */
int
tor_log2(uint64_t u64)
@@@ -380,36 -354,6 +380,36 @@@ round_to_power_of_2(uint64_t u64
return low;
}
+/** Return the lowest x such that x is at least <b>number</b>, and x modulo
+ * <b>divisor</b> == 0. */
+unsigned
+round_to_next_multiple_of(unsigned number, unsigned divisor)
+{
+ number += divisor - 1;
+ number -= number % divisor;
+ return number;
+}
+
+/** Return the lowest x such that x is at least <b>number</b>, and x modulo
+ * <b>divisor</b> == 0. */
+uint32_t
+round_uint32_to_next_multiple_of(uint32_t number, uint32_t divisor)
+{
+ number += divisor - 1;
+ number -= number % divisor;
+ return number;
+}
+
+/** Return the lowest x such that x is at least <b>number</b>, and x modulo
+ * <b>divisor</b> == 0. */
+uint64_t
+round_uint64_to_next_multiple_of(uint64_t number, uint64_t divisor)
+{
+ number += divisor - 1;
+ number -= number % divisor;
+ return number;
+}
+
/* =====
* String manipulation
* ===== */
@@@ -692,29 -636,6 +692,29 @@@ find_whitespace_eos(const char *s, cons
return s;
}
+/** Return the first occurrence of <b>needle</b> in <b>haystack</b> that
+ * occurs at the start of a line (that is, at the beginning of <b>haystack</b>
+ * or immediately after a newline). Return NULL if no such string is found.
+ */
+const char *
+find_str_at_start_of_line(const char *haystack, const char *needle)
+{
+ size_t needle_len = strlen(needle);
+
+ do {
+ if (!strncmp(haystack, needle, needle_len))
+ return haystack;
+
+ haystack = strchr(haystack, '\n');
+ if (!haystack)
+ return NULL;
+ else
+ ++haystack;
+ } while (*haystack);
+
+ return NULL;
+}
+
/** Return true iff the 'len' bytes at 'mem' are all zero. */
int
tor_mem_is_zero(const char *mem, size_t len)
@@@ -742,13 -663,6 +742,13 @@@ tor_digest_is_zero(const char *digest
return tor_mem_is_zero(digest, DIGEST_LEN);
}
+/** Return true iff the DIGEST256_LEN bytes in digest are all zero. */
+int
+tor_digest256_is_zero(const char *digest)
+{
+ return tor_mem_is_zero(digest, DIGEST256_LEN);
+}
+
/* Helper: common code to check whether the result of a strtol or strtoul or
* strtoll is correct. */
#define CHECK_STRTOX_RESULT() \
@@@ -800,18 -714,7 +800,18 @@@ tor_parse_ulong(const char *s, int base
CHECK_STRTOX_RESULT();
}
-/** As tor_parse_log, but return a unit64_t. Only base 10 is guaranteed to
+/** As tor_parse_long(), but return a double. */
+double
+tor_parse_double(const char *s, double min, double max, int *ok, char **next)
+{
+ char *endptr;
+ double r;
+
+ r = strtod(s, &endptr);
+ CHECK_STRTOX_RESULT();
+}
+
+/** As tor_parse_long, but return a uint64_t. Only base 10 is guaranteed to
* work for now. */
uint64_t
tor_parse_uint64(const char *s, int base, uint64_t min,
@@@ -950,9 -853,6 +950,9 @@@ esc_for_log(const char *s
case '\\':
case '\"':
case '\'':
+ case '\r':
+ case '\n':
+ case '\t':
len += 2;
break;
default:
@@@ -1014,7 -914,8 +1014,7 @@@ const char
escaped(const char *s)
{
static char *_escaped_val = NULL;
- if (_escaped_val)
- tor_free(_escaped_val);
+ tor_free(_escaped_val);
if (s)
_escaped_val = esc_for_log(s);
@@@ -1101,42 -1002,6 +1101,42 @@@ wrap_string(smartlist_t *out, const cha
* Time
* ===== */
+/**
+ * Converts struct timeval to a double value.
+ * Preserves microsecond precision, but just barely.
+ * Error is approx +/- 0.1 usec when dealing with epoch values.
+ */
+double
+tv_to_double(const struct timeval *tv)
+{
+ double conv = tv->tv_sec;
+ conv += tv->tv_usec/1000000.0;
+ return conv;
+}
+
+/**
+ * Converts timeval to milliseconds.
+ */
+int64_t
+tv_to_msec(const struct timeval *tv)
+{
+ int64_t conv = ((int64_t)tv->tv_sec)*1000L;
+ /* Round ghetto-style */
+ conv += ((int64_t)tv->tv_usec+500)/1000L;
+ return conv;
+}
+
+/**
+ * Converts timeval to microseconds.
+ */
+int64_t
+tv_to_usec(const struct timeval *tv)
+{
+ int64_t conv = ((int64_t)tv->tv_sec)*1000000L;
+ conv += tv->tv_usec;
+ return conv;
+}
+
/** Return the number of microseconds elapsed between *start and *end.
*/
long
@@@ -1146,8 -1011,7 +1146,8 @@@ tv_udiff(const struct timeval *start, c
long secdiff = end->tv_sec - start->tv_sec;
if (labs(secdiff+1) > LONG_MAX/1000000) {
- log_warn(LD_GENERAL, "comparing times too far apart.");
+ log_warn(LD_GENERAL, "comparing times on microsecond detail too far "
+ "apart: %ld seconds", secdiff);
return LONG_MAX;
}
@@@ -1155,26 -1019,6 +1155,26 @@@
return udiff;
}
+/** Return the number of milliseconds elapsed between *start and *end.
+ */
+long
+tv_mdiff(const struct timeval *start, const struct timeval *end)
+{
+ long mdiff;
+ long secdiff = end->tv_sec - start->tv_sec;
+
+ if (labs(secdiff+1) > LONG_MAX/1000) {
+ log_warn(LD_GENERAL, "comparing times on millisecond detail too far "
+ "apart: %ld seconds", secdiff);
+ return LONG_MAX;
+ }
+
+ /* Subtract and round */
+ mdiff = secdiff*1000L +
+ ((long)end->tv_usec - (long)start->tv_usec + 500L) / 1000L;
+ return mdiff;
+}
+
/** Yield true iff <b>y</b> is a leap-year. */
#define IS_LEAPYEAR(y) (!(y % 4) && ((y % 100) || !(y % 400)))
/** Helper: Return the number of leap-days between Jan 1, y1 and Jan 1, y2. */
@@@ -1250,7 -1094,7 +1250,7 @@@ format_rfc1123_time(char *buf, time_t t
memcpy(buf+8, MONTH_NAMES[tm.tm_mon], 3);
}
-/** Parse the the RFC1123 encoding of some time (in GMT) from <b>buf</b>,
+/** Parse the RFC1123 encoding of some time (in GMT) from <b>buf</b>,
* and store the result in *<b>t</b>.
*
* Return 0 on success, -1 on failure.
@@@ -1588,49 -1432,6 +1588,49 @@@ ftime_definitely_before(time_t now, tim
}
/* =====
+ * Rate limiting
+ * ===== */
+
+/** If the rate-limiter <b>lim</b> is ready at <b>now</b>, return the number
+ * of calls to rate_limit_is_ready (including this one!) since the last time
+ * rate_limit_is_ready returned nonzero. Otherwise return 0. */
+static int
+rate_limit_is_ready(ratelim_t *lim, time_t now)
+{
+ if (lim->rate + lim->last_allowed <= now) {
+ int res = lim->n_calls_since_last_time + 1;
+ lim->last_allowed = now;
+ lim->n_calls_since_last_time = 0;
+ return res;
+ } else {
+ ++lim->n_calls_since_last_time;
+ return 0;
+ }
+}
+
+/** If the rate-limiter <b>lim</b> is ready at <b>now</b>, return a newly
+ * allocated string indicating how many messages were suppressed, suitable to
+ * append to a log message. Otherwise return NULL. */
+char *
+rate_limit_log(ratelim_t *lim, time_t now)
+{
+ int n;
+ if ((n = rate_limit_is_ready(lim, now))) {
+ if (n == 1) {
+ return tor_strdup("");
+ } else {
+ char *cp=NULL;
+ tor_asprintf(&cp,
+ " [%d similar message(s) suppressed in last %d seconds]",
+ n-1, lim->rate);
+ return cp;
+ }
+ } else {
+ return NULL;
+ }
+}
+
+/* =====
* File helpers
* ===== */
@@@ -1754,22 -1555,22 +1754,22 @@@ check_private_dir(const char *dirname,
tor_free(f);
if (r) {
if (errno != ENOENT) {
- log(LOG_WARN, LD_FS, "Directory %s cannot be read: %s", dirname,
- strerror(errno));
+ log_warn(LD_FS, "Directory %s cannot be read: %s", dirname,
+ strerror(errno));
return -1;
}
if (check == CPD_NONE) {
- log(LOG_WARN, LD_FS, "Directory %s does not exist.", dirname);
+ log_warn(LD_FS, "Directory %s does not exist.", dirname);
return -1;
} else if (check == CPD_CREATE) {
log_info(LD_GENERAL, "Creating directory %s", dirname);
-#ifdef MS_WINDOWS
+#if defined (MS_WINDOWS) && !defined (WINCE)
r = mkdir(dirname);
#else
r = mkdir(dirname, 0700);
#endif
if (r) {
- log(LOG_WARN, LD_FS, "Error creating directory %s: %s", dirname,
+ log_warn(LD_FS, "Error creating directory %s: %s", dirname,
strerror(errno));
return -1;
}
@@@ -1779,7 -1580,7 +1779,7 @@@
return 0;
}
if (!(st.st_mode & S_IFDIR)) {
- log(LOG_WARN, LD_FS, "%s is not a directory", dirname);
+ log_warn(LD_FS, "%s is not a directory", dirname);
return -1;
}
#ifndef MS_WINDOWS
@@@ -1792,7 -1593,7 +1792,7 @@@
pw = getpwuid(st.st_uid);
- log(LOG_WARN, LD_FS, "%s is not owned by this user (%s, %d) but by "
+ log_warn(LD_FS, "%s is not owned by this user (%s, %d) but by "
"%s (%d). Perhaps you are running Tor as the wrong user?",
dirname, process_ownername, (int)getuid(),
pw ? pw->pw_name : "<unknown>", (int)st.st_uid);
@@@ -1801,9 -1602,9 +1801,9 @@@
return -1;
}
if (st.st_mode & 0077) {
- log(LOG_WARN, LD_FS, "Fixing permissions on directory %s", dirname);
+ log_warn(LD_FS, "Fixing permissions on directory %s", dirname);
if (chmod(dirname, 0700)) {
- log(LOG_WARN, LD_FS, "Could not chmod directory %s: %s", dirname,
+ log_warn(LD_FS, "Could not chmod directory %s: %s", dirname,
strerror(errno));
return -1;
} else {
@@@ -1834,13 -1635,12 +1834,13 @@@ write_str_to_file(const char *fname, co
}
/** Represents a file that we're writing to, with support for atomic commit:
- * we can write into a a temporary file, and either remove the file on
+ * we can write into a temporary file, and either remove the file on
* failure, or replace the original file on success. */
struct open_file_t {
char *tempname; /**< Name of the temporary file. */
char *filename; /**< Name of the original file. */
- int rename_on_close; /**< Are we using the temporary file or not? */
+ unsigned rename_on_close:1; /**< Are we using the temporary file or not? */
+ unsigned binary:1; /**< Did we open in binary mode? */
int fd; /**< fd for the open file. */
FILE *stdio_file; /**< stdio wrapper for <b>fd</b>. */
};
@@@ -1888,7 -1688,7 +1888,7 @@@ start_writing_to_file(const char *fname
} else {
open_name = new_file->tempname = tor_malloc(tempname_len);
if (tor_snprintf(new_file->tempname, tempname_len, "%s.tmp", fname)<0) {
- log(LOG_WARN, LD_GENERAL, "Failed to generate filename");
+ log_warn(LD_GENERAL, "Failed to generate filename");
goto err;
}
/* We always replace an existing temporary file if there is one. */
@@@ -1896,12 -1696,9 +1896,12 @@@
open_flags &= ~O_EXCL;
new_file->rename_on_close = 1;
}
+ if (open_flags & O_BINARY)
+ new_file->binary = 1;
- if ((new_file->fd = open(open_name, open_flags, mode)) < 0) {
- log(LOG_WARN, LD_FS, "Couldn't open \"%s\" (%s) for writing: %s",
+ new_file->fd = open(open_name, open_flags, mode);
+ if (new_file->fd < 0) {
+ log_warn(LD_FS, "Couldn't open \"%s\" (%s) for writing: %s",
open_name, fname, strerror(errno));
goto err;
}
@@@ -1937,8 -1734,7 +1937,8 @@@ fdopen_file(open_file_t *file_data
if (file_data->stdio_file)
return file_data->stdio_file;
tor_assert(file_data->fd >= 0);
- if (!(file_data->stdio_file = fdopen(file_data->fd, "a"))) {
+ if (!(file_data->stdio_file = fdopen(file_data->fd,
+ file_data->binary?"ab":"a"))) {
log_warn(LD_FS, "Couldn't fdopen \"%s\" [%d]: %s", file_data->filename,
file_data->fd, strerror(errno));
}
@@@ -2038,7 -1834,7 +2038,7 @@@ write_chunks_to_file_impl(const char *f
{
result = write_all(fd, chunk->bytes, chunk->len, 0);
if (result < 0) {
- log(LOG_WARN, LD_FS, "Error writing to \"%s\": %s", fname,
+ log_warn(LD_FS, "Error writing to \"%s\": %s", fname,
strerror(errno));
goto err;
}
@@@ -2140,7 -1936,7 +2140,7 @@@ read_file_to_str(const char *filename,
return NULL;
}
- if ((uint64_t)(statbuf.st_size)+1 > SIZE_T_CEILING)
+ if ((uint64_t)(statbuf.st_size)+1 >= SIZE_T_CEILING)
return NULL;
string = tor_malloc((size_t)(statbuf.st_size+1));
@@@ -2294,40 -2090,7 +2294,40 @@@ unescape_string(const char *s, char **r
const char *
parse_config_line_from_str(const char *line, char **key_out, char **value_out)
{
+ /* I believe the file format here is supposed to be:
+ FILE = (EMPTYLINE | LINE)* (EMPTYLASTLINE | LASTLINE)?
+
+ EMPTYLASTLINE = SPACE* | COMMENT
+ EMPTYLINE = EMPTYLASTLINE NL
+ SPACE = ' ' | '\r' | '\t'
+ COMMENT = '#' NOT-NL*
+ NOT-NL = Any character except '\n'
+ NL = '\n'
+
+ LASTLINE = SPACE* KEY SPACE* VALUES
+ LINE = LASTLINE NL
+ KEY = KEYCHAR+
+ KEYCHAR = Any character except ' ', '\r', '\n', '\t', '#', "\"
+
+ VALUES = QUOTEDVALUE | NORMALVALUE
+ QUOTEDVALUE = QUOTE QVITEM* QUOTE EOLSPACE?
+ QUOTE = '"'
+ QVCHAR = KEYCHAR | ESC ('n' | 't' | 'r' | '"' | ESC |'\'' | OCTAL | HEX)
+ ESC = "\\"
+ OCTAL = ODIGIT (ODIGIT ODIGIT?)?
+ HEX = ('x' | 'X') HEXDIGIT HEXDIGIT
+ ODIGIT = '0' .. '7'
+ HEXDIGIT = '0'..'9' | 'a' .. 'f' | 'A' .. 'F'
+ EOLSPACE = SPACE* COMMENT?
+
+ NORMALVALUE = (VALCHAR | ESC ESC_IGNORE | CONTINUATION)* EOLSPACE?
+ VALCHAR = Any character except ESC, '#', and '\n'
+ ESC_IGNORE = Any character except '#' or '\n'
+ CONTINUATION = ESC NL ( COMMENT NL )*
+ */
+
const char *key, *val, *cp;
+ int continuation = 0;
tor_assert(key_out);
tor_assert(value_out);
@@@ -2351,10 -2114,9 +2351,10 @@@
return line;
}
- /* Skip until the next space. */
+ /* Skip until the next space or \ followed by newline. */
key = line;
- while (*line && !TOR_ISSPACE(*line) && *line != '#')
+ while (*line && !TOR_ISSPACE(*line) && *line != '#' &&
+ ! (line[0] == '\\' && line[1] == '\n'))
++line;
*key_out = tor_strndup(key, line-key);
@@@ -2365,7 -2127,7 +2365,7 @@@
val = line;
/* Find the end of the line. */
- if (*line == '\"') {
+ if (*line == '\"') { // XXX No continuation handling is done here
if (!(line = unescape_string(line, value_out, NULL)))
return NULL;
while (*line == ' ' || *line == '\t')
@@@ -2373,53 -2135,18 +2373,53 @@@
if (*line && *line != '#' && *line != '\n')
return NULL;
} else {
- while (*line && *line != '\n' && *line != '#')
- ++line;
+ /* Look for the end of the line. */
+ while (*line && *line != '\n' && (*line != '#' || continuation)) {
+ if (*line == '\\' && line[1] == '\n') {
+ continuation = 1;
+ line += 2;
+ } else if (*line == '#') {
+ do {
+ ++line;
+ } while (*line && *line != '\n');
+ if (*line == '\n')
+ ++line;
+ } else {
+ ++line;
+ }
+ }
+
if (*line == '\n') {
cp = line++;
} else {
cp = line;
}
+ /* Now back cp up to be the last nonspace character */
while (cp>val && TOR_ISSPACE(*(cp-1)))
--cp;
tor_assert(cp >= val);
+
+ /* Now copy out and decode the value. */
*value_out = tor_strndup(val, cp-val);
+ if (continuation) {
+ char *v_out, *v_in;
+ v_out = v_in = *value_out;
+ while (*v_in) {
+ if (*v_in == '#') {
+ do {
+ ++v_in;
+ } while (*v_in && *v_in != '\n');
+ if (*v_in == '\n')
+ ++v_in;
+ } else if (v_in[0] == '\\' && v_in[1] == '\n') {
+ v_in += 2;
+ } else {
+ *v_out++ = *v_in++;
+ }
+ }
+ *v_out = '\0';
+ }
}
if (*line == '#') {
@@@ -2438,22 -2165,19 +2438,22 @@@ char
expand_filename(const char *filename)
{
tor_assert(filename);
+#ifdef MS_WINDOWS
+ return tor_strdup(filename);
+#else
if (*filename == '~') {
- size_t len;
- char *home, *result;
+ char *home, *result=NULL;
const char *rest;
if (filename[1] == '/' || filename[1] == '\0') {
home = getenv("HOME");
if (!home) {
log_warn(LD_CONFIG, "Couldn't find $HOME environment variable while "
- "expanding \"%s\"", filename);
- return NULL;
+ "expanding \"%s\"; defaulting to \"\".", filename);
+ home = tor_strdup("");
+ } else {
+ home = tor_strdup(home);
}
- home = tor_strdup(home);
rest = strlen(filename)>=2?(filename+2):"";
} else {
#ifdef HAVE_PWD_H
@@@ -2480,19 -2204,21 +2480,19 @@@
if (strlen(home)>1 && !strcmpend(home,PATH_SEPARATOR)) {
home[strlen(home)-1] = '\0';
}
- /* Plus one for /, plus one for NUL.
- * Round up to 16 in case we can't do math. */
- len = strlen(home)+strlen(rest)+16;
- result = tor_malloc(len);
- tor_snprintf(result,len,"%s"PATH_SEPARATOR"%s",home,rest);
+ tor_asprintf(&result,"%s"PATH_SEPARATOR"%s",home,rest);
tor_free(home);
return result;
} else {
return tor_strdup(filename);
}
+#endif
}
#define MAX_SCANF_WIDTH 9999
-/** DOCDOC */
+/** Helper: given an ASCII-encoded decimal digit, return its numeric value.
+ * NOTE: requires that its input be in-bounds. */
static int
digit_to_num(char d)
{
@@@ -2501,10 -2227,7 +2501,10 @@@
return num;
}
-/** DOCDOC */
+/** Helper: Read an unsigned int from *<b>bufp</b> of up to <b>width</b>
+ * characters. (Handle arbitrary width if <b>width</b> is less than 0.) On
+ * success, store the result in <b>out</b>, advance bufp to the next
+ * character, and return 0. On failure, return -1. */
static int
scan_unsigned(const char **bufp, unsigned *out, int width)
{
@@@ -2531,9 -2254,7 +2531,9 @@@
return 0;
}
-/** DOCDOC */
+/** Helper: copy up to <b>width</b> non-space characters from <b>bufp</b> to
+ * <b>out</b>. Make sure <b>out</b> is nul-terminated. Advance <b>bufp</b>
+ * to the next non-space character or the EOS. */
static int
scan_string(const char **bufp, char *out, int width)
{
@@@ -2622,12 -2343,7 +2622,12 @@@ tor_vsscanf(const char *buf, const cha
* and store the results in the corresponding argument fields. Differs from
* sscanf in that it: Only handles %u and %Ns. Does not handle arbitrarily
* long widths. %u does not consume any space. Is locale-independent.
- * Returns -1 on malformed patterns. */
+ * Returns -1 on malformed patterns.
+ *
+ * (As with other locale-independent functions, we need this to parse data that
+ * is in ASCII without worrying that the C library's locale-handling will make
+ * miscellaneous characters look like numbers, spaces, and so on.)
+ */
int
tor_sscanf(const char *buf, const char *pattern, ...)
{
@@@ -2648,32 -2364,20 +2648,32 @@@ tor_listdir(const char *dirname
smartlist_t *result;
#ifdef MS_WINDOWS
char *pattern;
+ TCHAR tpattern[MAX_PATH] = {0};
+ char name[MAX_PATH] = {0};
HANDLE handle;
WIN32_FIND_DATA findData;
size_t pattern_len = strlen(dirname)+16;
pattern = tor_malloc(pattern_len);
tor_snprintf(pattern, pattern_len, "%s\\*", dirname);
- if (INVALID_HANDLE_VALUE == (handle = FindFirstFile(pattern, &findData))) {
+#ifdef UNICODE
+ mbstowcs(tpattern,pattern,MAX_PATH);
+#else
+ strlcpy(tpattern, pattern, MAX_PATH);
+#endif
+ if (INVALID_HANDLE_VALUE == (handle = FindFirstFile(tpattern, &findData))) {
tor_free(pattern);
return NULL;
}
result = smartlist_create();
while (1) {
- if (strcmp(findData.cFileName, ".") &&
- strcmp(findData.cFileName, "..")) {
- smartlist_add(result, tor_strdup(findData.cFileName));
+#ifdef UNICODE
+ wcstombs(name,findData.cFileName,MAX_PATH);
+#else
+ strlcpy(name,findData.cFileName,sizeof(name));
+#endif
+ if (strcmp(name, ".") &&
+ strcmp(name, "..")) {
+ smartlist_add(result, tor_strdup(name));
}
if (!FindNextFile(handle, &findData)) {
DWORD err;
@@@ -2872,18 -2576,3 +2872,18 @@@ write_pidfile(char *filename
}
}
+#ifdef MS_WINDOWS
+HANDLE
+load_windows_system_library(const TCHAR *library_name)
+{
+ TCHAR path[MAX_PATH];
+ unsigned n;
+ n = GetSystemDirectory(path, MAX_PATH);
+ if (n == 0 || n + _tcslen(library_name) + 2 >= MAX_PATH)
+ return 0;
+ _tcscat(path, TEXT("\\"));
+ _tcscat(path, library_name);
+ return LoadLibrary(path);
+}
+#endif
+