Skip to content

Commit 4867afe

Browse files
committed
Code cleanup in path.c and exec.c. Handle Windows drive and network specs
everywhere not just some places, get rid of . and .. when joining path sections together. This should eliminate most of the ugly paths like /foo/bar/./baz that we've been generating.
1 parent 3d6e538 commit 4867afe

File tree

3 files changed

+176
-166
lines changed

3 files changed

+176
-166
lines changed

src/include/port.h

Lines changed: 14 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
/*-------------------------------------------------------------------------
22
*
33
* port.h
4-
* Header for /port compatibility functions.
4+
* Header for src/port/ compatibility functions.
55
*
66
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
9-
* $PostgreSQL: pgsql/src/include/port.h,v 1.64 2004/10/11 22:50:33 momjian Exp $
9+
* $PostgreSQL: pgsql/src/include/port.h,v 1.65 2004/11/06 01:16:14 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -20,25 +20,15 @@
2020
#include <ctype.h>
2121

2222
/* non-blocking */
23-
bool set_noblock(int sock);
23+
extern bool set_noblock(int sock);
2424

2525
/* Portable path handling for Unix/Win32 */
2626

27-
/* Find the location of the first directory separator, return
28-
* NULL if not found.
29-
*/
3027
extern char *first_dir_separator(const char *filename);
31-
32-
/* Find the location of the last directory separator, return
33-
* NULL if not found.
34-
*/
3528
extern char *last_dir_separator(const char *filename);
36-
37-
/* Find the location of the first path separator (i.e. ':' on
38-
* Unix, ';' on Windows), return NULL if not found.
39-
*/
40-
extern char *first_path_separator(const char *filename);
41-
29+
extern char *first_path_separator(const char *pathlist);
30+
extern void join_path_components(char *ret_path,
31+
const char *head, const char *tail);
4232
extern void canonicalize_path(char *path);
4333
extern void make_native_path(char *path);
4434
extern const char *get_progname(const char *argv0);
@@ -123,11 +113,6 @@ extern unsigned char pg_tolower(unsigned char ch);
123113
/* Portable prompt handling */
124114
extern char *simple_prompt(const char *prompt, int maxlen, bool echo);
125115

126-
#if defined(bsdi) || defined(netbsd)
127-
extern int fseeko(FILE *stream, off_t offset, int whence);
128-
extern off_t ftello(FILE *stream);
129-
#endif
130-
131116
/*
132117
* WIN32 doesn't allow descriptors returned by pipe() to be used in select(),
133118
* so for that platform we use socket() instead of pipe().
@@ -185,7 +170,7 @@ extern int pgsymlink(const char *oldpath, const char *newpath);
185170
#define symlink(oldpath, newpath) pgsymlink(oldpath, newpath)
186171
#endif
187172

188-
#endif
173+
#endif /* defined(WIN32) || defined(__CYGWIN__) */
189174

190175
extern bool rmtree(char *path, bool rmtopdir);
191176

@@ -212,14 +197,14 @@ extern void srand48(long seed);
212197
/* Last parameter not used */
213198
extern int gettimeofday(struct timeval * tp, struct timezone * tzp);
214199

215-
#else
200+
#else /* !WIN32 */
216201

217202
/*
218203
* Win32 requires a special close for sockets and pipes, while on Unix
219204
* close() does them all.
220205
*/
221206
#define closesocket close
222-
#endif
207+
#endif /* WIN32 */
223208

