Skip to content

Commit bffe45a

Browse files
committed
Simplify relative-path logic, on the assumption that compiled-in paths
won't have trivial differences in their common prefix.
1 parent 04baa0e commit bffe45a

File tree

1 file changed

+65
-163
lines changed

1 file changed

+65
-163
lines changed

src/port/path.c

Lines changed: 65 additions & 163 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/port/path.c,v 1.43 2004/11/06 04:24:14 tgl Exp $
11+
* $PostgreSQL: pgsql/src/port/path.c,v 1.44 2004/11/06 21:39:45 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -32,17 +32,11 @@
3232
#define IS_PATH_SEP(ch) ((ch) == ';')
3333
#endif
3434

35-
static const char *relative_path(const char *bin_path, const char *other_path);
36-
static void make_relative(const char *my_exec_path, const char *p, char *ret_path);
35+
static void make_relative_path(char *ret_path, const char *target_path,
36+
const char *bin_path, const char *my_exec_path);
3737
static void trim_directory(char *path);
3838
static void trim_trailing_separator(char *path);
3939

40-
/* Move to last of consecutive separators or to null byte */
41-
#define MOVE_TO_SEP_END(p) \
42-
{ \
43-
while (IS_DIR_SEP((p)[0]) && (IS_DIR_SEP((p)[1]) || !(p)[1])) \
44-
(p)++; \
45-
}
4640

4741
/*
4842
* skip_drive
@@ -252,11 +246,11 @@ canonicalize_path(char *path)
252246
{
253247
int len = strlen(path);
254248

255-
if (len >= 2 && strcmp(path + len - 2, "/.") == 0)
249+
if (len > 2 && strcmp(path + len - 2, "/.") == 0)
256250
{
257251
trim_directory(path);
258252
}
259-
else if (len >= 3 && strcmp(path + len - 3, "/..") == 0)
253+
else if (len > 3 && strcmp(path + len - 3, "/..") == 0)
260254
{
261255
trim_directory(path);
262256
trim_directory(path); /* remove directory above */
@@ -305,132 +299,123 @@ get_progname(const char *argv0)
305299

306300

307301
/*
308-
* get_share_path
302+
* make_relative_path - make a path relative to the actual binary location
303+
*
304+
* This function exists to support relocation of installation trees.
305+
*
306+
* ret_path is the output area (must be of size MAXPGPATH)
307+
* target_path is the compiled-in path to the directory we want to find
308+
* bin_path is the compiled-in path to the directory of executables
309+
* my_exec_path is the actual location of my executable
310+
*
311+
* If target_path matches bin_path up to the last directory component of
312+
* bin_path, then we build the result as my_exec_path (less the executable
313+
* name and last directory) joined to the non-matching part of target_path.
314+
* Otherwise, we return target_path as-is.
315+
*
316+
* For example:
317+
* target_path = '/usr/local/share/postgresql'
318+
* bin_path = '/usr/local/bin'
319+
* my_exec_path = '/opt/pgsql/bin/postmaster'
320+
* Given these inputs we would return '/opt/pgsql/share/postgresql'
309321
*/
310-
void
311-
get_share_path(const char *my_exec_path, char *ret_path)
322+
static void
323+
make_relative_path(char *ret_path, const char *target_path,
324+
const char *bin_path, const char *my_exec_path)
312325
{
313-
const char *p;
326+
const char *bin_end;
327+
int prefix_len;
328+
329+
bin_end = last_dir_separator(bin_path);
330+
if (!bin_end)
331+
goto no_match;
332+
prefix_len = bin_end - bin_path + 1;
333+
if (strncmp(target_path, bin_path, prefix_len) != 0)
334+
goto no_match;
335+
336+
StrNCpy(ret_path, my_exec_path, MAXPGPATH);
337+
trim_directory(ret_path); /* remove my executable name */
338+
trim_directory(ret_path); /* remove last directory component (/bin) */
339+
join_path_components(ret_path, ret_path, target_path + prefix_len);
340+
canonicalize_path(ret_path);
341+
return;
314342

315-
if ((p = relative_path(PGBINDIR, PGSHAREDIR)))
316-
make_relative(my_exec_path, p, ret_path);
317-
else
318-
StrNCpy(ret_path, PGSHAREDIR, MAXPGPATH);
343+
no_match:
344+
StrNCpy(ret_path, target_path, MAXPGPATH);
319345
canonicalize_path(ret_path);
320346
}
321347

