PostgreSQL Source Code git master
path.c File Reference
#include "postgres.h"
#include <ctype.h>
#include <sys/stat.h>
#include <pwd.h>
#include <unistd.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 char * trim_directory (char *path)
 
static void trim_trailing_separator (char *path)
 
static char * append_subdir_to_path (char *path, char *subdir)
 
bool has_drive_prefix (const char *path)
 
char * first_dir_separator (const char *filename)
 
char * first_path_var_separator (const char *pathlist)
 
char * last_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)
 
bool path_contains_parent_reference (const char *path)
 
bool path_is_relative_and_below_cwd (const char *path)
 
bool path_is_prefix_of_path (const char *path1, const char *path2)
 
const char * get_progname (const char *argv0)
 
static int dir_strcmp (const char *s1, const char *s2)
 
char * make_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 43 of file path.c.

◆ skip_drive

#define skip_drive (   path)    (path)

Definition at line 80 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 243 of file path.c.

244{
245 ABSOLUTE_PATH_INIT, /* Just past the leading '/' (and Windows
246 * drive name if any) of an absolute path */
247 ABSOLUTE_WITH_N_DEPTH, /* We collected 'pathdepth' directories in an
248 * absolute path */
249 RELATIVE_PATH_INIT, /* At start of a relative path */
250 RELATIVE_WITH_N_DEPTH, /* We collected 'pathdepth' directories in a
251 * relative path */
252 RELATIVE_WITH_PARENT_REF, /* Relative path containing only double-dots */
canonicalize_state
Definition: path.c:244
@ ABSOLUTE_WITH_N_DEPTH
Definition: path.c:247
@ RELATIVE_WITH_N_DEPTH
Definition: path.c:250
@ ABSOLUTE_PATH_INIT
Definition: path.c:245
@ RELATIVE_PATH_INIT
Definition: path.c:249
@ RELATIVE_WITH_PARENT_REF
Definition: path.c:252

Function Documentation

◆ append_subdir_to_path()

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

Definition at line 1062 of file path.c.

1063{
1064 size_t len = strlen(subdir);
1065
1066 /* No need to copy data if path and subdir are the same. */
1067 if (path != subdir)
1068 memmove(path, subdir, len);
1069
1070 return path + len;
1071}
const void size_t len

References len.

Referenced by canonicalize_path().

◆ canonicalize_path()

void canonicalize_path ( char *  path)

Definition at line 265 of file path.c.

266{
267 char *p,
268 *to_p;
269 char *spath;
270 char *parsed;
271 char *unparse;
272 bool was_sep = false;
274 int pathdepth = 0; /* counts collected regular directory names */
275
276#ifdef WIN32
277
278 /*
279 * The Windows command processor will accept suitably quoted paths with
280 * forward slashes, but barfs badly with mixed forward and back slashes.
281 */
282 for (p = path; *p; p++)
283 {
284 if (*p == '\\')
285 *p = '/';
286 }
287
288 /*
289 * In Win32, if you do: prog.exe "a b" "\c\d\" the system will pass \c\d"
290 * as argv[2], so trim off trailing quote.
291 */
292 if (p > path && *(p - 1) == '"')
293 *(p - 1) = '/';
294#endif
295
296 /*
297 * Removing the trailing slash on a path means we never get ugly double
298 * trailing slashes. Also, Win32 can't stat() a directory with a trailing
299 * slash. Don't remove a leading slash, though.
300 */
302
303 /*
304 * Remove duplicate adjacent separators
305 */
306 p = path;
307#ifdef WIN32
308 /* Don't remove leading double-slash on Win32 */
309 if (*p)
310 p++;
311#endif
312 to_p = p;
313 for (; *p; p++, to_p++)
314 {
315 /* Handle many adjacent slashes, like "/a///b" */
316 while (*p == '/' && was_sep)
317 p++;
318 if (to_p != p)
319 *to_p = *p;
320 was_sep = (*p == '/');
321 }
322 *to_p = '\0';
323
324 /*
325 * Remove any uses of "." and process ".." ourselves
326 *
327 * Note that "/../.." should reduce to just "/", while "../.." has to be
328 * kept as-is. Also note that we want a Windows drive spec to be visible
329 * to trim_directory(), but it's not part of the logic that's looking at
330 * the name components; hence distinction between path and spath.
331 *
332 * This loop overwrites the path in-place. This is safe since we'll never
333 * make the path longer. "unparse" points to where we are reading the
334 * path, "parse" to where we are writing.
335 */
336 spath = skip_drive(path);
337 if (*spath == '\0')
338 return; /* empty path is returned as-is */
339
340 if (*spath == '/')
341 {
343 /* Skip the leading slash for absolute path */
344 parsed = unparse = (spath + 1);
345 }
346 else
347 {
349 parsed = unparse = spath;
350 }
351
352 while (*unparse != '\0')
353 {
354 char *unparse_next;
355 bool is_double_dot;
356
357 /* Split off this dir name, and set unparse_next to the next one */
358 unparse_next = unparse;
359 while (*unparse_next && *unparse_next != '/')
360 unparse_next++;
361 if (*unparse_next != '\0')
362 *unparse_next++ = '\0';
363
364 /* Identify type of this dir name */
365 if (strcmp(unparse, ".") == 0)
366 {
367 /* We can ignore "." components in all cases */
368 unparse = unparse_next;
369 continue;
370 }
371
372 if (strcmp(unparse, "..") == 0)
373 is_double_dot = true;
374 else
375 {
376 /* adjacent separators were eliminated above */
377 Assert(*unparse != '\0');
378 is_double_dot = false;
379 }
380
381 switch (state)
382 {
384 /* We can ignore ".." immediately after / */
385 if (!is_double_dot)
386 {
387 /* Append first dir name (we already have leading slash) */
388 parsed = append_subdir_to_path(parsed, unparse);
390 pathdepth++;
391 }
392 break;
394 if (is_double_dot)
395 {
396 /* Remove last parsed dir */
397 /* (trim_directory won't remove the leading slash) */
398 *parsed = '\0';
399 parsed = trim_directory(path);
400 if (--pathdepth == 0)
402 }
403 else
404 {
405 /* Append normal dir */
406 *parsed++ = '/';
407 parsed = append_subdir_to_path(parsed, unparse);
408 pathdepth++;
409 }
410 break;
412 if (is_double_dot)
413 {
414 /* Append irreducible double-dot (..) */
415 parsed = append_subdir_to_path(parsed, unparse);
417 }
418 else
419 {
420 /* Append normal dir */
421 parsed = append_subdir_to_path(parsed, unparse);
423 pathdepth++;
424 }
425 break;
427 if (is_double_dot)
428 {
429 /* Remove last parsed dir */
430 *parsed = '\0';
431 parsed = trim_directory(path);
432 if (--pathdepth == 0)
433 {
434 /*
435 * If the output path is now empty, we're back to the
436 * INIT state. However, we could have processed a
437 * path like "../dir/.." and now be down to "..", in
438 * which case enter the correct state for that.
439 */
440 if (parsed == spath)
442 else
444 }
445 }
446 else
447 {
448 /* Append normal dir */
449 *parsed++ = '/';
450 parsed = append_subdir_to_path(parsed, unparse);
451 pathdepth++;
452 }
453 break;
455 if (is_double_dot)
456 {
457 /* Append next irreducible double-dot (..) */
458 *parsed++ = '/';
459 parsed = append_subdir_to_path(parsed, unparse);
460 }
461 else
462 {
463 /* Append normal dir */
464 *parsed++ = '/';
465 parsed = append_subdir_to_path(parsed, unparse);
466
467 /*
468 * We can now start counting normal dirs. But if later
469 * double-dots make us remove this dir again, we'd better
470 * revert to RELATIVE_WITH_PARENT_REF not INIT state.
471 */
473 pathdepth = 1;
474 }
475 break;
476 }
477
478 unparse = unparse_next;
479 }
480
481 /*
482 * If our output path is empty at this point, insert ".". We don't want
483 * to do this any earlier because it'd result in an extra dot in corner
484 * cases such as "../dir/..". Since we rejected the wholly-empty-path
485 * case above, there is certainly room.
486 */
487 if (parsed == spath)
488 *parsed++ = '.';
489
490 /* And finally, ensure the output path is nul-terminated. */
491 *parsed = '\0';
492}
#define Assert(condition)
Definition: c.h:815
static char * append_subdir_to_path(char *path, char *subdir)
Definition: path.c:1062
static void trim_trailing_separator(char *path)
Definition: path.c:1040
static char * trim_directory(char *path)
Definition: path.c:1008
#define skip_drive(path)
Definition: path.c:80
Definition: regguts.h:323

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

Referenced by AbsoluteConfigLocation(), add_tablespace_mapping(), adjust_data_dir(), check_canonical_path(), check_required_directory(), convert_and_check_filename(), create_script_for_old_cluster_deletion(), create_xlog_or_symlink(), CreateTableSpace(), do_copy(), exec_command_edit(), exec_command_write(), find_in_dynamic_libpath(), find_my_exec(), find_other_exec(), get_tablespace_mapping(), GetConfFilesInDir(), main(), make_absolute_path(), make_relative_path(), member_verify_header(), normalize_exec_path(), parseCommandLine(), process_file(), scan_for_existing_tablespaces(), setup(), setup_bin_paths(), setup_pgdata(), SplitDirectoriesString(), tablespace_list_append(), and test_canonicalize_path().

◆ cleanup_path()

void cleanup_path ( char *  path)

Definition at line 187 of file path.c.

188{
189#ifdef WIN32
190 char *ptr;
191
192 /*
193 * GetShortPathName() will fail if the path does not exist, or short names
194 * are disabled on this file system. In both cases, we just return the
195 * original path. This is particularly useful for --sysconfdir, which
196 * might not exist.
197 */
198 GetShortPathName(path, path, MAXPGPATH - 1);
199
200 /* Replace '\' with '/' */
201 for (ptr = path; *ptr; ptr++)
202 {
203 if (*ptr == '\\')
204 *ptr = '/';
205 }
206#endif
207}
#define MAXPGPATH

References MAXPGPATH.

Referenced by get_configdata().

◆ dir_strcmp()

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

Definition at line 613 of file path.c.

614{
615 while (*s1 && *s2)
616 {
617 if (
618#ifndef WIN32
619 *s1 != *s2
620#else
621 /* On windows, paths are case-insensitive */
622 pg_tolower((unsigned char) *s1) != pg_tolower((unsigned char) *s2)
623#endif
624 && !(IS_DIR_SEP(*s1) && IS_DIR_SEP(*s2)))
625 return (int) *s1 - (int) *s2;
626 s1++, s2++;
627 }
628 if (*s1)
629 return 1; /* s1 longer */
630 if (*s2)
631 return -1; /* s2 longer */
632 return 0;
633}
unsigned char pg_tolower(unsigned char ch)
Definition: pgstrcasecmp.c:122
#define IS_DIR_SEP(ch)
Definition: port.h:102
char * s1
char * s2

References 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 105 of file path.c.

106{
107 const char *p;
108
109 for (p = skip_drive(filename); *p; p++)
110 if (IS_DIR_SEP(*p))
111 return unconstify(char *, p);
112 return NULL;
113}
#define unconstify(underlying_type, expr)
Definition: c.h:1202
static char * filename
Definition: pg_dumpall.c:119

References 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_dynamic_libpath(), find_my_exec(), load_libraries(), and substitute_libpath_macro().

◆ first_path_var_separator()

char * first_path_var_separator ( const char *  pathlist)

Definition at line 122 of file path.c.

123{
124 const char *p;
125
126 /* skip_drive is not needed */
127 for (p = pathlist; *p; p++)
128 if (IS_PATH_VAR_SEP(*p))
129 return unconstify(char *, p);
130 return NULL;
131}
#define IS_PATH_VAR_SEP(ch)
Definition: path.c:43

References IS_PATH_VAR_SEP, and unconstify.

Referenced by find_in_dynamic_libpath(), and find_my_exec().

◆ get_doc_path()

void get_doc_path ( const char *  my_exec_path,
char *  ret_path 
)

Definition at line 897 of file path.c.

898{
899 make_relative_path(ret_path, DOCDIR, PGBINDIR, my_exec_path);
900}
char my_exec_path[MAXPGPATH]
Definition: globals.c:80
static void make_relative_path(char *ret_path, const char *target_path, const char *bin_path, const char *my_exec_path)
Definition: path.c:661

References 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 
)

Definition at line 834 of file path.c.

835{
836 make_relative_path(ret_path, SYSCONFDIR, PGBINDIR, my_exec_path);
837}

References make_relative_path(), and my_exec_path.

Referenced by get_configdata(), process_psqlrc(), and set_pglocale_pgservice().

◆ get_home_path()

bool get_home_path ( char *  ret_path)

Definition at line 928 of file path.c.

929{
930#ifndef WIN32
931 /*
932 * We first consult $HOME. If that's unset, try to get the info from
933 * <pwd.h>.
934 */
935 const char *home;
936
937 home = getenv("HOME");
938 if (home && home[0])
939 {
940 strlcpy(ret_path, home, MAXPGPATH);
941 return true;
942 }
943 else
944 {
945 struct passwd pwbuf;
946 struct passwd *pw;
947 char buf[1024];
948 int rc;
949
950 rc = getpwuid_r(geteuid(), &pwbuf, buf, sizeof buf, &pw);
951 if (rc != 0 || !pw)
952 return false;
953 strlcpy(ret_path, pw->pw_dir, MAXPGPATH);
954 return true;
955 }
956#else
957 char *tmppath;
958
959 /*
960 * Note: We use getenv() here because the more modern SHGetFolderPath()
961 * would force the backend to link with shell32.lib, which eats valuable
962 * desktop heap. XXX This function is used only in psql, which already
963 * brings in shell32 via libpq. Moving this function to its own file
964 * would keep it out of the backend, freeing it from this concern.
965 */
966 tmppath = getenv("APPDATA");
967 if (!tmppath)
968 return false;
969 snprintf(ret_path, MAXPGPATH, "%s/postgresql", tmppath);
970 return true;
971#endif
972}
static char * buf
Definition: pg_test_fsync.c:72
#define snprintf
Definition: port.h:238
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45

References buf, 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 906 of file path.c.

907{
908 make_relative_path(ret_path, HTMLDIR, PGBINDIR, my_exec_path);
909}

References 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 843 of file path.c.

844{
845 make_relative_path(ret_path, INCLUDEDIR, PGBINDIR, my_exec_path);
846}

References 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 861 of file path.c.

862{
863 make_relative_path(ret_path, INCLUDEDIRSERVER, PGBINDIR, my_exec_path);
864}

References 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 870 of file path.c.

871{
872 make_relative_path(ret_path, LIBDIR, PGBINDIR, my_exec_path);
873}

References 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 
)

Definition at line 888 of file path.c.

889{
890 make_relative_path(ret_path, LOCALEDIR, PGBINDIR, my_exec_path);
891}

References make_relative_path(), and my_exec_path.

Referenced by get_configdata(), pg_bindtextdomain(), and set_pglocale_pgservice().

◆ get_man_path()

void get_man_path ( const char *  my_exec_path,
char *  ret_path 
)

Definition at line 915 of file path.c.

916{
917 make_relative_path(ret_path, MANDIR, PGBINDIR, my_exec_path);
918}

References make_relative_path(), and my_exec_path.

Referenced by get_configdata().

◆ get_parent_directory()

void get_parent_directory ( char *  path)

◆ get_pkginclude_path()

void get_pkginclude_path ( const char *  my_exec_path,
char *  ret_path 
)

Definition at line 852 of file path.c.

853{
854 make_relative_path(ret_path, PKGINCLUDEDIR, PGBINDIR, my_exec_path);
855}

References 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 
)

Definition at line 879 of file path.c.

880{
881 make_relative_path(ret_path, PKGLIBDIR, PGBINDIR, my_exec_path);
882}

References make_relative_path(), and my_exec_path.

Referenced by get_configdata(), getInstallationPaths(), and InitStandaloneProcess().

◆ get_progname()

const char * get_progname ( const char *  argv0)

Definition at line 575 of file path.c.

576{
577 const char *nodir_name;
578 char *progname;
579
580 nodir_name = last_dir_separator(argv0);
581 if (nodir_name)
582 nodir_name++;
583 else
584 nodir_name = skip_drive(argv0);
585
586 /*
587 * Make a copy in case argv[0] is modified by ps_status. Leaks memory, but
588 * called only once.
589 */
590 progname = strdup(nodir_name);
591 if (progname == NULL)
592 {
593 fprintf(stderr, "%s: out of memory\n", nodir_name);
594 abort(); /* This could exit the postmaster */
595 }
596
597#if defined(__CYGWIN__) || defined(WIN32)
598 /* strip ".exe" suffix, regardless of case */
599 if (strlen(progname) > sizeof(EXE) - 1 &&
600 pg_strcasecmp(progname + strlen(progname) - (sizeof(EXE) - 1), EXE) == 0)
601 progname[strlen(progname) - (sizeof(EXE) - 1)] = '\0';
602#endif
603
604 return progname;
605}
#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:140
static char * argv0
Definition: pg_ctl.c:93
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
#define EXE
Definition: port.h:154

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

Referenced by get_opts(), handle_help_version_opts(), 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 89 of file path.c.

90{
91#ifdef WIN32
92 return skip_drive(path) != path;
93#else
94 return false;
95#endif
96}

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 220 of file path.c.

222{
223 if (ret_path != head)
224 strlcpy(ret_path, head, MAXPGPATH);
225
226 /*
227 * We used to try to simplify some cases involving "." and "..", but now
228 * we just leave that to be done by canonicalize_path() later.
229 */
230
231 if (*tail)
232 {
233 /* only separate with slash if head wasn't empty */
234 snprintf(ret_path + strlen(ret_path), MAXPGPATH - strlen(ret_path),
235 "%s%s",
236 (*(skip_drive(head)) != '\0') ? "/" : "",
237 tail);
238 }
239}

References 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 140 of file path.c.

141{
142 const char *p,
143 *ret = NULL;
144
145 for (p = skip_drive(filename); *p; p++)
146 if (IS_DIR_SEP(*p))
147 ret = p;
148 return unconstify(char *, ret);
149}

References filename, IS_DIR_SEP, skip_drive, and unconstify.

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

◆ make_absolute_path()

char * make_absolute_path ( const char *  path)

Definition at line 730 of file path.c.

731{
732 char *new;
733
734 /* Returning null for null input is convenient for some callers */
735 if (path == NULL)
736 return NULL;
737
738 if (!is_absolute_path(path))
739 {
740 char *buf;
741 size_t buflen;
742
743 buflen = MAXPGPATH;
744 for (;;)
745 {
746 buf = malloc(buflen);
747 if (!buf)
748 {
749#ifndef FRONTEND
751 (errcode(ERRCODE_OUT_OF_MEMORY),
752 errmsg("out of memory")));
753#else
754 fprintf(stderr, _("out of memory\n"));
755 return NULL;
756#endif
757 }
758
759 if (getcwd(buf, buflen))
760 break;
761 else if (errno == ERANGE)
762 {
763 free(buf);
764 buflen *= 2;
765 continue;
766 }
767 else
768 {
769 int save_errno = errno;
770
771 free(buf);
772 errno = save_errno;
773#ifndef FRONTEND
774 elog(ERROR, "could not get current working directory: %m");
775#else
776 fprintf(stderr, _("could not get current working directory: %m\n"));
777 return NULL;
778#endif
779 }
780 }
781
782 new = malloc(strlen(buf) + strlen(path) + 2);
783 if (!new)
784 {
785 free(buf);
786#ifndef FRONTEND
788 (errcode(ERRCODE_OUT_OF_MEMORY),
789 errmsg("out of memory")));
790#else
791 fprintf(stderr, _("out of memory\n"));
792 return NULL;
793#endif
794 }
795 sprintf(new, "%s/%s", buf, path);
796 free(buf);
797 }
798 else
799 {
800 new = strdup(path);
801 if (!new)
802 {
803#ifndef FRONTEND
805 (errcode(ERRCODE_OUT_OF_MEMORY),
806 errmsg("out of memory")));
807#else
808 fprintf(stderr, _("out of memory\n"));
809 return NULL;
810#endif
811 }
812 }
813
814 /* Make sure punctuation is canonical, too */
816
817 return new;
818}
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define _(x)
Definition: elog.c:90
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#define ereport(elevel,...)
Definition: elog.h:149
#define free(a)
Definition: header.h:65
#define malloc(a)
Definition: header.h:50
void canonicalize_path(char *path)
Definition: path.c:265
#define is_absolute_path(filename)
Definition: port.h:103
#define sprintf
Definition: port.h:240

References _, buf, canonicalize_path(), elog, ereport, errcode(), errmsg(), ERROR, 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 168 of file path.c.

169{
170#ifdef WIN32
171 char *p;
172
173 for (p = filename; *p; p++)
174 if (*p == '/')
175 *p = '\\';
176#endif
177}

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 661 of file path.c.

