pg.ddx.io  pgsql-bugs@postgresql.org mailing list archive  
help / color / mirror / Atom feed
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.c index 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

view thread (29+ messages)  latest in thread

Message-ID: <9e4efe29-0ff9-0808-fe32-d1d50e0be4fa@postgrespro.ru>
Permalink:  ../9e4efe29-0ff9-0808-fe32-d1d50e0be4fa@postgrespro.ru/
Also on:    postgresql.org/message-id/9e4efe29-0ff9-0808-fe32-d1d50e0be4fa@postgrespro.ru

 ·  · 

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: 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