dynamic_library_path on Win32

Started by Thomas Hallgrenover 21 years ago9 messages
#1Thomas Hallgren
thhal@mailblocks.com

I'm using CVS HEAD in a windows environment. I'm trying to start the
postmaster using "postmaster -c dynamic_library_path=C:/foo/bar". It starts
just fine, then, when I ask it to load a module, an error is generating
stating:

ERROR: component in parameter "dynamic_library_path" is not an absolute path

I added a trace to find out what it thinks the path is. It prints "C".
Obviously it treats ':' as a path separator somewhere. Is that the intended
behavior on win32?

Kind regards,

Thomas Hallgren

#2Andrew Dunstan
andrew@dunslane.net
In reply to: Thomas Hallgren (#1)
Re: dynamic_library_path on Win32

Thomas Hallgren wrote:

I'm using CVS HEAD in a windows environment. I'm trying to start the
postmaster using "postmaster -c dynamic_library_path=C:/foo/bar". It starts
just fine, then, when I ask it to load a module, an error is generating
stating:

ERROR: component in parameter "dynamic_library_path" is not an absolute path

I added a trace to find out what it thinks the path is. It prints "C".
Obviously it treats ':' as a path separator somewhere. Is that the intended
behavior on win32?

You've found a bug. Clearly we need to adjust the parsing of
dynamic_library_path and probably preload_libraries for Win32.

cheers

andrew

#3Tom Lane
tgl@sss.pgh.pa.us
In reply to: Thomas Hallgren (#1)
Re: dynamic_library_path on Win32

"Thomas Hallgren" <thhal@mailblocks.com> writes:

I'm using CVS HEAD in a windows environment. I'm trying to start the
postmaster using "postmaster -c dynamic_library_path=C:/foo/bar". It starts
just fine, then, when I ask it to load a module, an error is generating
stating:

ERROR: component in parameter "dynamic_library_path" is not an absolute path

I added a trace to find out what it thinks the path is. It prints "C".
Obviously it treats ':' as a path separator somewhere.

Yeah. dynamic_library_path follows the universal Unix convention that
search path components are separated by ':'. Is there any equivalent
convention in Windows?

regards, tom lane

#4Thomas Hallgren
thhal@mailblocks.com
In reply to: Thomas Hallgren (#1)
Re: dynamic_library_path on Win32

Yes, on windows, you use a semicolon as path separator.

regards,

- thomas

----- Original Message -----
From: "Tom Lane" <tgl@sss.pgh.pa.us>
To: "Thomas Hallgren" <thhal@mailblocks.com>
Cc: <pgsql-hackers@postgresql.org>
Sent: Saturday, May 29, 2004 17:20
Subject: Re: [HACKERS] dynamic_library_path on Win32

"Thomas Hallgren" <thhal@mailblocks.com> writes:

I'm using CVS HEAD in a windows environment. I'm trying to start the
postmaster using "postmaster -c dynamic_library_path=C:/foo/bar". It

starts

just fine, then, when I ask it to load a module, an error is generating
stating:

ERROR: component in parameter "dynamic_library_path" is not an absolute

path

Show quoted text

I added a trace to find out what it thinks the path is. It prints "C".
Obviously it treats ':' as a path separator somewhere.

Yeah. dynamic_library_path follows the universal Unix convention that
search path components are separated by ':'. Is there any equivalent
convention in Windows?

regards, tom lane

#5Magnus Hagander
mha@sollentuna.net
In reply to: Thomas Hallgren (#4)
Re: dynamic_library_path on Win32

I'm using CVS HEAD in a windows environment. I'm trying to start the
postmaster using "postmaster -c

dynamic_library_path=C:/foo/bar". It starts

just fine, then, when I ask it to load a module, an error is

generating

stating:

ERROR: component in parameter "dynamic_library_path" is not

an absolute path

I added a trace to find out what it thinks the path is. It

prints "C".

Obviously it treats ':' as a path separator somewhere.

Yeah. dynamic_library_path follows the universal Unix convention that
search path components are separated by ':'. Is there any equivalent
convention in Windows?

';' is what's used in PATH, and several other such places.

//Magnus

#6Andrew Dunstan
andrew@dunslane.net
In reply to: Tom Lane (#3)
Re: dynamic_library_path on Win32

Tom Lane wrote:

"Thomas Hallgren" <thhal@mailblocks.com> writes:

I'm using CVS HEAD in a windows environment. I'm trying to start the
postmaster using "postmaster -c dynamic_library_path=C:/foo/bar". It starts
just fine, then, when I ask it to load a module, an error is generating
stating:

ERROR: component in parameter "dynamic_library_path" is not an absolute path

I added a trace to find out what it thinks the path is. It prints "C".
Obviously it treats ':' as a path separator somewhere.

Yeah. dynamic_library_path follows the universal Unix convention that
search path components are separated by ':'. Is there any equivalent
convention in Windows?

src/port/exec.c has this:

#ifdef WIN32
#define PATHSEP ';'
#else
#define PATHSEP ':'
#endif

It should probably move to c.h.

cheers

andrew

#7Tom Lane
tgl@sss.pgh.pa.us
In reply to: Andrew Dunstan (#2)
Re: dynamic_library_path on Win32

Andrew Dunstan <andrew@dunslane.net> writes:

You've found a bug. Clearly we need to adjust the parsing of
dynamic_library_path and probably preload_libraries for Win32.

Yup. Using PATHSEP sounded reasonable to me. Any volunteer to fix
this? (Don't forget to patch the docs for these variables, too.)

regards, tom lane

#8Bruce Momjian
pgman@candle.pha.pa.us
In reply to: Tom Lane (#7)
Re: dynamic_library_path on Win32

I can do it but will be a few days until I get to it.

---------------------------------------------------------------------------

Tom Lane wrote:

Andrew Dunstan <andrew@dunslane.net> writes:

You've found a bug. Clearly we need to adjust the parsing of
dynamic_library_path and probably preload_libraries for Win32.

Yup. Using PATHSEP sounded reasonable to me. Any volunteer to fix
this? (Don't forget to patch the docs for these variables, too.)

regards, tom lane

---------------------------(end of broadcast)---------------------------
TIP 4: Don't 'kill -9' the postmaster

-- 
  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
#9Thomas Hallgren
thhal@mailblocks.com
In reply to: Tom Lane (#7)
1 attachment(s)
Re: [HACKERS] dynamic_library_path on Win32

Attached is a patch that takes care of the PATHSEP issue. I made a more
extensive change then what was suggested. I found the file path.c that
contained a lot of "Unix/Windows" agnostic functions so I added a function
there instead and removed the PATHSEP declaration in exec.c altogether. All
to keep things from scattering all over the code.

I also took the liberty of changing the name of the functions
"first_path_sep" and "last_path_sep". Where I come from (and I'm apparently
not alone given the former macro name PATHSEP), they should be called
"first_dir_sep" and "last_dir_sep". The new function I introduced, that
actually finds path separators, is now the "first_path_sep". The patch
contains changes on all affected places of course.

I also changed the documentation on dynamic_library_path to reflect the
chagnes.

Kind regards,

Thomas Hallgren

"Bruce Momjian" <pgman@candle.pha.pa.us> wrote in message
news:200405300307.i4U37sE17714@candle.pha.pa.us...

I can do it but will be a few days until I get to it.

--------------------------------------------------------------------------

-

Tom Lane wrote:

Andrew Dunstan <andrew@dunslane.net> writes:

You've found a bug. Clearly we need to adjust the parsing of
dynamic_library_path and probably preload_libraries for Win32.

Yup. Using PATHSEP sounded reasonable to me. Any volunteer to fix
this? (Don't forget to patch the docs for these variables, too.)

regards, tom lane

---------------------------(end of broadcast)---------------------------
TIP 4: Don't 'kill -9' the postmaster

-- 
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

Show quoted text

---------------------------(end of broadcast)---------------------------
TIP 6: Have you searched our list archives?

http://archives.postgresql.org

Attachments:

patch.txttext/plain; name=patch.txtDownload
Index: doc/src/sgml/runtime.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql-server/doc/src/sgml/runtime.sgml,v
retrieving revision 1.265
diff -u -r1.265 runtime.sgml
--- doc/src/sgml/runtime.sgml	26 May 2004 18:51:43 -0000	1.265
+++ doc/src/sgml/runtime.sgml	7 Jun 2004 21:48:09 -0000
@@ -2617,8 +2617,9 @@
        </para>
 
        <para>
-        The value for <varname>dynamic_library_path</varname> has to be a colon-separated
-        list of absolute directory names. If a directory name starts
+        The value for <varname>dynamic_library_path</varname> has to be a
+        list of absolute directory names separated by colon or, in windows
+        environments with semi-colon. If a directory name starts
         with the special value <literal>$libdir</literal>, the
         compiled-in <productname>PostgreSQL</productname> package
         library directory is substituted. This where the modules
@@ -2628,6 +2629,10 @@
         example:
 <programlisting>
 dynamic_library_path = '/usr/local/lib/postgresql:/home/my_project/lib:$libdir'
+</programlisting>
+        or, in a windows environment:
+<programlisting>
+dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir'
 </programlisting>
        </para>
 
Index: src/backend/commands/dbcommands.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/commands/dbcommands.c,v
retrieving revision 1.134
diff -u -r1.134 dbcommands.c
--- src/backend/commands/dbcommands.c	26 May 2004 13:56:45 -0000	1.134
+++ src/backend/commands/dbcommands.c	7 Jun 2004 21:48:09 -0000
@@ -941,7 +941,7 @@
 	if (dbpath == NULL || dbpath[0] == '\0')
 		return NULL;
 
-	if (first_path_separator(dbpath))
+	if (first_dir_separator(dbpath))
 	{
 		if (!is_absolute_path(dbpath))
 			ereport(ERROR,
Index: src/backend/utils/fmgr/dfmgr.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/fmgr/dfmgr.c,v
retrieving revision 1.73
diff -u -r1.73 dfmgr.c
--- src/backend/utils/fmgr/dfmgr.c	26 May 2004 18:35:39 -0000	1.73
+++ src/backend/utils/fmgr/dfmgr.c	7 Jun 2004 21:48:10 -0000
@@ -288,7 +288,7 @@
 
 	AssertArg(name);
 
-	have_slash = (first_path_separator(name) != NULL);
+	have_slash = (first_dir_separator(name) != NULL);
 
 	if (!have_slash)
 	{
@@ -343,7 +343,7 @@
 	if (name[0] != '$')
 		return pstrdup(name);
 
-	if ((sep_ptr = first_path_separator(name)) == NULL)
+	if ((sep_ptr = first_dir_separator(name)) == NULL)
 		sep_ptr = name + strlen(name);
 		
 	if (strlen("$libdir") != sep_ptr - name ||
@@ -374,7 +374,7 @@
 	size_t		baselen;
 
 	AssertArg(basename != NULL);
-	AssertArg(first_path_separator(basename) == NULL);
+	AssertArg(first_dir_separator(basename) == NULL);
 	AssertState(Dynamic_library_path != NULL);
 
 	p = Dynamic_library_path;
@@ -389,13 +389,18 @@
 		char	   *piece;
 		char	   *mangled;
 		char	   *full;
+		const char *pathSep;
 
-		len = strcspn(p, ":");
-
-		if (len == 0)
+		piece = first_path_separator(p);
+		if(piece == p)
 			ereport(ERROR,
 					(errcode(ERRCODE_INVALID_NAME),
 			   errmsg("zero-length component in parameter \"dynamic_library_path\"")));
+
+		if(piece == 0)
+		   len = strlen(p);
+		else
+		   len = piece - p;
 
 		piece = palloc(len + 1);
 		strncpy(piece, p, len);
Index: src/bin/initdb/initdb.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/bin/initdb/initdb.c,v
retrieving revision 1.35
diff -u -r1.35 initdb.c
--- src/bin/initdb/initdb.c	3 Jun 2004 00:07:36 -0000	1.35
+++ src/bin/initdb/initdb.c	7 Jun 2004 21:48:11 -0000
@@ -1934,7 +1934,7 @@
 
 	/* store binary directory */
 	strcpy(bin_path, backend_exec);
-	*last_path_separator(bin_path) = '\0';
+	*last_dir_separator(bin_path) = '\0';
 
 	if (!share_path)
 	{
Index: src/include/port.h
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/include/port.h,v
retrieving revision 1.40
diff -u -r1.40 port.h
--- src/include/port.h	3 Jun 2004 00:07:38 -0000	1.40
+++ src/include/port.h	7 Jun 2004 21:48:11 -0000
@@ -22,8 +22,22 @@
 bool set_noblock(int sock);
 
 /* Portable path handling for Unix/Win32 */
+
+/* Find the location of the first directory separator, return
+ * NULL if not found.
+ */
+extern char *first_dir_separator(const char *filename);
+
+/* Find the location of the last directory separator, return
+ * NULL if not found.
+ */
+extern char *last_dir_separator(const char *filename);
+
+/* Find the location of the first path separator (i.e. ':' on
+ * Unix, ';' on Windows), return NULL if not found.
+ */
 extern char *first_path_separator(const char *filename);
-extern char *last_path_separator(const char *filename);
+
 extern void canonicalize_path(char *path);
 extern const char *get_progname(const char *argv0);
 extern void get_share_path(const char *my_exec_path, char *ret_path);
Index: src/interfaces/ecpg/ecpglib/connect.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/ecpg/ecpglib/connect.c,v
retrieving revision 1.21
diff -u -r1.21 connect.c
--- src/interfaces/ecpg/ecpglib/connect.c	15 Mar 2004 16:27:43 -0000	1.21
+++ src/interfaces/ecpg/ecpglib/connect.c	7 Jun 2004 21:48:11 -0000
@@ -323,7 +323,7 @@
 				*tmp = '\0';
 			}
 
-			tmp = last_path_separator(dbname + offset);
+			tmp = last_dir_separator(dbname + offset);
 			if (tmp != NULL)	/* database name given */
 			{
 				realname = strdup(tmp + 1);
Index: src/interfaces/ecpg/preproc/ecpg.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/ecpg/preproc/ecpg.c,v
retrieving revision 1.87
diff -u -r1.87 ecpg.c
--- src/interfaces/ecpg/preproc/ecpg.c	17 May 2004 14:35:34 -0000	1.87
+++ src/interfaces/ecpg/preproc/ecpg.c	7 Jun 2004 21:48:11 -0000
@@ -268,7 +268,7 @@
 				strcpy(input_filename, argv[fnr]);
 
 				/* take care of relative paths */
-				ptr2ext = last_path_separator(input_filename);
+				ptr2ext = last_dir_separator(input_filename);
 				ptr2ext = (ptr2ext ? strrchr(ptr2ext, '.') : strrchr(input_filename, '.'));
 
 				/* no extension? */
Index: src/interfaces/libpq/fe-connect.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/fe-connect.c,v
retrieving revision 1.272
diff -u -r1.272 fe-connect.c
--- src/interfaces/libpq/fe-connect.c	3 Jun 2004 00:07:38 -0000	1.272
+++ src/interfaces/libpq/fe-connect.c	7 Jun 2004 21:48:12 -0000
@@ -679,7 +679,7 @@
 				*tmp = '\0';
 			}
 
-			tmp = last_path_separator(conn->dbName + offset);
+			tmp = last_dir_separator(conn->dbName + offset);
 			if (tmp != NULL)	/* database name given */
 			{
 				if (conn->dbName)
Index: src/port/exec.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/port/exec.c,v
retrieving revision 1.15
diff -u -r1.15 exec.c
--- src/port/exec.c	24 May 2004 22:35:37 -0000	1.15
+++ src/port/exec.c	7 Jun 2004 21:48:12 -0000
@@ -28,13 +28,6 @@
 
 #define _(x) gettext(x)
 
-/* $PATH (or %PATH%) path separator */
-#ifdef WIN32
-#define PATHSEP ';'
-#else
-#define PATHSEP ':'
-#endif
-
 #ifndef S_IRUSR					/* XXX [TRH] should be in a header */
 #define S_IRUSR		 S_IREAD
 #define S_IWUSR		 S_IWRITE
@@ -196,7 +189,7 @@
 	 * it).
 	 */
 	/* Does argv0 have a separator? */
-	if ((path = last_path_separator(argv0)))
+	if ((path = last_dir_separator(argv0)))
 	{
 		if (*++path == '\0')
 		{
@@ -247,7 +240,7 @@
 			else
 				startp = endp + 1;
 
-			endp = strchr(startp, PATHSEP);
+			endp = first_path_separator(startp);
 			if (!endp)
 				endp = startp + strlen(startp);	/* point to end */
 
@@ -303,7 +296,7 @@
 		return -1;
 
 	/* Trim off program name and keep just directory */	
-	*last_path_separator(retpath) = '\0';
+	*last_dir_separator(retpath) = '\0';
 
 	snprintf(retpath + strlen(retpath), MAXPGPATH - strlen(retpath),
 			 "/%s%s", target, EXE);
Index: src/port/path.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/port/path.c,v
retrieving revision 1.17
diff -u -r1.17 path.c
--- src/port/path.c	3 Jun 2004 00:07:38 -0000	1.17
+++ src/port/path.c	7 Jun 2004 21:48:12 -0000
@@ -21,9 +21,15 @@
 
 
 #ifndef WIN32
-#define	ISSEP(ch)	((ch) == '/')
+#define	IS_DIR_SEP(ch)	((ch) == '/')
 #else
-#define	ISSEP(ch)	((ch) == '/' || (ch) == '\\')
+#define	IS_DIR_SEP(ch)	((ch) == '/' || (ch) == '\\')
+#endif
+
+#ifndef WIN32
+#define	IS_PATH_SEP(ch)	((ch) == ':')
+#else
+#define	IS_PATH_SEP(ch)	((ch) == ';')
 #endif
 
 const static char *relative_path(const char *bin_path, const char *other_path);
@@ -33,7 +39,7 @@
 /* Move to last of consecutive separators or to null byte */
 #define MOVE_TO_SEP_END(p) \
 { \
-	while (ISSEP((p)[0]) && (ISSEP((p)[1]) || !(p)[1])) \
+	while (IS_DIR_SEP((p)[0]) && (IS_DIR_SEP((p)[1]) || !(p)[1])) \
 		(p)++; \
 }
 
@@ -47,6 +53,20 @@
 } while (0)
 
 /*
+ *	first_dir_separator
+ */
+char *
+first_dir_separator(const char *filename)
+{
+	char	   *p;
+
+	for (p = (char *)filename; *p; p++)
+		if (IS_DIR_SEP(*p))
+			return p;
+	return NULL;
+}
+
+/*
  *	first_path_separator
  */
 char *
@@ -55,22 +75,21 @@
 	char	   *p;
 
 	for (p = (char *)filename; *p; p++)
-		if (ISSEP(*p))
+		if (IS_PATH_SEP(*p))
 			return p;
 	return NULL;
 }
 
-
 /*
- *	last_path_separator
+ *	last_dir_separator
  */
 char *
-last_path_separator(const char *filename)
+last_dir_separator(const char *filename)
 {
 	char	   *p, *ret = NULL;
 
 	for (p = (char *)filename; *p; p++)
-		if (ISSEP(*p))
+		if (IS_DIR_SEP(*p))
 			ret = p;
 	return ret;
 }
@@ -108,10 +127,10 @@
 const char *
 get_progname(const char *argv0)
 {
-	if (!last_path_separator(argv0))
+	if (!last_dir_separator(argv0))
 		return argv0;
 	else
-		return last_path_separator(argv0) + 1;
+		return last_dir_separator(argv0) + 1;
 }
 
 
@@ -307,7 +326,7 @@
 			break;
 
 		/* Win32 filesystem is case insensitive */
-		if ((!ISSEP(*bin_path) || !ISSEP(*other_path)) &&
+		if ((!IS_DIR_SEP(*bin_path) || !IS_DIR_SEP(*other_path)) &&
 #ifndef WIN32
 			*bin_path != *other_path)
 #else
@@ -315,7 +334,7 @@
 #endif
 				break;
 
-		if (ISSEP(*other_path))
+		if (IS_DIR_SEP(*other_path))
 			other_sep = other_path + 1;		/* past separator */
 			
 		bin_path++;
@@ -327,7 +346,7 @@
 		return NULL;
 
 	/* advance past directory name */	
-	while (!ISSEP(*bin_path) && *bin_path)
+	while (!IS_DIR_SEP(*bin_path) && *bin_path)
 		bin_path++;
 
 	MOVE_TO_SEP_END(bin_path);
@@ -353,9 +372,9 @@
 	if (path[0] == '\0')
 		return;
 
-	for (p = path + strlen(path) - 1; ISSEP(*p) && p > path; p--)
+	for (p = path + strlen(path) - 1; IS_DIR_SEP(*p) && p > path; p--)
 		;
-	for (; !ISSEP(*p) && p > path; p--)
+	for (; !IS_DIR_SEP(*p) && p > path; p--)
 		;
 	*p = '\0';
 	return;
@@ -373,6 +392,6 @@
 	
 	/* trim off trailing slashes */
 	if (p > path)
-		for (p--; p >= path && ISSEP(*p); p--)
+		for (p--; p >= path && IS_DIR_SEP(*p); p--)
 			*p = '\0';
 }