Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit34105ee

Browse files
committed
Fix detection of unseekable files for fseek() and ftello() with MSVC
Calling fseek() or ftello() on a handle to a non-seeking device such asa pipe or a communications device is not supported. Unfortunately,MSVC's flavor of these routines, _fseeki64() and _ftelli64(), do notreturn an error when given a pipe as handle. Some of the logic ofpg_dump and restore relies on these routines to check if a handle isseekable, causing failures when passing the contents of pg_dump topg_restore through a pipe, for example.This commit introduces wrappers for fseeko() and ftello() on MSVC so asany callers are able to properly detect the cases of non-seekablehandles. This relies mainly on GetFileType(), sharing a bit of codewith the MSVC port for fstat(). The code in charge of getting a filetype is refactored into a new file called win32common.c, shared bywin32stat.c and the new win32fseek.c. It includes the MSVC ports forfseeko() and ftello().Like765f5df, this is backpatched down to 14, where the fstat()implementation for MSVC is able to understand about files larger than4GB in size. Using a TAP test for that is proving to be tricky asIPC::Run handles the pipes by itself, still I have been able to checkthe fix manually.Reported-by: Daniel WatzingerAuthor: Juan José Santamaría Flecha, Michael PaquierDiscussion:https://postgr.es/m/CAC+AXB26a4EmxM2suXxPpJaGrqAdxracd7hskLg-zxtPB50h7A@mail.gmail.comBackpatch-through: 14
1 parent0cb01a0 commit34105ee

File tree

7 files changed

+164
-23
lines changed

7 files changed

+164
-23
lines changed

‎configure

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16984,6 +16984,12 @@ esac
1698416984
;;
1698516985
esac
1698616986

16987+
case " $LIBOBJS " in
16988+
*" win32common.$ac_objext "* ) ;;
16989+
*) LIBOBJS="$LIBOBJS win32common.$ac_objext"
16990+
;;
16991+
esac
16992+
1698716993
case " $LIBOBJS " in
1698816994
*" win32env.$ac_objext "* ) ;;
1698916995
*) LIBOBJS="$LIBOBJS win32env.$ac_objext"

‎configure.ac

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1932,6 +1932,7 @@ if test "$PORTNAME" = "win32"; then
19321932
AC_LIBOBJ(kill)
19331933
AC_LIBOBJ(open)
19341934
AC_LIBOBJ(system)
1935+
AC_LIBOBJ(win32common)
19351936
AC_LIBOBJ(win32env)
19361937
AC_LIBOBJ(win32error)
19371938
AC_LIBOBJ(win32security)

‎src/include/port/win32_port.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,15 +193,21 @@ struct itimerval
193193

194194
intsetitimer(intwhich,conststructitimerval*value,structitimerval*ovalue);
195195

196+
/* Convenience wrapper for GetFileType() */
197+
externDWORDpgwin32_get_file_type(HANDLEhFile);
198+
196199
/*
197200
* WIN32 does not provide 64-bit off_t, but does provide the functions operating
198-
* with 64-bit offsets.
201+
* with 64-bit offsets. Also, fseek() might not give an error for unseekable
202+
* streams, so harden that function with our version.
199203
*/
200204
#definepgoff_t __int64
201205

202206
#ifdef_MSC_VER
203-
#definefseeko(stream,offset,origin) _fseeki64(stream, offset, origin)
204-
#defineftello(stream) _ftelli64(stream)
207+
externint_pgfseeko64(FILE*stream,pgoff_toffset,intorigin);
208+
externpgoff_t_pgftello64(FILE*stream);
209+
#definefseeko(stream,offset,origin) _pgfseeko64(stream, offset, origin)
210+
#defineftello(stream) _pgftello64(stream)
205211
#else
206212
#ifndeffseeko
207213
#definefseeko(stream,offset,origin) fseeko64(stream, offset, origin)

‎src/port/win32common.c

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*-------------------------------------------------------------------------
2+
*
3+
* win32common.c
4+
* Common routines shared among the win32*.c ports.
5+
*
6+
* Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
7+
* Portions Copyright (c) 1994, Regents of the University of California
8+
*
9+
*
10+
* IDENTIFICATION
11+
* src/port/win32common.c
12+
*
13+
*-------------------------------------------------------------------------
14+
*/
15+
16+
#ifdefFRONTEND
17+
#include"postgres_fe.h"
18+
#else
19+
#include"postgres.h"
20+
#endif
21+
22+
#ifdefWIN32
23+
24+
/*
25+
* pgwin32_get_file_type
26+
*
27+
* Convenience wrapper for GetFileType() with specific error handling for all the
28+
* port implementations. Returns the file type associated with a HANDLE.
29+
*
30+
* On error, sets errno with FILE_TYPE_UNKNOWN as file type.
31+
*/
32+
DWORD
33+
pgwin32_get_file_type(HANDLEhFile)
34+
{
35+
DWORDfileType=FILE_TYPE_UNKNOWN;
36+
DWORDlastError;
37+
38+
errno=0;
39+
40+
/*
41+
* When stdin, stdout, and stderr aren't associated with a stream the
42+
* special value -2 is returned:
43+
* https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/get-osfhandle
44+
*/
45+
if (hFile==INVALID_HANDLE_VALUE||hFile== (HANDLE)-2)
46+
{
47+
errno=EINVAL;
48+
returnFILE_TYPE_UNKNOWN;
49+
}
50+
51+
fileType=GetFileType(hFile);
52+
lastError=GetLastError();
53+
54+
/*
55+
* Invoke GetLastError in order to distinguish between a "valid" return of
56+
* FILE_TYPE_UNKNOWN and its return due to a calling error. In case of
57+
* success, GetLastError() returns NO_ERROR.
58+
*/
59+
if (fileType==FILE_TYPE_UNKNOWN&&lastError!=NO_ERROR)
60+
{
61+
_dosmaperr(lastError);
62+
returnFILE_TYPE_UNKNOWN;
63+
}
64+
65+
returnfileType;
66+
}
67+
68+
#endif/* WIN32 */

‎src/port/win32fseek.c

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*-------------------------------------------------------------------------
2+
*
3+
* win32fseek.c
4+
* Replacements for fseeko() and ftello().
5+
*
6+
* Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
7+
*
8+
* IDENTIFICATION
9+
* src/port/win32fseek.c
10+
*
11+
*-------------------------------------------------------------------------
12+
*/
13+
14+
#ifdefFRONTEND
15+
#include"postgres_fe.h"
16+
#else
17+
#include"postgres.h"
18+
#endif
19+
20+
#if defined(WIN32)&& defined(_MSC_VER)
21+
22+
/*
23+
* _pgfseeko64
24+
*
25+
* Calling fseek() on a handle to a non-seeking device such as a pipe or
26+
* a communications device is not supported, and fseek() may not return
27+
* an error. This wrapper relies on the file type to check which cases
28+
* are supported.
29+
*/
30+
int
31+
_pgfseeko64(FILE*stream,pgoff_toffset,intorigin)
32+
{
33+
DWORDfileType;
34+
HANDLEhFile= (HANDLE)_get_osfhandle(_fileno(stream));
35+
36+
fileType=pgwin32_get_file_type(hFile);
37+
if (errno!=0)
38+
return-1;
39+
40+
if (fileType==FILE_TYPE_DISK)
41+
return_fseeki64(stream,offset,origin);
42+
elseif (fileType==FILE_TYPE_CHAR||fileType==FILE_TYPE_PIPE)
43+
errno=ESPIPE;
44+
else
45+
errno=EINVAL;
46+
47+
return-1;
48+
}
49+
50+
/*
51+
* _pgftello64
52+
*
53+
* Same as _pgfseeko64().
54+
*/
55+
pgoff_t
56+
_pgftello64(FILE*stream)
57+
{
58+
DWORDfileType;
59+
HANDLEhFile= (HANDLE)_get_osfhandle(_fileno(stream));
60+
61+
fileType=pgwin32_get_file_type(hFile);
62+
if (errno!=0)
63+
return-1;
64+
65+
if (fileType==FILE_TYPE_DISK)
66+
return_ftelli64(stream);
67+
elseif (fileType==FILE_TYPE_CHAR||fileType==FILE_TYPE_PIPE)
68+
errno=ESPIPE;
69+
else
70+
errno=EINVAL;
71+
72+
return-1;
73+
}
74+
75+
#endif/* defined(WIN32) && defined(_MSC_VER) */

‎src/port/win32stat.c

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -290,33 +290,17 @@ _pgfstat64(int fileno, struct stat *buf)
290290
{
291291
HANDLEhFile= (HANDLE)_get_osfhandle(fileno);
292292
DWORDfileType=FILE_TYPE_UNKNOWN;
293-
DWORDlastError;
294293
unsigned shortst_mode;
295294

296-
/*
297-
* When stdin, stdout, and stderr aren't associated with a stream the
298-
* special value -2 is returned:
299-
* https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/get-osfhandle
300-
*/
301-
if (hFile==INVALID_HANDLE_VALUE||hFile== (HANDLE)-2||buf==NULL)
295+
if (buf==NULL)
302296
{
303297
errno=EINVAL;
304298
return-1;
305299
}
306300

307-
fileType=GetFileType(hFile);
308-
lastError=GetLastError();
309-
310-
/*
311-
* Invoke GetLastError in order to distinguish between a "valid" return of
312-
* FILE_TYPE_UNKNOWN and its return due to a calling error. In case of
313-
* success, GetLastError returns NO_ERROR.
314-
*/
315-
if (fileType==FILE_TYPE_UNKNOWN&&lastError!=NO_ERROR)
316-
{
317-
_dosmaperr(lastError);
301+
fileType=pgwin32_get_file_type(hFile);
302+
if (errno!=0)
318303
return-1;
319-
}
320304

321305
switch (fileType)
322306
{

‎src/tools/msvc/Mkvcbuild.pm

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,8 @@ sub mkvcbuild
111111
pg_strong_random.c pgcheckdir.c pgmkdirp.c pgsleep.c pgstrcasecmp.c
112112
pqsignal.c mkdtemp.c qsort.c qsort_arg.c bsearch_arg.c quotes.c system.c
113113
strerror.c tar.c thread.c
114-
win32env.c win32error.c win32security.c win32setlocale.c win32stat.c);
114+
win32common.c win32env.c win32error.c win32fseek.c win32security.c
115+
win32setlocale.c win32stat.c);
115116

116117
push(@pgportfiles,'strtof.c')if ($vsVersion <'14.00');
117118

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp