Here is my first patch toward the native Win32 port. It is taken from
PeerDirect/Jan's Win32 port, with reference to SRA's port.
The patch deals with file path separators '/' vs '\' (Win32 supports
both in C), and Win32 drive letter handling.
The patch is 700 lines, but adds only two WIN32's to the code. The
majority of the work is done in port/path.c. While /port was for
port-specific stuff, in this case, it seems like the best place to put
functions that are used by both the backend and interfaces/clients.
I just hope my other patches are as clean as this one. :-)
Here is a rough outline of the major Win32 item needed:
*file path separators
*root directory
handle \r in COPY
copydir for cp -r
rmdir not recursive for rm -r
rename atomicity
shared memory could map to new address in exec child
compatibility defines
spinlock changes
DWORD in help.c
initdb
fork/exec
--
Bruce Momjian | http://candle.pha.pa.us
pgman@candle.pha.pa.us | (610) 359-1001
+ If your life is a hard drive, | 13 Roberts Road
+ Christ can be your backup. | Newtown Square, Pennsylvania 19073
Index: configure
===================================================================
RCS file: /cvsroot/pgsql-server/configure,v
retrieving revision 1.247
diff -c -c -r1.247 configure
*** configure 29 Mar 2003 11:31:50 -0000 1.247
--- configure 2 Apr 2003 20:01:00 -0000
***************
*** 10502,10507 ****
--- 10502,10509 ----
fi
+ # Do path handling in Unix/Win32 portable way
+ LIBOBJS="$LIBOBJS path.$ac_objext"
# We use our snprintf.c emulation if either snprintf() or vsnprintf()
# is missing. Yes, there are machines that have only one. We may
Index: configure.in
===================================================================
RCS file: /cvsroot/pgsql-server/configure.in,v
retrieving revision 1.240
diff -c -c -r1.240 configure.in
*** configure.in 29 Mar 2003 11:31:51 -0000 1.240
--- configure.in 2 Apr 2003 20:01:02 -0000
***************
*** 811,816 ****
--- 811,818 ----
AC_DEFINE([HAVE_PS_STRINGS], [], [Define if the PS_STRINGS thing exists.])
fi
+ # Do path handling in Unix/Win32 portable way
+ AC_LIBOBJ(path)
# We use our snprintf.c emulation if either snprintf() or vsnprintf()
# is missing. Yes, there are machines that have only one. We may
Index: src/backend/commands/copy.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/commands/copy.c,v
retrieving revision 1.190
diff -c -c -r1.190 copy.c
*** src/backend/commands/copy.c 27 Mar 2003 16:51:27 -0000 1.190
--- src/backend/commands/copy.c 2 Apr 2003 20:01:04 -0000
***************
*** 476,482 ****
* Prevent write to relative path ... too easy to shoot
* oneself in the foot by overwriting a database file ...
*/
! if (filename[0] != '/')
elog(ERROR, "Relative path not allowed for server side"
" COPY command");
--- 476,482 ----
* Prevent write to relative path ... too easy to shoot
* oneself in the foot by overwriting a database file ...
*/
! if (!is_absolute_path(filename))
elog(ERROR, "Relative path not allowed for server side"
" COPY command");
Index: src/backend/commands/dbcommands.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/commands/dbcommands.c,v
retrieving revision 1.110
diff -c -c -r1.110 dbcommands.c
*** src/backend/commands/dbcommands.c 27 Jan 2003 00:46:41 -0000 1.110
--- src/backend/commands/dbcommands.c 2 Apr 2003 20:01:05 -0000
***************
*** 694,702 ****
if (dbpath == NULL || dbpath[0] == '\0')
return NULL;
! if (strchr(dbpath, '/'))
{
! if (dbpath[0] != '/')
elog(ERROR, "Relative paths are not allowed as database locations");
#ifndef ALLOW_ABSOLUTE_DBPATHS
elog(ERROR, "Absolute paths are not allowed as database locations");
--- 694,702 ----
if (dbpath == NULL || dbpath[0] == '\0')
return NULL;
! if (first_path_separator(dbpath))
{
! if (!is_absolute_path(dbpath))
elog(ERROR, "Relative paths are not allowed as database locations");
#ifndef ALLOW_ABSOLUTE_DBPATHS
elog(ERROR, "Absolute paths are not allowed as database locations");
***************
*** 710,716 ****
if (!var)
elog(ERROR, "Postmaster environment variable '%s' not set", dbpath);
! if (var[0] != '/')
elog(ERROR, "Postmaster environment variable '%s' must be absolute path", dbpath);
prefix = var;
}
--- 710,716 ----
if (!var)
elog(ERROR, "Postmaster environment variable '%s' not set", dbpath);
! if (!is_absolute_path(var))
elog(ERROR, "Postmaster environment variable '%s' must be absolute path", dbpath);
prefix = var;
}
Index: src/backend/storage/file/fd.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/storage/file/fd.c,v
retrieving revision 1.96
diff -c -c -r1.96 fd.c
*** src/backend/storage/file/fd.c 27 Mar 2003 16:51:29 -0000 1.96
--- src/backend/storage/file/fd.c 2 Apr 2003 20:01:07 -0000
***************
*** 607,613 ****
char *buf;
/* Not an absolute path name? Then fill in with database path... */
! if (*filename != '/')
{
buf = (char *) palloc(strlen(DatabasePath) + strlen(filename) + 2);
sprintf(buf, "%s/%s", DatabasePath, filename);
--- 607,613 ----
char *buf;
/* Not an absolute path name? Then fill in with database path... */
! if (!is_absolute_path(filename))
{
buf = (char *) palloc(strlen(DatabasePath) + strlen(filename) + 2);
sprintf(buf, "%s/%s", DatabasePath, filename);
Index: src/backend/utils/fmgr/dfmgr.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/utils/fmgr/dfmgr.c,v
retrieving revision 1.57
diff -c -c -r1.57 dfmgr.c
*** src/backend/utils/fmgr/dfmgr.c 2 Sep 2002 02:47:05 -0000 1.57
--- src/backend/utils/fmgr/dfmgr.c 2 Apr 2003 20:01:07 -0000
***************
*** 271,277 ****
AssertArg(name);
! have_slash = (strchr(name, '/') != NULL);
if (!have_slash)
{
--- 271,277 ----
AssertArg(name);
! have_slash = (first_path_separator(name) != NULL);
if (!have_slash)
{
***************
*** 326,332 ****
if (name[0] != '$')
return pstrdup(name);
! macroname_len = strcspn(name + 1, "/") + 1;
if (strncmp(name, "$libdir", macroname_len) == 0)
replacement = PKGLIBDIR;
--- 326,338 ----
if (name[0] != '$')
return pstrdup(name);
! macroname_len = strcspn(name + 1,
! #ifndef WIN32
! "/"
! #else
! "/\\"
! #endif
! ) + 1;
if (strncmp(name, "$libdir", macroname_len) == 0)
replacement = PKGLIBDIR;
***************
*** 362,368 ****
size_t baselen;
AssertArg(basename != NULL);
! AssertArg(strchr(basename, '/') == NULL);
AssertState(Dynamic_library_path != NULL);
p = Dynamic_library_path;
--- 368,374 ----
size_t baselen;
AssertArg(basename != NULL);
! AssertArg(first_path_separator(basename) == NULL);
AssertState(Dynamic_library_path != NULL);
p = Dynamic_library_path;
***************
*** 391,397 ****
pfree(piece);
/* only absolute paths */
! if (mangled[0] != '/')
elog(ERROR, "dynamic_library_path component is not absolute");
full = palloc(strlen(mangled) + 1 + baselen + 1);
--- 397,403 ----
pfree(piece);
/* only absolute paths */
! if (!is_absolute_path(mangled))
elog(ERROR, "dynamic_library_path component is not absolute");
full = palloc(strlen(mangled) + 1 + baselen + 1);
Index: src/backend/utils/init/findbe.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/utils/init/findbe.c,v
retrieving revision 1.31
diff -c -c -r1.31 findbe.c
*** src/backend/utils/init/findbe.c 2 Nov 2002 15:54:13 -0000 1.31
--- src/backend/utils/init/findbe.c 2 Apr 2003 20:01:08 -0000
***************
*** 159,172 ****
* (making sure that a relative path is made absolute before returning
* it).
*/
! if (argv0 && (p = strrchr(argv0, '/')) && *++p)
{
! if (*argv0 == '/' || !getcwd(buf, MAXPGPATH))
buf[0] = '\0';
else
strcat(buf, "/");
strcat(buf, argv0);
! p = strrchr(buf, '/');
strcpy(++p, binary_name);
if (ValidateBinary(buf) == 0)
{
--- 159,172 ----
* (making sure that a relative path is made absolute before returning
* it).
*/
! if (argv0 && (p = last_path_separator(argv0)) && *++p)
{
! if (is_absolute_path(argv0) || !getcwd(buf, MAXPGPATH))
buf[0] = '\0';
else
strcat(buf, "/");
strcat(buf, argv0);
! p = last_path_separator(buf);
strcpy(++p, binary_name);
if (ValidateBinary(buf) == 0)
{
***************
*** 194,200 ****
continue;
if (endp)
*endp = '\0';
! if (*startp == '/' || !getcwd(buf, MAXPGPATH))
buf[0] = '\0';
else
strcat(buf, "/");
--- 194,200 ----
continue;
if (endp)
*endp = '\0';
! if (is_absolute_path(startp) || !getcwd(buf, MAXPGPATH))
buf[0] = '\0';
else
strcat(buf, "/");
Index: src/backend/utils/init/miscinit.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/utils/init/miscinit.c,v
retrieving revision 1.101
diff -c -c -r1.101 miscinit.c
*** src/backend/utils/init/miscinit.c 20 Mar 2003 04:51:44 -0000 1.101
--- src/backend/utils/init/miscinit.c 2 Apr 2003 20:01:08 -0000
***************
*** 134,140 ****
AssertArg(dir);
/* If presented path is relative, convert to absolute */
! if (dir[0] != '/')
{
char *buf;
size_t buflen;
--- 134,140 ----
AssertArg(dir);
/* If presented path is relative, convert to absolute */
! if (!is_absolute_path(dir))
{
char *buf;
size_t buflen;
***************
*** 179,185 ****
* generating funny-looking paths to individual files.
*/
newlen = strlen(new);
! if (newlen > 1 && new[newlen - 1] == '/')
new[newlen - 1] = '\0';
if (DataDir)
--- 179,189 ----
* generating funny-looking paths to individual files.
*/
newlen = strlen(new);
! if (newlen > 1 && new[newlen - 1] == '/'
! #ifdef WIN32
! || new[newlen - 1] == '\\'
! #endif
! )
new[newlen - 1] = '\0';
if (DataDir)
Index: src/backend/utils/misc/database.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/utils/misc/database.c,v
retrieving revision 1.55
diff -c -c -r1.55 database.c
*** src/backend/utils/misc/database.c 10 Mar 2003 22:28:19 -0000 1.55
--- src/backend/utils/misc/database.c 2 Apr 2003 20:01:09 -0000
***************
*** 50,59 ****
return NULL; /* ain't gonna fit nohow */
/* leading path delimiter? then already absolute path */
! if (*dbpath == '/')
{
#ifdef ALLOW_ABSOLUTE_DBPATHS
! cp = strrchr(dbpath, '/');
len = cp - dbpath;
strncpy(buf, dbpath, len);
snprintf(&buf[len], MAXPGPATH - len, "/base/%s", (cp + 1));
--- 50,59 ----
return NULL; /* ain't gonna fit nohow */
/* leading path delimiter? then already absolute path */
! if (is_absolute_path(dbpath))
{
#ifdef ALLOW_ABSOLUTE_DBPATHS
! cp = last_path_separator(dbpath);
len = cp - dbpath;
strncpy(buf, dbpath, len);
snprintf(&buf[len], MAXPGPATH - len, "/base/%s", (cp + 1));
***************
*** 62,68 ****
#endif
}
/* path delimiter somewhere? then has leading environment variable */
! else if ((cp = strchr(dbpath, '/')) != NULL)
{
const char *envvar;
--- 62,68 ----
#endif
}
/* path delimiter somewhere? then has leading environment variable */
! else if ((cp = first_path_separator(dbpath)) != NULL)
{
const char *envvar;
Index: src/bin/pg_controldata/pg_controldata.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/pg_controldata/pg_controldata.c,v
retrieving revision 1.8
diff -c -c -r1.8 pg_controldata.c
*** src/bin/pg_controldata/pg_controldata.c 8 Jan 2003 22:26:34 -0000 1.8
--- src/bin/pg_controldata/pg_controldata.c 2 Apr 2003 20:01:10 -0000
***************
*** 82,91 ****
textdomain("pg_controldata");
#endif
! if (!strrchr(argv[0], '/'))
! progname = argv[0];
! else
! progname = strrchr(argv[0], '/') + 1;
if (argc > 1)
{
--- 82,88 ----
textdomain("pg_controldata");
#endif
! progname = get_progname(argv[0]);
if (argc > 1)
{
Index: src/bin/pg_dump/pg_dump.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/pg_dump/pg_dump.c,v
retrieving revision 1.325
diff -c -c -r1.325 pg_dump.c
*** src/bin/pg_dump/pg_dump.c 31 Mar 2003 20:48:45 -0000 1.325
--- src/bin/pg_dump/pg_dump.c 2 Apr 2003 20:01:15 -0000
***************
*** 244,253 ****
dataOnly = schemaOnly = dumpData = attrNames = false;
! if (!strrchr(argv[0], '/'))
! progname = argv[0];
! else
! progname = strrchr(argv[0], '/') + 1;
/* Set default options based on progname */
if (strcmp(progname, "pg_backup") == 0)
--- 244,250 ----
dataOnly = schemaOnly = dumpData = attrNames = false;
! progname = get_progname(argv[0]);
/* Set default options based on progname */
if (strcmp(progname, "pg_backup") == 0)
Index: src/bin/pg_dump/pg_dumpall.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/pg_dump/pg_dumpall.c,v
retrieving revision 1.16
diff -c -c -r1.16 pg_dumpall.c
*** src/bin/pg_dump/pg_dumpall.c 14 Mar 2003 22:45:49 -0000 1.16
--- src/bin/pg_dump/pg_dumpall.c 2 Apr 2003 20:01:16 -0000
***************
*** 100,109 ****
textdomain("pg_dump");
#endif
! if (!strrchr(argv[0], '/'))
! progname = argv[0];
! else
! progname = strrchr(argv[0], '/') + 1;
if (argc > 1)
{
--- 100,106 ----
textdomain("pg_dump");
#endif
! progname = get_progname(argv[0]);
if (argc > 1)
{
***************
*** 730,736 ****
return result;
cmd = createPQExpBuffer();
! last = strrchr(argv0, '/');
if (!last)
appendPQExpBuffer(cmd, "pg_dump");
--- 727,733 ----
return result;
cmd = createPQExpBuffer();
! last = last_path_separator(argv0);
if (!last)
appendPQExpBuffer(cmd, "pg_dump");
Index: src/bin/pg_dump/pg_restore.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/pg_dump/pg_restore.c,v
retrieving revision 1.44
diff -c -c -r1.44 pg_restore.c
*** src/bin/pg_dump/pg_restore.c 6 Jan 2003 18:53:25 -0000 1.44
--- src/bin/pg_dump/pg_restore.c 2 Apr 2003 20:01:16 -0000
***************
*** 137,146 ****
opts = NewRestoreOptions();
! if (!strrchr(argv[0], '/'))
! progname = argv[0];
! else
! progname = strrchr(argv[0], '/') + 1;
if (argc > 1)
{
--- 137,143 ----
opts = NewRestoreOptions();
! progname = get_progname(argv[0]);
if (argc > 1)
{
Index: src/bin/pg_resetxlog/pg_resetxlog.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/pg_resetxlog/pg_resetxlog.c,v
retrieving revision 1.8
diff -c -c -r1.8 pg_resetxlog.c
*** src/bin/pg_resetxlog/pg_resetxlog.c 18 Oct 2002 22:05:36 -0000 1.8
--- src/bin/pg_resetxlog/pg_resetxlog.c 2 Apr 2003 20:01:17 -0000
***************
*** 105,114 ****
textdomain("pg_resetxlog");
#endif
! if (!strrchr(argv[0], '/'))
! progname = argv[0];
! else
! progname = strrchr(argv[0], '/') + 1;
if (argc > 1)
{
--- 105,111 ----
textdomain("pg_resetxlog");
#endif
! progname = get_progname(argv[0]);
if (argc > 1)
{
Index: src/bin/psql/prompt.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/psql/prompt.c,v
retrieving revision 1.24
diff -c -c -r1.24 prompt.c
*** src/bin/psql/prompt.c 20 Mar 2003 15:39:53 -0000 1.24
--- src/bin/psql/prompt.c 2 Apr 2003 20:01:17 -0000
***************
*** 130,136 ****
const char *host = PQhost(pset.db);
/* INET socket */
! if (host && host[0] && host[0] != '/')
{
strncpy(buf, host, MAX_PROMPT_SIZE);
if (*p == 'm')
--- 130,136 ----
const char *host = PQhost(pset.db);
/* INET socket */
! if (host && host[0] && !is_absolute_path(host))
{
strncpy(buf, host, MAX_PROMPT_SIZE);
if (*p == 'm')
Index: src/bin/psql/startup.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/psql/startup.c,v
retrieving revision 1.72
diff -c -c -r1.72 startup.c
*** src/bin/psql/startup.c 20 Mar 2003 06:43:35 -0000 1.72
--- src/bin/psql/startup.c 2 Apr 2003 20:01:18 -0000
***************
*** 110,119 ****
textdomain("psql");
#endif
! if (!strrchr(argv[0], '/'))
! pset.progname = argv[0];
! else
! pset.progname = strrchr(argv[0], '/') + 1;
if (argc > 1)
{
--- 110,116 ----
textdomain("psql");
#endif
! pset.progname = get_progname(argv[0]);
if (argc > 1)
{
Index: src/bin/scripts/common.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/scripts/common.c,v
retrieving revision 1.1
diff -c -c -r1.1 common.c
*** src/bin/scripts/common.c 18 Mar 2003 22:19:46 -0000 1.1
--- src/bin/scripts/common.c 2 Apr 2003 20:01:18 -0000
***************
*** 36,54 ****
/*
- * Extracts the actual name of the program as called.
- */
- char *
- get_progname(char *argv0)
- {
- if (!strrchr(argv0, '/'))
- return argv0;
- else
- return strrchr(argv0, '/') + 1;
- }
-
-
- /*
* Initialized NLS if enabled.
*/
void
--- 36,41 ----
Index: src/bin/scripts/common.h
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/scripts/common.h,v
retrieving revision 1.1
diff -c -c -r1.1 common.h
*** src/bin/scripts/common.h 18 Mar 2003 22:19:46 -0000 1.1
--- src/bin/scripts/common.h 2 Apr 2003 20:01:18 -0000
***************
*** 16,22 ****
#endif
const char *get_user_name(const char *progname);
- char *get_progname(char *argv0);
#define _(x) gettext((x))
void init_nls(void);
--- 16,21 ----
Index: src/include/c.h
===================================================================
RCS file: /cvsroot/pgsql-server/src/include/c.h,v
retrieving revision 1.135
diff -c -c -r1.135 c.h
*** src/include/c.h 9 Jan 2003 18:00:24 -0000 1.135
--- src/include/c.h 2 Apr 2003 20:01:19 -0000
***************
*** 692,697 ****
--- 692,703 ----
#include <unistd.h>
#endif
+ /* Portable path handling for Unix/Win32 */
+ bool is_absolute_path(const char *filename);
+ char *first_path_separator(const char *filename);
+ char *last_path_separator(const char *filename);
+ char *get_progname(char *argv0);
+
#if defined(bsdi) || defined(netbsd)
int fseeko(FILE *stream, off_t offset, int whence);
off_t ftello(FILE *stream);
Index: src/interfaces/ecpg/ecpglib/connect.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/interfaces/ecpg/ecpglib/connect.c,v
retrieving revision 1.1
diff -c -c -r1.1 connect.c
*** src/interfaces/ecpg/ecpglib/connect.c 16 Mar 2003 10:42:53 -0000 1.1
--- src/interfaces/ecpg/ecpglib/connect.c 2 Apr 2003 20:01:19 -0000
***************
*** 326,332 ****
*tmp = '\0';
}
! tmp = strrchr(dbname + offset, '/');
if (tmp != NULL) /* database name given */
{
realname = strdup(tmp + 1);
--- 326,332 ----
*tmp = '\0';
}
! tmp = last_path_separator(dbname + offset);
if (tmp != NULL) /* database name given */
{
realname = strdup(tmp + 1);
Index: src/interfaces/ecpg/preproc/ecpg.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/interfaces/ecpg/preproc/ecpg.c,v
retrieving revision 1.64
diff -c -c -r1.64 ecpg.c
*** src/interfaces/ecpg/preproc/ecpg.c 27 Mar 2003 14:29:17 -0000 1.64
--- src/interfaces/ecpg/preproc/ecpg.c 2 Apr 2003 20:01:20 -0000
***************
*** 105,114 ****
struct _include_path *ip;
char *progname;
! if (!strrchr(argv[0], '/'))
! progname = argv[0];
! else
! progname = strrchr(argv[0], '/') + 1;
if (argc > 1)
{
--- 105,111 ----
struct _include_path *ip;
char *progname;
! progname = get_progname(argv[0]);
if (argc > 1)
{
***************
*** 213,219 ****
strcpy(input_filename, argv[fnr]);
/* take care of relative paths */
! ptr2ext = strrchr(input_filename, '/');
ptr2ext = (ptr2ext ? strrchr(ptr2ext, '.') : strrchr(input_filename, '.'));
/* no extension? */
--- 210,216 ----
strcpy(input_filename, argv[fnr]);
/* take care of relative paths */
! ptr2ext = last_path_separator(input_filename);
ptr2ext = (ptr2ext ? strrchr(ptr2ext, '.') : strrchr(input_filename, '.'));
/* no extension? */
Index: src/interfaces/libpq/fe-connect.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/interfaces/libpq/fe-connect.c,v
retrieving revision 1.229
diff -c -c -r1.229 fe-connect.c
*** src/interfaces/libpq/fe-connect.c 29 Mar 2003 11:31:51 -0000 1.229
--- src/interfaces/libpq/fe-connect.c 2 Apr 2003 20:01:23 -0000
***************
*** 330,336 ****
/*
* Allow unix socket specification in the host name
*/
! if (conn->pghost && conn->pghost[0] == '/')
{
if (conn->pgunixsocket)
free(conn->pgunixsocket);
--- 330,336 ----
/*
* Allow unix socket specification in the host name
*/
! if (conn->pghost && is_absolute_path(conn->pghost))
{
if (conn->pgunixsocket)
free(conn->pgunixsocket);
***************
*** 449,455 ****
* We don't allow unix socket path as a function parameter. This
* allows unix socket specification in the host name.
*/
! if (conn->pghost && conn->pghost[0] == '/')
{
if (conn->pgunixsocket)
free(conn->pgunixsocket);
--- 449,455 ----
* We don't allow unix socket path as a function parameter. This
* allows unix socket specification in the host name.
*/
! if (conn->pghost && is_absolute_path(conn->pghost))
{
if (conn->pgunixsocket)
free(conn->pgunixsocket);
***************
*** 604,610 ****
*tmp = '\0';
}
! tmp = strrchr(conn->dbName + offset, '/');
if (tmp != NULL) /* database name given */
{
if (conn->dbName)
--- 604,610 ----
*tmp = '\0';
}
! tmp = last_path_separator(conn->dbName + offset);
if (tmp != NULL) /* database name given */
{
if (conn->dbName)
*** /dev/null Wed Apr 2 15:04:42 2003
--- src/port/path.c Wed Apr 2 14:56:23 2003
***************
*** 0 ****
--- 1,78 ----
+ /* $Id: path.c,v 1.1 2002/07/18 04:13:59 momjian Exp $ */
+
+ #include "c.h"
+ #include <ctype.h>
+
+ /*
+ * is_absolute_path
+ */
+ bool is_absolute_path(const char *filename)
+ {
+ return filename[0] == '/'
+ #ifdef WIN32 /* WIN32 paths can either have forward or backward slashes */
+ || filename[0] == '\\'
+ || (toupper(filename[0]) >= 'A' && toupper(filename[0]) <= 'Z' &&
+ filename[1] == ':' && (filename[2] == '\\' || filename[2] == '/'))
+ #endif
+ ;
+ }
+
+
+
+ /*
+ * first_path_separator
+ */
+ char *first_path_separator(const char *filename)
+ {
+ #ifndef WIN32
+ return strchr(filename, '/');
+ #else
+ char *slash, *bslash;
+
+ /* How should we handle "C:file.c"? */
+ slash = strchr(filename, '/');
+ bslash = strchr(filename, '\\');
+ if (slash == NULL)
+ return bslash;
+ else if (bslash == NULL)
+ return slash;
+ else
+ return (slash < bslash) ? slash : bslash;
+ #endif
+ }
+
+
+ /*
+ * last_path_separator
+ */
+ char *last_path_separator(const char *filename)
+ {
+ #ifndef WIN32
+ return strrchr(filename, '/');
+ #else
+ char *slash, *bslash;
+
+ /* How should we handle "C:file.c"? */
+ slash = strrchr(filename, '/');
+ bslash = strrchr(filename, '\\');
+ if (slash == NULL)
+ return bslash;
+ else if (bslash == NULL)
+ return slash;
+ else
+ return (slash > bslash) ? slash : bslash;
+ #endif
+ }
+
+
+ /*
+ * Extracts the actual name of the program as called.
+ */
+ char *
+ get_progname(char *argv0)
+ {
+ if (!last_path_separator(argv0))
+ return argv0;
+ else
+ return last_path_separator(argv0) + 1;
+ }