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);
536 #ifdef GLOB_ALTDIRFUNC
539 prot_opendir(
const char *
name)
541 if (sandbox_interned_string_is_missing(
name)) {
550 prot_stat(
const char *pathname,
struct stat *buf)
552 if (sandbox_interned_string_is_missing(pathname)) {
561 prot_lstat(
const char *pathname,
struct stat *buf)
563 if (sandbox_interned_string_is_missing(pathname)) {
571 wrap_closedir(
void *arg)
584 glob_errfunc(
const char *epath,
int eerrno)
587 return eerrno == ENOENT || eerrno == ENOTDIR ? 0 : -1;
603 char *pattern_normalized = tor_strdup(pattern);
609 int flags = GLOB_NOSORT;
610 #ifdef GLOB_ALTDIRFUNC
612 flags |= GLOB_ALTDIRFUNC;
613 typedef void *(*gl_opendir)(
const char *
name);
614 typedef struct dirent *(*gl_readdir)(
void *);
615 typedef void (*gl_closedir)(
void *);
616 matches.gl_opendir = (gl_opendir) &prot_opendir;
617 matches.gl_readdir = (gl_readdir) &readdir;
618 matches.gl_closedir = (gl_closedir) &wrap_closedir;
619 matches.gl_stat = &prot_stat;
620 matches.gl_lstat = &prot_lstat;
625 int ret = glob(pattern, flags, glob_errfunc, &matches);
626 if (ret == GLOB_NOMATCH) {
628 }
else if (ret != 0) {
637 size_t pattern_len = strlen(pattern);
638 bool dir_only = pattern_len > 0 && pattern[pattern_len-1] == *PATH_SEPARATOR;
642 for (i = 0; i < matches.gl_pathc; i++) {
643 char *match = tor_strdup(matches.gl_pathv[i]);
644 size_t len = strlen(match);
645 if (len > 0 && match[len-1] == *PATH_SEPARATOR) {
670 for (i = 0; s[i]; i++) {
688 if (
has_glob(&pattern[next_sep+1])) {
691 char *glob_path = tor_strndup(pattern, next_sep);
695 smartlist_free(result);
699 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.
file_status_t file_status(const char *filename)
bool is_file(file_status_t file_type)
bool is_dir(file_status_t file_type)
Headers for util_malloc.c.
static bool add_non_glob_path(const char *path, struct smartlist_t *result)
int get_parent_directory(char *fname)
struct smartlist_t * tor_glob(const char *pattern)
static bool is_glob_char(const char *pattern, int pos)
void clean_fname_for_stat(char *name)
bool has_glob(const char *s)
static struct smartlist_t * get_glob_paths(const char *pattern, unglob_fn unglob, bool final)
char * get_unquoted_path(const char *path)
char * expand_filename(const char *filename)
static struct smartlist_t * unglob_opened_files(const char *pattern, int prev_sep, int next_sep)
static char * alloc_getcwd(void)
int path_is_relative(const char *filename)
char * make_path_absolute(const char *fname)
struct smartlist_t * get_glob_opened_files(const char *pattern)
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.