Tom Lane писал(а) 2026-07-31 20:07:
Vladlen Popolitov <[email protected]> writes:
Tom Lane писал(а) 2026-07-31 17:08:
Interesting.  I wonder if it'd be sane to put in an explicit mapping
for ERROR_INVALID_FUNCTION, although I'm not quite sure whether to
prefer ENOTSUP or EOPNOTSUPP.

We could try other approach - avoid changing zic and _dosmaperr()
and fix link() like this in src/port/win32link.c:

                if (returncode == ERROR_INVALID_FUNCTION)
                        errno = ENOTSUP;
                else
                        dosmaperr(returncode);

Yeah, that sounds like the solution with the smallest blast radius.
We know that ERROR_INVALID_FUNCTION means this for link(), but
it's hardly clear that that applies across-the-board; it seems
like EINVAL is probably the best translation in other cases.

Another advantage is that we don't have to sync it with changes in
zic.c: this will still do what we want after Eggert's changes of
today[1] arrive, whereas other answers might not.

I'll go make it so in a bit.  Thanks for the report!

I have already created and tested a new patch based on this idea.

It fixes the link() error handling. The patch also fixes dolink()
on Linux and FreeBSD, since these platforms are affected as well.
I hope this can be fixed in upstream tzcode. Otherwise, we can
apply the patch only to our PostgreSQL code.

ENOTSUP is the constant returned on macOS, where this code
works without problems.

I also verified that PostgreSQL build on Ubuntu with an exFAT
drive fails with EPERM (Operation not permitted).

This patch fixes the code for Linux and the *BSD systems.
I tested it on exFAT.

It is worth noting that exFAT is a modern filesystem supported
by all major operating systems. It is commonly used as a portable
filesystem for exchanging data between drives. Supporting it
would be beneficial.

--
Best regards,

Vladlen Popolitov.
From 7196b7979be870fbf6636dbc9354195bbe835c2d Mon Sep 17 00:00:00 2001
From: "v.popolitov" <[email protected]>
Date: Thu, 30 Jul 2026 13:14:51 +0300
Subject: [PATCH v2] zic: fix PostgreSQL build failure on filesystems without
 hard link support

zic: fix PostgreSQL build failure on filesystems without hard link support
---
 src/port/win32link.c | 10 +++++++++-
 src/timezone/zic.c   | 16 ++++++++++++++--
 2 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/src/port/win32link.c b/src/port/win32link.c
index e7c8623810f..cf60f20f1b9 100644
--- a/src/port/win32link.c
+++ b/src/port/win32link.c
@@ -23,7 +23,15 @@ link(const char *src, const char *dst)
 	 */
 	if (CreateHardLinkA(dst, src, NULL) == 0)
 	{
-		_dosmaperr(GetLastError());
+		DWORD errcode;
+
+		errcode = GetLastError();
+
+		if (errcode == ERROR_INVALID_FUNCTION)
+			errno = ENOTSUP;
+		else
+			_dosmaperr(errcode);
+
 		return -1;
 	}
 	else
diff --git a/src/timezone/zic.c b/src/timezone/zic.c
index cc6550bdb14..c790f1e25ea 100644
--- a/src/timezone/zic.c
+++ b/src/timezone/zic.c
@@ -1902,7 +1902,13 @@ dolink(char const *target, char const *linkname, bool staysymlink)
 			}
 			link_errno = errno;
 		}
-		if (link_errno == EXDEV || link_errno == ENOTSUP)
+		if (link_errno == EXDEV
+#if		defined(__linux__)
+			|| link_errno == EPERM
+#elif	defined(__FreeBSD__) || defined(__NetBSD__)
+			|| link_errno == EOPNOTSUPP
+#endif
+			|| link_errno == ENOTSUP)
 			break;
 
 		if (link_errno == EEXIST)
@@ -1983,7 +1989,13 @@ dolink(char const *target, char const *linkname, bool staysymlink)
 				putc(c, tp);
 			close_file(tp, directory, linkname, tempname);
 			close_file(fp, directory, target, NULL);
-			if (link_errno != ENOTSUP)
+			if (link_errno != ENOTSUP
+#if		defined(__linux__)
+					&& link_errno != EPERM
+#elif	defined(__FreeBSD__) || defined(__NetBSD__)
+					&& link_errno != EOPNOTSUPP
+#endif
+				)
 				warning(_("copy used because hard link failed: %s"),
 						strerror(link_errno));
 #ifdef HAVE_SYMLINK
-- 
2.52.0.windows.1

Reply via email to