663{
664 int prefix_len;
665 int tail_start;
666 int tail_len;
667 int i;
668
669 /*
670 * Determine the common prefix --- note we require it to end on a
671 * directory separator, consider eg '/usr/lib' and '/usr/libexec'.
672 */
673 prefix_len = 0;
674 for (i = 0; target_path[i] && bin_path[i]; i++)
675 {
676 if (IS_DIR_SEP(target_path[i]) && IS_DIR_SEP(bin_path[i]))
677 prefix_len = i + 1;
678 else if (target_path[i] != bin_path[i])
679 break;
680 }
681 if (prefix_len == 0)
682 goto no_match; /* no common prefix? */
683 tail_len = strlen(bin_path) - prefix_len;
684
685 /*
686 * Set up my_exec_path without the actual executable name, and
687 * canonicalize to simplify comparison to bin_path.
688 */
689 strlcpy(ret_path, my_exec_path, MAXPGPATH);
690 trim_directory(ret_path); /* remove my executable name */
691 canonicalize_path(ret_path);
692
693 /*
694 * Tail match?
695 */
696 tail_start = (int) strlen(ret_path) - tail_len;
697 if (tail_start > 0 &&
698 IS_DIR_SEP(ret_path[tail_start - 1]) &&
699 dir_strcmp(ret_path + tail_start, bin_path + prefix_len) == 0)
700 {
701 ret_path[tail_start] = '\0';
702 trim_trailing_separator(ret_path);
703 join_path_components(ret_path, ret_path, target_path + prefix_len);
704 canonicalize_path(ret_path);
705 return;
706 }
707
708no_match:
709 strlcpy(ret_path, target_path, MAXPGPATH);
710 canonicalize_path(ret_path);
711}
static char bin_path[MAXPGPATH]
Definition: initdb.c:258
int i
Definition: isn.c:72
void join_path_components(char *ret_path, const char *head, const char *tail)
Definition: path.c:220
static int dir_strcmp(const char *s1, const char *s2)
Definition: path.c:613

References bin_path, canonicalize_path(), dir_strcmp(), 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 500 of file path.c.

501{
502 /*
503 * Once canonicalized, an absolute path cannot contain any ".." at all,
504 * while a relative path could contain ".."(s) only at the start. So it
505 * is sufficient to check the start of the path, after skipping any
506 * Windows drive/network specifier.
507 */
508 path = skip_drive(path); /* C: shouldn't affect our conclusion */
509
510 if (path[0] == '.' &&
511 path[1] == '.' &&
512 (path[2] == '\0' || path[2] == '/'))
513 return true;
514
515 return false;
516}

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 560 of file path.c.

561{
562 int path1_len = strlen(path1);
563
564 if (strncmp(path1, path2, path1_len) == 0 &&
565 (IS_DIR_SEP(path2[path1_len]) || path2[path1_len] == '\0'))
566 return true;
567 return false;
568}

References 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 527 of file path.c.

528{
529 if (is_absolute_path(path))
530 return false;
531 /* don't allow anything above the cwd */
532 else if (path_contains_parent_reference(path))
533 return false;
534#ifdef WIN32
535
536 /*
537 * On Win32, a drive letter _not_ followed by a slash, e.g. 'E:abc', is
538 * relative to the cwd on that drive, or the drive's root directory if
539 * that drive has no cwd. Because the path itself cannot tell us which is
540 * the case, we have to assume the worst, i.e. that it is not below the
541 * cwd. We could use GetFullPathName() to find the full path but that
542 * could change if the current directory for the drive changes underneath
543 * us, so we just disallow it.
544 */
545 else if (isalpha((unsigned char) path[0]) && path[1] == ':' &&
546 !IS_DIR_SEP(path[2]))
547 return false;
548#endif
549 else
550 return true;
551}
bool path_contains_parent_reference(const char *path)
Definition: path.c:500

References is_absolute_path, IS_DIR_SEP, and path_contains_parent_reference().

Referenced by convert_and_check_filename().

◆ trim_directory()

static char * trim_directory ( char *  path)
static

Definition at line 1008 of file path.c.

1009{
1010 char *p;
1011
1012 path = skip_drive(path);
1013
1014 if (path[0] == '\0')
1015 return path;
1016
1017 /* back up over trailing slash(es) */
1018 for (p = path + strlen(path) - 1; IS_DIR_SEP(*p) && p > path; p--)
1019 ;
1020 /* back up over directory name */
1021 for (; !IS_DIR_SEP(*p) && p > path; p--)
1022 ;
1023 /* if multiple slashes before directory name, remove 'em all */
1024 for (; p > path && IS_DIR_SEP(*(p - 1)); p--)
1025 ;
1026 /* don't erase a leading slash */
1027 if (p == path && IS_DIR_SEP(*p))
1028 p++;
1029 *p = '\0';
1030 return p;
1031}

References IS_DIR_SEP, and skip_drive.

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

◆ trim_trailing_separator()

static void trim_trailing_separator ( char *  path)
static

Definition at line 1040 of file path.c.

1041{
1042 char *p;
1043
1044 path = skip_drive(path);
1045 p = path + strlen(path);
1046 if (p > path)
1047 for (p--; p > path && IS_DIR_SEP(*p); p--)
1048 *p = '\0';
1049}

References IS_DIR_SEP, and skip_drive.

Referenced by canonicalize_path(), and make_relative_path().