Skip to content

Commit 93c301f

Browse files
committed
Fix multiple bugs in tablespace symlink removal.
Don't try to examine S_ISLNK(st.st_mode) after a failed lstat(). It's undefined. Also, if the lstat() reported ENOENT, we do not wish that to be a hard error, but the code might nonetheless treat it as one (giving an entirely misleading error message, too) depending on luck-of-the-draw as to what S_ISLNK() returned. Don't throw error for ENOENT from rmdir(), either. (We're not really expecting ENOENT because we just stat'd the file successfully; but if we're going to allow ENOENT in the symlink code path, surely the directory code path should too.) Generate an appropriate errcode for its-the-wrong-type-of-file complaints. (ERRCODE_SYSTEM_ERROR doesn't seem appropriate, and failing to write errcode() around it certainly doesn't work, and not writing an errcode at all is not per project policy.) Valgrind noticed the undefined S_ISLNK result; the other problems emerged while reading the code in the area. All of this appears to have been introduced in 8f15f74. Back-patch to 9.5 where that commit appeared.
1 parent 752b948 commit 93c301f

File tree

1 file changed

+23
-9
lines changed

1 file changed

+23
-9
lines changed

src/backend/commands/tablespace.c

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -773,13 +773,26 @@ destroy_tablespace_directories(Oid tablespaceoid, bool redo)
773773
remove_symlink:
774774
linkloc = pstrdup(linkloc_with_version_dir);
775775
get_parent_directory(linkloc);
776-
if (lstat(linkloc, &st) == 0 && S_ISDIR(st.st_mode))
776+
if (lstat(linkloc, &st) < 0)
777+
{
778+
int saved_errno = errno;
779+
780+
ereport(redo ? LOG : (saved_errno == ENOENT ? WARNING : ERROR),
781+
(errcode_for_file_access(),
782+
errmsg("could not stat file \"%s\": %m",
783+
linkloc)));
784+
}
785+
else if (S_ISDIR(st.st_mode))
777786
{
778787
if (rmdir(linkloc) < 0)
779-
ereport(redo ? LOG : ERROR,
788+
{
789+
int saved_errno = errno;
790+
791+
ereport(redo ? LOG : (saved_errno == ENOENT ? WARNING : ERROR),
780792
(errcode_for_file_access(),
781793
errmsg("could not remove directory \"%s\": %m",
782794
linkloc)));
795+
}
783796
}
784797
#ifdef S_ISLNK
785798
else if (S_ISLNK(st.st_mode))
@@ -799,7 +812,7 @@ destroy_tablespace_directories(Oid tablespaceoid, bool redo)
799812
{
800813
/* Refuse to remove anything that's not a directory or symlink */
801814
ereport(redo ? LOG : ERROR,
802-
(ERRCODE_SYSTEM_ERROR,
815+
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
803816
errmsg("\"%s\" is not a directory or symbolic link",
804817
linkloc)));
805818
}
@@ -851,7 +864,7 @@ remove_tablespace_symlink(const char *linkloc)
851864
{
852865
struct stat st;
853866

854-
if (lstat(linkloc, &st) != 0)
867+
if (lstat(linkloc, &st) < 0)
855868
{
856869
if (errno == ENOENT)
857870
return;
@@ -863,10 +876,10 @@ remove_tablespace_symlink(const char *linkloc)
863876
if (S_ISDIR(st.st_mode))
864877
{
865878
/*
866-
* This will fail if the directory isn't empty, but not
867-
* if it's a junction point.
879+
* This will fail if the directory isn't empty, but not if it's a
880+
* junction point.
868881
*/
869-
if (rmdir(linkloc) < 0)
882+
if (rmdir(linkloc) < 0 && errno != ENOENT)
870883
ereport(ERROR,
871884
(errcode_for_file_access(),
872885
errmsg("could not remove directory \"%s\": %m",
@@ -878,15 +891,16 @@ remove_tablespace_symlink(const char *linkloc)
878891
if (unlink(linkloc) < 0 && errno != ENOENT)
879892
ereport(ERROR,
880893
(errcode_for_file_access(),
881-
errmsg("could not remove symbolic link \"%s\": %m",
894+
errmsg("could not remove symbolic link \"%s\": %m",
882895
linkloc)));
883896
}
884897
#endif
885898
else
886899
{
887900
/* Refuse to remove anything that's not a directory or symlink */
888901
ereport(ERROR,
889-
(errmsg("\"%s\" is not a directory or symbolic link",
902+
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
903+
errmsg("\"%s\" is not a directory or symbolic link",
890904
linkloc)));
891905
}
892906
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy