26#ifdef HAVE_SYS_TYPES_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):
"";
113 slash = strchr(filename,
'/');
115 username = tor_strndup(filename+1,slash-filename-1);
117 username = tor_strdup(filename+1);
119 log_warn(
LD_CONFIG,
"Couldn't get homedir for \"%s\"",username);
124 rest = slash ? (slash+1) :
"";
126 log_warn(
LD_CONFIG,
"Couldn't expand homedir on system without pwd.h");
127 return tor_strdup(filename);
132 if (strlen(home)>1 && !
strcmpend(home,PATH_SEPARATOR)) {
133 home[strlen(home)-1] =
'\0';
139 return tor_strdup(filename);
148 if (filename && filename[0] ==
'/')
151 else if (filename && filename[0] ==
'\\')
153 else if (filename && strlen(filename)>3 && TOR_ISALPHA(filename[0]) &&
154 filename[1] ==
':' && filename[2] ==
'\\')
168 size_t len = strlen(
name);
171 if (
name[len-1]==
'\\' ||
name[len-1]==
'/') {
172 if (len == 1 || (len==3 &&
name[1]==
':'))
204 if (fname[0] && fname[1] ==
':') {
214 cp = fname + strlen(fname);
216 while (--cp >= fname) {
217 int is_sep = (*cp ==
'/'
246#ifdef HAVE_GET_CURRENT_DIR_NAME
248 char *cwd = get_current_dir_name();
252 result = tor_strdup(cwd);
261 while (ptr == NULL) {
262 buf = tor_realloc(buf, size);
263 ptr = getcwd(buf, size);
265 if (ptr == NULL && errno != ERANGE) {
284 char *absfname_malloced = _fullpath(NULL, fname, 1);
288 char *absfname = tor_strdup(absfname_malloced ? absfname_malloced : fname);
289 if (absfname_malloced) raw_free(absfname_malloced);
293 char *absfname = NULL, *path = NULL;
297 if (fname[0] ==
'/') {
298 absfname = tor_strdup(fname);
308 log_warn(
LD_GENERAL,
"Unable to find current working directory: %s",
310 absfname = tor_strdup(fname);
375 bool is_glob = pattern[pos] ==
'*' || pattern[pos] ==
'?';
379 bool is_escaped = pos > 0 && pattern[pos-1] ==
'\\';
380 return is_glob && !is_escaped;
390typedef struct smartlist_t * unglob_fn(
const char *pattern,
int prev_sep,
400 if (file_type == FN_ERROR) {
402 }
else if (file_type != FN_NOENT) {
403 char *to_add = tor_strdup(path);
422 int i, prev_sep = -1, next_sep = -1;
423 bool is_glob =
false, error_found =
false, is_sep =
false, is_last =
false;
426 for (i = 0; pattern[i]; i++) {
428 is_last = !pattern[i+1];
429 is_sep = pattern[i] == *PATH_SEPARATOR || pattern[i] ==
'/';
430 if (is_sep || is_last) {
449 int len = prev_sep < 1 ? prev_sep + 1 : prev_sep;
450 char *path_until_glob = tor_strndup(pattern, len);
454 smartlist_t *unglobbed_paths = unglob(pattern, prev_sep, next_sep);
455 if (!unglobbed_paths) {
462 tor_asprintf(&next_path,
"%s"PATH_SEPARATOR
"%s", current_path,
463 &pattern[next_sep+1]);
471 smartlist_free(opened_next);
472 } SMARTLIST_FOREACH_END(current_path);
474 smartlist_free(unglobbed_paths);
480 smartlist_free(result);
492unglob_win32(
const char *pattern,
int prev_sep,
int next_sep)
495 int len = prev_sep < 1 ? prev_sep + 1 : prev_sep;
496 char *path_until_glob = tor_strndup(pattern, len);
498 if (!is_file(file_status(path_until_glob))) {
501 smartlist_free(result);
505 TCHAR tpattern[MAX_PATH] = {0};
506 TCHAR tfile[MAX_PATH] = {0};
509 path_until_glob, filename);
510 char *path_curr_glob = tor_strndup(pattern, next_sep + 1);
512 if (is_dir(file_status(full_path))) {
516 mbstowcs(tpattern, path_curr_glob, MAX_PATH);
517 mbstowcs(tfile, full_path, MAX_PATH);
519 strlcpy(tpattern, path_curr_glob, MAX_PATH);
520 strlcpy(tfile, full_path, MAX_PATH);
522 if (PathMatchSpec(tfile, tpattern)) {
528 } SMARTLIST_FOREACH_END(filename);
530 smartlist_free(filenames);
537#ifdef GLOB_ALTDIRFUNC
540prot_opendir(
const char *
name)
542 if (sandbox_interned_string_is_missing(
name)) {
551prot_stat(
const char *pathname,
struct stat *buf)
553 if (sandbox_interned_string_is_missing(pathname)) {
562prot_lstat(
const char *pathname,
struct stat *buf)
564 if (sandbox_interned_string_is_missing(pathname)) {
572wrap_closedir(
void *arg)
585glob_errfunc(
const char *epath,
int eerrno)
588 return eerrno == ENOENT || eerrno == ENOTDIR ? 0 : -1;
604 char *pattern_normalized = tor_strdup(pattern);
610 int flags = GLOB_NOSORT;
611#ifdef GLOB_ALTDIRFUNC
613 flags |= GLOB_ALTDIRFUNC;
614 typedef void *(*gl_opendir)(
const char *
name);
615 typedef struct dirent *(*gl_readdir)(
void *);
616 typedef void (*gl_closedir)(
void *);
617 matches.gl_opendir = (gl_opendir) &prot_opendir;
618 matches.gl_readdir = (gl_readdir) &readdir;
619 matches.gl_closedir = (gl_closedir) &wrap_closedir;
620 matches.gl_stat = &prot_stat;
621 matches.gl_lstat = &prot_lstat;
626 int ret = glob(pattern, flags, glob_errfunc, &matches);
627 if (ret == GLOB_NOMATCH) {
629 }
else if (ret != 0) {
638 size_t pattern_len = strlen(pattern);
639 bool dir_only = pattern_len > 0 && pattern[pattern_len-1] == *PATH_SEPARATOR;
643 for (i = 0; i < matches.gl_pathc; i++) {
644 char *match = tor_strdup(matches.gl_pathv[i]);
645 size_t len = strlen(match);
646 if (len > 0 && match[len-1] == *PATH_SEPARATOR) {
650 if (!dir_only || (dir_only && is_dir(file_status(match)))) {
671 for (i = 0; s[i]; i++) {
689 if (
has_glob(&pattern[next_sep+1])) {
692 char *glob_path = tor_strndup(pattern, next_sep);
696 smartlist_free(result);
700 smartlist_free(child_paths);
Locale-independent character-type inspection (header)
Header for compat_string.c.
smartlist_t * tor_listdir(const char *dirname)
Wrappers for reading and writing data to files on disk.
Headers for util_malloc.c.
static bool add_non_glob_path(const char *path, struct smartlist_t *result)
int get_parent_directory(char *fname)
char * make_path_absolute(const char *fname)
static bool is_glob_char(const char *pattern, int pos)
static struct smartlist_t * get_glob_paths(const char *pattern, unglob_fn unglob, bool final)
void clean_fname_for_stat(char *name)
static char * alloc_getcwd(void)
struct smartlist_t * tor_glob(const char *pattern)
bool has_glob(const char *s)
static struct smartlist_t * unglob_opened_files(const char *pattern, int prev_sep, int next_sep)
struct smartlist_t * get_glob_opened_files(const char *pattern)
int path_is_relative(const char *filename)
char * get_unquoted_path(const char *path)
char * expand_filename(const char *filename)
int tor_asprintf(char **strp, const char *fmt,...)
Header file for sandbox.c.
#define sandbox_intern_string(s)
void smartlist_add_all(smartlist_t *s1, const smartlist_t *s2)
smartlist_t * smartlist_new(void)
void smartlist_add(smartlist_t *sl, void *element)
#define SMARTLIST_FOREACH_BEGIN(sl, type, var)
#define SMARTLIST_FOREACH(sl, type, var, cmd)
char * get_user_homedir(const char *username)
Macros to manage assertions, fatal and non-fatal.
int strcmpend(const char *s1, const char *s2)
void tor_strreplacechar(char *s, char find, char replacement)
Header for util_string.c.