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