Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit936d43d

Browse files
committed
Fix make_relative_path() to support cases where target_path and bin_path
differ by more than the last directory component. Instead of insistingthat they match up to the last component, accept whatever common prefixthey have, and try to replace the non-matching part of bin_path withthe non-matching part of target_path in the actual executable's path.In one way this is tighter than the old code, because it insists ona match to the part of bin_path we want to substitute for, rather thanblindly stripping one directory component from the executable's path.Per gripe from Martin Pitt and subsequent discussion.
1 parent98b3c3c commit936d43d

File tree

1 file changed

+67
-16
lines changed

1 file changed

+67
-16
lines changed

‎src/port/path.c

Lines changed: 67 additions & 16 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.62 2005/11/22 18:17:34 momjian Exp $
11+
* $PostgreSQL: pgsql/src/port/path.c,v 1.63 2005/12/23 22:34:22 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -418,6 +418,27 @@ get_progname(const char *argv0)
418418
}
419419

420420

421+
/*
422+
* dir_strcmp: strcmp except any two DIR_SEP characters are considered equal
423+
*/
424+
staticint
425+
dir_strcmp(constchar*s1,constchar*s2)
426+
{
427+
while (*s1&&*s2)
428+
{
429+
if (*s1!=*s2&&
430+
!(IS_DIR_SEP(*s1)&&IS_DIR_SEP(*s2)))
431+
return (int)*s1- (int)*s2;
432+
s1++,s2++;
433+
}
434+
if (*s1)
435+
return1;/* s1 longer */
436+
if (*s2)
437+
return-1;/* s2 longer */
438+
return0;
439+
}
440+
441+
421442
/*
422443
* make_relative_path - make a path relative to the actual binary location
423444
*
@@ -428,37 +449,67 @@ get_progname(const char *argv0)
428449
*bin_path is the compiled-in path to the directory of executables
429450
*my_exec_path is the actual location of my executable
430451
*
431-
* If target_path matches bin_path up to the last directory component of
432-
* bin_path, then we build the result as my_exec_path (less the executable
433-
* name and last directory) joined to the non-matching part of target_path.
434-
* Otherwise, we return target_path as-is.
452+
* We determine the common prefix of target_path and bin_path, then compare
453+
* the remainder of bin_path to the last directory component(s) of
454+
* my_exec_path. If they match, build the result as the part of my_exec_path
455+
* preceding the match, joined to the remainder of target_path. If no match,
456+
* return target_path as-is.
435457
*
436458
* For example:
437459
*target_path = '/usr/local/share/postgresql'
438460
*bin_path = '/usr/local/bin'
439461
*my_exec_path = '/opt/pgsql/bin/postmaster'
440-
* Given these inputs we would return '/opt/pgsql/share/postgresql'
462+
* Given these inputs, the common prefix is '/usr/local/', the tail of
463+
* bin_path is 'bin' which does match the last directory component of
464+
* my_exec_path, so we would return '/opt/pgsql/share/postgresql'
441465
*/
442466
staticvoid
443467
make_relative_path(char*ret_path,constchar*target_path,
444468
constchar*bin_path,constchar*my_exec_path)
445469
{
446-
constchar*bin_end;
447470
intprefix_len;
471+
inttail_start;
472+
inttail_len;
473+
inti;
448474

449-
bin_end=last_dir_separator(bin_path);
450-
if (!bin_end)
451-
gotono_match;
452-
prefix_len=bin_end-bin_path+1;
453-
if (strncmp(target_path,bin_path,prefix_len)!=0)
454-
gotono_match;
475+
/*
476+
* Determine the common prefix --- note we require it to end on a
477+
* directory separator, consider eg '/usr/lib' and '/usr/libexec'.
478+
*/
479+
prefix_len=0;
480+
for (i=0;target_path[i]&&bin_path[i];i++)
481+
{
482+
if (IS_DIR_SEP(target_path[i])&&IS_DIR_SEP(bin_path[i]))
483+
prefix_len=i+1;
484+
elseif (target_path[i]!=bin_path[i])
485+
break;
486+
}
487+
if (prefix_len==0)
488+
gotono_match;/* no common prefix? */
489+
tail_len=strlen(bin_path)-prefix_len;
455490

491+
/*
492+
* Set up my_exec_path without the actual executable name, and
493+
* canonicalize to simplify comparison to bin_path.
494+
*/
456495
StrNCpy(ret_path,my_exec_path,MAXPGPATH);
457496
trim_directory(ret_path);/* remove my executable name */
458-
trim_directory(ret_path);/* remove last directory component (/bin) */
459-
join_path_components(ret_path,ret_path,target_path+prefix_len);
460497
canonicalize_path(ret_path);
461-
return;
498+
499+
/*
500+
* Tail match?
501+
*/
502+
tail_start= (int)strlen(ret_path)-tail_len;
503+
if (tail_start>0&&
504+
IS_DIR_SEP(ret_path[tail_start-1])&&
505+
dir_strcmp(ret_path+tail_start,bin_path+prefix_len)==0)
506+
{
507+
ret_path[tail_start]='\0';
508+
trim_trailing_separator(ret_path);
509+
join_path_components(ret_path,ret_path,target_path+prefix_len);
510+
canonicalize_path(ret_path);
511+
return;
512+
}
462513

463514
no_match:
464515
StrNCpy(ret_path,target_path,MAXPGPATH);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp