PostgreSQL Source Code git master
Loading...
Searching...
No Matches
path.c File Reference
#include "postgres.h"
#include <ctype.h>
#include <sys/stat.h>
#include <pwd.h>
#include <unistd.h>
#include "mb/pg_wchar.h"
#include "pg_config_paths.h"
Include dependency graph for path.c:

Go to the source code of this file.

Macros

#define IS_PATH_VAR_SEP(ch)   ((ch) == ':')
 
#define skip_drive(path)   (path)
 

Enumerations

enum  canonicalize_state {
  ABSOLUTE_PATH_INIT , ABSOLUTE_WITH_N_DEPTH , RELATIVE_PATH_INIT , RELATIVE_WITH_N_DEPTH ,
  RELATIVE_WITH_PARENT_REF
}
 

Functions

static void make_relative_path (char *ret_path, const char *target_path, const char *bin_path, const char *my_exec_path)
 
static chartrim_directory (char *path)
 
static void trim_trailing_separator (char *path)
 
static charappend_subdir_to_path (char *path, char *subdir)
 
bool has_drive_prefix (const char *path)
 
charfirst_dir_separator (const char *filename)
 
charfirst_path_var_separator (const char *pathlist)
 
charlast_dir_separator (const char *filename)
 
void make_native_path (char *filename)
 
void cleanup_path (char *path)
 
void join_path_components (char *ret_path, const char *head, const char *tail)
 
void canonicalize_path (char *path)
 
void canonicalize_path_enc (char *path, int encoding)
 
bool path_contains_parent_reference (const char *path)
 
bool path_is_relative_and_below_cwd (const char *path)
 
bool path_is_safe_for_extraction (const char *path)
 
bool path_is_prefix_of_path (const char *path1, const char *path2)
 
const charget_progname (const char *argv0)
 
static int dir_strcmp (const char *s1, const char *s2)
 
charmake_absolute_path (const char *path)
 
void get_share_path (const char *my_exec_path, char *ret_path)
 
void get_etc_path (const char *my_exec_path, char *ret_path)
 
void get_include_path (const char *my_exec_path, char *ret_path)
 
void get_pkginclude_path (const char *my_exec_path, char *ret_path)
 
void get_includeserver_path (const char *my_exec_path, char *ret_path)
 
void get_lib_path (const char *my_exec_path, char *ret_path)
 
void get_pkglib_path (const char *my_exec_path, char *ret_path)
 
void get_locale_path (const char *my_exec_path, char *ret_path)
 
void get_doc_path (const char *my_exec_path, char *ret_path)
 
void get_html_path (const char *my_exec_path, char *ret_path)
 
void get_man_path (const char *my_exec_path, char *ret_path)
 
bool get_home_path (char *ret_path)
 
void get_parent_directory (char *path)
 

Macro Definition Documentation

◆ IS_PATH_VAR_SEP

#define IS_PATH_VAR_SEP (   ch)    ((ch) == ':')

Definition at line 44 of file path.c.

◆ skip_drive

#define skip_drive (   path)    (path)

Definition at line 85 of file path.c.

Enumeration Type Documentation

◆ canonicalize_state

Enumerator
ABSOLUTE_PATH_INIT 
ABSOLUTE_WITH_N_DEPTH 
RELATIVE_PATH_INIT 
RELATIVE_WITH_N_DEPTH 
RELATIVE_WITH_PARENT_REF 

Definition at line 309 of file path.c.

