0002-Use-pgoff_t-in-system-call-replacements-on-Windows.patch
text/x-patch
Filename: 0002-Use-pgoff_t-in-system-call-replacements-on-Windows.patch
Type: text/x-patch
Part: 1
Message:
Large files for relations
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch 0002
Subject: Use pgoff_t in system call replacements on Windows.
| File | + | − |
|---|---|---|
| configure | 6 | 0 |
| configure.ac | 1 | 0 |
| src/common/file_utils.c | 2 | 2 |
| src/include/common/file_utils.h | 2 | 2 |
| src/include/port.h | 1 | 1 |
| src/include/port/pg_iovec.h | 2 | 2 |
| src/include/port/win32_port.h | 19 | 4 |
| src/port/meson.build | 1 | 0 |
| src/port/preadv.c | 1 | 1 |
| src/port/pwritev.c | 1 | 1 |
| src/port/win32ftruncate.c | 65 | 0 |
| src/port/win32pread.c | 2 | 1 |
| src/port/win32pwrite.c | 2 | 1 |
| src/tools/msvc/Mkvcbuild.pm | 1 | 0 |
From 6154e35d35515a7536524b79cb7ccd6a39d41afe Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Sun, 5 Mar 2023 11:24:51 +1300
Subject: [PATCH 02/11] Use pgoff_t in system call replacements on Windows.
All modern Unix systems have 64 bit off_t, but Windows does not. Use
our pgoff_t type in our POSIX-style replacement functions (lseek(),
ftruncate(), pread(), pwrite() etc etc). Also in closely related
functions like pg_pwrite_zeros().
---
configure | 6 +++
configure.ac | 1 +
src/common/file_utils.c | 4 +-
src/include/common/file_utils.h | 4 +-
src/include/port.h | 2 +-
src/include/port/pg_iovec.h | 4 +-
src/include/port/win32_port.h | 23 ++++++++++--
src/port/meson.build | 1 +
src/port/preadv.c | 2 +-
src/port/pwritev.c | 2 +-
src/port/win32ftruncate.c | 65 +++++++++++++++++++++++++++++++++
src/port/win32pread.c | 3 +-
src/port/win32pwrite.c | 3 +-
src/tools/msvc/Mkvcbuild.pm | 1 +
14 files changed, 106 insertions(+), 15 deletions(-)
create mode 100644 src/port/win32ftruncate.c
diff --git a/configure b/configure
index 15daccc87f..47ba18491c 100755
--- a/configure
+++ b/configure
@@ -16537,6 +16537,12 @@ esac
;;
esac
+ case " $LIBOBJS " in
+ *" win32ftruncate.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS win32ftruncate.$ac_objext"
+ ;;
+esac
+
case " $LIBOBJS " in
*" win32getrusage.$ac_objext "* ) ;;
*) LIBOBJS="$LIBOBJS win32getrusage.$ac_objext"
diff --git a/configure.ac b/configure.ac
index 97f5be6c73..2b3b1b4dca 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1905,6 +1905,7 @@ if test "$PORTNAME" = "win32"; then
AC_LIBOBJ(win32env)
AC_LIBOBJ(win32error)
AC_LIBOBJ(win32fdatasync)
+ AC_LIBOBJ(win32ftruncate)
AC_LIBOBJ(win32getrusage)
AC_LIBOBJ(win32link)
AC_LIBOBJ(win32ntdll)
diff --git a/src/common/file_utils.c b/src/common/file_utils.c
index 74833c4acb..7a63434bc4 100644
--- a/src/common/file_utils.c
+++ b/src/common/file_utils.c
@@ -469,7 +469,7 @@ get_dirent_type(const char *path,
* error is returned, it is unspecified how much has been written.
*/
ssize_t
-pg_pwritev_with_retry(int fd, const struct iovec *iov, int iovcnt, off_t offset)
+pg_pwritev_with_retry(int fd, const struct iovec *iov, int iovcnt, pgoff_t offset)
{
struct iovec iov_copy[PG_IOV_MAX];
ssize_t sum = 0;
@@ -538,7 +538,7 @@ pg_pwritev_with_retry(int fd, const struct iovec *iov, int iovcnt, off_t offset)
* is returned with errno set.
*/
ssize_t
-pg_pwrite_zeros(int fd, size_t size, off_t offset)
+pg_pwrite_zeros(int fd, size_t size, pgoff_t offset)
{
static const PGIOAlignedBlock zbuffer = {{0}}; /* worth BLCKSZ */
void *zerobuf_addr = unconstify(PGIOAlignedBlock *, &zbuffer)->data;
diff --git a/src/include/common/file_utils.h b/src/include/common/file_utils.h
index b7efa1226d..534277b12d 100644
--- a/src/include/common/file_utils.h
+++ b/src/include/common/file_utils.h
@@ -42,8 +42,8 @@ extern PGFileType get_dirent_type(const char *path,
extern ssize_t pg_pwritev_with_retry(int fd,
const struct iovec *iov,
int iovcnt,
- off_t offset);
+ pgoff_t offset);
-extern ssize_t pg_pwrite_zeros(int fd, size_t size, off_t offset);
+extern ssize_t pg_pwrite_zeros(int fd, size_t size, pgoff_t offset);
#endif /* FILE_UTILS_H */
diff --git a/src/include/port.h b/src/include/port.h
index a88d403483..f7707a390e 100644
--- a/src/include/port.h
+++ b/src/include/port.h
@@ -368,7 +368,7 @@ extern FILE *pgwin32_popen(const char *command, const char *type);
* When necessary, these routines are provided by files in src/port/.
*/
-/* Type to use with fseeko/ftello */
+/* Type to use with lseek/ftruncate/pread/fseeko/ftello */
#ifndef WIN32 /* WIN32 is handled in port/win32_port.h */
#define pgoff_t off_t
#endif
diff --git a/src/include/port/pg_iovec.h b/src/include/port/pg_iovec.h
index 689799c425..c762fab662 100644
--- a/src/include/port/pg_iovec.h
+++ b/src/include/port/pg_iovec.h
@@ -43,13 +43,13 @@ struct iovec
#if HAVE_DECL_PREADV
#define pg_preadv preadv
#else
-extern ssize_t pg_preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset);
+extern ssize_t pg_preadv(int fd, const struct iovec *iov, int iovcnt, pgoff_t offset);
#endif
#if HAVE_DECL_PWRITEV
#define pg_pwritev pwritev
#else
-extern ssize_t pg_pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset);
+extern ssize_t pg_pwritev(int fd, const struct iovec *iov, int iovcnt, pgoff_t offset);
#endif
#endif /* PG_IOVEC_H */
diff --git a/src/include/port/win32_port.h b/src/include/port/win32_port.h
index 58965e0dfd..c757687386 100644
--- a/src/include/port/win32_port.h
+++ b/src/include/port/win32_port.h
@@ -76,11 +76,19 @@
#undef fstat
#undef stat
+/* and likewise for lseek hack */
+#define lseek microsoft_native_lseek
+#include <io.h>
+#undef lseek
+
+/* and also ftruncate, as defined by MinGW headers with 32 bit offset */
+#define ftruncate mingw_native_ftruncate
+#include <unistd.h>
+#undef ftruncate
+
/* Must be here to avoid conflicting with prototype in windows.h */
#define mkdir(a,b) mkdir(a)
-#define ftruncate(a,b) chsize(a,b)
-
/* Windows doesn't have fsync() as such, use _commit() */
#define fsync(fd) _commit(fd)
@@ -219,6 +227,7 @@ 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)
+#define lseek(fd, offset, origin) _lseeki64((fd), (offset), (origin))
#else
#ifndef fseeko
#define fseeko(stream, offset, origin) fseeko64(stream, offset, origin)
@@ -226,7 +235,13 @@ extern pgoff_t _pgftello64(FILE *stream);
#ifndef ftello
#define ftello(stream) ftello64(stream)
#endif
+#ifndef lseek
+#define lseek(fd, offset, origin) _lseeki64((fd), (offset), (origin))
#endif
+#endif
+
+/* 64 bit ftruncate is in win32ftruncate.c */
+extern int ftruncate(int fd, pgoff_t length);
/*
* Win32 also doesn't have symlinks, but we can emulate them with
@@ -586,9 +601,9 @@ typedef unsigned short mode_t;
#endif
/* in port/win32pread.c */
-extern ssize_t pg_pread(int fd, void *buf, size_t nbyte, off_t offset);
+extern ssize_t pg_pread(int fd, void *buf, size_t nbyte, pgoff_t offset);
/* in port/win32pwrite.c */
-extern ssize_t pg_pwrite(int fd, const void *buf, size_t nbyte, off_t offset);
+extern ssize_t pg_pwrite(int fd, const void *buf, size_t nbyte, pgoff_t offset);
#endif /* PG_WIN32_PORT_H */
diff --git a/src/port/meson.build b/src/port/meson.build
index 24416b9bfc..54ce59806a 100644
--- a/src/port/meson.build
+++ b/src/port/meson.build
@@ -35,6 +35,7 @@ if host_system == 'windows'
'win32error.c',
'win32fdatasync.c',
'win32fseek.c',
+ 'win32ftruncate.c',
'win32getrusage.c',
'win32link.c',
'win32ntdll.c',
diff --git a/src/port/preadv.c b/src/port/preadv.c
index e762283e67..6e5e92234f 100644
--- a/src/port/preadv.c
+++ b/src/port/preadv.c
@@ -19,7 +19,7 @@
#include "port/pg_iovec.h"
ssize_t
-pg_preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset)
+pg_preadv(int fd, const struct iovec *iov, int iovcnt, pgoff_t offset)
{
ssize_t sum = 0;
ssize_t part;
diff --git a/src/port/pwritev.c b/src/port/pwritev.c
index 519de45037..c430f99806 100644
--- a/src/port/pwritev.c
+++ b/src/port/pwritev.c
@@ -19,7 +19,7 @@
#include "port/pg_iovec.h"
ssize_t
-pg_pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset)
+pg_pwritev(int fd, const struct iovec *iov, int iovcnt, pgoff_t offset)
{
ssize_t sum = 0;
ssize_t part;
diff --git a/src/port/win32ftruncate.c b/src/port/win32ftruncate.c
new file mode 100644
index 0000000000..5e6d4f3e92
--- /dev/null
+++ b/src/port/win32ftruncate.c
@@ -0,0 +1,65 @@
+/*-------------------------------------------------------------------------
+ *
+ * win32ftruncate.c
+ * Win32 ftruncate() replacement
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ *
+ * src/port/win32ftruncate.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifdef FRONTEND
+#include "postgres_fe.h"
+#else
+#include "postgres.h"
+#endif
+
+int
+ftruncate(int fd, pgoff_t length)
+{
+ HANDLE handle;
+ pgoff_t save_position;
+
+ /*
+ * We can't use chsize() because it works with 32 bit off_t. We can't use
+ * _chsize_s() because it isn't available in MinGW. So we have to use
+ * SetEndOfFile(), but that works with the current position. So we save
+ * and restore it.
+ */
+
+ handle = (HANDLE) _get_osfhandle(fd);
+ if (handle == INVALID_HANDLE_VALUE)
+ {
+ errno = EBADF;
+ return -1;
+ }
+
+ save_position = lseek(fd, 0, SEEK_CUR);
+ if (save_position < 0)
+ return -1;
+
+ if (lseek(fd, length, SEEK_SET) < 0)
+ {
+ int save_errno = errno;
+ lseek(fd, save_position, SEEK_SET);
+ errno = save_errno;
+ return -1;
+ }
+
+ if (!SetEndOfFile(handle))
+ {
+ int save_errno;
+
+ _dosmaperr(GetLastError());
+ save_errno = errno;
+ lseek(fd, save_position, SEEK_SET);
+ errno = save_errno;
+ return -1;
+ }
+ lseek(fd, save_position, SEEK_SET);
+
+ return 0;
+}
diff --git a/src/port/win32pread.c b/src/port/win32pread.c
index 905cf9f42b..6e6366faaa 100644
--- a/src/port/win32pread.c
+++ b/src/port/win32pread.c
@@ -17,7 +17,7 @@
#include <windows.h>
ssize_t
-pg_pread(int fd, void *buf, size_t size, off_t offset)
+pg_pread(int fd, void *buf, size_t size, pgoff_t offset)
{
OVERLAPPED overlapped = {0};
HANDLE handle;
@@ -32,6 +32,7 @@ pg_pread(int fd, void *buf, size_t size, off_t offset)
/* Note that this changes the file position, despite not using it. */
overlapped.Offset = offset;
+ overlapped.OffsetHigh = offset >> 32;
if (!ReadFile(handle, buf, size, &result, &overlapped))
{
if (GetLastError() == ERROR_HANDLE_EOF)
diff --git a/src/port/win32pwrite.c b/src/port/win32pwrite.c
index 5dd10821cf..90dd93dbc5 100644
--- a/src/port/win32pwrite.c
+++ b/src/port/win32pwrite.c
@@ -17,7 +17,7 @@
#include <windows.h>
ssize_t
-pg_pwrite(int fd, const void *buf, size_t size, off_t offset)
+pg_pwrite(int fd, const void *buf, size_t size, pgoff_t offset)
{
OVERLAPPED overlapped = {0};
HANDLE handle;
@@ -32,6 +32,7 @@ pg_pwrite(int fd, const void *buf, size_t size, off_t offset)
/* Note that this changes the file position, despite not using it. */
overlapped.Offset = offset;
+ overlapped.OffsetHigh = offset >> 32;
if (!WriteFile(handle, buf, size, &result, &overlapped))
{
_dosmaperr(GetLastError());
diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm
index 958206f315..4b96c2bb44 100644
--- a/src/tools/msvc/Mkvcbuild.pm
+++ b/src/tools/msvc/Mkvcbuild.pm
@@ -113,6 +113,7 @@ sub mkvcbuild
win32env.c win32error.c
win32fdatasync.c
win32fseek.c
+ win32ftruncate.c
win32getrusage.c
win32gettimeofday.c
win32link.c
--
2.40.1