On 2022-08-11 07:55, Thomas Munro wrote:
I checked a few variants:

21.07.2022  15:11    <JUNCTION>     HOME [\??\Volume{GUID}\]
09.08.2022  15:06    <JUNCTION>     Test1 [\\?\Volume{GUID}\]
09.08.2022  15:06    <JUNCTION>     Test2 [\\.\Volume{GUID}\]
09.08.2022  15:17    <JUNCTION>     Test3 [\??\Volume{GUID}\]
09.08.2022  15:27    <JUNCTION>     Test4 [C:\temp\1]
09.08.2022  15:28    <JUNCTION>     Test5 [C:\HOME\Temp\1]

One more thing I wondered about, now that we're following junctions
outside PGDATA: can a junction point to another junction?  If so, I
didn't allow for that: stat() gives up after one hop, because I
figured that was enough for the stuff we expect inside PGDATA and I
couldn't find any evidence in the man pages that referred to chains.
But if you *are* allowed to create a junction "c:\huey" that points to
junction "c:\dewey" that points to "c:\louie", and then you do initdb
-D c:\huey\pgdata, then I guess it would fail.  Would you mind
checking if that is a real possibility, and if so, testing this
chain-following patch to see if it fixes it?

I made some junctions and rechecked both patches.

11.08.2022  16:11    <JUNCTION>     donald [C:\huey]
11.08.2022  13:23    <JUNCTION>     huey [C:\dewey]
11.08.2022  13:23    <JUNCTION>     dewey [C:\louie]
11.08.2022  16:57    <DIR>          louie

With the small attached patch initdb succeeded in any of these
"directories". If the junction chain is too long, initdb fails with
"could not create directory" as expected.

initdb -D huey/pgdata
...
Success.

initdb -N -D donald
...
Success.

11.08.2022  17:32    <DIR>          1
11.08.2022  17:32    <JUNCTION>     2 [C:\1]
11.08.2022  17:32    <JUNCTION>     3 [C:\2]
11.08.2022  17:32    <JUNCTION>     4 [C:\3]
11.08.2022  17:32    <JUNCTION>     5 [C:\4]
11.08.2022  17:32    <JUNCTION>     6 [C:\5]
11.08.2022  17:32    <JUNCTION>     7 [C:\6]
11.08.2022  17:32    <JUNCTION>     8 [C:\7]
11.08.2022  17:32    <JUNCTION>     9 [C:\8]
11.08.2022  17:32    <JUNCTION>     10 [C:\9]

initdb -D 10/pgdata
...
creating directory 10/pgdata ... initdb: error: could not create directory "10": File exists

initdb -D 9/pgdata
...
Success.
--- win32stat.c.bak	2022-08-11 17:15:10.775412600 +0700
+++ win32stat.c	2022-08-11 16:47:41.992805700 +0700
@@ -186,9 +186,12 @@
 {
 	int			loops = 0;
 	int			ret;
+	char		curr[MAXPGPATH];
 
 	ret = _pglstat64(name, buf);
 
+	strlcpy(curr, name, MAXPGPATH);
+
 	/* Do we need to follow a symlink (junction point)? */
 	while (ret == 0 && S_ISLNK(buf->st_mode))
 	{
@@ -211,7 +214,7 @@
 		 * That could be optimized, but stat() on symlinks is probably rare
 		 * and this way is simple.
 		 */
-		size = readlink(name, next, sizeof(next));
+		size = readlink(curr, next, sizeof(next));
 		if (size < 0)
 		{
 			if (errno == EACCES &&
@@ -230,6 +233,7 @@
 		next[size] = 0;
 
 		ret = _pglstat64(next, buf);
+		strcpy(curr, next);
 	}
 
 	return ret;

Reply via email to