aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThomas Munro <tmunro@postgresql.org>2022-08-06 12:01:42 +1200
committerAndrew Dunstan <andrew@dunslane.net>2024-11-08 09:30:09 +1030
commitb9d4a927d627bf5802e7e8e797ffc60d21bbac8b (patch)
tree825ad844f4aeabd4ab67a108f00b9a537f5c6986 /src
parentf95ad555de5623588bcc6e48fe8a3fd50d721216 (diff)
downloadpostgresql-b9d4a927d627bf5802e7e8e797ffc60d21bbac8b.tar.gz
postgresql-b9d4a927d627bf5802e7e8e797ffc60d21bbac8b.zip
Make unlink() work for junction points on Windows.
To support harmonization of Windows and Unix code, teach our unlink() wrapper that junction points need to be unlinked with rmdir() on Windows. Tested-by: Andrew Dunstan <andrew@dunslane.net> Discussion: https://postgr.es/m/CA%2BhUKGLfOOeyZpm5ByVcAt7x5Pn-%3DxGRNCvgiUPVVzjFLtnY0w%40mail.gmail.com (cherry picked from commit f357233c9db8be2a015163da8e1ab0630f444340) Author: Thomas Munro <tmunro@postgresql.org> Author: Alexandra Wang <alexandra.wang.oss@gmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/port/dirmod.c28
1 files changed, 27 insertions, 1 deletions
diff --git a/src/port/dirmod.c b/src/port/dirmod.c
index 881d23cc243..2818bfd2e95 100644
--- a/src/port/dirmod.c
+++ b/src/port/dirmod.c
@@ -99,6 +99,32 @@ int
pgunlink(const char *path)
{
int loops = 0;
+ struct stat st;
+
+ /*
+ * This function might be called for a regular file or for a junction
+ * point (which we use to emulate symlinks). The latter must be unlinked
+ * with rmdir() on Windows. Before we worry about any of that, let's see
+ * if we can unlink directly, since that's expected to be the most common
+ * case.
+ */
+ if (unlink(path) == 0)
+ return 0;
+ if (errno != EACCES)
+ return -1;
+
+ /*
+ * EACCES is reported for many reasons including unlink() of a junction
+ * point. Check if that's the case so we can redirect to rmdir().
+ *
+ * Note that by checking only once, we can't cope with a path that changes
+ * from regular file to junction point underneath us while we're retrying
+ * due to sharing violations, but that seems unlikely. We could perhaps
+ * prevent that by holding a file handle ourselves across the lstat() and
+ * the retry loop, but that seems like over-engineering for now.
+ */
+ if (lstat(path, &st) < 0)
+ return -1;
/*
* We need to loop because even though PostgreSQL uses flags that allow
@@ -107,7 +133,7 @@ pgunlink(const char *path)
* someone else to close the file, as the caller might be holding locks
* and blocking other backends.
*/
- while (unlink(path))
+ while ((S_ISLNK(st.st_mode) ? rmdir(path) : unlink(path)) < 0)
{
if (errno != EACCES)
return -1;