Win32 path patch - Mailing list pgsql-patches
From | Bruce Momjian |
---|---|
Subject | Win32 path patch |
Date | |
Msg-id | 200304022015.h32KFxR06550@candle.pha.pa.us Whole thread Raw |
Responses |
Re: Win32 path patch
|
List | pgsql-patches |
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; + }
pgsql-patches by date: