v2-0002-improve-detection-file-type-for-WIN32-stat.patch

application/octet-stream

Filename: v2-0002-improve-detection-file-type-for-WIN32-stat.patch
Type: application/octet-stream
Part: 0
Message: Re: pg_dump/pg_restore: Fix stdin/stdout handling of custom format on Win32

Patch

Format: format-patch
Series: patch v2-0002
Subject: improve detection file type for WIN32 stat Use native GetFileType() to detect file types.
File+
src/port/win32stat.c 44 18
From 0d128d6a818884d870de9d48b70bccb6e4879a4c Mon Sep 17 00:00:00 2001
From: Juan Jose Santamaria Flecha <juanjo.santamaria@gmail.com>
Date: Thu, 9 Mar 2023 13:22:46 -0500
Subject: [PATCH 2/2] improve detection file type for WIN32 stat Use native
 GetFileType() to detect file types.

---
 src/port/win32stat.c | 62 +++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 44 insertions(+), 18 deletions(-)

diff --git a/src/port/win32stat.c b/src/port/win32stat.c
index a3c42f0..51ae77d 100644
--- a/src/port/win32stat.c
+++ b/src/port/win32stat.c
@@ -256,35 +256,61 @@ _pgstat64(const char *name, struct stat *buf)
 int
 _pgfstat64(int fileno, struct stat *buf)
 {
-	HANDLE		hFile = (HANDLE) _get_osfhandle(fileno);
-	BY_HANDLE_FILE_INFORMATION fiData;
+	HANDLE			hFile = (HANDLE) _get_osfhandle(fileno);
+	DWORD			fileType = FILE_TYPE_UNKNOWN;
+	DWORD			lastError;
+	unsigned short	st_mode;
 
-	if (hFile == INVALID_HANDLE_VALUE || buf == NULL)
+	/*
+	 * When stdin, stdout, and stderr aren't associated with a stream the special
+	 * value -2 is returned.
+	 */
+	if (hFile == INVALID_HANDLE_VALUE || hFile == (HANDLE) -2 || buf == NULL)
 	{
 		errno = EINVAL;
 		return -1;
 	}
 
+	fileType = GetFileType(hFile);
+	lastError = GetLastError();
+
 	/*
-	 * Check if the fileno is a data stream.  If so, unless it has been
-	 * redirected to a file, getting information through its HANDLE will fail,
-	 * so emulate its stat information in the most appropriate way and return
-	 * it instead.
+	 * Invoke GetLastError in order to distinguish between a "valid"
+	 * return of FILE_TYPE_UNKNOWN and its return due to a calling error.
+	 * In case of success, GetLastError returns NO_ERROR.
 	 */
-	if ((fileno == _fileno(stdin) ||
-		 fileno == _fileno(stdout) ||
-		 fileno == _fileno(stderr)) &&
-		!GetFileInformationByHandle(hFile, &fiData))
+	if (fileType == FILE_TYPE_UNKNOWN && lastError != NO_ERROR) {
+		_dosmaperr(lastError);
+		return -1;
+	}
+
+	switch (fileType)
 	{
-		memset(buf, 0, sizeof(*buf));
-		buf->st_mode = _S_IFCHR;
-		buf->st_dev = fileno;
-		buf->st_rdev = fileno;
-		buf->st_nlink = 1;
-		return 0;
+		/* The specified file is a disk file */
+		case FILE_TYPE_DISK:
+			return fileinfo_to_stat(hFile, buf);
+		/* The specified file is a socket, a named pipe, or an anonymous pipe */
+		case FILE_TYPE_PIPE:
+			st_mode = _S_IFIFO;
+			break;
+		/* The specified file is a character file */
+		case FILE_TYPE_CHAR:
+			st_mode = _S_IFCHR;
+			break;
+		/* Unused flag and unknown file type */
+		case FILE_TYPE_REMOTE:
+		case FILE_TYPE_UNKNOWN:
+		default:
+			errno = EINVAL;
+			return -1;
 	}
 
-	return fileinfo_to_stat(hFile, buf);
+	memset(buf, 0, sizeof(*buf));
+	buf->st_mode = st_mode;
+	buf->st_dev = fileno;
+	buf->st_rdev = fileno;
+	buf->st_nlink = 1;
+	return 0;
 }
 
 #endif							/* WIN32 */
-- 
2.11.0