@@ -627,31 +627,9 @@ create_tablespace_directories(const char *location, const Oid tablespaceoid)
627
627
628
628
/*
629
629
* In recovery, remove old symlink, in case it points to the wrong place.
630
- *
631
- * On Windows, junction points act like directories so we must be able to
632
- * apply rmdir; in general it seems best to make this code work like the
633
- * symlink removal code in destroy_tablespace_directories, except that
634
- * failure to remove is always an ERROR.
635
630
*/
636
631
if (InRecovery )
637
- {
638
- if (lstat (linkloc , & st ) == 0 && S_ISDIR (st .st_mode ))
639
- {
640
- if (rmdir (linkloc ) < 0 )
641
- ereport (ERROR ,
642
- (errcode_for_file_access (),
643
- errmsg ("could not remove directory \"%s\": %m" ,
644
- linkloc )));
645
- }
646
- else
647
- {
648
- if (unlink (linkloc ) < 0 && errno != ENOENT )
649
- ereport (ERROR ,
650
- (errcode_for_file_access (),
651
- errmsg ("could not remove symbolic link \"%s\": %m" ,
652
- linkloc )));
653
- }
654
- }
632
+ remove_tablespace_symlink (linkloc );
655
633
656
634
/*
657
635
* Create the symlink under PGDATA
@@ -802,7 +780,8 @@ destroy_tablespace_directories(Oid tablespaceoid, bool redo)
802
780
errmsg ("could not remove directory \"%s\": %m" ,
803
781
linkloc )));
804
782
}
805
- else
783
+ #ifdef S_ISLNK
784
+ else if (S_ISLNK (st .st_mode ))
806
785
{
807
786
if (unlink (linkloc ) < 0 )
808
787
{
@@ -814,6 +793,15 @@ destroy_tablespace_directories(Oid tablespaceoid, bool redo)
814
793
linkloc )));
815
794
}
816
795
}
796
+ #endif
797
+ else
798
+ {
799
+ /* Refuse to remove anything that's not a directory or symlink */
800
+ ereport (redo ? LOG : ERROR ,
801
+ (ERRCODE_SYSTEM_ERROR ,
802
+ errmsg ("not a directory or symbolic link: \"%s\"" ,
803
+ linkloc )));
804
+ }
817
805
818
806
pfree (linkloc_with_version_dir );
819
807
pfree (linkloc );
@@ -848,6 +836,59 @@ directory_is_empty(const char *path)
848
836
return true;
849
837
}
850
838
839
+ /*
840
+ * remove_tablespace_symlink
841
+ *
842
+ * This function removes symlinks in pg_tblspc. On Windows, junction points
843
+ * act like directories so we must be able to apply rmdir. This function
844
+ * works like the symlink removal code in destroy_tablespace_directories,
845
+ * except that failure to remove is always an ERROR. But if the file doesn't
846
+ * exist at all, that's OK.
847
+ */
848
+ void
849
+ remove_tablespace_symlink (const char * linkloc )
850
+ {
851
+ struct stat st ;
852
+
853
+ if (lstat (linkloc , & st ) != 0 )
854
+ {
855
+ if (errno == ENOENT )
856
+ return ;
857
+ ereport (ERROR ,
858
+ (errcode_for_file_access (),
859
+ errmsg ("could not stat \"%s\": %m" , linkloc )));
860
+ }
861
+
862
+ if (S_ISDIR (st .st_mode ))
863
+ {
864
+ /*
865
+ * This will fail if the directory isn't empty, but not
866
+ * if it's a junction point.
867
+ */
868
+ if (rmdir (linkloc ) < 0 )
869
+ ereport (ERROR ,
870
+ (errcode_for_file_access (),
871
+ errmsg ("could not remove directory \"%s\": %m" ,
872
+ linkloc )));
873
+ }
874
+ #ifdef S_ISLNK
875
+ else if (S_ISLNK (st .st_mode ))
876
+ {
877
+ if (unlink (linkloc ) < 0 && errno != ENOENT )
878
+ ereport (ERROR ,
879
+ (errcode_for_file_access (),
880
+ errmsg ("could not remove symbolic link \"%s\": %m" ,
881
+ linkloc )));
882
+ }
883
+ #endif
884
+ else
885
+ {
886
+ /* Refuse to remove anything that's not a directory or symlink */
887
+ ereport (ERROR ,
888
+ (errmsg ("not a directory or symbolic link: \"%s\"" ,
889
+ linkloc )));
890
+ }
891
+ }
851
892
852
893
/*
853
894
* Rename a tablespace
0 commit comments