static Boolean test_canonicalize_path(int verbose) { static struct stringtest { char *str1; char *str2; } tests[] = { { "/foo/a/bz.to/bar.dvi", "/foo/a/bz.to/bar.dvi" }, { "/foo/../bar.dvi", "/bar.dvi" }, { "/foo/../bar.dvi", "/bar.dvi" }, { "/foo/./roo/./bar.dvi", "/foo/roo/bar.dvi" }, { "/foo/./roo/../bar.dvi", "/foo/bar.dvi" }, }; size_t i; Boolean result = True; for (i = 0; i < (sizeof tests / sizeof tests[0]); i++) { if (verbose) { INFO((stderr, "canonicalize_path(%s) -> %s == %s?\n", tests[i].str1, canonicalize_path(tests[i].str1), tests[i].str2)); } if (!test_str_equality(verbose, canonicalize_path(tests[i].str1), tests[i].str2)) { result = False; } } return result; }
/* * make_relative_path - make a path relative to the actual binary location * * This function exists to support relocation of installation trees. * * ret_path is the output area (must be of size MAXPGPATH) * target_path is the compiled-in path to the directory we want to find * bin_path is the compiled-in path to the directory of executables * my_exec_path is the actual location of my executable * * If target_path matches bin_path up to the last directory component of * bin_path, then we build the result as my_exec_path (less the executable * name and last directory) joined to the non-matching part of target_path. * Otherwise, we return target_path as-is. * * For example: * target_path = '/usr/local/share/postgresql' * bin_path = '/usr/local/bin' * my_exec_path = '/opt/pgsql/bin/postmaster' * Given these inputs we would return '/opt/pgsql/share/postgresql' */ static void make_relative_path(char *ret_path, const char *target_path, const char *bin_path, const char *my_exec_path) { const char *bin_end; int prefix_len; bin_end = last_dir_separator(bin_path); if (!bin_end) goto no_match; prefix_len = bin_end - bin_path + 1; if (strncmp(target_path, bin_path, prefix_len) != 0) goto no_match; StrNCpy(ret_path, my_exec_path, MAXPGPATH); trim_directory(ret_path); /* remove my executable name */ trim_directory(ret_path); /* remove last directory component (/bin) */ join_path_components(ret_path, ret_path, target_path + prefix_len); canonicalize_path(ret_path); return; no_match: StrNCpy(ret_path, target_path, MAXPGPATH); canonicalize_path(ret_path); }
int to_canonic_path(const char path[], char buf[], size_t buf_len) { if(!is_path_absolute(path)) { char cwd[PATH_MAX]; char full_path[PATH_MAX]; if(getcwd(cwd, sizeof(cwd)) == NULL) { /* getcwd() failed, we can't use relative path, so fail. */ LOG_SERROR_MSG(errno, "Can't get CWD"); return 1; } snprintf(full_path, sizeof(full_path), "%s/%s", cwd, path); canonicalize_path(full_path, buf, buf_len); } else { canonicalize_path(path, buf, buf_len); } chosp(buf); return 0; }
/* * load_config() * * Set default options and overwrite with values from provided configuration * file. * * Returns true if a configuration file could be parsed, otherwise false. * * Any configuration options changed in this function must also be changed in * reload_config() */ bool load_config(const char *config_file, t_configuration_options *options, char *argv0) { struct stat config; /* Sanity checks */ /* * If a configuration file was provided, check it exists, otherwise * emit an error and terminate */ if (config_file[0]) { strncpy(config_file_path, config_file, MAXPGPATH); canonicalize_path(config_file_path); if (stat(config_file_path, &config) != 0) { log_err(_("provided configuration file '%s' not found: %s\n"), config_file, strerror(errno) ); exit(ERR_BAD_CONFIG); } config_file_provided = true; } /* * If no configuration file was provided, attempt to find a default file */ if (config_file_provided == false) { char my_exec_path[MAXPGPATH]; char etc_path[MAXPGPATH]; /* First check if one is in the default sysconfdir */ if (find_my_exec(argv0, my_exec_path) < 0) { fprintf(stderr, _("%s: could not find own program executable\n"), argv0); exit(EXIT_FAILURE); } get_etc_path(my_exec_path, etc_path); snprintf(config_file_path, MAXPGPATH, "%s/repmgr.conf", etc_path); log_debug(_("Looking for configuration file in %s\n"), etc_path); if (stat(config_file_path, &config) != 0) { /* Not found - default to ./repmgr.conf */ strncpy(config_file_path, DEFAULT_CONFIG_FILE, MAXPGPATH); canonicalize_path(config_file_path); log_debug(_("Looking for configuration file in %s\n"), config_file_path); } } return parse_config(options); }
/* Return a new heap-allocated string representing to absolute path to the file referred to by PATH. If PATH is an absolute path, then the returned path is a copy of PATH. If PATH is a relative path, then BASE is with PATH used to construct the absolute path. */ char * grub_resolve_relative_path (const char *base, const char *path) { char *abspath; char *canonpath; char *p; grub_size_t l; /* If PATH is an absolute path, then just use it as is. */ if (path[0] == '/' || path[0] == '(') return canonicalize_path (path); abspath = grub_malloc (grub_strlen (base) + grub_strlen (path) + 3); if (! abspath) return 0; /* Concatenate BASE and PATH. */ p = grub_stpcpy (abspath, base); l = grub_strlen (abspath); if (l == 0 || abspath[l-1] != '/') { *p = '/'; p++; *p = 0; } grub_stpcpy (p, path); canonpath = canonicalize_path (abspath); if (! canonpath) return abspath; grub_free (abspath); return canonpath; }
/* * Split argument into old_dir and new_dir and append to tablespace mapping * list. * * Adapted from pg_basebackup.c */ static void tablespace_list_append(t_configuration_options *options, const char *arg) { TablespaceListCell *cell; char *dst; char *dst_ptr; const char *arg_ptr; cell = (TablespaceListCell *) pg_malloc0(sizeof(TablespaceListCell)); if (cell == NULL) { log_err(_("unable to allocate memory; terminating\n")); exit(ERR_BAD_CONFIG); } dst_ptr = dst = cell->old_dir; for (arg_ptr = arg; *arg_ptr; arg_ptr++) { if (dst_ptr - dst >= MAXPGPATH) { log_err(_("directory name too long\n")); exit(ERR_BAD_CONFIG); } if (*arg_ptr == '\\' && *(arg_ptr + 1) == '=') ; /* skip backslash escaping = */ else if (*arg_ptr == '=' && (arg_ptr == arg || *(arg_ptr - 1) != '\\')) { if (*cell->new_dir) { log_err(_("multiple \"=\" signs in tablespace mapping\n")); exit(ERR_BAD_CONFIG); } else { dst = dst_ptr = cell->new_dir; } } else *dst_ptr++ = *arg_ptr; } if (!*cell->old_dir || !*cell->new_dir) { log_err(_("invalid tablespace mapping format \"%s\", must be \"OLDDIR=NEWDIR\"\n"), arg); exit(ERR_BAD_CONFIG); } canonicalize_path(cell->old_dir); canonicalize_path(cell->new_dir); if (options->tablespace_mapping.tail) options->tablespace_mapping.tail->next = cell; else options->tablespace_mapping.head = cell; options->tablespace_mapping.tail = cell; }
/* * set_pglocale_pgservice * * Set application-specific locale and service directory * * This function takes the value of argv[0] rather than a full path. * * (You may be wondering why this is in exec.c. It requires this module's * services and doesn't introduce any new dependencies, so this seems as * good as anyplace.) */ void set_pglocale_pgservice(const char *argv0, const char *app) { char path[MAXPGPATH]; char my_exec_path[MAXPGPATH]; char env_path[MAXPGPATH + sizeof("PGSYSCONFDIR=")]; /* longer than * PGLOCALEDIR */ char *dup_path; /* don't set LC_ALL in the backend */ if (strcmp(app, PG_TEXTDOMAIN("postgres")) != 0) { setlocale(LC_ALL, ""); /* * One could make a case for reproducing here PostmasterMain()'s test * for whether the process is multithreaded. Unlike the postmaster, * no frontend program calls sigprocmask() or otherwise provides for * mutual exclusion between signal handlers. While frontends using * fork(), if multithreaded, are formally exposed to undefined * behavior, we have not witnessed a concrete bug. Therefore, * complaining about multithreading here may be mere pedantry. */ } if (find_my_exec(argv0, my_exec_path) < 0) return; #ifdef ENABLE_NLS get_locale_path(my_exec_path, path); bindtextdomain(app, path); textdomain(app); if (getenv("PGLOCALEDIR") == NULL) { /* set for libpq to use */ snprintf(env_path, sizeof(env_path), "PGLOCALEDIR=%s", path); canonicalize_path(env_path + 12); dup_path = strdup(env_path); if (dup_path) putenv(dup_path); } #endif if (getenv("PGSYSCONFDIR") == NULL) { get_etc_path(my_exec_path, path); /* set for libpq to use */ snprintf(env_path, sizeof(env_path), "PGSYSCONFDIR=%s", path); canonicalize_path(env_path + 13); dup_path = strdup(env_path); if (dup_path) putenv(dup_path); } }
static void treat_many_dots_right(void) { char buf[PATH_MAX]; canonicalize_path("...", buf, sizeof(buf)); #ifndef _WIN32 assert_string_equal(".../", buf); #else assert_string_equal("./", buf); #endif canonicalize_path(".../", buf, sizeof(buf)); #ifndef _WIN32 assert_string_equal(".../", buf); #else assert_string_equal("./", buf); #endif canonicalize_path("...abc", buf, sizeof(buf)); assert_string_equal("...abc/", buf); canonicalize_path(".abc", buf, sizeof(buf)); assert_string_equal(".abc/", buf); canonicalize_path("abc...", buf, sizeof(buf)); assert_string_equal("abc.../", buf); canonicalize_path("abc.", buf, sizeof(buf)); assert_string_equal("abc./", buf); canonicalize_path(ABS_PREFIX "/a/.../.", buf, sizeof(buf)); #ifndef _WIN32 assert_string_equal(ABS_PREFIX "/a/.../", buf); #else assert_string_equal(ABS_PREFIX "/a/", buf); #endif canonicalize_path(ABS_PREFIX "/windows/.../", buf, sizeof(buf)); #ifndef _WIN32 assert_string_equal(ABS_PREFIX "/windows/.../", buf); #else assert_string_equal(ABS_PREFIX "/windows/", buf); #endif canonicalize_path(ABS_PREFIX "/windows/...abc", buf, sizeof(buf)); assert_string_equal(ABS_PREFIX "/windows/...abc/", buf); canonicalize_path(ABS_PREFIX "/windows/..................", buf, sizeof(buf)); #ifndef _WIN32 assert_string_equal(ABS_PREFIX "/windows/................../", buf); #else assert_string_equal(ABS_PREFIX "/windows/", buf); #endif }
static void excess_slashes(void) { char buf[PATH_MAX]; canonicalize_path(ABS_PREFIX "//", buf, sizeof(buf)); assert_string_equal(ABS_PREFIX "/", buf); canonicalize_path(ABS_PREFIX "/////////////", buf, sizeof(buf)); assert_string_equal(ABS_PREFIX "/", buf); }
static void not_root_updir(void) { char buf[PATH_MAX]; canonicalize_path("../", buf, sizeof(buf)); assert_string_equal("../", buf); canonicalize_path("../../", buf, sizeof(buf)); assert_string_equal("../../", buf); }
int paths_are_equal(const char s[], const char t[]) { /* Some additional space is allocated for adding slashes. */ char s_can[strlen(s) + 8]; char t_can[strlen(t) + 8]; canonicalize_path(s, s_can, sizeof(s_can)); canonicalize_path(t, t_can, sizeof(t_can)); return stroscmp(s_can, t_can) == 0; }
const char * make_rel_path(const char path[], const char base[]) { static char buf[PATH_MAX]; const char *p = path, *b = base; int i; int nslashes; #ifdef _WIN32 if(path[1] == ':' && base[1] == ':' && path[0] != base[0]) { canonicalize_path(path, buf, sizeof(buf)); return buf; } #endif while(p[0] != '\0' && p[1] != '\0' && b[0] != '\0' && b[1] != '\0') { const char *op = p, *ob = b; if((p = strchr(p + 1, '/')) == NULL) p = path + strlen(path); if((b = strchr(b + 1, '/')) == NULL) b = base + strlen(base); if(p - path != b - base || strnoscmp(path, base, p - path) != 0) { p = op; b = ob; break; } } canonicalize_path(b, buf, sizeof(buf)); chosp(buf); nslashes = 0; for(i = 0; buf[i] != '\0'; i++) if(buf[i] == '/') nslashes++; buf[0] = '\0'; while(nslashes-- > 0) strcat(buf, "../"); if(*p == '/') p++; canonicalize_path(p, buf + strlen(buf), sizeof(buf) - strlen(buf)); chosp(buf); if(buf[0] == '\0') strcpy(buf, "."); return buf; }
/* * make_relative_path - make a path relative to the actual binary location * * This function exists to support relocation of installation trees. * * ret_path is the output area (must be of size MAXPGPATH) * target_path is the compiled-in path to the directory we want to find * bin_path is the compiled-in path to the directory of executables * my_exec_path is the actual location of my executable * * We determine the common prefix of target_path and bin_path, then compare * the remainder of bin_path to the last directory component(s) of * my_exec_path. If they match, build the result as the part of my_exec_path * preceding the match, joined to the remainder of target_path. If no match, * return target_path as-is. * * For example: * target_path = '/usr/local/share/postgresql' * bin_path = '/usr/local/bin' * my_exec_path = '/opt/pgsql/bin/postmaster' * Given these inputs, the common prefix is '/usr/local/', the tail of * bin_path is 'bin' which does match the last directory component of * my_exec_path, so we would return '/opt/pgsql/share/postgresql' */ static void make_relative_path(char *ret_path, const char *target_path, const char *bin_path, const char *my_exec_path) { int prefix_len; int tail_start; int tail_len; int i; /* * Determine the common prefix --- note we require it to end on a * directory separator, consider eg '/usr/lib' and '/usr/libexec'. */ prefix_len = 0; for (i = 0; target_path[i] && bin_path[i]; i++) { if (IS_DIR_SEP(target_path[i]) && IS_DIR_SEP(bin_path[i])) prefix_len = i + 1; else if (target_path[i] != bin_path[i]) break; } if (prefix_len == 0) goto no_match; /* no common prefix? */ tail_len = strlen(bin_path) - prefix_len; /* * Set up my_exec_path without the actual executable name, and * canonicalize to simplify comparison to bin_path. */ strlcpy(ret_path, my_exec_path, MAXPGPATH); trim_directory(ret_path); /* remove my executable name */ canonicalize_path(ret_path); /* * Tail match? */ tail_start = (int) strlen(ret_path) - tail_len; if (tail_start > 0 && IS_DIR_SEP(ret_path[tail_start - 1]) && dir_strcmp(ret_path + tail_start, bin_path + prefix_len) == 0) { ret_path[tail_start] = '\0'; trim_trailing_separator(ret_path); join_path_components(ret_path, ret_path, target_path + prefix_len); canonicalize_path(ret_path); return; } no_match: strlcpy(ret_path, target_path, MAXPGPATH); canonicalize_path(ret_path); }
static void remove_dots(void) { char buf[PATH_MAX]; canonicalize_path("./", buf, sizeof(buf)); assert_string_equal("./", buf); canonicalize_path(ABS_PREFIX "/a/./", buf, sizeof(buf)); assert_string_equal(ABS_PREFIX "/a/", buf); canonicalize_path("././././././", buf, sizeof(buf)); assert_string_equal("./", buf); }
static int test_canonicalize_path(const char *path, const char *expected) { char epath[PATH_MAX]; EXPECT_ZERO(zsnprintf(epath, PATH_MAX, "%s", path)); if (!expected) { EXPECT_NONZERO(canonicalize_path(epath)); } else { EXPECT_ZERO(canonicalize_path(epath)); EXPECT_ZERO(strcmp(epath, expected)); } return 0; }
static void complex_tests(void) { char buf[PATH_MAX]; canonicalize_path(ABS_PREFIX "/a/b/../c/../..", buf, sizeof(buf)); assert_string_equal(ABS_PREFIX "/", buf); canonicalize_path(ABS_PREFIX "/a/./b/./.././c/../../.", buf, sizeof(buf)); assert_string_equal(ABS_PREFIX "/", buf); canonicalize_path(ABS_PREFIX "//a//./b/./../////./c///.././/", buf, sizeof(buf)); assert_string_equal(ABS_PREFIX "/a/", buf); }
int cfg_set_fuse_home(const char new_value[]) { #ifdef _WIN32 char with_forward_slashes[strlen(new_value) + 1]; strcpy(with_forward_slashes, new_value); system_to_internal_slashes(with_forward_slashes); new_value = with_forward_slashes; #endif char canonicalized[PATH_MAX + 1]; canonicalize_path(new_value, canonicalized, sizeof(canonicalized)); if(!is_path_absolute(new_value)) { if(cfg.fuse_home == NULL) { /* Do not leave cfg.fuse_home uninitialized. */ cfg.fuse_home = strdup(""); } show_error_msgf("Error Setting FUSE Home Directory", "The path is not absolute: %s", canonicalized); return 1; } return replace_string(&cfg.fuse_home, canonicalized); }
static void setup(char *argv0, bool live_check) { char exec_path[MAXPGPATH]; /* full path to my executable */ /* * make sure the user has a clean environment, otherwise, we may confuse * libpq when we connect to one (or both) of the servers. */ check_pghost_envvar(); verify_directories(); /* no postmasters should be running */ if (!live_check && is_server_running(old_cluster.pgdata)) pg_log(PG_FATAL, "There seems to be a postmaster servicing the old cluster.\n" "Please shutdown that postmaster and try again.\n"); /* same goes for the new postmaster */ if (is_server_running(new_cluster.pgdata)) pg_log(PG_FATAL, "There seems to be a postmaster servicing the new cluster.\n" "Please shutdown that postmaster and try again.\n"); /* get path to pg_upgrade executable */ if (find_my_exec(argv0, exec_path) < 0) pg_log(PG_FATAL, "Could not get pathname to pg_upgrade: %s\n", getErrorText(errno)); /* Trim off program name and keep just path */ *last_dir_separator(exec_path) = '\0'; canonicalize_path(exec_path); os_info.exec_path = pg_strdup(exec_path); }
static int display_summary(void) { FILE *swaps; char line[1024] ; if ((swaps = fopen(_PATH_PROC_SWAPS, "r")) == NULL) { warn(_("%s: open failed"), _PATH_PROC_SWAPS); return -1; } while (fgets(line, sizeof(line), swaps)) { char *p, *dev, *cn; if (!strncmp(line, "Filename\t", 9)) { printf("%s", line); continue; } for (p = line; *p && *p != ' '; p++); *p = '\0'; for (++p; *p && isblank((unsigned int) *p); p++); dev = unmangle(line, NULL); if (!dev) continue; cn = canonicalize_path(dev); if (cn) printf("%-39s %s", cn, p); free(dev); free(cn); } fclose(swaps); return 0 ; }
/* buf should be at least PATH_MAX characters length */ static void parse_path(const char *dir, const char *path, char *buf) { strcpy(buf, path); #ifdef _WIN32 to_forward_slash(buf); #endif if(is_path_absolute(buf)) { snprintf(buf, PATH_MAX, "%s", path); } #ifdef _WIN32 else if(buf[0] == '/') { snprintf(buf, PATH_MAX, "%c:%s", dir[0], path); } #endif else { char new_path[PATH_MAX]; snprintf(new_path, sizeof(new_path), "%s/%s", dir, path); canonicalize_path(new_path, buf, PATH_MAX); } if(!is_root_dir(buf)) chosp(buf); #ifdef _WIN32 to_forward_slash(buf); #endif }
/* * get_safe_path - make a fullpath and check security. */ static char * get_safe_path(text *location, text *filename) { char *fullname; int aux_pos; int aux_len; NON_EMPTY_TEXT(location); NON_EMPTY_TEXT(filename); aux_pos = VARSIZE_ANY_EXHDR(location); aux_len = VARSIZE_ANY_EXHDR(filename); fullname = palloc(aux_pos + 1 + aux_len + 1); memcpy(fullname, VARDATA(location), aux_pos); fullname[aux_pos] = '/'; memcpy(fullname + aux_pos + 1, VARDATA(filename), aux_len); fullname[aux_pos + aux_len + 1] = '\0'; /* check locality in canonizalized form of path */ canonicalize_path(fullname); check_secure_locality(fullname); return fullname; }
/* * Convert a "text" filename argument to C string, and check it's allowable. * * Filename may be absolute or relative to the DataDir, but we only allow * absolute paths that match DataDir or Log_directory. */ static char * convert_and_check_filename(text *arg) { char *filename; filename = text_to_cstring(arg); canonicalize_path(filename); /* filename can change length here */ /* Disallow ".." in the path */ if (path_contains_parent_reference(filename)) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errmsg("reference to parent directory (\"..\") not allowed")))); if (is_absolute_path(filename)) { /* Allow absolute references within DataDir */ if (path_is_prefix_of_path(DataDir, filename)) return filename; /* The log directory might be outside our datadir, but allow it */ if (is_absolute_path(Log_directory) && path_is_prefix_of_path(Log_directory, filename)) return filename; ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errmsg("absolute path not allowed")))); return NULL; /* keep compiler quiet */ } else { return filename; } }
void __prefix_cwd(const char* in_path) { if (!*in_path) return; std::string path; std::list<std::string> path_components; // std::cout << "CWD to " << in_path << std::endl; pthread_rwlock_wrlock(&g_cwdLock); if (in_path[0] != '/') { path = g_cwd; path += in_path; } else path = in_path; path_components = explode_path(path); g_cwd = join_path(canonicalize_path(path_components)); if (g_cwd[g_cwd.length()-1] != '/') g_cwd += '/'; // std::cout << "\t+++ CWD In: " << in_path << "; out: " << g_cwd << std::endl; pthread_rwlock_unlock(&g_cwdLock); }
/* * Find another program in our binary's directory, * then make sure it is the proper version. */ int find_other_exec(const char *argv0, const char *target, const char *versionstr, char *retpath) { char cmd[MAXPGPATH]; char line[100]; if (find_my_exec(argv0, retpath) < 0) return -1; /* Trim off program name and keep just directory */ *last_dir_separator(retpath) = '\0'; canonicalize_path(retpath); /* Now append the other program's name */ snprintf(retpath + strlen(retpath), MAXPGPATH - strlen(retpath), "/%s%s", target, EXE); if (validate_exec(retpath) != 0) return -1; snprintf(cmd, sizeof(cmd), "\"%s\" -V 2>%s", retpath, DEVNULL); if (!pipe_read_line(cmd, line, sizeof(line))) return -1; if (strcmp(line, versionstr) != 0) return -2; return 0; }
static char *canonicalize_path_and_cache(const char *path, struct libmnt_cache *cache) { char *p = NULL; char *key = NULL; char *value = NULL; DBG(CACHE, ul_debugobj(cache, "canonicalize path %s", path)); p = canonicalize_path(path); if (p && cache) { value = p; key = strcmp(path, p) == 0 ? value : strdup(path); if (!key || !value) goto error; if (cache_add_entry(cache, key, value, MNT_CACHE_ISPATH)) goto error; } return p; error: if (value != key) free(value); free(key); return NULL; }
static void print_all_devices_pt(struct fdisk_context *cxt) { FILE *f; char line[128 + 1]; f = fopen(_PATH_PROC_PARTITIONS, "r"); if (!f) { warn(_("cannot open %s"), _PATH_PROC_PARTITIONS); return; } DBG(FRONTEND, dbgprint("reading "_PATH_PROC_PARTITIONS)); while (fgets(line, sizeof(line), f)) { char ptname[128 + 1], devname[256]; if (sscanf(line, " %*d %*d %*d %128[^\n ]", ptname) != 1) continue; snprintf(devname, sizeof(devname), "/dev/%s", ptname); DBG(FRONTEND, dbgprint("listing %s", devname)); if (is_whole_disk(devname)) { char *cn = canonicalize_path(devname); if (cn) { if (!is_ide_cdrom_or_tape(cn)) print_device_pt(cxt, cn); free(cn); } } } fclose(f); }
/* * Convert a "text" filename argument to C string, and check it's allowable. * * Filename may be absolute or relative to the DataDir, but we only allow * absolute paths that match DataDir or Log_directory. */ static char * convert_and_check_filename(text *arg, bool logAllowed) { char *filename = text_to_cstring(arg); canonicalize_path(filename); /* filename can change length here */ if (is_absolute_path(filename)) { /* Disallow '/a/b/data/..' */ if (path_contains_parent_reference(filename)) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errmsg("reference to parent directory (\"..\") not allowed")))); /* * Allow absolute paths if within DataDir or Log_directory, even * though Log_directory might be outside DataDir. */ if (!path_is_prefix_of_path(DataDir, filename) && (!logAllowed || !is_absolute_path(Log_directory) || !path_is_prefix_of_path(Log_directory, filename))) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errmsg("absolute path not allowed")))); } else if (!path_is_relative_and_below_cwd(filename)) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errmsg("path must be in or below the current directory")))); return filename; }
static void root_updir(void) { char buf[PATH_MAX]; canonicalize_path(ABS_PREFIX "/..", buf, sizeof(buf)); assert_string_equal(ABS_PREFIX "/", buf); canonicalize_path(ABS_PREFIX "/../", buf, sizeof(buf)); assert_string_equal(ABS_PREFIX "/", buf); canonicalize_path(ABS_PREFIX "/../..", buf, sizeof(buf)); assert_string_equal(ABS_PREFIX "/", buf); canonicalize_path(ABS_PREFIX "/../../", buf, sizeof(buf)); assert_string_equal(ABS_PREFIX "/", buf); }
char *canonicalize (const char *path) { char *res = canonicalize_path(path); if (!res) die(EX_SYSERR, _("not enough memory")); return res; }
static void read_proc_swaps(void) { FILE *swaps; char line[1024]; char *p, **q; size_t sz; numSwaps = 0; swapFiles = NULL; swaps = fopen(_PATH_PROC_SWAPS, "r"); if (swaps == NULL) return; /* nothing wrong */ /* skip the first line */ if (!fgets(line, sizeof(line), swaps)) { /* do not whine about an empty file */ if (ferror(swaps)) warn(_("%s: unexpected file format"), _PATH_PROC_SWAPS); fclose(swaps); return; } /* make sure the first line is the header */ if (line[0] != '\0' && strncmp(line, "Filename\t", 9)) goto valid_first_line; while (fgets(line, sizeof(line), swaps)) { valid_first_line: /* * Cut the line "swap_device ... more info" after device. * This will fail with names with embedded spaces. */ for (p = line; *p && *p != ' '; p++); *p = '\0'; /* the kernel can use " (deleted)" suffix for paths * in /proc/swaps, we have to remove this junk. */ sz = strlen(line); if (sz > PATH_DELETED_SUFFIX_SZ) { p = line + (sz - PATH_DELETED_SUFFIX_SZ); if (strcmp(p, PATH_DELETED_SUFFIX) == 0) *p = '\0'; } q = realloc(swapFiles, (numSwaps+1) * sizeof(*swapFiles)); if (q == NULL) break; swapFiles = q; if ((p = unmangle(line, NULL)) == NULL) break; swapFiles[numSwaps++] = canonicalize_path(p); free(p); } fclose(swaps); }