Calling fseek() or ftello() on a handle to a non-seeking device such as
a pipe or a communications device is not supported. Unfortunately,
MSVC's flavor of these routines, _fseeki64() and _ftelli64(), do not
return an error when given a pipe as handle. Some of the logic of
pg_dump and restore relies on these routines to check if a handle is
seekable, causing failures when passing the contents of pg_dump to
pg_restore through a pipe, for example.
This commit introduces wrappers for fseeko() and ftello() on MSVC so as
any callers are able to properly detect the cases of non-seekable
handles. This relies mainly on GetFileType(), sharing a bit of code
with the MSVC port for fstat(). The code in charge of getting a file
type is refactored into a new file called win32common.c, shared by
win32stat.c and the new win32fseek.c. It includes the MSVC ports for
fseeko() and ftello().
Like 765f5df
, this is backpatched down to 14, where the fstat()
implementation for MSVC is able to understand about files larger than
4GB in size. Using a TAP test for that is proving to be tricky as
IPC::Run handles the pipes by itself, still I have been able to check
the fix manually.
Reported-by: Daniel Watzinger
Author: Juan José Santamaría Flecha, Michael Paquier
Discussion: https://postgr.es/m/CAC+AXB26a4EmxM2suXxPpJaGrqAdxracd7hskLg-zxtPB50h7A@mail.gmail.com
Backpatch-through: 14
68 lines
1.6 KiB
C
68 lines
1.6 KiB
C
/*-------------------------------------------------------------------------
|
|
*
|
|
* win32common.c
|
|
* Common routines shared among the win32*.c ports.
|
|
*
|
|
* Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
*
|
|
*
|
|
* IDENTIFICATION
|
|
* src/port/win32common.c
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
|
|
#ifdef FRONTEND
|
|
#include "postgres_fe.h"
|
|
#else
|
|
#include "postgres.h"
|
|
#endif
|
|
|
|
#ifdef WIN32
|
|
|
|
/*
|
|
* pgwin32_get_file_type
|
|
*
|
|
* Convenience wrapper for GetFileType() with specific error handling for all the
|
|
* port implementations. Returns the file type associated with a HANDLE.
|
|
*
|
|
* On error, sets errno with FILE_TYPE_UNKNOWN as file type.
|
|
*/
|
|
DWORD
|
|
pgwin32_get_file_type(HANDLE hFile)
|
|
{
|
|
DWORD fileType = FILE_TYPE_UNKNOWN;
|
|
DWORD lastError;
|
|
|
|
errno = 0;
|
|
|
|
/*
|
|
* When stdin, stdout, and stderr aren't associated with a stream the
|
|
* special value -2 is returned:
|
|
* https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/get-osfhandle
|
|
*/
|
|
if (hFile == INVALID_HANDLE_VALUE || hFile == (HANDLE) -2)
|
|
{
|
|
errno = EINVAL;
|
|
return FILE_TYPE_UNKNOWN;
|
|
}
|
|
|
|
fileType = GetFileType(hFile);
|
|
lastError = GetLastError();
|
|
|
|
/*
|
|
* 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 (fileType == FILE_TYPE_UNKNOWN && lastError != NO_ERROR)
|
|
{
|
|
_dosmaperr(lastError);
|
|
return FILE_TYPE_UNKNOWN;
|
|
}
|
|
|
|
return fileType;
|
|
}
|
|
|
|
#endif /* WIN32 */
|