322348

349+
/*
350+
* get_share_path
351+
*/
352+
void
353+
get_share_path(const char *my_exec_path, char *ret_path)
354+
{
355+
make_relative_path(ret_path, PGSHAREDIR, PGBINDIR, my_exec_path);
356+
}
357+
323358
/*
324359
* get_etc_path
325360
*/
326361
void
327362
get_etc_path(const char *my_exec_path, char *ret_path)
328363
{
329-
const char *p;
330-
331-
if ((p = relative_path(PGBINDIR, SYSCONFDIR)))
332-
make_relative(my_exec_path, p, ret_path);
333-
else
334-
StrNCpy(ret_path, SYSCONFDIR, MAXPGPATH);
335-
canonicalize_path(ret_path);
364+
make_relative_path(ret_path, SYSCONFDIR, PGBINDIR, my_exec_path);
336365
}
337366

338-
339367
/*
340368
* get_include_path
341369
*/
342370
void
343371
get_include_path(const char *my_exec_path, char *ret_path)
344372
{
345-
const char *p;
346-
347-
if ((p = relative_path(PGBINDIR, INCLUDEDIR)))
348-
make_relative(my_exec_path, p, ret_path);
349-
else
350-
StrNCpy(ret_path, INCLUDEDIR, MAXPGPATH);
351-
canonicalize_path(ret_path);
373+
make_relative_path(ret_path, INCLUDEDIR, PGBINDIR, my_exec_path);
352374
}
353375

354-
355376
/*
356377
* get_pkginclude_path
357378
*/
358379
void
359380
get_pkginclude_path(const char *my_exec_path, char *ret_path)
360381
{
361-
const char *p;
362-
363-
if ((p = relative_path(PGBINDIR, PKGINCLUDEDIR)))
364-
make_relative(my_exec_path, p, ret_path);
365-
else
366-
StrNCpy(ret_path, PKGINCLUDEDIR, MAXPGPATH);
367-
canonicalize_path(ret_path);
382+
make_relative_path(ret_path, PKGINCLUDEDIR, PGBINDIR, my_exec_path);
368383
}
369384

370-
371385
/*
372386
* get_includeserver_path
373387
*/
374388
void
375389
get_includeserver_path(const char *my_exec_path, char *ret_path)
376390
{
377-
const char *p;
378-
379-
if ((p = relative_path(PGBINDIR, INCLUDEDIRSERVER)))
380-
make_relative(my_exec_path, p, ret_path);
381-
else
382-
StrNCpy(ret_path, INCLUDEDIRSERVER, MAXPGPATH);
383-
canonicalize_path(ret_path);
391+
make_relative_path(ret_path, INCLUDEDIRSERVER, PGBINDIR, my_exec_path);
384392
}
385393

386-
387394
/*
388395
* get_lib_path
389396
*/
390397
void
391398
get_lib_path(const char *my_exec_path, char *ret_path)
392399
{
393-
const char *p;
394-
395-
if ((p = relative_path(PGBINDIR, LIBDIR)))
396-
make_relative(my_exec_path, p, ret_path);
397-
else
398-
StrNCpy(ret_path, LIBDIR, MAXPGPATH);
399-
canonicalize_path(ret_path);
400+
make_relative_path(ret_path, LIBDIR, PGBINDIR, my_exec_path);
400401
}
401402

402-
403403
/*
404404
* get_pkglib_path
405405
*/
406406
void
407407
get_pkglib_path(const char *my_exec_path, char *ret_path)
408408
{
409-
const char *p;
410-
411-
if ((p = relative_path(PGBINDIR, PKGLIBDIR)))
412-
make_relative(my_exec_path, p, ret_path);
413-
else
414-
StrNCpy(ret_path, PKGLIBDIR, MAXPGPATH);
415-
canonicalize_path(ret_path);
409+
make_relative_path(ret_path, PKGLIBDIR, PGBINDIR, my_exec_path);
416410
}
417411

418-
419412
/*
420413
* get_locale_path
421-
*
422-
* Return locale path, either relative to /bin or hardcoded
423414
*/
424415
void
425416
get_locale_path(const char *my_exec_path, char *ret_path)
426417
{
427-
const char *p;
428-
429-
if ((p = relative_path(PGBINDIR, LOCALEDIR)))
430-
make_relative(my_exec_path, p, ret_path);
431-
else
432-
StrNCpy(ret_path, LOCALEDIR, MAXPGPATH);
433-
canonicalize_path(ret_path);
418+
make_relative_path(ret_path, LOCALEDIR, PGBINDIR, my_exec_path);
434419
}
435420

436421

@@ -440,14 +425,16 @@ get_locale_path(const char *my_exec_path, char *ret_path)
440425
bool
441426
get_home_path(char *ret_path)
442427
{
443-
if (getenv(HOMEDIR) == NULL)
428+
const char *homedir = getenv(HOMEDIR);
429+
430+
if (homedir == NULL)
444431
{
445432
*ret_path = '\0';
446433
return false;
447434
}
448435
else
449436
{
450-
StrNCpy(ret_path, getenv(HOMEDIR), MAXPGPATH);
437+
StrNCpy(ret_path, homedir, MAXPGPATH);
451438
canonicalize_path(ret_path);
452439
return true;
453440
}
@@ -515,91 +502,6 @@ set_pglocale_pgservice(const char *argv0, const char *app)
515502
}
516503

517504

518-
/*
519-
* make_relative - adjust path to be relative to bin/
520-
*
521-
* ret_path is the output area (must be of size MAXPGPATH)
522-
*/
523-
static void
524-
make_relative(const char *my_exec_path, const char *p, char *ret_path)
525-
{
526-
char path[MAXPGPATH];
527-
528-
StrNCpy(path, my_exec_path, MAXPGPATH);
529-
trim_directory(path); /* remove my executable name */
530-
trim_directory(path); /* remove last directory component (/bin) */
531-
join_path_components(ret_path, path, p);
532-
}
533-
534-
535-
/*
536-
* relative_path
537-
*
538-
* Do the supplied paths differ only in their last component?
539-
*/
540-
static const char *
541-
relative_path(const char *bin_path, const char *other_path)
542-
{
543-
#ifdef WIN32
544-
/* Driver letters match? */
545-
if (isalpha(*bin_path) && bin_path[1] == ':' &&
546-
(!isalpha(*other_path) || !other_path[1] == ':'))
547-
return NULL;
548-
if ((!isalpha(*bin_path) || !bin_path[1] == ':') &&
549-
(isalpha(*other_path) && other_path[1] == ':'))
550-
return NULL;
551-
if (isalpha(*bin_path) && bin_path[1] == ':' &&
552-
isalpha(*other_path) && other_path[1] == ':')
553-
{
554-
if (toupper(*bin_path) != toupper(*other_path))
555-
return NULL;
556-
bin_path += 2;
557-
other_path += 2;
558-
}
559-
#endif
560-
561-
while (1)
562-
{
563-
/* Move past adjacent slashes like //, and trailing ones */
564-
MOVE_TO_SEP_END(bin_path);
565-
MOVE_TO_SEP_END(other_path);
566-
567-
/* One of the paths is done? */
568-
if (!*bin_path || !*other_path)
569-
break;
570-
571-
/* Win32 filesystem is case insensitive */
572-
if ((!IS_DIR_SEP(*bin_path) || !IS_DIR_SEP(*other_path)) &&
573-
#ifndef WIN32
574-
*bin_path != *other_path
575-
#else
576-
toupper((unsigned char) *bin_path) != toupper((unsigned char) *other_path)
577-
#endif
578-
)
579-
break;
580-
581-
bin_path++;
582-
other_path++;
583-
}
584-
585-
/* identical? */
586-
if (!*bin_path && !*other_path)
587-
return NULL;
588-
589-
/* advance past directory name */
590-
while (!IS_DIR_SEP(*bin_path) && *bin_path)
591-
bin_path++;
592-
593-
MOVE_TO_SEP_END(bin_path);
594-
595-
/* Is bin done? */
596-
if (!*bin_path)
597-
return other_path;
598-
else
599-
return NULL;
600-
}
601-
602-
603505
/*
604506
* trim_directory
605507
*

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy