0001-Raise-errors-in-pgwin32_is_junction.patch
text/x-patch
Filename: 0001-Raise-errors-in-pgwin32_is_junction.patch
Type: text/x-patch
Part: 0
Patch
Format: format-patch
Series: patch 0001
Subject: Raise errors in pgwin32_is_junction().
| File | + | − |
|---|---|---|
| src/backend/access/transam/xlog.c | 1 | 1 |
| src/backend/replication/basebackup.c | 2 | 2 |
| src/backend/storage/file/fd.c | 1 | 1 |
| src/backend/utils/adt/misc.c | 1 | 1 |
| src/bin/pg_checksums/pg_checksums.c | 1 | 1 |
| src/bin/pg_rewind/file_ops.c | 1 | 1 |
| src/common/file_utils.c | 4 | 1 |
| src/include/port.h | 1 | 1 |
| src/include/port/win32_port.h | 1 | 1 |
| src/port/dirmod.c | 33 | 3 |
From 8e0e51359c0191cf673c3ddc87a3262b13f530a4 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Wed, 16 Mar 2022 23:05:39 +1300
Subject: [PATCH] Raise errors in pgwin32_is_junction().
XXX It's not very nice to use elevel like this in frontend code
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/replication/basebackup.c | 4 ++--
src/backend/storage/file/fd.c | 2 +-
src/backend/utils/adt/misc.c | 2 +-
src/bin/pg_checksums/pg_checksums.c | 2 +-
src/bin/pg_rewind/file_ops.c | 2 +-
src/common/file_utils.c | 5 +++-
src/include/port.h | 2 +-
src/include/port/win32_port.h | 2 +-
src/port/dirmod.c | 36 +++++++++++++++++++++++++---
10 files changed, 46 insertions(+), 13 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 4ac3871c74..819b05177d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -8314,7 +8314,7 @@ do_pg_start_backup(const char *backupidstr, bool fast, TimeLineID *starttli_p,
* directories directly under pg_tblspc, which would fail below.
*/
#ifdef WIN32
- if (!pgwin32_is_junction(fullpath))
+ if (!pgwin32_is_junction(fullpath, false, ERROR))
continue;
#else
if (get_dirent_type(fullpath, de, false, ERROR) != PGFILETYPE_LNK)
diff --git a/src/backend/replication/basebackup.c b/src/backend/replication/basebackup.c
index 6884cad2c0..4be9090445 100644
--- a/src/backend/replication/basebackup.c
+++ b/src/backend/replication/basebackup.c
@@ -1352,7 +1352,7 @@ sendDir(bbsink *sink, const char *path, int basepathlen, bool sizeonly,
#ifndef WIN32
S_ISLNK(statbuf.st_mode)
#else
- pgwin32_is_junction(pathbuf)
+ pgwin32_is_junction(pathbuf, true, ERROR)
#endif
)
{
@@ -1840,7 +1840,7 @@ convert_link_to_directory(const char *pathbuf, struct stat *statbuf)
#ifndef WIN32
if (S_ISLNK(statbuf->st_mode))
#else
- if (pgwin32_is_junction(pathbuf))
+ if (pgwin32_is_junction(pathbuf, true, ERROR))
#endif
statbuf->st_mode = S_IFDIR | pg_dir_create_mode;
}
diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c
index 14b77f2861..ec2f49fefa 100644
--- a/src/backend/storage/file/fd.c
+++ b/src/backend/storage/file/fd.c
@@ -3453,7 +3453,7 @@ SyncDataDirectory(void)
xlog_is_symlink = true;
}
#else
- if (pgwin32_is_junction("pg_wal"))
+ if (pgwin32_is_junction("pg_wal", false, LOG))
xlog_is_symlink = true;
#endif
diff --git a/src/backend/utils/adt/misc.c b/src/backend/utils/adt/misc.c
index 89690be2ed..723504ab10 100644
--- a/src/backend/utils/adt/misc.c
+++ b/src/backend/utils/adt/misc.c
@@ -317,7 +317,7 @@ pg_tablespace_location(PG_FUNCTION_ARGS)
* found, a relative path to the data directory is returned.
*/
#ifdef WIN32
- if (!pgwin32_is_junction(sourcepath))
+ if (!pgwin32_is_junction(sourcepath, false, ERROR))
PG_RETURN_TEXT_P(cstring_to_text(sourcepath));
#else
if (lstat(sourcepath, &st) < 0)
diff --git a/src/bin/pg_checksums/pg_checksums.c b/src/bin/pg_checksums/pg_checksums.c
index 5f0f5ee62d..5720907d33 100644
--- a/src/bin/pg_checksums/pg_checksums.c
+++ b/src/bin/pg_checksums/pg_checksums.c
@@ -404,7 +404,7 @@ scan_directory(const char *basedir, const char *subdir, bool sizeonly)
#ifndef WIN32
else if (S_ISDIR(st.st_mode) || S_ISLNK(st.st_mode))
#else
- else if (S_ISDIR(st.st_mode) || pgwin32_is_junction(fn))
+ else if (S_ISDIR(st.st_mode) || pgwin32_is_junction(fn, false, 1))
#endif
{
/*
diff --git a/src/bin/pg_rewind/file_ops.c b/src/bin/pg_rewind/file_ops.c
index 6cb288f099..1eda2baf2f 100644
--- a/src/bin/pg_rewind/file_ops.c
+++ b/src/bin/pg_rewind/file_ops.c
@@ -434,7 +434,7 @@ recurse_dir(const char *datadir, const char *parentpath,
#ifndef WIN32
else if (S_ISLNK(fst.st_mode))
#else
- else if (pgwin32_is_junction(fullpath))
+ else if (pgwin32_is_junction(fullpath, false, 1))
#endif
{
#if defined(HAVE_READLINK) || defined(WIN32)
diff --git a/src/common/file_utils.c b/src/common/file_utils.c
index 7138068633..2db909a3aa 100644
--- a/src/common/file_utils.c
+++ b/src/common/file_utils.c
@@ -88,8 +88,11 @@ fsync_pgdata(const char *pg_data,
else if (S_ISLNK(st.st_mode))
xlog_is_symlink = true;
}
+#elif defined(FRONTEND)
+ if (pgwin32_is_junction(pg_wal, false, 1))
+ xlog_is_symlink = true;
#else
- if (pgwin32_is_junction(pg_wal))
+ if (pgwin32_is_junction(pg_wal, false, ERROR))
xlog_is_symlink = true;
#endif
diff --git a/src/include/port.h b/src/include/port.h
index 3d103a2b31..b8118a3d51 100644
--- a/src/include/port.h
+++ b/src/include/port.h
@@ -284,7 +284,7 @@ extern int pgunlink(const char *path);
#if defined(WIN32) && !defined(__CYGWIN__)
extern int pgsymlink(const char *oldpath, const char *newpath);
extern int pgreadlink(const char *path, char *buf, size_t size);
-extern bool pgwin32_is_junction(const char *path);
+extern bool pgwin32_is_junction(const char *path, bool missing_ok, int elevel);
#define symlink(oldpath, newpath) pgsymlink(oldpath, newpath)
#define readlink(path, buf, size) pgreadlink(path, buf, size)
diff --git a/src/include/port/win32_port.h b/src/include/port/win32_port.h
index d3cb765976..d9bec24348 100644
--- a/src/include/port/win32_port.h
+++ b/src/include/port/win32_port.h
@@ -230,7 +230,7 @@ int setitimer(int which, const struct itimerval *value, struct itimerval *oval
*/
extern int pgsymlink(const char *oldpath, const char *newpath);
extern int pgreadlink(const char *path, char *buf, size_t size);
-extern bool pgwin32_is_junction(const char *path);
+extern bool pgwin32_is_junction(const char *path, bool missing_ok, int elevel);
#define symlink(oldpath, newpath) pgsymlink(oldpath, newpath)
#define readlink(path, buf, size) pgreadlink(path, buf, size)
diff --git a/src/port/dirmod.c b/src/port/dirmod.c
index 7ce042e75d..127cb6a576 100644
--- a/src/port/dirmod.c
+++ b/src/port/dirmod.c
@@ -337,19 +337,49 @@ pgreadlink(const char *path, char *buf, size_t size)
}
/*
- * Assumes the file exists, so will return false if it doesn't
- * (since a nonexistent file is not a junction)
+ * In frontend code, elevel must be 0 or 1, where 1 means write an error and
+ * exit(1); in backend code it should be 0 or a level from elog.h, to pass to
+ * ereport(). If elevel is 0, or missing_ok is set and the path doesn't exist,
+ * no logging is done. The caller should check errno on false return, unless
+ * elevel is set to a level that doesn't return on error.
*/
bool
-pgwin32_is_junction(const char *path)
+pgwin32_is_junction(const char *path, bool missing_ok, int elevel)
{
DWORD attr = GetFileAttributes(path);
+#ifdef FRONTEND
+ /*
+ * We can't use ereport, and libport can't use the logging from libcommon
+ * due to library order, so the options for logging are limited.
+ */
+ Assert(elevel == 0 || elevel == 1);
+#endif
+
if (attr == INVALID_FILE_ATTRIBUTES)
{
_dosmaperr(GetLastError());
+
+ if (errno == ENOENT && missing_ok)
+ return false;
+
+ if (elevel != 0)
+ {
+#ifndef FRONTEND
+ ereport(elevel,
+ (errcode_for_file_access(),
+ errmsg("could not get attributes for file \"%s\": %m",
+ path)));
+#else
+ int save_errno = errno;
+ fprintf(stderr, _("could not get attributes for file \"%s\": %s\n"),
+ path, strerror(save_errno));
+ exit(1);
+#endif
+ }
return false;
}
+ errno = 0;
return ((attr & FILE_ATTRIBUTE_REPARSE_POINT) == FILE_ATTRIBUTE_REPARSE_POINT);
}
#endif /* defined(WIN32) && !defined(__CYGWIN__) */
--
2.35.1