diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 5f0551a..f64a7eda 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -6125,7 +6125,6 @@ StartupXLOG(void) if (read_tablespace_map(&tablespaces)) { ListCell *lc; - struct stat st; foreach(lc, tablespaces) { @@ -6136,27 +6135,9 @@ StartupXLOG(void) /* * Remove the existing symlink if any and Create the symlink - * under PGDATA. We need to use rmtree instead of rmdir as - * the link location might contain directories or files - * corresponding to the actual path. Some tar utilities do - * things that way while extracting symlinks. + * under PGDATA. */ - if (lstat(linkloc, &st) == 0 && S_ISDIR(st.st_mode)) - { - if (!rmtree(linkloc,true)) - ereport(ERROR, - (errcode_for_file_access(), - errmsg("could not remove directory \"%s\": %m", - linkloc))); - } - else - { - if (unlink(linkloc) < 0 && errno != ENOENT) - ereport(ERROR, - (errcode_for_file_access(), - errmsg("could not remove symbolic link \"%s\": %m", - linkloc))); - } + rmsymlink(linkloc); if (symlink(ti->path, linkloc) < 0) ereport(ERROR, diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c index 4ec1aff..76e62b2 100644 --- a/src/backend/commands/tablespace.c +++ b/src/backend/commands/tablespace.c @@ -627,31 +627,9 @@ create_tablespace_directories(const char *location, const Oid tablespaceoid) /* * In recovery, remove old symlink, in case it points to the wrong place. - * - * On Windows, junction points act like directories so we must be able to - * apply rmdir; in general it seems best to make this code work like the - * symlink removal code in destroy_tablespace_directories, except that - * failure to remove is always an ERROR. */ if (InRecovery) - { - if (lstat(linkloc, &st) == 0 && S_ISDIR(st.st_mode)) - { - if (rmdir(linkloc) < 0) - ereport(ERROR, - (errcode_for_file_access(), - errmsg("could not remove directory \"%s\": %m", - linkloc))); - } - else - { - if (unlink(linkloc) < 0 && errno != ENOENT) - ereport(ERROR, - (errcode_for_file_access(), - errmsg("could not remove symbolic link \"%s\": %m", - linkloc))); - } - } + rmsymlink(linkloc); /* * Create the symlink under PGDATA diff --git a/src/common/rmtree.c b/src/common/rmtree.c index 75f47f7..8facfd5 100644 --- a/src/common/rmtree.c +++ b/src/common/rmtree.c @@ -129,3 +129,36 @@ rmtree(const char *path, bool rmtopdir) return result; } + +#ifndef FRONTEND +/* + * rmsymlink + * + * This function removes symlinks. On Windows, junction points act + * like directories so we must be able to apply rmdir. This function + * works like the symlink removal code in destroy_tablespace_directories, + * except that failure to remove is always an ERROR. + */ +void +rmsymlink(const char *linkloc) +{ + struct stat st; + + if (lstat(linkloc, &st) == 0 && S_ISDIR(st.st_mode)) + { + if (rmdir(linkloc) < 0) + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not remove directory \"%s\": %m", + linkloc))); + } + else + { + if (unlink(linkloc) < 0 && errno != ENOENT) + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not remove symbolic link \"%s\": %m", + linkloc))); + } +} +#endif diff --git a/src/include/port.h b/src/include/port.h index 3787cbf..f2b19f9 100644 --- a/src/include/port.h +++ b/src/include/port.h @@ -256,6 +256,7 @@ extern bool pgwin32_is_junction(char *path); #endif extern bool rmtree(const char *path, bool rmtopdir); +extern void rmsymlink(const char *linkloc); /* * stat() is not guaranteed to set the st_size field on win32, so we