PostgreSQL Source Code  git master
path.c File Reference
#include "postgres.h"
#include <ctype.h>
#include <sys/stat.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 42 of file path.c.

◆ skip_drive

#define skip_drive (   path)    (path)

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

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

Function Documentation

◆ append_subdir_to_path()

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

Definition at line 1048 of file path.c.

1049 {
1050  size_t len = strlen(subdir);
1051 
1052  /* No need to copy data if path and subdir are the same. */
1053  if (path != subdir)
1054  memmove(path, subdir, len);
1055 
1056  return path + len;
1057 }
const void size_t len

References len.

Referenced by canonicalize_path().

◆ canonicalize_path()

void canonicalize_path ( char *  path)

Definition at line 264 of file path.c.

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

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 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(), main(), make_absolute_path(), make_relative_path(), parseCommandLine(), process_file(), resolve_symlinks(), setup(), setup_bin_paths(), setup_pgdata(), SplitDirectoriesString(), tablespace_list_append(), test_canonicalize_path(), and tokenize_inc_file().

◆ cleanup_path()

void cleanup_path ( char *  path)

Definition at line 186 of file path.c.

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

References MAXPGPATH.

Referenced by get_configdata().

◆ dir_strcmp()

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

Definition at line 612 of file path.c.

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

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

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

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

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:76
static void make_relative_path(char *ret_path, const char *target_path, const char *bin_path, const char *my_exec_path)
Definition: path.c:660

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 == NULL || home[0] == '\0')
939  return pg_get_user_home_dir(geteuid(), ret_path, MAXPGPATH);
940  strlcpy(ret_path, home, MAXPGPATH);
941  return true;
942 #else
943  char *tmppath;
944 
945  /*
946  * Note: We use getenv() here because the more modern SHGetFolderPath()
947  * would force the backend to link with shell32.lib, which eats valuable
948  * desktop heap. XXX This function is used only in psql, which already
949  * brings in shell32 via libpq. Moving this function to its own file
950  * would keep it out of the backend, freeing it from this concern.
951  */
952  tmppath = getenv("APPDATA");
953  if (!tmppath)
954  return false;
955  snprintf(ret_path, MAXPGPATH, "%s/postgresql", tmppath);
956  return true;
957 #endif
958 }
bool pg_get_user_home_dir(uid_t user_id, char *buffer, size_t buflen)
Definition: thread.c:121
#define snprintf
Definition: port.h:225
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45

References MAXPGPATH, pg_get_user_home_dir(), 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 574 of file path.c.

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

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

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

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

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

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

Referenced by find_my_exec(), main(), make_relative_path(), process_file(), resolve_symlinks(), and tokenize_inc_file().

◆ last_dir_separator()

char* last_dir_separator ( const char *  filename)

Definition at line 139 of file path.c.

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

References filename, IS_DIR_SEP, skip_drive, and unconstify.

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

◆ make_absolute_path()

char* make_absolute_path ( const char *  path)

Definition at line 729 of file path.c.

730 {
731  char *new;
732 
733  /* Returning null for null input is convenient for some callers */
734  if (path == NULL)
735  return NULL;
736 
737  if (!is_absolute_path(path))
738  {
739  char *buf;
740  size_t buflen;
741 
742  buflen = MAXPGPATH;
743  for (;;)
744  {
745  buf = malloc(buflen);
746  if (!buf)
747  {
748 #ifndef FRONTEND
749  ereport(ERROR,
750  (errcode(ERRCODE_OUT_OF_MEMORY),
751  errmsg("out of memory")));
752 #else
753  fprintf(stderr, _("out of memory\n"));
754  return NULL;
755 #endif
756  }
757 
758  if (getcwd(buf, buflen))
759  break;
760  else if (errno == ERANGE)
761  {
762  free(buf);
763  buflen *= 2;
764  continue;
765  }
766  else
767  {
768  int save_errno = errno;
769 
770  free(buf);
771  errno = save_errno;
772 #ifndef FRONTEND
773  elog(ERROR, "could not get current working directory: %m");
774 #else
775  fprintf(stderr, _("could not get current working directory: %s\n"),
776  strerror(errno));
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
787  ereport(ERROR,
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
804  ereport(ERROR,
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 */
815  canonicalize_path(new);
816 
817  return new;
818 }
int errcode(int sqlerrcode)
Definition: elog.c:693
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define _(x)
Definition: elog.c:89
#define ERROR
Definition: elog.h:33
#define elog(elevel,...)
Definition: elog.h:218
#define ereport(elevel,...)
Definition: elog.h:143
#define free(a)
Definition: header.h:65
#define malloc(a)
Definition: header.h:50
void canonicalize_path(char *path)
Definition: path.c:264
static char * buf
Definition: pg_test_fsync.c:67
#define is_absolute_path(filename)
Definition: port.h:89
#define sprintf
Definition: port.h:227
#define strerror
Definition: port.h:238

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

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

◆ make_native_path()

void make_native_path ( char *  filename)

Definition at line 167 of file path.c.

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

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

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

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

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

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

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

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

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

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

995 {
996  char *p;
997 
998  path = skip_drive(path);
999 
1000  if (path[0] == '\0')
1001  return path;
1002 
1003  /* back up over trailing slash(es) */
1004  for (p = path + strlen(path) - 1; IS_DIR_SEP(*p) && p > path; p--)
1005  ;
1006  /* back up over directory name */
1007  for (; !IS_DIR_SEP(*p) && p > path; p--)
1008  ;
1009  /* if multiple slashes before directory name, remove 'em all */
1010  for (; p > path && IS_DIR_SEP(*(p - 1)); p--)
1011  ;
1012  /* don't erase a leading slash */
1013  if (p == path && IS_DIR_SEP(*p))
1014  p++;
1015  *p = '\0';
1016  return p;
1017 }

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

1027 {
1028  char *p;
1029 
1030  path = skip_drive(path);
1031  p = path + strlen(path);
1032  if (p > path)
1033  for (p--; p > path && IS_DIR_SEP(*p); p--)
1034  *p = '\0';
1035 }

References IS_DIR_SEP, and skip_drive.

Referenced by canonicalize_path(), and make_relative_path().