26 #ifdef HAVE_SYS_TYPES_H
27 #include <sys/types.h>
29 #ifdef HAVE_SYS_STAT_H
53 size_t len = strlen(path);
56 return tor_strdup(
"");
59 int has_start_quote = (path[0] ==
'\"');
60 int has_end_quote = (len > 0 && path[len-1] ==
'\"');
61 if (has_start_quote != has_end_quote || (len == 1 && has_start_quote)) {
65 char *unquoted_path = tor_malloc(len - has_start_quote - has_end_quote + 1);
66 char *s = unquoted_path;
68 for (i = has_start_quote; i < len - has_end_quote; i++) {
69 if (path[i] ==
'\"' && (i > 0 && path[i-1] ==
'\\')) {
71 }
else if (path[i] !=
'\"') {
93 return tor_strdup(filename);
95 if (*filename ==
'~') {
96 char *home, *result=NULL;
99 if (filename[1] ==
'/' || filename[1] ==
'\0') {
100 home = getenv(
"HOME");
102 log_warn(
LD_CONFIG,
"Couldn't find $HOME environment variable while "
103 "expanding \"%s\"; defaulting to \"\".", filename);
104 home = tor_strdup(
"");
106 home = tor_strdup(home);
108 rest = strlen(filename)>=2?(filename+2):
"";
111 char *username, *slash;
112 slash = strchr(filename,
'/');
114 username = tor_strndup(filename+1,slash-filename-1);
116 username = tor_strdup(filename+1);
118 log_warn(
LD_CONFIG,
"Couldn't get homedir for \"%s\"",username);
123 rest = slash ? (slash+1) :
"";
125 log_warn(
LD_CONFIG,
"Couldn't expand homedir on system without pwd.h");
126 return tor_strdup(filename);
131 if (strlen(home)>1 && !
strcmpend(home,PATH_SEPARATOR)) {
132 home[strlen(home)-1] =
'\0';
138 return tor_strdup(filename);
147 if (filename && filename[0] ==
'/')
150 else if (filename && filename[0] ==
'\\')
152 else if (filename && strlen(filename)>3 && TOR_ISALPHA(filename[0]) &&
153 filename[1] ==
':' && filename[2] ==
'\\')
167 size_t len = strlen(
name);
170 if (
name[len-1]==
'\\' ||
name[len-1]==
'/') {
171 if (len == 1 || (len==3 &&
name[1]==
':'))
203 if (fname[0] && fname[1] ==
':') {
213 cp = fname + strlen(fname);
215 while (--cp >= fname) {
216 int is_sep = (*cp ==
'/'
245 #ifdef HAVE_GET_CURRENT_DIR_NAME
247 char *cwd = get_current_dir_name();
251 result = tor_strdup(cwd);
260 while (ptr == NULL) {
261 buf = tor_realloc(buf, size);
262 ptr = getcwd(buf, size);
264 if (ptr == NULL && errno != ERANGE) {
283 char *absfname_malloced = _fullpath(NULL, fname, 1);
287 char *absfname = tor_strdup(absfname_malloced ? absfname_malloced : fname);
288 if (absfname_malloced) raw_free(absfname_malloced);
292 char *absfname = NULL, *path = NULL;
296 if (fname[0] ==
'/') {
297 absfname = tor_strdup(fname);
307 log_warn(
LD_GENERAL,
"Unable to find current working directory: %s",
309 absfname = tor_strdup(fname);
374 bool is_glob = pattern[pos] ==
'*' || pattern[pos] ==
'?';
378 bool is_escaped = pos > 0 && pattern[pos-1] ==
'\\';
379 return is_glob && !is_escaped;
389 typedef struct smartlist_t * unglob_fn(
const char *pattern,
int prev_sep,
399 if (file_type == FN_ERROR) {
401 }
else if (file_type != FN_NOENT) {
402 char *to_add = tor_strdup(path);
421 int i, prev_sep = -1, next_sep = -1;
422 bool is_glob =
false, error_found =
false, is_sep =
false, is_last =
false;
425 for (i = 0; pattern[i]; i++) {
427 is_last = !pattern[i+1];
428 is_sep = pattern[i] == *PATH_SEPARATOR || pattern[i] ==
'/';
429 if (is_sep || is_last) {
448 int len = prev_sep < 1 ? prev_sep + 1 : prev_sep;
449 char *path_until_glob = tor_strndup(pattern, len);
453 smartlist_t *unglobbed_paths = unglob(pattern, prev_sep, next_sep);
454 if (!unglobbed_paths) {
461 tor_asprintf(&next_path,
"%s"PATH_SEPARATOR
"%s", current_path,
462 &pattern[next_sep+1]);
470 smartlist_free(opened_next);
471 } SMARTLIST_FOREACH_END(current_path);
473 smartlist_free(unglobbed_paths);
479 smartlist_free(result);
491 unglob_win32(
const char *pattern,
int prev_sep,
int next_sep)
494 int len = prev_sep < 1 ? prev_sep + 1 : prev_sep;
495 char *path_until_glob = tor_strndup(pattern, len);
500 smartlist_free(result);
504 TCHAR tpattern[MAX_PATH] = {0};
505 TCHAR tfile[MAX_PATH] = {0};
508 path_until_glob, filename);
509 char *path_curr_glob = tor_strndup(pattern, next_sep + 1);
515 mbstowcs(tpattern, path_curr_glob, MAX_PATH);
516 mbstowcs(tfile, full_path, MAX_PATH);
518 strlcpy(tpattern, path_curr_glob, MAX_PATH);
519 strlcpy(tfile, full_path, MAX_PATH);
521 if (PathMatchSpec(tfile, tpattern)) {
527 } SMARTLIST_FOREACH_END(filename);
529 smartlist_free(filenames);
538 prot_opendir(
const char *
name)
540 if (sandbox_interned_string_is_missing(
name)) {
549 prot_stat(
const char *pathname,
struct stat *buf)
551 if (sandbox_interned_string_is_missing(pathname)) {
560 prot_lstat(
const char *pathname,
struct stat *buf)
562 if (sandbox_interned_string_is_missing(pathname)) {
570 wrap_closedir(
void *arg)
588 char *pattern_normalized = tor_strdup(pattern);
594 int flags = GLOB_ERR | GLOB_NOSORT;
595 #ifdef GLOB_ALTDIRFUNC
597 flags |= GLOB_ALTDIRFUNC;
598 typedef void *(*gl_opendir)(
const char *
name);
599 typedef struct dirent *(*gl_readdir)(
void *);
600 typedef void (*gl_closedir)(
void *);
601 matches.gl_opendir = (gl_opendir) &prot_opendir;
602 matches.gl_readdir = (gl_readdir) &readdir;
603 matches.gl_closedir = (gl_closedir) &wrap_closedir;
604 matches.gl_stat = &prot_stat;
605 matches.gl_lstat = &prot_lstat;
607 int ret = glob(pattern, flags, NULL, &matches);
608 if (ret == GLOB_NOMATCH) {
610 }
else if (ret != 0) {
616 size_t pattern_len = strlen(pattern);
617 bool dir_only =
has_glob(pattern) &&
618 pattern_len > 0 && pattern[pattern_len-1] == *PATH_SEPARATOR;
622 for (i = 0; i < matches.gl_pathc; i++) {
623 char *match = tor_strdup(matches.gl_pathv[i]);
624 size_t len = strlen(match);
625 if (len > 0 && match[len-1] == *PATH_SEPARATOR) {
650 for (i = 0; s[i]; i++) {
668 if (
has_glob(&pattern[next_sep+1])) {
671 char *glob_path = tor_strndup(pattern, next_sep);
675 smartlist_free(result);
679 smartlist_free(child_paths);