From 45ea3338e10c6b296ddc1cedb80ce8e5f103e51d Mon Sep 17 00:00:00 2001 From: Juan Jose Santamaria Flecha Date: Wed, 15 Mar 2023 07:04:44 -0400 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/meson.build | 1 + src/port/win32fseek.c | 68 +++++++++++++++++++++++++++++++++++++++++++ src/tools/msvc/Mkvcbuild.pm | 1 + 4 files changed, 76 insertions(+), 3 deletions(-) create mode 100644 src/port/win32fseek.c diff --git a/src/include/port/win32_port.h b/src/include/port/win32_port.h index 9488195..66553fe 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 function 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 _pgfseeko64(FILE *stream, pgoff_t offset, int origin); +extern pgoff_t _pgftello64(FILE *stream); +#define fseeko(stream, offset, origin) _pgfseeko64(stream, offset, origin) +#define ftello(stream) _pgftello64(stream) #else #ifndef fseeko #define fseeko(stream, offset, origin) fseeko64(stream, offset, origin) diff --git a/src/port/meson.build b/src/port/meson.build index b174b25..3d8eeb4 100644 --- a/src/port/meson.build +++ b/src/port/meson.build @@ -33,6 +33,7 @@ if host_system == 'windows' 'win32env.c', 'win32error.c', 'win32fdatasync.c', + 'win32fseek.c', 'win32getrusage.c', 'win32link.c', 'win32ntdll.c', diff --git a/src/port/win32fseek.c b/src/port/win32fseek.c new file mode 100644 index 0000000..6cf62db --- /dev/null +++ b/src/port/win32fseek.c @@ -0,0 +1,68 @@ +/*------------------------------------------------------------------------- + * + * win32fseek.c + * Replacements for fseeko() and ftello(). + * + * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group + * + * IDENTIFICATION + * src/port/win32fseek.c + * + *------------------------------------------------------------------------- + */ + +#ifdef FRONTEND +#include "postgres_fe.h" +#else +#include "postgres.h" +#endif + +#if defined(WIN32) && defined(_MSC_VER) + +/* + * _pgfseeko64 + * + * 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 +_pgfseeko64(FILE *stream, pgoff_t offset, int origin) +{ + DWORD fileType; + + fileType = GetFileType((HANDLE) _get_osfhandle(_fileno(stream))); + + if (fileType == FILE_TYPE_DISK) + return _fseeki64(stream, offset, origin); + else if (fileType == FILE_TYPE_CHAR || fileType == FILE_TYPE_PIPE) + errno = ESPIPE; + else + errno = EINVAL; + + return -1; +} + +/* + * _pgftello64 + * + * Same as _pgfseeko64(). + */ +pgoff_t +_pgftello64(FILE *stream) +{ + DWORD fileType; + + fileType = GetFileType((HANDLE) _get_osfhandle(_fileno(stream))); + + if (fileType == FILE_TYPE_DISK) + return _ftelli64(stream); + else if (fileType == FILE_TYPE_CHAR || fileType == FILE_TYPE_PIPE) + errno = ESPIPE; + else + errno = EINVAL; + + return -1; +} + +#endif /* defined(WIN32) && defined(_MSC_VER) */ diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm index f1c9ddf..61ace57 100644 --- a/src/tools/msvc/Mkvcbuild.pm +++ b/src/tools/msvc/Mkvcbuild.pm @@ -111,6 +111,7 @@ sub mkvcbuild win32dlopen.c win32env.c win32error.c win32fdatasync.c + win32fseek.c win32getrusage.c win32gettimeofday.c win32link.c -- 2.11.0