From: Tom Lane Date: Fri, 31 Jul 2026 18:39:29 +0000 (-0400) Subject: On Windows, make link(2) report ENOTSUP when appropriate. X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=HEAD;p=thirdparty%2Fpostgresql.git On Windows, make link(2) report ENOTSUP when appropriate. CreateHardLinkA reports ERROR_INVALID_FUNCTION if the target file is on a filesystem that doesn't support hard links. _dosmaperr maps that to EINVAL, which confuses zic.c into failure. zic.c is expecting ENOTSUP if the filesystem lacks link support, and will properly fall back to making a physical copy if it gets that. Hence, add code to map ERROR_INVALID_FUNCTION to ENOTSUP. (We could instead teach _dosmaperr to do that, but it's far from clear that this would be appropriate as a global behavior: intuitively it seems like EINVAL should be appropriate most of the time.) We didn't need this before commit aeb07c55f, because the tzcode version we were using before that didn't have this particular error-handling logic. Hence, no back-patch for now; but if we decide to back-patch tzcode 2026b or later, we'll need this too. Author: Vladlen Popolitov Reviewed-by: Tom Lane Discussion: https://postgr.es/m/e6122f9b2eef9096f1f11ecc058bcd91@postgrespro.ru --- diff --git a/src/port/win32link.c b/src/port/win32link.c index e7c8623810f..1acea199cb3 100644 --- a/src/port/win32link.c +++ b/src/port/win32link.c @@ -23,7 +23,20 @@ link(const char *src, const char *dst) */ if (CreateHardLinkA(dst, src, NULL) == 0) { - _dosmaperr(GetLastError()); + /* + * CreateHardLinkA reports ERROR_INVALID_FUNCTION if the target file + * is on a filesystem that doesn't support hard links. _dosmaperr + * would map that to EINVAL by default, but we want to report ENOTSUP + * because that will cause zic.c to fall back to making copies. + * However, EINVAL is probably the best translation in most cases, so + * tweak it here rather than changing _dosmaperr's behavior. + */ + DWORD error = GetLastError(); + + if (error == ERROR_INVALID_FUNCTION) + errno = ENOTSUP; + else + _dosmaperr(error); return -1; } else