char *linkloc = palloc(OIDCHARS + OIDCHARS + 1);
char *location_with_version_dir = palloc(strlen(location) + 1 +
strlen(TABLESPACE_VERSION_DIRECTORY) + 1);
+ struct stat st;
sprintf(linkloc, "pg_tblspc/%u", tablespaceoid);
sprintf(location_with_version_dir, "%s/%s", location,
if (InRecovery)
{
- struct stat st;
-
/*
* Our theory for replaying a CREATE is to forcibly drop the target
* subdirectory if present, and then recreate it. This may be more
location_with_version_dir)));
}
- /* Remove old symlink in recovery, in case it points to the wrong place */
+ /*
+ * 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 (unlink(linkloc) < 0 && errno != ENOENT)
- ereport(ERROR,
- (errcode_for_file_access(),
- errmsg("could not remove symbolic link \"%s\": %m",
- linkloc)));
+ 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)));
+ }
}
/*