224209
/*
225210
* Default "extern" declarations or macro substitutes for library routines.
@@ -229,6 +214,11 @@ extern int gettimeofday(struct timeval * tp, struct timezone * tzp);
229214
extern char *crypt(const char *key, const char *setting);
230215
#endif
231216

217+
#if defined(bsdi) || defined(netbsd)
218+
extern int fseeko(FILE *stream, off_t offset, int whence);
219+
extern off_t ftello(FILE *stream);
220+
#endif
221+
232222
#ifndef HAVE_FSEEKO
233223
#define fseeko(a, b, c) fseek((a), (b), (c))
234224
#define ftello(a) ftell((a))

src/port/exec.c

Lines changed: 32 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $PostgreSQL: pgsql/src/port/exec.c,v 1.30 2004/10/18 19:08:58 momjian Exp $
10+
* $PostgreSQL: pgsql/src/port/exec.c,v 1.31 2004/11/06 01:16:22 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -42,15 +42,12 @@
4242

4343
#ifndef FRONTEND
4444
/* We use only 3-parameter elog calls in this file, for simplicity */
45-
#define log_error(str, param) elog(LOG, (str), (param))
45+
#define log_error(str, param) elog(LOG, str, param)
4646
#else
47-
#define log_error(str, param) fprintf(stderr, (str), (param))
47+
#define log_error(str, param) (fprintf(stderr, str, param), fputc('\n', stderr))
4848
#endif
4949

5050

51-
static void win32_make_absolute(char *path);
52-
53-
5451
/*
5552
* validate_exec -- validate "path" as an executable file
5653
*
@@ -165,7 +162,7 @@ validate_exec(const char *path)
165162
* executable's location. Also, we need a full path not a relative
166163
* path because we will later change working directory.
167164
*
168-
* This function is not thread-safe because of it calls validate_exec(),
165+
* This function is not thread-safe because it calls validate_exec(),
169166
* which calls getgrgid(). This function should be used only in
170167
* non-threaded binaries, not in library routines.
171168
*/
@@ -178,61 +175,40 @@ find_my_exec(const char *argv0, char *retpath)
178175

179176
#ifndef WIN32_CLIENT_ONLY
180177
if (!getcwd(cwd, MAXPGPATH))
178+
strcpy(cwd, "."); /* cheesy, but better than nothing */
181179
#else
182180
if (!GetCurrentDirectory(MAXPGPATH, cwd))
181+
strcpy(cwd, "."); /* cheesy, but better than nothing */
183182
#endif
184-
cwd[0] = '\0';
185183

186184
/*
187-
* First try: use the binary that's located in the same directory if
188-
* it was invoked with an explicit path. Presumably the user used an
189-
* explicit path because it wasn't in PATH, and we don't want to use
190-
* incompatible executables.
191-
*
192-
* For the binary: First try: if we're given some kind of path, use it
193-
* (making sure that a relative path is made absolute before returning
194-
* it).
185+
* If argv0 contains a separator, then PATH wasn't used.
195186
*/
196-
/* Does argv0 have a separator? */
197-
if ((path = last_dir_separator(argv0)))
187+
if (first_dir_separator(argv0) != NULL)
198188
{
199-
if (*++path == '\0')
200-
{
201-
log_error("argv[0] ends with a path separator \"%s\"", argv0);
202-
return -1;
203-
}
204-
205189
if (is_absolute_path(argv0))
206190
StrNCpy(retpath, argv0, MAXPGPATH);
207191
else
208-
snprintf(retpath, MAXPGPATH, "%s/%s", cwd, argv0);
209-
192+
join_path_components(retpath, cwd, argv0);
210193
canonicalize_path(retpath);
194+
211195
if (validate_exec(retpath) == 0)
212-
{
213-
win32_make_absolute(retpath);
214196
return 0;
215-
}
216-
else
217-
{
218-
log_error("invalid binary \"%s\"", retpath);
219-
return -1;
220-
}
197+
198+
log_error("invalid binary \"%s\"", retpath);
199+
return -1;
221200
}
222201

223202
#ifdef WIN32
224203
/* Win32 checks the current directory first for names without slashes */
225-
if (validate_exec(argv0) == 0)
226-
{
227-
snprintf(retpath, MAXPGPATH, "%s/%s", cwd, argv0);
228-
win32_make_absolute(retpath);
204+
join_path_components(retpath, cwd, argv0);
205+
if (validate_exec(retpath) == 0)
229206
return 0;
230-
}
231207
#endif
232208

233209
/*
234-
* Second try: since no explicit path was supplied, the user must have
235-
* been relying on PATH. We'll use the same PATH.
210+
* Since no explicit path was supplied, the user must have
211+
* been relying on PATH. We'll search the same PATH.
236212
*/
237213
if ((path = getenv("PATH")) && *path)
238214
{
@@ -253,40 +229,33 @@ find_my_exec(const char *argv0, char *retpath)
253229
StrNCpy(test_path, startp, Min(endp - startp + 1, MAXPGPATH));
254230

255231
if (is_absolute_path(test_path))
256-
snprintf(retpath, MAXPGPATH, "%s/%s", test_path, argv0);
232+
join_path_components(retpath, test_path, argv0);
257233
else
258-
snprintf(retpath, MAXPGPATH, "%s/%s/%s", cwd, test_path, argv0);
259-
234+
{
235+
join_path_components(retpath, cwd, test_path);
236+
join_path_components(retpath, retpath, argv0);
237+
}
260238
canonicalize_path(retpath);
239+
261240
switch (validate_exec(retpath))
262241
{
263-
case 0: /* found ok */
264-
win32_make_absolute(retpath);
242+
case 0: /* found ok */
265243
return 0;
266244
case -1: /* wasn't even a candidate, keep looking */
267-
continue;
245+
break;
268246
case -2: /* found but disqualified */
269247
log_error("could not read binary \"%s\"", retpath);
270-
continue;
248+
break;
271249
}
272250
} while (*endp);
273251
}
274252

275253
log_error("could not find a \"%s\" to execute", argv0);
276254
return -1;
277-
278-
#if NOT_USED
279-
/*
280-
* Win32 has a native way to find the executable name, but the above
281-
* method works too.
282-
*/
283-
if (GetModuleFileName(NULL, retpath, MAXPGPATH) == 0)
284-
log_error("GetModuleFileName failed (%i)", (int) GetLastError());
285-
#endif
286255
}
287256

288257
/*
289-
* The runtime librarys popen() on win32 does not work when being
258+
* The runtime library's popen() on win32 does not work when being
290259
* called from a service when running on windows <= 2000, because
291260
* there is no stdin/stdout/stderr.
292261
*
@@ -427,10 +396,9 @@ pipe_read_line(char *cmd, char *line, int maxsize)
427396
}
428397

429398

430-
431399
/*
432-
* Find our binary directory, then make sure the "target" executable
433-
* is the proper version.
400+
* Find another program in our binary's directory,
401+
* then make sure it is the proper version.
434402
*/
435403
int
436404
find_other_exec(const char *argv0, const char *target,
@@ -487,41 +455,19 @@ pclose_check(FILE *stream)
487455
}
488456
else if (WIFEXITED(exitstatus))
489457
{
490-
log_error(_("child process exited with exit code %d\n"),
458+
log_error(_("child process exited with exit code %d"),
491459
WEXITSTATUS(exitstatus));
492460
}
493461
else if (WIFSIGNALED(exitstatus))
494462
{
495-
log_error(_("child process was terminated by signal %d\n"),
463+
log_error(_("child process was terminated by signal %d"),
496464
WTERMSIG(exitstatus));
497465
}
498466
else
499467
{
500-
log_error(_("child process exited with unrecognized status %d\n"),
468+
log_error(_("child process exited with unrecognized status %d"),
501469
exitstatus);
502470
}
503471

504472
return -1;
505473
}
506-
507-
508-
/*
509-
* Windows doesn't like relative paths to executables (other things work fine)
510-
* so we call its builtin function to expand them. Elsewhere this is a NOOP
511-
*/
512-
static void
513-
win32_make_absolute(char *path)
514-
{
515-
#ifdef WIN32
516-
char abspath[MAXPGPATH];
517-
518-
if (_fullpath(abspath, path, MAXPGPATH) == NULL)
519-
{
520-
log_error("Win32 path expansion failed: %s", strerror(errno));
521-
StrNCpy(abspath, path, MAXPGPATH);
522-
}
523-
canonicalize_path(abspath);
524-
525-
StrNCpy(path, abspath, MAXPGPATH);
526-
#endif
527-
}

0 commit comments

Comments
 (0)