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

Commit336969e

Browse files
committed
Add code to find_my_exec() to resolve a symbolic link down to the
actual executable location. This allows people to continue to usesetups where, eg, postmaster is symlinked from a convenient place.Per gripe from Josh Berkus.
1 parentbffe45a commit336969e

File tree

4 files changed

+173
-61
lines changed

4 files changed

+173
-61
lines changed

‎configure

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11295,7 +11295,8 @@ test $ac_cv_func_memcmp_working = no && LIBOBJS="$LIBOBJS memcmp.$ac_objext"
1129511295

1129611296

1129711297

11298-
for ac_func in cbrt dlopen fcvt fdatasync getpeereid memmove poll pstat setproctitle setsid sigprocmask symlink sysconf towlower utime utimes waitpid wcstombs
11298+
11299+
for ac_func in cbrt dlopen fcvt fdatasync getpeereid memmove poll pstat readlink setproctitle setsid sigprocmask symlink sysconf towlower utime utimes waitpid wcstombs
1129911300
do
1130011301
as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
1130111302
echo "$as_me:$LINENO: checking for $ac_func" >&5

‎configure.in

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
dnl Process this file with autoconf to produce a configure script.
2-
dnl $PostgreSQL: pgsql/configure.in,v 1.384 2004/11/02 05:44:45 momjian Exp $
2+
dnl $PostgreSQL: pgsql/configure.in,v 1.385 2004/11/06 23:06:15 tgl Exp $
33
dnl
44
dnl Developers, please strive to achieve this order:
55
dnl
@@ -826,7 +826,7 @@ PGAC_FUNC_GETTIMEOFDAY_1ARG
826826
# SunOS doesn't handle negative byte comparisons properly with +/- return
827827
AC_FUNC_MEMCMP
828828

829-
AC_CHECK_FUNCS([cbrt dlopen fcvt fdatasync getpeereid memmove poll pstat setproctitle setsid sigprocmask symlink sysconf towlower utime utimes waitpid wcstombs])
829+
AC_CHECK_FUNCS([cbrt dlopen fcvt fdatasync getpeereid memmove poll pstatreadlinksetproctitle setsid sigprocmask symlink sysconf towlower utime utimes waitpid wcstombs])
830830

