File tree 1 file changed +27
-1
lines changed
1 file changed +27
-1
lines changed Original file line number Diff line number Diff line change 99
99
pgunlink (const char * path )
100
100
{
101
101
int loops = 0 ;
102
+ struct stat st ;
103
+
104
+ /*
105
+ * This function might be called for a regular file or for a junction
106
+ * point (which we use to emulate symlinks). The latter must be unlinked
107
+ * with rmdir() on Windows. Before we worry about any of that, let's see
108
+ * if we can unlink directly, since that's expected to be the most common
109
+ * case.
110
+ */
111
+ if (unlink (path ) == 0 )
112
+ return 0 ;
113
+ if (errno != EACCES )
114
+ return -1 ;
115
+
116
+ /*
117
+ * EACCES is reported for many reasons including unlink() of a junction
118
+ * point. Check if that's the case so we can redirect to rmdir().
119
+ *
120
+ * Note that by checking only once, we can't cope with a path that changes
121
+ * from regular file to junction point underneath us while we're retrying
122
+ * due to sharing violations, but that seems unlikely. We could perhaps
123
+ * prevent that by holding a file handle ourselves across the lstat() and
124
+ * the retry loop, but that seems like over-engineering for now.
125
+ */
126
+ if (lstat (path , & st ) < 0 )
127
+ return -1 ;
102
128
103
129
/*
104
130
* We need to loop because even though PostgreSQL uses flags that allow
@@ -107,7 +133,7 @@ pgunlink(const char *path)
107
133
* someone else to close the file, as the caller might be holding locks
108
134
* and blocking other backends.
109
135
*/
110
- while (unlink (path ))
136
+ while (( S_ISLNK ( st . st_mode ) ? rmdir ( path ) : unlink (path )) < 0 )
111
137
{
112
138
if (errno != EACCES )
113
139
return -1 ;
You can’t perform that action at this time.
0 commit comments