310{
311 ABSOLUTE_PATH_INIT, /* Just past the leading '/' (and Windows
312 * drive name if any) of an absolute path */
313 ABSOLUTE_WITH_N_DEPTH, /* We collected 'pathdepth' directories in an
314 * absolute path */
315 RELATIVE_PATH_INIT, /* At start of a relative path */
316 RELATIVE_WITH_N_DEPTH, /* We collected 'pathdepth' directories in a
317 * relative path */
318 RELATIVE_WITH_PARENT_REF, /* Relative path containing only double-dots */
canonicalize_state
Definition path.c:310
@ ABSOLUTE_WITH_N_DEPTH
Definition path.c:313
@ RELATIVE_WITH_N_DEPTH
Definition path.c:316
@ ABSOLUTE_PATH_INIT
Definition path.c:311
@ RELATIVE_PATH_INIT
Definition path.c:315
@ RELATIVE_WITH_PARENT_REF
Definition path.c:318

Function Documentation

◆ append_subdir_to_path()

static char * append_subdir_to_path ( char path,
char subdir 
)
static

Definition at line 1156 of file path.c.

1157{
1158 size_t len = strlen(subdir);
1159
1160 /* No need to copy data if path and subdir are the same. */
1161 if (path != subdir)
1162 memmove(path, subdir, len);
1163
1164 return path + len;
1165}
const void size_t len
static int fb(int x)

References fb(), and len.

Referenced by canonicalize_path_enc().

◆ canonicalize_path()

◆ canonicalize_path_enc()

void canonicalize_path_enc ( char path,
int  encoding 
)

Definition at line 344 of file path.c.

345{
346 char *p,
347 *to_p;
348 char *spath;
349 char *parsed;
350 char *unparse;
351 bool was_sep = false;
353 int pathdepth = 0; /* counts collected regular directory names */
354
355#ifdef WIN32
356
357 /*
358 * The Windows command processor will accept suitably quoted paths with
359 * forward slashes, but barfs badly with mixed forward and back slashes.
360 * Hence, start by converting all back slashes to forward slashes.
361 */
363
364 /*
365 * In Win32, if you do: prog.exe "a b" "\c\d\" the system will pass \c\d"
366 * as argv[2], so trim off trailing quote.
367 */
368 p = path + strlen(path);
369 if (p > path && *(p - 1) == '"')
370 *(p - 1) = '/';
371#endif
372
373 /*
374 * Removing the trailing slash on a path means we never get ugly double
375 * trailing slashes. Also, Win32 can't stat() a directory with a trailing
376 * slash. Don't remove a leading slash, though.
377 */
379
380 /*
381 * Remove duplicate adjacent separators
382 */
383 p = path;
384#ifdef WIN32
385 /* Don't remove leading double-slash on Win32 */
386 if (*p)
387 p++;
388#endif
389 to_p = p;
390 for (; *p; p++, to_p++)
391 {
392 /* Handle many adjacent slashes, like "/a///b" */
393 while (*p == '/' && was_sep)
394 p++;
395 if (to_p != p)
396 *to_p = *p;
397 was_sep = (*p == '/');
398 }
399 *to_p = '\0';
400
401 /*
402 * Remove any uses of "." and process ".." ourselves
403 *
404 * Note that "/../.." should reduce to just "/", while "../.." has to be
405 * kept as-is. Also note that we want a Windows drive spec to be visible
406 * to trim_directory(), but it's not part of the logic that's looking at
407 * the name components; hence distinction between path and spath.
408 *
409 * This loop overwrites the path in-place. This is safe since we'll never
410 * make the path longer. "unparse" points to where we are reading the
411 * path, "parse" to where we are writing.
412 */
413 spath = skip_drive(path);
414 if (*spath == '\0')
415 return; /* empty path is returned as-is */
416
417 if (*spath == '/')
418 {
420 /* Skip the leading slash for absolute path */
421 parsed = unparse = (spath + 1);
422 }
423 else
424 {
426 parsed = unparse = spath;
427 }
428
429 while (*unparse != '\0')
430 {
431 char *unparse_next;
432 bool is_double_dot;
433
434 /* Split off this dir name, and set unparse_next to the next one */
436 while (*unparse_next && *unparse_next != '/')
437 unparse_next++;
438 if (*unparse_next != '\0')
439 *unparse_next++ = '\0';
440
441 /* Identify type of this dir name */
442 if (strcmp(unparse, ".") == 0)
443 {
444 /* We can ignore "." components in all cases */
446 continue;
447 }
448
449 if (strcmp(unparse, "..") == 0)
450 is_double_dot = true;
451 else
452 {
453 /* adjacent separators were eliminated above */
454 Assert(*unparse != '\0');
455 is_double_dot = false;
456 }
457
458 switch (state)
459 {
461 /* We can ignore ".." immediately after / */
462 if (!is_double_dot)
463 {
464 /* Append first dir name (we already have leading slash) */
467 pathdepth++;
468 }
469 break;
471 if (is_double_dot)
472 {
473 /* Remove last parsed dir */
474 /* (trim_directory won't remove the leading slash) */
475 *parsed = '\0';
476 parsed = trim_directory(path);
477 if (--pathdepth == 0)
479 }
480 else
481 {
482 /* Append normal dir */
483 *parsed++ = '/';
485 pathdepth++;
486 }
487 break;
489 if (is_double_dot)
490 {
491 /* Append irreducible double-dot (..) */
494 }
495 else
496 {
497 /* Append normal dir */
500 pathdepth++;
501 }
502 break;
504 if (is_double_dot)
505 {
506 /* Remove last parsed dir */
507 *parsed = '\0';
508 parsed = trim_directory(path);
509 if (--pathdepth == 0)
510 {
511 /*
512 * If the output path is now empty, we're back to the
513 * INIT state. However, we could have processed a
514 * path like "../dir/.." and now be down to "..", in
515 * which case enter the correct state for that.
516 */
517 if (parsed == spath)
519 else
521 }
522 }
523 else
524 {
525 /* Append normal dir */
526 *parsed++ = '/';
528 pathdepth++;
529 }
530 break;
532 if (is_double_dot)
533 {
534 /* Append next irreducible double-dot (..) */
535 *parsed++ = '/';
537 }
538 else
539 {
540 /* Append normal dir */
541 *parsed++ = '/';
543
544 /*
545 * We can now start counting normal dirs. But if later
546 * double-dots make us remove this dir again, we'd better
547 * revert to RELATIVE_WITH_PARENT_REF not INIT state.
548 */
550 pathdepth = 1;
551 }
552 break;
553 }
554
556 }
557
558 /*
559 * If our output path is empty at this point, insert ".". We don't want
560 * to do this any earlier because it'd result in an extra dot in corner
561 * cases such as "../dir/..". Since we rejected the wholly-empty-path
562 * case above, there is certainly room.
563 */
564 if (parsed == spath)
565 *parsed++ = '.';
566
567 /* And finally, ensure the output path is nul-terminated. */
568 *parsed = '\0';
569}
#define Assert(condition)
Definition c.h:943
static char * encoding
Definition initdb.c:139
static char * append_subdir_to_path(char *path, char *subdir)
Definition path.c:1156
static void trim_trailing_separator(char *path)
Definition path.c:1134
static char * trim_directory(char *path)
Definition path.c:1102
#define skip_drive(path)
Definition path.c:85

References ABSOLUTE_PATH_INIT, ABSOLUTE_WITH_N_DEPTH, append_subdir_to_path(), Assert, encoding, fb(), RELATIVE_PATH_INIT, RELATIVE_WITH_N_DEPTH, RELATIVE_WITH_PARENT_REF, skip_drive, trim_directory(), and trim_trailing_separator().

Referenced by canonicalize_path(), do_copy(), exec_command_edit(), exec_command_write(), and process_file().

◆ cleanup_path()

void cleanup_path ( char path)

Definition at line 258 of file path.c.

259{
260#ifdef WIN32
261 /*
262 * GetShortPathName() will fail if the path does not exist, or short names
263 * are disabled on this file system. In both cases, we just return the
264 * original path. This is particularly useful for --sysconfdir, which
265 * might not exist.
266 */
267 GetShortPathName(path, path, MAXPGPATH - 1);
268
269 /* Replace '\' with '/' */
270 /* All server-safe encodings are alike here, so just use PG_SQL_ASCII */
272#endif
273}
#define MAXPGPATH

References fb(), MAXPGPATH, and PG_SQL_ASCII.

Referenced by get_configdata().

◆ dir_strcmp()

static int dir_strcmp ( const char s1,
const char s2 
)
static

Definition at line 707 of file path.c.

708{
709 while (*s1 && *s2)
710 {
711 if (
713 *s1 != *s2
714#else
715 /* On windows, paths are case-insensitive */
716 pg_tolower((unsigned char) *s1) != pg_tolower((unsigned char) *s2)
717#endif
718 && !(IS_DIR_SEP(*s1) && IS_DIR_SEP(*s2)))
719 return (int) *s1 - (int) *s2;
720 s1++, s2++;
721 }
722 if (*s1)
723 return 1; /* s1 longer */
724 if (*s2)
725 return -1; /* s2 longer */
726 return 0;
727}
unsigned char pg_tolower(unsigned char ch)
#define IS_DIR_SEP(ch)
Definition port.h:104
char * s1
char * s2

References fb(), IS_DIR_SEP, pg_tolower(), s1, and s2.

Referenced by make_relative_path().

◆ first_dir_separator()

char * first_dir_separator ( const char filename)

Definition at line 110 of file path.c.

111{
112 const char *p;
113
114 for (p = skip_drive(filename); *p; p++)
115 if (IS_DIR_SEP(*p))
116 return unconstify(char *, p);
117 return NULL;
118}
#define unconstify(underlying_type, expr)
Definition c.h:1325
static char * filename
Definition pg_dumpall.c:133

References fb(), filename, IS_DIR_SEP, skip_drive, and unconstify.

Referenced by check_restricted_library_name(), check_valid_extension_name(), check_valid_version_name(), expand_dynamic_library_name(), find_in_path(), find_my_exec(), load_external_function(), load_libraries(), and substitute_path_macro().

◆ first_path_var_separator()

char * first_path_var_separator ( const char pathlist)

Definition at line 127 of file path.c.

128{
129 const char *p;
130
131 /* skip_drive is not needed */
132 for (p = pathlist; *p; p++)
133 if (IS_PATH_VAR_SEP(*p))
134 return unconstify(char *, p);
135 return NULL;
136}
#define IS_PATH_VAR_SEP(ch)
Definition path.c:44

References fb(), IS_PATH_VAR_SEP, and unconstify.

Referenced by find_in_path(), find_my_exec(), and get_extension_control_directories().

◆ get_doc_path()

void get_doc_path ( const char my_exec_path,
char ret_path 
)

Definition at line 991 of file path.c.

992{
994}
char my_exec_path[MAXPGPATH]
Definition globals.c:83
static void make_relative_path(char *ret_path, const char *target_path, const char *bin_path, const char *my_exec_path)
Definition path.c:755

References fb(), make_relative_path(), and my_exec_path.

Referenced by get_configdata().

◆ get_etc_path()

void get_etc_path ( const char my_exec_path,
char ret_path 
)

◆ get_home_path()

bool get_home_path ( char ret_path)

Definition at line 1022 of file path.c.

1023{
1024#ifndef WIN32
1025 /*
1026 * We first consult $HOME. If that's unset, try to get the info from
1027 * <pwd.h>.
1028 */
1029 const char *home;
1030
1031 home = getenv("HOME");
1032 if (home && home[0])
1033 {
1035 return true;
1036 }
1037 else
1038 {
1039 struct passwd pwbuf;
1040 struct passwd *pw;
1041 char buf[1024];
1042 int rc;
1043
1044 rc = getpwuid_r(geteuid(), &pwbuf, buf, sizeof buf, &pw);
1045 if (rc != 0 || !pw)
1046 return false;
1047 strlcpy(ret_path, pw->pw_dir, MAXPGPATH);
1048 return true;
1049 }
1050#else
1051 char *tmppath;
1052
1053 /*
1054 * Note: We use getenv() here because the more modern SHGetFolderPath()
1055 * would force the backend to link with shell32.lib, which eats valuable
1056 * desktop heap. XXX This function is used only in psql, which already
1057 * brings in shell32 via libpq. Moving this function to its own file
1058 * would keep it out of the backend, freeing it from this concern.
1059 */
1060 tmppath = getenv("APPDATA");
1061 if (!tmppath)
1062 return false;
1063 snprintf(ret_path, MAXPGPATH, "%s/postgresql", tmppath);
1064 return true;
1065#endif
1066}
static char buf[DEFAULT_XLOG_SEG_SIZE]
#define snprintf
Definition port.h:261
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition strlcpy.c:45

References buf, fb(), MAXPGPATH, snprintf, and strlcpy().

Referenced by expand_tilde(), initializeInput(), and process_psqlrc().

◆ get_html_path()

void get_html_path ( const char my_exec_path,
char ret_path 
)

Definition at line 1000 of file path.c.

References fb(), make_relative_path(), and my_exec_path.

Referenced by get_configdata().

◆ get_include_path()

void get_include_path ( const char my_exec_path,
char ret_path 
)

Definition at line 937 of file path.c.

References fb(), make_relative_path(), and my_exec_path.

Referenced by get_configdata(), and main().

◆ get_includeserver_path()

void get_includeserver_path ( const char my_exec_path,
char ret_path 
)

Definition at line 955 of file path.c.

References fb(), make_relative_path(), and my_exec_path.

Referenced by get_configdata().

◆ get_lib_path()

void get_lib_path ( const char my_exec_path,
char ret_path 
)

Definition at line 964 of file path.c.

References fb(), make_relative_path(), and my_exec_path.

Referenced by get_configdata().

◆ get_locale_path()

void get_locale_path ( const char my_exec_path,
char ret_path 
)

◆ get_man_path()

void get_man_path ( const char my_exec_path,
char ret_path 
)

Definition at line 1009 of file path.c.

References fb(), make_relative_path(), and my_exec_path.

Referenced by get_configdata().

◆ get_parent_directory()

void get_parent_directory ( char path)

Definition at line 1085 of file path.c.

1086{
1087 trim_directory(path);
1088}

References trim_directory().

Referenced by AbsoluteConfigLocation(), dbase_redo(), destroy_tablespace_directories(), fsync_parent_path(), main(), and process_file().

◆ get_pkginclude_path()

void get_pkginclude_path ( const char my_exec_path,
char ret_path 
)

Definition at line 946 of file path.c.

References fb(), make_relative_path(), and my_exec_path.

Referenced by get_configdata(), and main().

◆ get_pkglib_path()

void get_pkglib_path ( const char my_exec_path,
char ret_path 
)

◆ get_progname()

const char * get_progname ( const char argv0)

Definition at line 669 of file path.c.

670{
671 const char *nodir_name;
672 char *progname;
673
675 if (nodir_name)
676 nodir_name++;
677 else
679
680 /*
681 * Make a copy in case argv[0] is modified by ps_status. Leaks memory, but
682 * called only once.
683 */
685 if (progname == NULL)
686 {
687 fprintf(stderr, "%s: out of memory\n", nodir_name);
688 abort(); /* This could exit the postmaster */
689 }
690
691#if defined(__CYGWIN__) || defined(WIN32)
692 /* strip ".exe" suffix, regardless of case */
693 if (strlen(progname) > sizeof(EXE) - 1 &&
694 pg_strcasecmp(progname + strlen(progname) - (sizeof(EXE) - 1), EXE) == 0)
695 progname[strlen(progname) - (sizeof(EXE) - 1)] = '\0';
696#endif
697
698 return progname;
699}
#define fprintf(file, fmt, msg)
Definition cubescan.l:21
const char * progname
Definition main.c:44
char * last_dir_separator(const char *filename)
Definition path.c:145
static char * argv0
Definition pg_ctl.c:94
int pg_strcasecmp(const char *s1, const char *s2)
#define EXE
Definition port.h:156

References argv0, EXE, fb(), fprintf, last_dir_separator(), pg_strcasecmp(), progname, and skip_drive.

Referenced by get_opts(), handle_help_version_opts(), main(), main(), main(), parseCommandLine(), pg_logging_init(), and regression_main().

◆ get_share_path()

void get_share_path ( const char my_exec_path,
char ret_path 
)

◆ has_drive_prefix()

bool has_drive_prefix ( const char path)

Definition at line 94 of file path.c.

95{
96#ifdef WIN32
97 return skip_drive(path) != path;
98#else
99 return false;
100#endif
101}

References skip_drive.

Referenced by process_file().

◆ join_path_components()

void join_path_components ( char ret_path,
const char head,
const char tail 
)

Definition at line 286 of file path.c.

288{
289 if (ret_path != head)
290 strlcpy(ret_path, head, MAXPGPATH);
291
292 /*
293 * We used to try to simplify some cases involving "." and "..", but now
294 * we just leave that to be done by canonicalize_path() later.
295 */
296
297 if (*tail)
298 {
299 /* only separate with slash if head wasn't empty */
301 "%s%s",
302 (*(skip_drive(head)) != '\0') ? "/" : "",
303 tail);
304 }
305}

References fb(), MAXPGPATH, skip_drive, snprintf, and strlcpy().

Referenced by AbsoluteConfigLocation(), find_my_exec(), GetConfFilesInDir(), main(), make_relative_path(), and process_file().

◆ last_dir_separator()

char * last_dir_separator ( const char filename)

Definition at line 145 of file path.c.

146{
147 const char *p,
148 *ret = NULL;
149
150 for (p = skip_drive(filename); *p; p++)
151 if (IS_DIR_SEP(*p))
152 ret = p;
153 return unconstify(char *, ret);
154}

References fb(), filename, IS_DIR_SEP, skip_drive, and unconstify.

Referenced by check_file_excluded(), decide_file_action(), ECPGconnect(), find_other_exec(), get_progname(), main(), pg_get_loaded_modules(), sendDir(), setup(), setup_bin_paths(), and should_allow_existing_directory().

◆ make_absolute_path()

char * make_absolute_path ( const char path)

Definition at line 824 of file path.c.

825{
826 char *new;
827
828 /* Returning null for null input is convenient for some callers */
829 if (path == NULL)
830 return NULL;
831
832 if (!is_absolute_path(path))
833 {
834 char *buf;
835 size_t buflen;
836
837 buflen = MAXPGPATH;
838 for (;;)
839 {
840 buf = malloc(buflen);
841 if (!buf)
842 {
843#ifndef FRONTEND
846 errmsg("out of memory")));
847#else
848 fprintf(stderr, _("out of memory\n"));
849 return NULL;
850#endif
851 }
852
853 if (getcwd(buf, buflen))
854 break;
855 else if (errno == ERANGE)
856 {
857 free(buf);
858 buflen *= 2;
859 continue;
860 }
861 else
862 {
863 int save_errno = errno;
864
865 free(buf);
867#ifndef FRONTEND
868 elog(ERROR, "could not get current working directory: %m");
869#else
870 fprintf(stderr, _("could not get current working directory: %m\n"));
871 return NULL;
872#endif
873 }
874 }
875
876 new = malloc(strlen(buf) + strlen(path) + 2);
877 if (!new)
878 {
879 free(buf);
880#ifndef FRONTEND
883 errmsg("out of memory")));
884#else
885 fprintf(stderr, _("out of memory\n"));
886 return NULL;
887#endif
888 }
889 sprintf(new, "%s/%s", buf, path);
890 free(buf);
891 }
892 else
893 {
894 new = strdup(path);
895 if (!new)
896 {
897#ifndef FRONTEND
900 errmsg("out of memory")));
901#else
902 fprintf(stderr, _("out of memory\n"));
903 return NULL;
904#endif
905 }
906 }
907
908 /* Make sure punctuation is canonical, too */
910
911 return new;
912}
int errcode(int sqlerrcode)
Definition elog.c:875
#define _(x)
Definition elog.c:96
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
#define ereport(elevel,...)
Definition elog.h:152
static char * errmsg
void canonicalize_path(char *path)
Definition path.c:337
#define is_absolute_path(filename)
Definition port.h:105
#define sprintf
Definition port.h:263
#define free(a)
#define malloc(a)

References _, buf, canonicalize_path(), elog, ereport, errcode(), errmsg, ERROR, fb(), fprintf, free, is_absolute_path, malloc, MAXPGPATH, and sprintf.

Referenced by regression_main(), SelectConfigFiles(), and SetDataDir().

◆ make_native_path()

void make_native_path ( char filename)

Definition at line 236 of file path.c.

237{
238#ifdef WIN32
239 char *p;
240
241 for (p = filename; *p; p++)
242 if (*p == '/')
243 *p = '\\';
244#endif
245}

References filename.

Referenced by BuildRestoreCommand(), main(), and shell_archive_file().

◆ make_relative_path()

static void make_relative_path ( char ret_path,
const char target_path,
const char bin_path,
const char my_exec_path 
)
static

Definition at line 755 of file path.c.

757{
758 int prefix_len;
759 int tail_start;
760 int tail_len;
761 int i;
762
763 /*
764 * Determine the common prefix --- note we require it to end on a
765 * directory separator, consider eg '/usr/lib' and '/usr/libexec'.
766 */
767 prefix_len = 0;
768 for (i = 0; target_path[i] && bin_path[i]; i++)
769 {
770 if (IS_DIR_SEP(target_path[i]) && IS_DIR_SEP(bin_path[i]))
771 prefix_len = i + 1;
772 else if (target_path[i] != bin_path[i])
773 break;
774 }
775 if (prefix_len == 0)
776 goto no_match; /* no common prefix? */
778
779 /*
780 * Set up my_exec_path without the actual executable name, and
781 * canonicalize to simplify comparison to bin_path.
782 */
784 trim_directory(ret_path); /* remove my executable name */
786
787 /*
788 * Tail match?
789 */
791 if (tail_start > 0 &&
794 {
795 ret_path[tail_start] = '\0';
799 return;
800 }
801
803 strlcpy(ret_path, target_path, MAXPGPATH);
805}
static char bin_path[MAXPGPATH]
Definition initdb.c:260
int i
Definition isn.c:77
void join_path_components(char *ret_path, const char *head, const char *tail)
Definition path.c:286
static int dir_strcmp(const char *s1, const char *s2)
Definition path.c:707

References bin_path, canonicalize_path(), dir_strcmp(), fb(), i, IS_DIR_SEP, join_path_components(), MAXPGPATH, my_exec_path, strlcpy(), trim_directory(), and trim_trailing_separator().

Referenced by get_doc_path(), get_etc_path(), get_html_path(), get_include_path(), get_includeserver_path(), get_lib_path(), get_locale_path(), get_man_path(), get_pkginclude_path(), get_pkglib_path(), and get_share_path().

◆ path_contains_parent_reference()

bool path_contains_parent_reference ( const char path)

Definition at line 577 of file path.c.

578{
579 /*
580 * Once canonicalized, an absolute path cannot contain any ".." at all,
581 * while a relative path could contain ".."(s) only at the start. So it
582 * is sufficient to check the start of the path, after skipping any
583 * Windows drive/network specifier.
584 */
585 path = skip_drive(path); /* C: shouldn't affect our conclusion */
586
587 if (path[0] == '.' &&
588 path[1] == '.' &&
589 (path[2] == '\0' || path[2] == '/'))
590 return true;
591
592 return false;
593}

References skip_drive.

Referenced by path_is_relative_and_below_cwd().

◆ path_is_prefix_of_path()

bool path_is_prefix_of_path ( const char path1,
const char path2 
)

Definition at line 654 of file path.c.

655{
656 int path1_len = strlen(path1);
657
658 if (strncmp(path1, path2, path1_len) == 0 &&
659 (IS_DIR_SEP(path2[path1_len]) || path2[path1_len] == '\0'))
660 return true;
661 return false;
662}

References fb(), and IS_DIR_SEP.

Referenced by convert_and_check_filename(), create_script_for_old_cluster_deletion(), CreateTableSpace(), and parseCommandLine().

◆ path_is_relative_and_below_cwd()

bool path_is_relative_and_below_cwd ( const char path)

Definition at line 604 of file path.c.

605{
606 if (is_absolute_path(path))
607 return false;
608 /* don't allow anything above the cwd */
609 else if (path_contains_parent_reference(path))
610 return false;
611#ifdef WIN32
612
613 /*
614 * On Win32, a drive letter _not_ followed by a slash, e.g. 'E:abc', is
615 * relative to the cwd on that drive, or the drive's root directory if
616 * that drive has no cwd. Because the path itself cannot tell us which is
617 * the case, we have to assume the worst, i.e. that it is not below the
618 * cwd. We could use GetFullPathName() to find the full path but that
619 * could change if the current directory for the drive changes underneath
620 * us, so we just disallow it.
621 */
622 else if (isalpha((unsigned char) path[0]) && path[1] == ':' &&
623 !IS_DIR_SEP(path[2]))
624 return false;
625#endif
626 else
627 return true;
628}
bool path_contains_parent_reference(const char *path)
Definition path.c:577

References fb(), is_absolute_path, IS_DIR_SEP, and path_contains_parent_reference().

Referenced by convert_and_check_filename(), and path_is_safe_for_extraction().

◆ path_is_safe_for_extraction()

bool path_is_safe_for_extraction ( const char path)

◆ trim_directory()

static char * trim_directory ( char path)
static

Definition at line 1102 of file path.c.

1103{
1104 char *p;
1105
1106 path = skip_drive(path);
1107
1108 if (path[0] == '\0')
1109 return path;
1110
1111 /* back up over trailing slash(es) */
1112 for (p = path + strlen(path) - 1; IS_DIR_SEP(*p) && p > path; p--)
1113 ;
1114 /* back up over directory name */
1115 for (; !IS_DIR_SEP(*p) && p > path; p--)
1116 ;
1117 /* if multiple slashes before directory name, remove 'em all */
1118 for (; p > path && IS_DIR_SEP(*(p - 1)); p--)
1119 ;
1120 /* don't erase a leading slash */
1121 if (p == path && IS_DIR_SEP(*p))
1122 p++;
1123 *p = '\0';
1124 return p;
1125}

References fb(), IS_DIR_SEP, and skip_drive.

Referenced by canonicalize_path_enc(), get_parent_directory(), and make_relative_path().

◆ trim_trailing_separator()

static void trim_trailing_separator ( char path)
static

Definition at line 1134 of file path.c.

1135{
1136 char *p;
1137
1138 path = skip_drive(path);
1139 p = path + strlen(path);
1140 if (p > path)
1141 for (p--; p > path && IS_DIR_SEP(*p); p--)
1142 *p = '\0';
1143}

References fb(), IS_DIR_SEP, and skip_drive.

Referenced by canonicalize_path_enc(), and make_relative_path().