831831
AC_CHECK_DECLS(fdatasync, [], [], [#include <unistd.h>])
832832

‎src/include/pg_config.h.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,9 @@
345345
/* Define to 1 if you have the <readline/readline.h> header file. */
346346
#undef HAVE_READLINE_READLINE_H
347347

348+
/* Define to 1 if you have the `readlink' function. */
349+
#undef HAVE_READLINK
350+
348351
/* Define to 1 if you have the `replace_history_entry' function. */
349352
#undef HAVE_REPLACE_HISTORY_ENTRY
350353

‎src/port/exec.c

Lines changed: 166 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
/*-------------------------------------------------------------------------
22
*
33
* exec.c
4+
*Functions for finding and validating executable files
5+
*
46
*
57
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
68
* Portions Copyright (c) 1994, Regents of the University of California
79
*
810
*
911
* IDENTIFICATION
10-
* $PostgreSQL: pgsql/src/port/exec.c,v 1.31 2004/11/0601:16:22 tgl Exp $
12+
* $PostgreSQL: pgsql/src/port/exec.c,v 1.32 2004/11/0623:06:29 tgl Exp $
1113
*
1214
*-------------------------------------------------------------------------
1315
*/
@@ -47,6 +49,14 @@
4749
#definelog_error(str,param)(fprintf(stderr, str, param), fputc('\n', stderr))
4850
#endif
4951

52+
#ifdefWIN32_CLIENT_ONLY
53+
#definegetcwd(cwd,len) GetCurrentDirectory(len, cwd)
54+
#endif
55+
56+
staticintvalidate_exec(constchar*path);
57+
staticintresolve_symlinks(char*path);
58+
staticchar*pipe_read_line(char*cmd,char*line,intmaxsize);
59+
5060

5161
/*
5262
* validate_exec -- validate "path" as an executable file
@@ -154,13 +164,20 @@ validate_exec(const char *path)
154164
#endif
155165
}
156166

167+
157168
/*
158169
* find_my_exec -- find an absolute path to a valid executable
159170
*
171+
*argv0 is the name passed on the command line
172+
*retpath is the output area (must be of size MAXPGPATH)
173+
*Returns 0 if OK, -1 if error.
174+
*
160175
* The reason we have to work so hard to find an absolute path is that
161176
* on some platforms we can't do dynamic loading unless we know the
162177
* executable's location. Also, we need a full path not a relative
163-
* path because we will later change working directory.
178+
* path because we will later change working directory. Finally, we want
179+
* a true path not a symlink location, so that we can locate other files
180+
* that are part of our installation relative to the executable.
164181
*
165182
* This function is not thread-safe because it calls validate_exec(),
166183
* which calls getgrgid().This function should be used only in
@@ -173,13 +190,12 @@ find_my_exec(const char *argv0, char *retpath)
173190
test_path[MAXPGPATH];
174191
char*path;
175192

176-
#ifndefWIN32_CLIENT_ONLY
177193
if (!getcwd(cwd,MAXPGPATH))
178-
strcpy(cwd,".");/* cheesy, but better than nothing */
179-
#else
180-
if (!GetCurrentDirectory(MAXPGPATH,cwd))
181-
strcpy(cwd,".");/* cheesy, but better than nothing */
182-
#endif
194+
{
195+
log_error(_("could not identify current directory: %s"),
196+
strerror(errno));
197+
return-1;
198+
}
183199

184200
/*
185201
* If argv0 contains a separator, then PATH wasn't used.
@@ -193,7 +209,7 @@ find_my_exec(const char *argv0, char *retpath)
193209
canonicalize_path(retpath);
194210

195211
if (validate_exec(retpath)==0)
196-
return0;
212+
returnresolve_symlinks(retpath);
197213

198214
log_error("invalid binary \"%s\"",retpath);
199215
return-1;
@@ -203,7 +219,7 @@ find_my_exec(const char *argv0, char *retpath)
203219
/* Win32 checks the current directory first for names without slashes */
204220
join_path_components(retpath,cwd,argv0);
205221
if (validate_exec(retpath)==0)
206-
return0;
222+
returnresolve_symlinks(retpath);
207223
#endif
208224

209225
/*
@@ -240,7 +256,7 @@ find_my_exec(const char *argv0, char *retpath)
240256
switch (validate_exec(retpath))
241257
{
242258
case0:/* found ok */
243-
return0;
259+
returnresolve_symlinks(retpath);
244260
case-1:/* wasn't even a candidate, keep looking */
245261
break;
246262
case-2:/* found but disqualified */
@@ -254,6 +270,141 @@ find_my_exec(const char *argv0, char *retpath)
254270
return-1;
255271
}
256272

273+
274+
/*
275+
* resolve_symlinks - resolve symlinks to the underlying file
276+
*
277+
* If path does not point to a symlink, leave it alone. If it does,
278+
* replace it by the absolute path to the referenced file.
279+
*
280+
* Returns 0 if OK, -1 if error.
281+
*
282+
* Note: we are not particularly tense about producing nice error messages
283+
* because we are not really expecting error here; we just determined that
284+
* the symlink does point to a valid executable.
285+
*/
286+
staticint
287+
resolve_symlinks(char*path)
288+
{
289+
#ifdefHAVE_READLINK
290+
structstatbuf;
291+
charorig_wd[MAXPGPATH],
292+
link_buf[MAXPGPATH];
293+
char*fname;
294+
295+
/* Quick out if it's not a symlink */
296+
if (lstat(path,&buf)<0||
297+
(buf.st_mode&S_IFMT)!=S_IFLNK)
298+
return0;
299+
300+
/*
301+
* To resolve a symlink properly, we have to chdir into its directory
302+
* and then chdir to where the symlink points; otherwise we may fail to
303+
* resolve relative links correctly (consider cases involving mount
304+
* points, for example). After following the final symlink, we use
305+
* getcwd() to figure out where the heck we're at.
306+
*/
307+
if (!getcwd(orig_wd,MAXPGPATH))
308+
{
309+
log_error(_("could not identify current directory: %s"),
310+
strerror(errno));
311+
return-1;
312+
}
313+
314+
for (;;)
315+
{
316+
char*lsep;
317+
intrllen;
318+
319+
lsep=last_dir_separator(path);
320+
if (lsep)
321+
{
322+
*lsep='\0';
323+
if (chdir(path)==-1)
324+
{
325+
log_error(_("could not change directory to \"%s\""),path);
326+
return-1;
327+
}
328+
fname=lsep+1;
329+
}
330+
else
331+
fname=path;
332+
333+
if (lstat(fname,&buf)<0||
334+
(buf.st_mode&S_IFMT)!=S_IFLNK)
335+
break;
336+
337+
rllen=readlink(fname,link_buf,sizeof(link_buf));
338+
if (rllen<0||rllen >=sizeof(link_buf))
339+
{
340+
log_error(_("could not read symbolic link \"%s\""),fname);
341+
return-1;
342+
}
343+
link_buf[rllen]='\0';
344+
strcpy(path,link_buf);
345+
}
346+
347+
/* must copy final component out of 'path' temporarily */
348+
strcpy(link_buf,fname);
349+
350+
if (!getcwd(path,MAXPGPATH))
351+
{
352+
log_error(_("could not identify current directory: %s"),
353+
strerror(errno));
354+
return-1;
355+
}
356+
join_path_components(path,path,link_buf);
357+
canonicalize_path(path);
358+
359+
if (chdir(orig_wd)==-1)
360+
{
361+
log_error(_("could not change directory to \"%s\""),orig_wd);
362+
return-1;
363+
}
364+
365+
#endif/* HAVE_READLINK */
366+
367+
return0;
368+
}
369+
370+
371+
/*
372+
* Find another program in our binary's directory,
373+
* then make sure it is the proper version.
374+
*/
375+
int
376+
find_other_exec(constchar*argv0,constchar*target,
377+
constchar*versionstr,char*retpath)
378+
{
379+
charcmd[MAXPGPATH];
380+
charline[100];
381+
382+
if (find_my_exec(argv0,retpath)<0)
383+
return-1;
384+
385+
/* Trim off program name and keep just directory */
386+
*last_dir_separator(retpath)='\0';
387+
canonicalize_path(retpath);
388+
389+
/* Now append the other program's name */
390+
snprintf(retpath+strlen(retpath),MAXPGPATH-strlen(retpath),
391+
"/%s%s",target,EXE);
392+
393+
if (validate_exec(retpath)!=0)
394+
return-1;
395+
396+
snprintf(cmd,sizeof(cmd),"\"%s\" -V 2>%s",retpath,DEVNULL);
397+
398+
if (!pipe_read_line(cmd,line,sizeof(line)))
399+
return-1;
400+
401+
if (strcmp(line,versionstr)!=0)
402+
return-2;
403+
404+
return0;
405+
}
406+
407+
257408
/*
258409
* The runtime library's popen() on win32 does not work when being
259410
* called from a service when running on windows <= 2000, because
@@ -262,7 +413,6 @@ find_my_exec(const char *argv0, char *retpath)
262413
* Executing a command in a pipe and reading the first line from it
263414
* is all we need.
264415
*/
265-
266416
staticchar*
267417
pipe_read_line(char*cmd,char*line,intmaxsize)
268418
{
@@ -286,8 +436,9 @@ pipe_read_line(char *cmd, char *line, int maxsize)
286436
returnNULL;
287437

288438
returnline;
289-
#else
290-
/* Win32 */
439+
440+
#else/* WIN32 */
441+
291442
SECURITY_ATTRIBUTESsattr;
292443
HANDLEchildstdoutrd,
293444
childstdoutwr,
@@ -392,44 +543,7 @@ pipe_read_line(char *cmd, char *line, int maxsize)
392543
CloseHandle(childstdoutrddup);
393544

394545
returnretval;
395-
#endif
396-
}
397-
398-
399-
/*
400-
* Find another program in our binary's directory,
401-
* then make sure it is the proper version.
402-
*/
403-
int
404-
find_other_exec(constchar*argv0,constchar*target,
405-
constchar*versionstr,char*retpath)
406-
{
407-
charcmd[MAXPGPATH];
408-
charline[100];
409-
410-
if (find_my_exec(argv0,retpath)<0)
411-
return-1;
412-
413-
/* Trim off program name and keep just directory */
414-
*last_dir_separator(retpath)='\0';
415-
canonicalize_path(retpath);
416-
417-
/* Now append the other program's name */
418-
snprintf(retpath+strlen(retpath),MAXPGPATH-strlen(retpath),
419-
"/%s%s",target,EXE);
420-
421-
if (validate_exec(retpath))
422-
return-1;
423-
424-
snprintf(cmd,sizeof(cmd),"\"%s\" -V 2>%s",retpath,DEVNULL);
425-
426-
if (!pipe_read_line(cmd,line,sizeof(line)))
427-
return-1;
428-
429-
if (strcmp(line,versionstr)!=0)
430-
return-2;
431-
432-
return0;
546+
#endif/* WIN32 */
433547
}
434548

435549

@@ -454,20 +568,14 @@ pclose_check(FILE *stream)
454568
perror("pclose failed");
455569
}
456570
elseif (WIFEXITED(exitstatus))
457-
{
458571
log_error(_("child process exited with exit code %d"),
459572
WEXITSTATUS(exitstatus));
460-
}
461573
elseif (WIFSIGNALED(exitstatus))
462-
{
463574
log_error(_("child process was terminated by signal %d"),
464575
WTERMSIG(exitstatus));
465-
}
466576
else
467-
{
468577
log_error(_("child process exited with unrecognized status %d"),
469578
exitstatus);
470-
}
471579

472580
return-1;
473581
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp