From: Dmitry Koval <d.koval@postgrespro.ru>
To: Michael Paquier <michael@paquier.xyz>
Cc: pgsql-bugs@lists.postgresql.org
Subject: Re: BUG #17288: PSQL bug with COPY command (Windows)
Date: Thu, 18 Nov 2021 16:23:54 +0300
Message-ID: <9e4efe29-0ff9-0808-fe32-d1d50e0be4fa@postgrespro.ru> (raw)
In-Reply-To: <YZYDZwDtw/Ioojb4@paquier.xyz>
References: <17288-6b58a91025a8a8a3@postgresql.org>
<b95273fb-a51a-d0a9-e4a8-501e32e204e5@postgrespro.ru>
<YZYDZwDtw/Ioojb4@paquier.xyz>
>_fstat64() and _stat64() have proved to be tricky to work with and
>rather unworkable across all the build systems we support
I agree, it is better not use them.
>I think that we had better never call GetFileInformationByHandle() if
>we use a fileno that maps to stdin, stdout or stderr.
Probably we should call GetFileInformationByHandle() for case standard
streams stdin/stdout/stderr are redirected to files.
See file src\backend\utils\error\elog.c, for example. It contains
lines:
if (!freopen(OutputFileName, "a", stderr))
if (!freopen(OutputFileName, "a", stdout))
And this command with "stderr" works in PSQL without crash (in
contrast to "stdout"):
\copy (SELECT 1) TO stderr
(it put resullt into file with name "stderr").
We can emulate stats for stdin/stdout/stderr after call
GetFileInformationByHandle().
>Just to be sure, this is the code path in psql's copy.c where we check
>that a specified copystream is not a directory, right?
Yes, fstat() called from file src/bin/psql/copy.c:
/* make sure the specified file is not a directory */
if ((result = fstat(fileno(copystream), &st)) < 0)
I attached new patch version.
With best regards,
Dmitry Koval.
Attachments:v3_0001-Fixed-Windows-stat-emulation-working-with-streams.patch (text/plain, 2.0K) download
From 4ad82a8f7b115ff975165c0c329250e9714bee78 Mon Sep 17 00:00:00 2001
From: Koval Dmitry <d.koval@postgrespro.ru>
Date: Wed, 17 Nov 2021 13:23:50 +0300
Subject: [PATCH] Fixed Windows stat() emulation: working with streams
---
src/port/win32stat.c | 35 +++++++++++++++++++++++++++++++----
1 file changed, 31 insertions(+), 4 deletions(-)
diff --git a/src/port/win32stat.c b/src/port/win32stat.cindex 2ad8ee1359..a3ea239190 100644--- a/src/port/win32stat.c+++ b/src/port/win32stat.c@@ -112,7 +112,7 @@ fileattr_to_unixmode(int attr)
* Convert WIN32 file information (from a HANDLE) to a struct stat.
*/
static int
-fileinfo_to_stat(HANDLE hFile, struct stat *buf)+fileinfo_to_stat(HANDLE hFile, int fileno, struct stat *buf)
{
BY_HANDLE_FILE_INFORMATION fiData;
@@ -124,7 +124,34 @@ fileinfo_to_stat(HANDLE hFile, struct stat *buf)
*/
if (!GetFileInformationByHandle(hFile, &fiData))
{
- _dosmaperr(GetLastError());+ DWORD error = GetLastError();++ if (fileno >= 0)+ {+ switch (error)+ {+ case ERROR_INVALID_PARAMETER:+ case ERROR_INVALID_FUNCTION:+ case ERROR_NOT_SUPPORTED:++ /*+ * Object is other than real file (stdout, for example).+ * So need to emulate call _fstat64() in this case.+ */+ if (fileno == _fileno(stdin) ||+ fileno == _fileno(stdout) ||+ fileno == _fileno(stderr))+ {+ buf->st_mode = _S_IFCHR;+ buf->st_dev = fileno;+ buf->st_rdev = fileno;+ buf->st_nlink = 1;+ return 0;+ }+ /* fallthrough */+ }+ }+ _dosmaperr(error);
return -1;
}
@@ -276,7 +303,7 @@ _pgstat64(const char *name, struct stat *buf)
}
/* At last we can invoke fileinfo_to_stat */
- ret = fileinfo_to_stat(hFile, buf);+ ret = fileinfo_to_stat(hFile, -1, buf);
CloseHandle(hFile);
return ret;
@@ -301,7 +328,7 @@ _pgfstat64(int fileno, struct stat *buf)
* ERROR_DELETE_PENDING.
*/
- return fileinfo_to_stat(hFile, buf);+ return fileinfo_to_stat(hFile, fileno, buf);
}
#endif /* WIN32 */
--
2.31.0.windows.1
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: pgsql-bugs@postgresql.org
Cc: d.koval@postgrespro.ru, michael@paquier.xyz, pgsql-bugs@lists.postgresql.org
Subject: Re: BUG #17288: PSQL bug with COPY command (Windows)
In-Reply-To: <9e4efe29-0ff9-0808-fe32-d1d50e0be4fa@postgrespro.ru>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox