public inbox for [email protected]  
help / color / mirror / Atom feed
From: Juan José Santamaría Flecha <[email protected]>
To: Pg Hackers <[email protected]>
To: Michael Paquier <[email protected]>
Subject: Fix fseek() detection of unseekable files on WIN32
Date: Tue, 14 Mar 2023 13:26:27 +0100
Message-ID: <CAC+AXB26a4EmxM2suXxPpJaGrqAdxracd7hskLg-zxtPB50h7A@mail.gmail.com> (raw)

Hello all,

As highlighted in [1] fseek() might fail to error even when accessing
unseekable streams.

PFA a patch that checks the file type before the actual fseek(), so only
supported calls are made.

[1]
https://www.postgresql.org/message-id/flat/[email protected]

Regards,

Juan José Santamaría Flecha


Attachments:

  [application/octet-stream] 0001-fix-fseek-detection-of-unseekable-files-for-WIN32.patch (2.6K, ../CAC+AXB26a4EmxM2suXxPpJaGrqAdxracd7hskLg-zxtPB50h7A@mail.gmail.com/3-0001-fix-fseek-detection-of-unseekable-files-for-WIN32.patch)
  download | inline diff:
From c7a183bc950495ddbf66aa31f3d6fe3074c5446a Mon Sep 17 00:00:00 2001
From: Juan Jose Santamaria Flecha <[email protected]>
Date: Thu, 9 Mar 2023 23:14:42 -0500
Subject: [PATCH] fix fseek detection of unseekable files for WIN32 Calling
 fseek() on a handle to a non-seeking device such as a pipe or a
 communications device is not supported, even though the fseek() may not
 return an error, so harden that funcion with our version.

---
 src/include/port/win32_port.h |  9 ++++++---
 src/port/dirmod.c             | 38 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 44 insertions(+), 3 deletions(-)

diff --git a/src/include/port/win32_port.h b/src/include/port/win32_port.h
index 9488195..8679a0a 100644
--- a/src/include/port/win32_port.h
+++ b/src/include/port/win32_port.h
@@ -206,13 +206,16 @@ int			setitimer(int which, const struct itimerval *value, struct itimerval *oval
 
 /*
  * WIN32 does not provide 64-bit off_t, but does provide the functions operating
- * with 64-bit offsets.
+ * with 64-bit offsets. Also, fseek() might not give an error for unseekable
+ * streams, so harden that funcion with our version.
  */
 #define pgoff_t __int64
 
 #ifdef _MSC_VER
-#define fseeko(stream, offset, origin) _fseeki64(stream, offset, origin)
-#define ftello(stream) _ftelli64(stream)
+extern int  	pgfseek64(FILE *stream, pgoff_t offset, int origin);
+extern pgoff_t	pgftell64(FILE *stream);
+#define fseeko(stream, offset, origin) pgfseek64(stream, offset, origin)
+#define ftello(stream) pgftell64(stream)
 #else
 #ifndef fseeko
 #define fseeko(stream, offset, origin) fseeko64(stream, offset, origin)
diff --git a/src/port/dirmod.c b/src/port/dirmod.c
index bf7f068..3770efc 100644
--- a/src/port/dirmod.c
+++ b/src/port/dirmod.c
@@ -419,4 +419,42 @@ pgreadlink(const char *path, char *buf, size_t size)
 	return r;
 }
 
+#ifdef _MSC_VER
+/*
+ * pgfseek64
+ *
+ * Calling fseek() on a handle to a non-seeking device such as a pipe or
+ * a communications device is not supported, even though the fseek() may
+ * not return an error.
+ */
+int
+pgfseek64(FILE *stream, pgoff_t offset, int origin)
+{
+	if (GetFileType((HANDLE) _get_osfhandle(_fileno(stream))) != FILE_TYPE_DISK)
+	{
+		errno = ESPIPE;
+		return -1;
+	}
+
+	return _fseeki64(stream, offset, origin);
+}
+
+/*
+ * pgftell64
+ *
+ * Same as pgfseek64().
+ */
+pgoff_t
+pgftell64(FILE *stream)
+{
+	if (GetFileType((HANDLE) _get_osfhandle(_fileno(stream))) != FILE_TYPE_DISK)
+	{
+		errno = ESPIPE;
+		return -1;
+	}
+
+	return _ftelli64(stream);
+}
+#endif							/* defined(_MSC_VER) */
+
 #endif							/* defined(WIN32) && !defined(__CYGWIN__) */
-- 
2.11.0



view thread (2+ messages)

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: [email protected]
  Cc: [email protected], [email protected]
  Subject: Re: Fix fseek() detection of unseekable files on WIN32
  In-Reply-To: <CAC+AXB26a4EmxM2suXxPpJaGrqAdxracd7hskLg-zxtPB50h7A@mail.gmail.com>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox