aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/postgresql
diff options
context:
space:
mode:
authorvvvv <vvvv@yandex-team.ru>2022-03-03 23:09:11 +0300
committervvvv <vvvv@yandex-team.ru>2022-03-03 23:09:11 +0300
commit8dbdbab054b6eb352cfffdad09991052008062fc (patch)
tree71befed92d327f2cc409bff4986ec510d0530d92 /contrib/libs/postgresql
parented3f4e21f3a3837059607ec2606e1dc910269ac0 (diff)
downloadydb-8dbdbab054b6eb352cfffdad09991052008062fc.tar.gz
YQL-13710 try to switch to new shiny PG
ref:2bed0445c8e8bd6c575883632adf19445f0a72a7
Diffstat (limited to 'contrib/libs/postgresql')
-rw-r--r--contrib/libs/postgresql/src/backend/port/atomics.c239
-rw-r--r--contrib/libs/postgresql/src/backend/port/posix_sema.c388
-rw-r--r--contrib/libs/postgresql/src/backend/port/sysv_shmem.c946
-rw-r--r--contrib/libs/postgresql/src/backend/port/win32/crashdump.c183
-rw-r--r--contrib/libs/postgresql/src/backend/port/win32/signal.c344
-rw-r--r--contrib/libs/postgresql/src/backend/port/win32/socket.c700
-rw-r--r--contrib/libs/postgresql/src/backend/port/win32/timer.c121
-rw-r--r--contrib/libs/postgresql/src/backend/port/win32_sema.c235
-rw-r--r--contrib/libs/postgresql/src/backend/port/win32_shmem.c607
-rw-r--r--contrib/libs/postgresql/src/port/README32
-rw-r--r--contrib/libs/postgresql/src/port/bsearch_arg.c78
-rw-r--r--contrib/libs/postgresql/src/port/chklocale.c457
-rw-r--r--contrib/libs/postgresql/src/port/dirmod.c355
-rw-r--r--contrib/libs/postgresql/src/port/dlopen.c145
-rw-r--r--contrib/libs/postgresql/src/port/erand48.c136
-rw-r--r--contrib/libs/postgresql/src/port/fls.c64
-rw-r--r--contrib/libs/postgresql/src/port/getaddrinfo.c396
-rw-r--r--contrib/libs/postgresql/src/port/getopt.c136
-rw-r--r--contrib/libs/postgresql/src/port/getpeereid.c80
-rw-r--r--contrib/libs/postgresql/src/port/getrusage.c110
-rw-r--r--contrib/libs/postgresql/src/port/gettimeofday.c118
-rw-r--r--contrib/libs/postgresql/src/port/inet_aton.c149
-rw-r--r--contrib/libs/postgresql/src/port/inet_net_ntop.c297
-rw-r--r--contrib/libs/postgresql/src/port/kill.c97
-rw-r--r--contrib/libs/postgresql/src/port/noblock.c66
-rw-r--r--contrib/libs/postgresql/src/port/open.c216
-rw-r--r--contrib/libs/postgresql/src/port/path.c916
-rw-r--r--contrib/libs/postgresql/src/port/pg_bitutils.c321
-rw-r--r--contrib/libs/postgresql/src/port/pg_config_paths.h12
-rw-r--r--contrib/libs/postgresql/src/port/pg_crc32c_sb8.c1169
-rw-r--r--contrib/libs/postgresql/src/port/pg_crc32c_sse42.c69
-rw-r--r--contrib/libs/postgresql/src/port/pg_crc32c_sse42_choose.c64
-rw-r--r--contrib/libs/postgresql/src/port/pg_strong_random.c182
-rw-r--r--contrib/libs/postgresql/src/port/pgcheckdir.c90
-rw-r--r--contrib/libs/postgresql/src/port/pgmkdirp.c148
-rw-r--r--contrib/libs/postgresql/src/port/pgsleep.c63
-rw-r--r--contrib/libs/postgresql/src/port/pgstrcasecmp.c151
-rw-r--r--contrib/libs/postgresql/src/port/pgstrsignal.c64
-rw-r--r--contrib/libs/postgresql/src/port/pqsignal.c61
-rw-r--r--contrib/libs/postgresql/src/port/pread.c58
-rw-r--r--contrib/libs/postgresql/src/port/pwrite.c55
-rw-r--r--contrib/libs/postgresql/src/port/pwritev.c58
-rw-r--r--contrib/libs/postgresql/src/port/qsort.c22
-rw-r--r--contrib/libs/postgresql/src/port/qsort_arg.c14
-rw-r--r--contrib/libs/postgresql/src/port/quotes.c51
-rw-r--r--contrib/libs/postgresql/src/port/snprintf.c1515
-rw-r--r--contrib/libs/postgresql/src/port/strerror.c314
-rw-r--r--contrib/libs/postgresql/src/port/system.c117
-rw-r--r--contrib/libs/postgresql/src/port/tar.c206
-rw-r--r--contrib/libs/postgresql/src/port/thread.c116
-rw-r--r--contrib/libs/postgresql/src/port/win32env.c163
-rw-r--r--contrib/libs/postgresql/src/port/win32error.c208
-rw-r--r--contrib/libs/postgresql/src/port/win32security.c178
-rw-r--r--contrib/libs/postgresql/src/port/win32setlocale.c193
-rw-r--r--contrib/libs/postgresql/src/port/win32stat.c327
55 files changed, 13600 insertions, 0 deletions
diff --git a/contrib/libs/postgresql/src/backend/port/atomics.c b/contrib/libs/postgresql/src/backend/port/atomics.c
new file mode 100644
index 0000000000..f9f8b098a5
--- /dev/null
+++ b/contrib/libs/postgresql/src/backend/port/atomics.c
@@ -0,0 +1,239 @@
+/*-------------------------------------------------------------------------
+ *
+ * atomics.c
+ * Non-Inline parts of the atomics implementation
+ *
+ * Portions Copyright (c) 2013-2021, PostgreSQL Global Development Group
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/port/atomics.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "miscadmin.h"
+#include "port/atomics.h"
+#include "storage/spin.h"
+
+#ifdef PG_HAVE_MEMORY_BARRIER_EMULATION
+#ifdef WIN32
+#error "barriers are required (and provided) on WIN32 platforms"
+#endif
+#include <signal.h>
+#endif
+
+#ifdef PG_HAVE_MEMORY_BARRIER_EMULATION
+void
+pg_spinlock_barrier(void)
+{
+ /*
+ * NB: we have to be reentrant here, some barriers are placed in signal
+ * handlers.
+ *
+ * We use kill(0) for the fallback barrier as we assume that kernels on
+ * systems old enough to require fallback barrier support will include an
+ * appropriate barrier while checking the existence of the postmaster pid.
+ */
+ (void) kill(PostmasterPid, 0);
+}
+#endif
+
+#ifdef PG_HAVE_COMPILER_BARRIER_EMULATION
+void
+pg_extern_compiler_barrier(void)
+{
+ /* do nothing */
+}
+#endif
+
+
+#ifdef PG_HAVE_ATOMIC_FLAG_SIMULATION
+
+void
+pg_atomic_init_flag_impl(volatile pg_atomic_flag *ptr)
+{
+ StaticAssertStmt(sizeof(ptr->sema) >= sizeof(slock_t),
+ "size mismatch of atomic_flag vs slock_t");
+
+#ifndef HAVE_SPINLOCKS
+
+ /*
+ * NB: If we're using semaphore based TAS emulation, be careful to use a
+ * separate set of semaphores. Otherwise we'd get in trouble if an atomic
+ * var would be manipulated while spinlock is held.
+ */
+ s_init_lock_sema((slock_t *) &ptr->sema, true);
+#else
+ SpinLockInit((slock_t *) &ptr->sema);
+#endif
+
+ ptr->value = false;
+}
+
+bool
+pg_atomic_test_set_flag_impl(volatile pg_atomic_flag *ptr)
+{
+ uint32 oldval;
+
+ SpinLockAcquire((slock_t *) &ptr->sema);
+ oldval = ptr->value;
+ ptr->value = true;
+ SpinLockRelease((slock_t *) &ptr->sema);
+
+ return oldval == 0;
+}
+
+void
+pg_atomic_clear_flag_impl(volatile pg_atomic_flag *ptr)
+{
+ SpinLockAcquire((slock_t *) &ptr->sema);
+ ptr->value = false;
+ SpinLockRelease((slock_t *) &ptr->sema);
+}
+
+bool
+pg_atomic_unlocked_test_flag_impl(volatile pg_atomic_flag *ptr)
+{
+ return ptr->value == 0;
+}
+
+#endif /* PG_HAVE_ATOMIC_FLAG_SIMULATION */
+
+#ifdef PG_HAVE_ATOMIC_U32_SIMULATION
+void
+pg_atomic_init_u32_impl(volatile pg_atomic_uint32 *ptr, uint32 val_)
+{
+ StaticAssertStmt(sizeof(ptr->sema) >= sizeof(slock_t),
+ "size mismatch of atomic_uint32 vs slock_t");
+
+ /*
+ * If we're using semaphore based atomic flags, be careful about nested
+ * usage of atomics while a spinlock is held.
+ */
+#ifndef HAVE_SPINLOCKS
+ s_init_lock_sema((slock_t *) &ptr->sema, true);
+#else
+ SpinLockInit((slock_t *) &ptr->sema);
+#endif
+ ptr->value = val_;
+}
+
+void
+pg_atomic_write_u32_impl(volatile pg_atomic_uint32 *ptr, uint32 val)
+{
+ /*
+ * One might think that an unlocked write doesn't need to acquire the
+ * spinlock, but one would be wrong. Even an unlocked write has to cause a
+ * concurrent pg_atomic_compare_exchange_u32() (et al) to fail.
+ */
+ SpinLockAcquire((slock_t *) &ptr->sema);
+ ptr->value = val;
+ SpinLockRelease((slock_t *) &ptr->sema);
+}
+
+bool
+pg_atomic_compare_exchange_u32_impl(volatile pg_atomic_uint32 *ptr,
+ uint32 *expected, uint32 newval)
+{
+ bool ret;
+
+ /*
+ * Do atomic op under a spinlock. It might look like we could just skip
+ * the cmpxchg if the lock isn't available, but that'd just emulate a
+ * 'weak' compare and swap. I.e. one that allows spurious failures. Since
+ * several algorithms rely on a strong variant and that is efficiently
+ * implementable on most major architectures let's emulate it here as
+ * well.
+ */
+ SpinLockAcquire((slock_t *) &ptr->sema);
+
+ /* perform compare/exchange logic */
+ ret = ptr->value == *expected;
+ *expected = ptr->value;
+ if (ret)
+ ptr->value = newval;
+
+ /* and release lock */
+ SpinLockRelease((slock_t *) &ptr->sema);
+
+ return ret;
+}
+
+uint32
+pg_atomic_fetch_add_u32_impl(volatile pg_atomic_uint32 *ptr, int32 add_)
+{
+ uint32 oldval;
+
+ SpinLockAcquire((slock_t *) &ptr->sema);
+ oldval = ptr->value;
+ ptr->value += add_;
+ SpinLockRelease((slock_t *) &ptr->sema);
+ return oldval;
+}
+
+#endif /* PG_HAVE_ATOMIC_U32_SIMULATION */
+
+
+#ifdef PG_HAVE_ATOMIC_U64_SIMULATION
+
+void
+pg_atomic_init_u64_impl(volatile pg_atomic_uint64 *ptr, uint64 val_)
+{
+ StaticAssertStmt(sizeof(ptr->sema) >= sizeof(slock_t),
+ "size mismatch of atomic_uint64 vs slock_t");
+
+ /*
+ * If we're using semaphore based atomic flags, be careful about nested
+ * usage of atomics while a spinlock is held.
+ */
+#ifndef HAVE_SPINLOCKS
+ s_init_lock_sema((slock_t *) &ptr->sema, true);
+#else
+ SpinLockInit((slock_t *) &ptr->sema);
+#endif
+ ptr->value = val_;
+}
+
+bool
+pg_atomic_compare_exchange_u64_impl(volatile pg_atomic_uint64 *ptr,
+ uint64 *expected, uint64 newval)
+{
+ bool ret;
+
+ /*
+ * Do atomic op under a spinlock. It might look like we could just skip
+ * the cmpxchg if the lock isn't available, but that'd just emulate a
+ * 'weak' compare and swap. I.e. one that allows spurious failures. Since
+ * several algorithms rely on a strong variant and that is efficiently
+ * implementable on most major architectures let's emulate it here as
+ * well.
+ */
+ SpinLockAcquire((slock_t *) &ptr->sema);
+
+ /* perform compare/exchange logic */
+ ret = ptr->value == *expected;
+ *expected = ptr->value;
+ if (ret)
+ ptr->value = newval;
+
+ /* and release lock */
+ SpinLockRelease((slock_t *) &ptr->sema);
+
+ return ret;
+}
+
+uint64
+pg_atomic_fetch_add_u64_impl(volatile pg_atomic_uint64 *ptr, int64 add_)
+{
+ uint64 oldval;
+
+ SpinLockAcquire((slock_t *) &ptr->sema);
+ oldval = ptr->value;
+ ptr->value += add_;
+ SpinLockRelease((slock_t *) &ptr->sema);
+ return oldval;
+}
+
+#endif /* PG_HAVE_ATOMIC_U64_SIMULATION */
diff --git a/contrib/libs/postgresql/src/backend/port/posix_sema.c b/contrib/libs/postgresql/src/backend/port/posix_sema.c
new file mode 100644
index 0000000000..114da3b30c
--- /dev/null
+++ b/contrib/libs/postgresql/src/backend/port/posix_sema.c
@@ -0,0 +1,388 @@
+/*-------------------------------------------------------------------------
+ *
+ * posix_sema.c
+ * Implement PGSemaphores using POSIX semaphore facilities
+ *
+ * We prefer the unnamed style of POSIX semaphore (the kind made with
+ * sem_init). We can cope with the kind made with sem_open, however.
+ *
+ * In either implementation, typedef PGSemaphore is equivalent to "sem_t *".
+ * With unnamed semaphores, the sem_t structs live in an array in shared
+ * memory. With named semaphores, that's not true because we cannot persuade
+ * sem_open to do its allocation there. Therefore, the named-semaphore code
+ * *does not cope with EXEC_BACKEND*. The sem_t structs will just be in the
+ * postmaster's private memory, where they are successfully inherited by
+ * forked backends, but they could not be accessed by exec'd backends.
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/backend/port/posix_sema.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include <fcntl.h>
+#include <semaphore.h>
+#include <signal.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+#include "miscadmin.h"
+#include "storage/ipc.h"
+#include "storage/pg_sema.h"
+#include "storage/shmem.h"
+
+
+/* see file header comment */
+#if defined(USE_NAMED_POSIX_SEMAPHORES) && defined(EXEC_BACKEND)
+#error cannot use named POSIX semaphores with EXEC_BACKEND
+#endif
+
+typedef union SemTPadded
+{
+ sem_t pgsem;
+ char pad[PG_CACHE_LINE_SIZE];
+} SemTPadded;
+
+/* typedef PGSemaphore is equivalent to pointer to sem_t */
+typedef struct PGSemaphoreData
+{
+ SemTPadded sem_padded;
+} PGSemaphoreData;
+
+#define PG_SEM_REF(x) (&(x)->sem_padded.pgsem)
+
+#define IPCProtection (0600) /* access/modify by user only */
+
+#ifdef USE_NAMED_POSIX_SEMAPHORES
+static sem_t **mySemPointers; /* keep track of created semaphores */
+#else
+static PGSemaphore sharedSemas; /* array of PGSemaphoreData in shared memory */
+#endif
+static int numSems; /* number of semas acquired so far */
+static int maxSems; /* allocated size of above arrays */
+static int nextSemKey; /* next name to try */
+
+
+static void ReleaseSemaphores(int status, Datum arg);
+
+
+#ifdef USE_NAMED_POSIX_SEMAPHORES
+
+/*
+ * PosixSemaphoreCreate
+ *
+ * Attempt to create a new named semaphore.
+ *
+ * If we fail with a failure code other than collision-with-existing-sema,
+ * print out an error and abort. Other types of errors suggest nonrecoverable
+ * problems.
+ */
+static sem_t *
+PosixSemaphoreCreate(void)
+{
+ int semKey;
+ char semname[64];
+ sem_t *mySem;
+
+ for (;;)
+ {
+ semKey = nextSemKey++;
+
+ snprintf(semname, sizeof(semname), "/pgsql-%d", semKey);
+
+ mySem = sem_open(semname, O_CREAT | O_EXCL,
+ (mode_t) IPCProtection, (unsigned) 1);
+
+#ifdef SEM_FAILED
+ if (mySem != (sem_t *) SEM_FAILED)
+ break;
+#else
+ if (mySem != (sem_t *) (-1))
+ break;
+#endif
+
+ /* Loop if error indicates a collision */
+ if (errno == EEXIST || errno == EACCES || errno == EINTR)
+ continue;
+
+ /*
+ * Else complain and abort
+ */
+ elog(FATAL, "sem_open(\"%s\") failed: %m", semname);
+ }
+
+ /*
+ * Unlink the semaphore immediately, so it can't be accessed externally.
+ * This also ensures that it will go away if we crash.
+ */
+ sem_unlink(semname);
+
+ return mySem;
+}
+#else /* !USE_NAMED_POSIX_SEMAPHORES */
+
+/*
+ * PosixSemaphoreCreate
+ *
+ * Attempt to create a new unnamed semaphore.
+ */
+static void
+PosixSemaphoreCreate(sem_t *sem)
+{
+ if (sem_init(sem, 1, 1) < 0)
+ elog(FATAL, "sem_init failed: %m");
+}
+#endif /* USE_NAMED_POSIX_SEMAPHORES */
+
+
+/*
+ * PosixSemaphoreKill - removes a semaphore
+ */
+static void
+PosixSemaphoreKill(sem_t *sem)
+{
+#ifdef USE_NAMED_POSIX_SEMAPHORES
+ /* Got to use sem_close for named semaphores */
+ if (sem_close(sem) < 0)
+ elog(LOG, "sem_close failed: %m");
+#else
+ /* Got to use sem_destroy for unnamed semaphores */
+ if (sem_destroy(sem) < 0)
+ elog(LOG, "sem_destroy failed: %m");
+#endif
+}
+
+
+/*
+ * Report amount of shared memory needed for semaphores
+ */
+Size
+PGSemaphoreShmemSize(int maxSemas)
+{
+#ifdef USE_NAMED_POSIX_SEMAPHORES
+ /* No shared memory needed in this case */
+ return 0;
+#else
+ /* Need a PGSemaphoreData per semaphore */
+ return mul_size(maxSemas, sizeof(PGSemaphoreData));
+#endif
+}
+
+/*
+ * PGReserveSemaphores --- initialize semaphore support
+ *
+ * This is called during postmaster start or shared memory reinitialization.
+ * It should do whatever is needed to be able to support up to maxSemas
+ * subsequent PGSemaphoreCreate calls. Also, if any system resources
+ * are acquired here or in PGSemaphoreCreate, register an on_shmem_exit
+ * callback to release them.
+ *
+ * In the Posix implementation, we acquire semaphores on-demand; the
+ * maxSemas parameter is just used to size the arrays. For unnamed
+ * semaphores, there is an array of PGSemaphoreData structs in shared memory.
+ * For named semaphores, we keep a postmaster-local array of sem_t pointers,
+ * which we use for releasing the semaphores when done.
+ * (This design minimizes the dependency of postmaster shutdown on the
+ * contents of shared memory, which a failed backend might have clobbered.
+ * We can't do much about the possibility of sem_destroy() crashing, but
+ * we don't have to expose the counters to other processes.)
+ */
+void
+PGReserveSemaphores(int maxSemas)
+{
+ struct stat statbuf;
+
+ /*
+ * We use the data directory's inode number to seed the search for free
+ * semaphore keys. This minimizes the odds of collision with other
+ * postmasters, while maximizing the odds that we will detect and clean up
+ * semaphores left over from a crashed postmaster in our own directory.
+ */
+ if (stat(DataDir, &statbuf) < 0)
+ ereport(FATAL,
+ (errcode_for_file_access(),
+ errmsg("could not stat data directory \"%s\": %m",
+ DataDir)));
+
+#ifdef USE_NAMED_POSIX_SEMAPHORES
+ mySemPointers = (sem_t **) malloc(maxSemas * sizeof(sem_t *));
+ if (mySemPointers == NULL)
+ elog(PANIC, "out of memory");
+#else
+
+ /*
+ * We must use ShmemAllocUnlocked(), since the spinlock protecting
+ * ShmemAlloc() won't be ready yet. (This ordering is necessary when we
+ * are emulating spinlocks with semaphores.)
+ */
+ sharedSemas = (PGSemaphore)
+ ShmemAllocUnlocked(PGSemaphoreShmemSize(maxSemas));
+#endif
+
+ numSems = 0;
+ maxSems = maxSemas;
+ nextSemKey = statbuf.st_ino;
+
+ on_shmem_exit(ReleaseSemaphores, 0);
+}
+
+/*
+ * Release semaphores at shutdown or shmem reinitialization
+ *
+ * (called as an on_shmem_exit callback, hence funny argument list)
+ */
+static void
+ReleaseSemaphores(int status, Datum arg)
+{
+ int i;
+
+#ifdef USE_NAMED_POSIX_SEMAPHORES
+ for (i = 0; i < numSems; i++)
+ PosixSemaphoreKill(mySemPointers[i]);
+ free(mySemPointers);
+#endif
+
+#ifdef USE_UNNAMED_POSIX_SEMAPHORES
+ for (i = 0; i < numSems; i++)
+ PosixSemaphoreKill(PG_SEM_REF(sharedSemas + i));
+#endif
+}
+
+/*
+ * PGSemaphoreCreate
+ *
+ * Allocate a PGSemaphore structure with initial count 1
+ */
+PGSemaphore
+PGSemaphoreCreate(void)
+{
+ PGSemaphore sema;
+ sem_t *newsem;
+
+ /* Can't do this in a backend, because static state is postmaster's */
+ Assert(!IsUnderPostmaster);
+
+ if (numSems >= maxSems)
+ elog(PANIC, "too many semaphores created");
+
+#ifdef USE_NAMED_POSIX_SEMAPHORES
+ newsem = PosixSemaphoreCreate();
+ /* Remember new sema for ReleaseSemaphores */
+ mySemPointers[numSems] = newsem;
+ sema = (PGSemaphore) newsem;
+#else
+ sema = &sharedSemas[numSems];
+ newsem = PG_SEM_REF(sema);
+ PosixSemaphoreCreate(newsem);
+#endif
+
+ numSems++;
+
+ return sema;
+}
+
+/*
+ * PGSemaphoreReset
+ *
+ * Reset a previously-initialized PGSemaphore to have count 0
+ */
+void
+PGSemaphoreReset(PGSemaphore sema)
+{
+ /*
+ * There's no direct API for this in POSIX, so we have to ratchet the
+ * semaphore down to 0 with repeated trywait's.
+ */
+ for (;;)
+ {
+ if (sem_trywait(PG_SEM_REF(sema)) < 0)
+ {
+ if (errno == EAGAIN || errno == EDEADLK)
+ break; /* got it down to 0 */
+ if (errno == EINTR)
+ continue; /* can this happen? */
+ elog(FATAL, "sem_trywait failed: %m");
+ }
+ }
+}
+
+/*
+ * PGSemaphoreLock
+ *
+ * Lock a semaphore (decrement count), blocking if count would be < 0
+ */
+void
+PGSemaphoreLock(PGSemaphore sema)
+{
+ int errStatus;
+
+ /* See notes in sysv_sema.c's implementation of PGSemaphoreLock. */
+ do
+ {
+ errStatus = sem_wait(PG_SEM_REF(sema));
+ } while (errStatus < 0 && errno == EINTR);
+
+ if (errStatus < 0)
+ elog(FATAL, "sem_wait failed: %m");
+}
+
+/*
+ * PGSemaphoreUnlock
+ *
+ * Unlock a semaphore (increment count)
+ */
+void
+PGSemaphoreUnlock(PGSemaphore sema)
+{
+ int errStatus;
+
+ /*
+ * Note: if errStatus is -1 and errno == EINTR then it means we returned
+ * from the operation prematurely because we were sent a signal. So we
+ * try and unlock the semaphore again. Not clear this can really happen,
+ * but might as well cope.
+ */
+ do
+ {
+ errStatus = sem_post(PG_SEM_REF(sema));
+ } while (errStatus < 0 && errno == EINTR);
+
+ if (errStatus < 0)
+ elog(FATAL, "sem_post failed: %m");
+}
+
+/*
+ * PGSemaphoreTryLock
+ *
+ * Lock a semaphore only if able to do so without blocking
+ */
+bool
+PGSemaphoreTryLock(PGSemaphore sema)
+{
+ int errStatus;
+
+ /*
+ * Note: if errStatus is -1 and errno == EINTR then it means we returned
+ * from the operation prematurely because we were sent a signal. So we
+ * try and lock the semaphore again.
+ */
+ do
+ {
+ errStatus = sem_trywait(PG_SEM_REF(sema));
+ } while (errStatus < 0 && errno == EINTR);
+
+ if (errStatus < 0)
+ {
+ if (errno == EAGAIN || errno == EDEADLK)
+ return false; /* failed to lock it */
+ /* Otherwise we got trouble */
+ elog(FATAL, "sem_trywait failed: %m");
+ }
+
+ return true;
+}
diff --git a/contrib/libs/postgresql/src/backend/port/sysv_shmem.c b/contrib/libs/postgresql/src/backend/port/sysv_shmem.c
new file mode 100644
index 0000000000..35cce89e9c
--- /dev/null
+++ b/contrib/libs/postgresql/src/backend/port/sysv_shmem.c
@@ -0,0 +1,946 @@
+/*-------------------------------------------------------------------------
+ *
+ * sysv_shmem.c
+ * Implement shared memory using SysV facilities
+ *
+ * These routines used to be a fairly thin layer on top of SysV shared
+ * memory functionality. With the addition of anonymous-shmem logic,
+ * they're a bit fatter now. We still require a SysV shmem block to
+ * exist, though, because mmap'd shmem provides no way to find out how
+ * many processes are attached, which we need for interlocking purposes.
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/backend/port/sysv_shmem.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include <signal.h>
+#include <unistd.h>
+#include <sys/file.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#ifdef HAVE_SYS_IPC_H
+#include <sys/ipc.h>
+#endif
+#ifdef HAVE_SYS_SHM_H
+#include <sys/shm.h>
+#endif
+
+#include "miscadmin.h"
+#include "port/pg_bitutils.h"
+#include "portability/mem.h"
+#include "storage/dsm.h"
+#include "storage/fd.h"
+#include "storage/ipc.h"
+#include "storage/pg_shmem.h"
+#include "utils/guc.h"
+#include "utils/pidfile.h"
+
+
+/*
+ * As of PostgreSQL 9.3, we normally allocate only a very small amount of
+ * System V shared memory, and only for the purposes of providing an
+ * interlock to protect the data directory. The real shared memory block
+ * is allocated using mmap(). This works around the problem that many
+ * systems have very low limits on the amount of System V shared memory
+ * that can be allocated. Even a limit of a few megabytes will be enough
+ * to run many copies of PostgreSQL without needing to adjust system settings.
+ *
+ * We assume that no one will attempt to run PostgreSQL 9.3 or later on
+ * systems that are ancient enough that anonymous shared memory is not
+ * supported, such as pre-2.4 versions of Linux. If that turns out to be
+ * false, we might need to add compile and/or run-time tests here and do this
+ * only if the running kernel supports it.
+ *
+ * However, we must always disable this logic in the EXEC_BACKEND case, and
+ * fall back to the old method of allocating the entire segment using System V
+ * shared memory, because there's no way to attach an anonymous mmap'd segment
+ * to a process after exec(). Since EXEC_BACKEND is intended only for
+ * developer use, this shouldn't be a big problem. Because of this, we do
+ * not worry about supporting anonymous shmem in the EXEC_BACKEND cases below.
+ *
+ * As of PostgreSQL 12, we regained the ability to use a large System V shared
+ * memory region even in non-EXEC_BACKEND builds, if shared_memory_type is set
+ * to sysv (though this is not the default).
+ */
+
+
+typedef key_t IpcMemoryKey; /* shared memory key passed to shmget(2) */
+typedef int IpcMemoryId; /* shared memory ID returned by shmget(2) */
+
+/*
+ * How does a given IpcMemoryId relate to this PostgreSQL process?
+ *
+ * One could recycle unattached segments of different data directories if we
+ * distinguished that case from other SHMSTATE_FOREIGN cases. Doing so would
+ * cause us to visit less of the key space, making us less likely to detect a
+ * SHMSTATE_ATTACHED key. It would also complicate the concurrency analysis,
+ * in that postmasters of different data directories could simultaneously
+ * attempt to recycle a given key. We'll waste keys longer in some cases, but
+ * avoiding the problems of the alternative justifies that loss.
+ */
+typedef enum
+{
+ SHMSTATE_ANALYSIS_FAILURE, /* unexpected failure to analyze the ID */
+ SHMSTATE_ATTACHED, /* pertinent to DataDir, has attached PIDs */
+ SHMSTATE_ENOENT, /* no segment of that ID */
+ SHMSTATE_FOREIGN, /* exists, but not pertinent to DataDir */
+ SHMSTATE_UNATTACHED /* pertinent to DataDir, no attached PIDs */
+} IpcMemoryState;
+
+
+unsigned long UsedShmemSegID = 0;
+void *UsedShmemSegAddr = NULL;
+
+static Size AnonymousShmemSize;
+static void *AnonymousShmem = NULL;
+
+static void *InternalIpcMemoryCreate(IpcMemoryKey memKey, Size size);
+static void IpcMemoryDetach(int status, Datum shmaddr);
+static void IpcMemoryDelete(int status, Datum shmId);
+static IpcMemoryState PGSharedMemoryAttach(IpcMemoryId shmId,
+ void *attachAt,
+ PGShmemHeader **addr);
+
+
+/*
+ * InternalIpcMemoryCreate(memKey, size)
+ *
+ * Attempt to create a new shared memory segment with the specified key.
+ * Will fail (return NULL) if such a segment already exists. If successful,
+ * attach the segment to the current process and return its attached address.
+ * On success, callbacks are registered with on_shmem_exit to detach and
+ * delete the segment when on_shmem_exit is called.
+ *
+ * If we fail with a failure code other than collision-with-existing-segment,
+ * print out an error and abort. Other types of errors are not recoverable.
+ */
+static void *
+InternalIpcMemoryCreate(IpcMemoryKey memKey, Size size)
+{
+ IpcMemoryId shmid;
+ void *requestedAddress = NULL;
+ void *memAddress;
+
+ /*
+ * Normally we just pass requestedAddress = NULL to shmat(), allowing the
+ * system to choose where the segment gets mapped. But in an EXEC_BACKEND
+ * build, it's possible for whatever is chosen in the postmaster to not
+ * work for backends, due to variations in address space layout. As a
+ * rather klugy workaround, allow the user to specify the address to use
+ * via setting the environment variable PG_SHMEM_ADDR. (If this were of
+ * interest for anything except debugging, we'd probably create a cleaner
+ * and better-documented way to set it, such as a GUC.)
+ */
+#ifdef EXEC_BACKEND
+ {
+ char *pg_shmem_addr = getenv("PG_SHMEM_ADDR");
+
+ if (pg_shmem_addr)
+ requestedAddress = (void *) strtoul(pg_shmem_addr, NULL, 0);
+ else
+ {
+#if defined(__darwin__) && SIZEOF_VOID_P == 8
+ /*
+ * Provide a default value that is believed to avoid problems with
+ * ASLR on the current macOS release.
+ */
+ requestedAddress = (void *) 0x80000000000;
+#endif
+ }
+ }
+#endif
+
+ shmid = shmget(memKey, size, IPC_CREAT | IPC_EXCL | IPCProtection);
+
+ if (shmid < 0)
+ {
+ int shmget_errno = errno;
+
+ /*
+ * Fail quietly if error indicates a collision with existing segment.
+ * One would expect EEXIST, given that we said IPC_EXCL, but perhaps
+ * we could get a permission violation instead? Also, EIDRM might
+ * occur if an old seg is slated for destruction but not gone yet.
+ */
+ if (shmget_errno == EEXIST || shmget_errno == EACCES
+#ifdef EIDRM
+ || shmget_errno == EIDRM
+#endif
+ )
+ return NULL;
+
+ /*
+ * Some BSD-derived kernels are known to return EINVAL, not EEXIST, if
+ * there is an existing segment but it's smaller than "size" (this is
+ * a result of poorly-thought-out ordering of error tests). To
+ * distinguish between collision and invalid size in such cases, we
+ * make a second try with size = 0. These kernels do not test size
+ * against SHMMIN in the preexisting-segment case, so we will not get
+ * EINVAL a second time if there is such a segment.
+ */
+ if (shmget_errno == EINVAL)
+ {
+ shmid = shmget(memKey, 0, IPC_CREAT | IPC_EXCL | IPCProtection);
+
+ if (shmid < 0)
+ {
+ /* As above, fail quietly if we verify a collision */
+ if (errno == EEXIST || errno == EACCES
+#ifdef EIDRM
+ || errno == EIDRM
+#endif
+ )
+ return NULL;
+ /* Otherwise, fall through to report the original error */
+ }
+ else
+ {
+ /*
+ * On most platforms we cannot get here because SHMMIN is
+ * greater than zero. However, if we do succeed in creating a
+ * zero-size segment, free it and then fall through to report
+ * the original error.
+ */
+ if (shmctl(shmid, IPC_RMID, NULL) < 0)
+ elog(LOG, "shmctl(%d, %d, 0) failed: %m",
+ (int) shmid, IPC_RMID);
+ }
+ }
+
+ /*
+ * Else complain and abort.
+ *
+ * Note: at this point EINVAL should mean that either SHMMIN or SHMMAX
+ * is violated. SHMALL violation might be reported as either ENOMEM
+ * (BSDen) or ENOSPC (Linux); the Single Unix Spec fails to say which
+ * it should be. SHMMNI violation is ENOSPC, per spec. Just plain
+ * not-enough-RAM is ENOMEM.
+ */
+ errno = shmget_errno;
+ ereport(FATAL,
+ (errmsg("could not create shared memory segment: %m"),
+ errdetail("Failed system call was shmget(key=%lu, size=%zu, 0%o).",
+ (unsigned long) memKey, size,
+ IPC_CREAT | IPC_EXCL | IPCProtection),
+ (shmget_errno == EINVAL) ?
+ errhint("This error usually means that PostgreSQL's request for a shared memory "
+ "segment exceeded your kernel's SHMMAX parameter, or possibly that "
+ "it is less than "
+ "your kernel's SHMMIN parameter.\n"
+ "The PostgreSQL documentation contains more information about shared "
+ "memory configuration.") : 0,
+ (shmget_errno == ENOMEM) ?
+ errhint("This error usually means that PostgreSQL's request for a shared "
+ "memory segment exceeded your kernel's SHMALL parameter. You might need "
+ "to reconfigure the kernel with larger SHMALL.\n"
+ "The PostgreSQL documentation contains more information about shared "
+ "memory configuration.") : 0,
+ (shmget_errno == ENOSPC) ?
+ errhint("This error does *not* mean that you have run out of disk space. "
+ "It occurs either if all available shared memory IDs have been taken, "
+ "in which case you need to raise the SHMMNI parameter in your kernel, "
+ "or because the system's overall limit for shared memory has been "
+ "reached.\n"
+ "The PostgreSQL documentation contains more information about shared "
+ "memory configuration.") : 0));
+ }
+
+ /* Register on-exit routine to delete the new segment */
+ on_shmem_exit(IpcMemoryDelete, Int32GetDatum(shmid));
+
+ /* OK, should be able to attach to the segment */
+ memAddress = shmat(shmid, requestedAddress, PG_SHMAT_FLAGS);
+
+ if (memAddress == (void *) -1)
+ elog(FATAL, "shmat(id=%d, addr=%p, flags=0x%x) failed: %m",
+ shmid, requestedAddress, PG_SHMAT_FLAGS);
+
+ /* Register on-exit routine to detach new segment before deleting */
+ on_shmem_exit(IpcMemoryDetach, PointerGetDatum(memAddress));
+
+ /*
+ * Store shmem key and ID in data directory lockfile. Format to try to
+ * keep it the same length always (trailing junk in the lockfile won't
+ * hurt, but might confuse humans).
+ */
+ {
+ char line[64];
+
+ sprintf(line, "%9lu %9lu",
+ (unsigned long) memKey, (unsigned long) shmid);
+ AddToDataDirLockFile(LOCK_FILE_LINE_SHMEM_KEY, line);
+ }
+
+ return memAddress;
+}
+
+/****************************************************************************/
+/* IpcMemoryDetach(status, shmaddr) removes a shared memory segment */
+/* from process' address space */
+/* (called as an on_shmem_exit callback, hence funny argument list) */
+/****************************************************************************/
+static void
+IpcMemoryDetach(int status, Datum shmaddr)
+{
+ /* Detach System V shared memory block. */
+ if (shmdt(DatumGetPointer(shmaddr)) < 0)
+ elog(LOG, "shmdt(%p) failed: %m", DatumGetPointer(shmaddr));
+}
+
+/****************************************************************************/
+/* IpcMemoryDelete(status, shmId) deletes a shared memory segment */
+/* (called as an on_shmem_exit callback, hence funny argument list) */
+/****************************************************************************/
+static void
+IpcMemoryDelete(int status, Datum shmId)
+{
+ if (shmctl(DatumGetInt32(shmId), IPC_RMID, NULL) < 0)
+ elog(LOG, "shmctl(%d, %d, 0) failed: %m",
+ DatumGetInt32(shmId), IPC_RMID);
+}
+
+/*
+ * PGSharedMemoryIsInUse
+ *
+ * Is a previously-existing shmem segment still existing and in use?
+ *
+ * The point of this exercise is to detect the case where a prior postmaster
+ * crashed, but it left child backends that are still running. Therefore
+ * we only care about shmem segments that are associated with the intended
+ * DataDir. This is an important consideration since accidental matches of
+ * shmem segment IDs are reasonably common.
+ */
+bool
+PGSharedMemoryIsInUse(unsigned long id1, unsigned long id2)
+{
+ PGShmemHeader *memAddress;
+ IpcMemoryState state;
+
+ state = PGSharedMemoryAttach((IpcMemoryId) id2, NULL, &memAddress);
+ if (memAddress && shmdt(memAddress) < 0)
+ elog(LOG, "shmdt(%p) failed: %m", memAddress);
+ switch (state)
+ {
+ case SHMSTATE_ENOENT:
+ case SHMSTATE_FOREIGN:
+ case SHMSTATE_UNATTACHED:
+ return false;
+ case SHMSTATE_ANALYSIS_FAILURE:
+ case SHMSTATE_ATTACHED:
+ return true;
+ }
+ return true;
+}
+
+/*
+ * Test for a segment with id shmId; see comment at IpcMemoryState.
+ *
+ * If the segment exists, we'll attempt to attach to it, using attachAt
+ * if that's not NULL (but it's best to pass NULL if possible).
+ *
+ * *addr is set to the segment memory address if we attached to it, else NULL.
+ */
+static IpcMemoryState
+PGSharedMemoryAttach(IpcMemoryId shmId,
+ void *attachAt,
+ PGShmemHeader **addr)
+{
+ struct shmid_ds shmStat;
+ struct stat statbuf;
+ PGShmemHeader *hdr;
+
+ *addr = NULL;
+
+ /*
+ * First, try to stat the shm segment ID, to see if it exists at all.
+ */
+ if (shmctl(shmId, IPC_STAT, &shmStat) < 0)
+ {
+ /*
+ * EINVAL actually has multiple possible causes documented in the
+ * shmctl man page, but we assume it must mean the segment no longer
+ * exists.
+ */
+ if (errno == EINVAL)
+ return SHMSTATE_ENOENT;
+
+ /*
+ * EACCES implies we have no read permission, which means it is not a
+ * Postgres shmem segment (or at least, not one that is relevant to
+ * our data directory).
+ */
+ if (errno == EACCES)
+ return SHMSTATE_FOREIGN;
+
+ /*
+ * Some Linux kernel versions (in fact, all of them as of July 2007)
+ * sometimes return EIDRM when EINVAL is correct. The Linux kernel
+ * actually does not have any internal state that would justify
+ * returning EIDRM, so we can get away with assuming that EIDRM is
+ * equivalent to EINVAL on that platform.
+ */
+#ifdef HAVE_LINUX_EIDRM_BUG
+ if (errno == EIDRM)
+ return SHMSTATE_ENOENT;
+#endif
+
+ /*
+ * Otherwise, we had better assume that the segment is in use. The
+ * only likely case is (non-Linux, assumed spec-compliant) EIDRM,
+ * which implies that the segment has been IPC_RMID'd but there are
+ * still processes attached to it.
+ */
+ return SHMSTATE_ANALYSIS_FAILURE;
+ }
+
+ /*
+ * Try to attach to the segment and see if it matches our data directory.
+ * This avoids any risk of duplicate-shmem-key conflicts on machines that
+ * are running several postmasters under the same userid.
+ *
+ * (When we're called from PGSharedMemoryCreate, this stat call is
+ * duplicative; but since this isn't a high-traffic case it's not worth
+ * trying to optimize.)
+ */
+ if (stat(DataDir, &statbuf) < 0)
+ return SHMSTATE_ANALYSIS_FAILURE; /* can't stat; be conservative */
+
+ hdr = (PGShmemHeader *) shmat(shmId, attachAt, PG_SHMAT_FLAGS);
+ if (hdr == (PGShmemHeader *) -1)
+ {
+ /*
+ * Attachment failed. The cases we're interested in are the same as
+ * for the shmctl() call above. In particular, note that the owning
+ * postmaster could have terminated and removed the segment between
+ * shmctl() and shmat().
+ *
+ * If attachAt isn't NULL, it's possible that EINVAL reflects a
+ * problem with that address not a vanished segment, so it's best to
+ * pass NULL when probing for conflicting segments.
+ */
+ if (errno == EINVAL)
+ return SHMSTATE_ENOENT; /* segment disappeared */
+ if (errno == EACCES)
+ return SHMSTATE_FOREIGN; /* must be non-Postgres */
+#ifdef HAVE_LINUX_EIDRM_BUG
+ if (errno == EIDRM)
+ return SHMSTATE_ENOENT; /* segment disappeared */
+#endif
+ /* Otherwise, be conservative. */
+ return SHMSTATE_ANALYSIS_FAILURE;
+ }
+ *addr = hdr;
+
+ if (hdr->magic != PGShmemMagic ||
+ hdr->device != statbuf.st_dev ||
+ hdr->inode != statbuf.st_ino)
+ {
+ /*
+ * It's either not a Postgres segment, or not one for my data
+ * directory.
+ */
+ return SHMSTATE_FOREIGN;
+ }
+
+ /*
+ * It does match our data directory, so now test whether any processes are
+ * still attached to it. (We are, now, but the shm_nattch result is from
+ * before we attached to it.)
+ */
+ return shmStat.shm_nattch == 0 ? SHMSTATE_UNATTACHED : SHMSTATE_ATTACHED;
+}
+
+#ifdef MAP_HUGETLB
+
+/*
+ * Identify the huge page size to use, and compute the related mmap flags.
+ *
+ * Some Linux kernel versions have a bug causing mmap() to fail on requests
+ * that are not a multiple of the hugepage size. Versions without that bug
+ * instead silently round the request up to the next hugepage multiple ---
+ * and then munmap() fails when we give it a size different from that.
+ * So we have to round our request up to a multiple of the actual hugepage
+ * size to avoid trouble.
+ *
+ * Doing the round-up ourselves also lets us make use of the extra memory,
+ * rather than just wasting it. Currently, we just increase the available
+ * space recorded in the shmem header, which will make the extra usable for
+ * purposes such as additional locktable entries. Someday, for very large
+ * hugepage sizes, we might want to think about more invasive strategies,
+ * such as increasing shared_buffers to absorb the extra space.
+ *
+ * Returns the (real, assumed or config provided) page size into *hugepagesize,
+ * and the hugepage-related mmap flags to use into *mmap_flags.
+ */
+static void
+GetHugePageSize(Size *hugepagesize, int *mmap_flags)
+{
+ Size default_hugepagesize = 0;
+
+ /*
+ * System-dependent code to find out the default huge page size.
+ *
+ * On Linux, read /proc/meminfo looking for a line like "Hugepagesize:
+ * nnnn kB". Ignore any failures, falling back to the preset default.
+ */
+#ifdef __linux__
+
+ {
+ FILE *fp = AllocateFile("/proc/meminfo", "r");
+ char buf[128];
+ unsigned int sz;
+ char ch;
+
+ if (fp)
+ {
+ while (fgets(buf, sizeof(buf), fp))
+ {
+ if (sscanf(buf, "Hugepagesize: %u %c", &sz, &ch) == 2)
+ {
+ if (ch == 'k')
+ {
+ default_hugepagesize = sz * (Size) 1024;
+ break;
+ }
+ /* We could accept other units besides kB, if needed */
+ }
+ }
+ FreeFile(fp);
+ }
+ }
+#endif /* __linux__ */
+
+ if (huge_page_size != 0)
+ {
+ /* If huge page size is requested explicitly, use that. */
+ *hugepagesize = (Size) huge_page_size * 1024;
+ }
+ else if (default_hugepagesize != 0)
+ {
+ /* Otherwise use the system default, if we have it. */
+ *hugepagesize = default_hugepagesize;
+ }
+ else
+ {
+ /*
+ * If we fail to find out the system's default huge page size, or no
+ * huge page size is requested explicitly, assume it is 2MB. This will
+ * work fine when the actual size is less. If it's more, we might get
+ * mmap() or munmap() failures due to unaligned requests; but at this
+ * writing, there are no reports of any non-Linux systems being picky
+ * about that.
+ */
+ *hugepagesize = 2 * 1024 * 1024;
+ }
+
+ *mmap_flags = MAP_HUGETLB;
+
+ /*
+ * On recent enough Linux, also include the explicit page size, if
+ * necessary.
+ */
+#if defined(MAP_HUGE_MASK) && defined(MAP_HUGE_SHIFT)
+ if (*hugepagesize != default_hugepagesize)
+ {
+ int shift = pg_ceil_log2_64(*hugepagesize);
+
+ *mmap_flags |= (shift & MAP_HUGE_MASK) << MAP_HUGE_SHIFT;
+ }
+#endif
+}
+
+#endif /* MAP_HUGETLB */
+
+/*
+ * Creates an anonymous mmap()ed shared memory segment.
+ *
+ * Pass the requested size in *size. This function will modify *size to the
+ * actual size of the allocation, if it ends up allocating a segment that is
+ * larger than requested.
+ */
+static void *
+CreateAnonymousSegment(Size *size)
+{
+ Size allocsize = *size;
+ void *ptr = MAP_FAILED;
+ int mmap_errno = 0;
+
+#ifndef MAP_HUGETLB
+ /* PGSharedMemoryCreate should have dealt with this case */
+ Assert(huge_pages != HUGE_PAGES_ON);
+#else
+ if (huge_pages == HUGE_PAGES_ON || huge_pages == HUGE_PAGES_TRY)
+ {
+ /*
+ * Round up the request size to a suitable large value.
+ */
+ Size hugepagesize;
+ int mmap_flags;
+
+ GetHugePageSize(&hugepagesize, &mmap_flags);
+
+ if (allocsize % hugepagesize != 0)
+ allocsize += hugepagesize - (allocsize % hugepagesize);
+
+ ptr = mmap(NULL, allocsize, PROT_READ | PROT_WRITE,
+ PG_MMAP_FLAGS | mmap_flags, -1, 0);
+ mmap_errno = errno;
+ if (huge_pages == HUGE_PAGES_TRY && ptr == MAP_FAILED)
+ elog(DEBUG1, "mmap(%zu) with MAP_HUGETLB failed, huge pages disabled: %m",
+ allocsize);
+ }
+#endif
+
+ if (ptr == MAP_FAILED && huge_pages != HUGE_PAGES_ON)
+ {
+ /*
+ * Use the original size, not the rounded-up value, when falling back
+ * to non-huge pages.
+ */
+ allocsize = *size;
+ ptr = mmap(NULL, allocsize, PROT_READ | PROT_WRITE,
+ PG_MMAP_FLAGS, -1, 0);
+ mmap_errno = errno;
+ }
+
+ if (ptr == MAP_FAILED)
+ {
+ errno = mmap_errno;
+ ereport(FATAL,
+ (errmsg("could not map anonymous shared memory: %m"),
+ (mmap_errno == ENOMEM) ?
+ errhint("This error usually means that PostgreSQL's request "
+ "for a shared memory segment exceeded available memory, "
+ "swap space, or huge pages. To reduce the request size "
+ "(currently %zu bytes), reduce PostgreSQL's shared "
+ "memory usage, perhaps by reducing shared_buffers or "
+ "max_connections.",
+ allocsize) : 0));
+ }
+
+ *size = allocsize;
+ return ptr;
+}
+
+/*
+ * AnonymousShmemDetach --- detach from an anonymous mmap'd block
+ * (called as an on_shmem_exit callback, hence funny argument list)
+ */
+static void
+AnonymousShmemDetach(int status, Datum arg)
+{
+ /* Release anonymous shared memory block, if any. */
+ if (AnonymousShmem != NULL)
+ {
+ if (munmap(AnonymousShmem, AnonymousShmemSize) < 0)
+ elog(LOG, "munmap(%p, %zu) failed: %m",
+ AnonymousShmem, AnonymousShmemSize);
+ AnonymousShmem = NULL;
+ }
+}
+
+/*
+ * PGSharedMemoryCreate
+ *
+ * Create a shared memory segment of the given size and initialize its
+ * standard header. Also, register an on_shmem_exit callback to release
+ * the storage.
+ *
+ * Dead Postgres segments pertinent to this DataDir are recycled if found, but
+ * we do not fail upon collision with foreign shmem segments. The idea here
+ * is to detect and re-use keys that may have been assigned by a crashed
+ * postmaster or backend.
+ */
+PGShmemHeader *
+PGSharedMemoryCreate(Size size,
+ PGShmemHeader **shim)
+{
+ IpcMemoryKey NextShmemSegID;
+ void *memAddress;
+ PGShmemHeader *hdr;
+ struct stat statbuf;
+ Size sysvsize;
+
+ /*
+ * We use the data directory's ID info (inode and device numbers) to
+ * positively identify shmem segments associated with this data dir, and
+ * also as seeds for searching for a free shmem key.
+ */
+ if (stat(DataDir, &statbuf) < 0)
+ ereport(FATAL,
+ (errcode_for_file_access(),
+ errmsg("could not stat data directory \"%s\": %m",
+ DataDir)));
+
+ /* Complain if hugepages demanded but we can't possibly support them */
+#if !defined(MAP_HUGETLB)
+ if (huge_pages == HUGE_PAGES_ON)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("huge pages not supported on this platform")));
+#endif
+
+ /* For now, we don't support huge pages in SysV memory */
+ if (huge_pages == HUGE_PAGES_ON && shared_memory_type != SHMEM_TYPE_MMAP)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("huge pages not supported with the current shared_memory_type setting")));
+
+ /* Room for a header? */
+ Assert(size > MAXALIGN(sizeof(PGShmemHeader)));
+
+ if (shared_memory_type == SHMEM_TYPE_MMAP)
+ {
+ AnonymousShmem = CreateAnonymousSegment(&size);
+ AnonymousShmemSize = size;
+
+ /* Register on-exit routine to unmap the anonymous segment */
+ on_shmem_exit(AnonymousShmemDetach, (Datum) 0);
+
+ /* Now we need only allocate a minimal-sized SysV shmem block. */
+ sysvsize = sizeof(PGShmemHeader);
+ }
+ else
+ sysvsize = size;
+
+ /*
+ * Loop till we find a free IPC key. Trust CreateDataDirLockFile() to
+ * ensure no more than one postmaster per data directory can enter this
+ * loop simultaneously. (CreateDataDirLockFile() does not entirely ensure
+ * that, but prefer fixing it over coping here.)
+ */
+ NextShmemSegID = statbuf.st_ino;
+
+ for (;;)
+ {
+ IpcMemoryId shmid;
+ PGShmemHeader *oldhdr;
+ IpcMemoryState state;
+
+ /* Try to create new segment */
+ memAddress = InternalIpcMemoryCreate(NextShmemSegID, sysvsize);
+ if (memAddress)
+ break; /* successful create and attach */
+
+ /* Check shared memory and possibly remove and recreate */
+
+ /*
+ * shmget() failure is typically EACCES, hence SHMSTATE_FOREIGN.
+ * ENOENT, a narrow possibility, implies SHMSTATE_ENOENT, but one can
+ * safely treat SHMSTATE_ENOENT like SHMSTATE_FOREIGN.
+ */
+ shmid = shmget(NextShmemSegID, sizeof(PGShmemHeader), 0);
+ if (shmid < 0)
+ {
+ oldhdr = NULL;
+ state = SHMSTATE_FOREIGN;
+ }
+ else
+ state = PGSharedMemoryAttach(shmid, NULL, &oldhdr);
+
+ switch (state)
+ {
+ case SHMSTATE_ANALYSIS_FAILURE:
+ case SHMSTATE_ATTACHED:
+ ereport(FATAL,
+ (errcode(ERRCODE_LOCK_FILE_EXISTS),
+ errmsg("pre-existing shared memory block (key %lu, ID %lu) is still in use",
+ (unsigned long) NextShmemSegID,
+ (unsigned long) shmid),
+ errhint("Terminate any old server processes associated with data directory \"%s\".",
+ DataDir)));
+ break;
+ case SHMSTATE_ENOENT:
+
+ /*
+ * To our surprise, some other process deleted since our last
+ * InternalIpcMemoryCreate(). Moments earlier, we would have
+ * seen SHMSTATE_FOREIGN. Try that same ID again.
+ */
+ elog(LOG,
+ "shared memory block (key %lu, ID %lu) deleted during startup",
+ (unsigned long) NextShmemSegID,
+ (unsigned long) shmid);
+ break;
+ case SHMSTATE_FOREIGN:
+ NextShmemSegID++;
+ break;
+ case SHMSTATE_UNATTACHED:
+
+ /*
+ * The segment pertains to DataDir, and every process that had
+ * used it has died or detached. Zap it, if possible, and any
+ * associated dynamic shared memory segments, as well. This
+ * shouldn't fail, but if it does, assume the segment belongs
+ * to someone else after all, and try the next candidate.
+ * Otherwise, try again to create the segment. That may fail
+ * if some other process creates the same shmem key before we
+ * do, in which case we'll try the next key.
+ */
+ if (oldhdr->dsm_control != 0)
+ dsm_cleanup_using_control_segment(oldhdr->dsm_control);
+ if (shmctl(shmid, IPC_RMID, NULL) < 0)
+ NextShmemSegID++;
+ break;
+ }
+
+ if (oldhdr && shmdt(oldhdr) < 0)
+ elog(LOG, "shmdt(%p) failed: %m", oldhdr);
+ }
+
+ /* Initialize new segment. */
+ hdr = (PGShmemHeader *) memAddress;
+ hdr->creatorPID = getpid();
+ hdr->magic = PGShmemMagic;
+ hdr->dsm_control = 0;
+
+ /* Fill in the data directory ID info, too */
+ hdr->device = statbuf.st_dev;
+ hdr->inode = statbuf.st_ino;
+
+ /*
+ * Initialize space allocation status for segment.
+ */
+ hdr->totalsize = size;
+ hdr->freeoffset = MAXALIGN(sizeof(PGShmemHeader));
+ *shim = hdr;
+
+ /* Save info for possible future use */
+ UsedShmemSegAddr = memAddress;
+ UsedShmemSegID = (unsigned long) NextShmemSegID;
+
+ /*
+ * If AnonymousShmem is NULL here, then we're not using anonymous shared
+ * memory, and should return a pointer to the System V shared memory
+ * block. Otherwise, the System V shared memory block is only a shim, and
+ * we must return a pointer to the real block.
+ */
+ if (AnonymousShmem == NULL)
+ return hdr;
+ memcpy(AnonymousShmem, hdr, sizeof(PGShmemHeader));
+ return (PGShmemHeader *) AnonymousShmem;
+}
+
+#ifdef EXEC_BACKEND
+
+/*
+ * PGSharedMemoryReAttach
+ *
+ * This is called during startup of a postmaster child process to re-attach to
+ * an already existing shared memory segment. This is needed only in the
+ * EXEC_BACKEND case; otherwise postmaster children inherit the shared memory
+ * segment attachment via fork().
+ *
+ * UsedShmemSegID and UsedShmemSegAddr are implicit parameters to this
+ * routine. The caller must have already restored them to the postmaster's
+ * values.
+ */
+void
+PGSharedMemoryReAttach(void)
+{
+ IpcMemoryId shmid;
+ PGShmemHeader *hdr;
+ IpcMemoryState state;
+ void *origUsedShmemSegAddr = UsedShmemSegAddr;
+
+ Assert(UsedShmemSegAddr != NULL);
+ Assert(IsUnderPostmaster);
+
+#ifdef __CYGWIN__
+ /* cygipc (currently) appears to not detach on exec. */
+ PGSharedMemoryDetach();
+ UsedShmemSegAddr = origUsedShmemSegAddr;
+#endif
+
+ elog(DEBUG3, "attaching to %p", UsedShmemSegAddr);
+ shmid = shmget(UsedShmemSegID, sizeof(PGShmemHeader), 0);
+ if (shmid < 0)
+ state = SHMSTATE_FOREIGN;
+ else
+ state = PGSharedMemoryAttach(shmid, UsedShmemSegAddr, &hdr);
+ if (state != SHMSTATE_ATTACHED)
+ elog(FATAL, "could not reattach to shared memory (key=%d, addr=%p): %m",
+ (int) UsedShmemSegID, UsedShmemSegAddr);
+ if (hdr != origUsedShmemSegAddr)
+ elog(FATAL, "reattaching to shared memory returned unexpected address (got %p, expected %p)",
+ hdr, origUsedShmemSegAddr);
+ dsm_set_control_handle(hdr->dsm_control);
+
+ UsedShmemSegAddr = hdr; /* probably redundant */
+}
+
+/*
+ * PGSharedMemoryNoReAttach
+ *
+ * This is called during startup of a postmaster child process when we choose
+ * *not* to re-attach to the existing shared memory segment. We must clean up
+ * to leave things in the appropriate state. This is not used in the non
+ * EXEC_BACKEND case, either.
+ *
+ * The child process startup logic might or might not call PGSharedMemoryDetach
+ * after this; make sure that it will be a no-op if called.
+ *
+ * UsedShmemSegID and UsedShmemSegAddr are implicit parameters to this
+ * routine. The caller must have already restored them to the postmaster's
+ * values.
+ */
+void
+PGSharedMemoryNoReAttach(void)
+{
+ Assert(UsedShmemSegAddr != NULL);
+ Assert(IsUnderPostmaster);
+
+#ifdef __CYGWIN__
+ /* cygipc (currently) appears to not detach on exec. */
+ PGSharedMemoryDetach();
+#endif
+
+ /* For cleanliness, reset UsedShmemSegAddr to show we're not attached. */
+ UsedShmemSegAddr = NULL;
+ /* And the same for UsedShmemSegID. */
+ UsedShmemSegID = 0;
+}
+
+#endif /* EXEC_BACKEND */
+
+/*
+ * PGSharedMemoryDetach
+ *
+ * Detach from the shared memory segment, if still attached. This is not
+ * intended to be called explicitly by the process that originally created the
+ * segment (it will have on_shmem_exit callback(s) registered to do that).
+ * Rather, this is for subprocesses that have inherited an attachment and want
+ * to get rid of it.
+ *
+ * UsedShmemSegID and UsedShmemSegAddr are implicit parameters to this
+ * routine, also AnonymousShmem and AnonymousShmemSize.
+ */
+void
+PGSharedMemoryDetach(void)
+{
+ if (UsedShmemSegAddr != NULL)
+ {
+ if ((shmdt(UsedShmemSegAddr) < 0)
+#if defined(EXEC_BACKEND) && defined(__CYGWIN__)
+ /* Work-around for cygipc exec bug */
+ && shmdt(NULL) < 0
+#endif
+ )
+ elog(LOG, "shmdt(%p) failed: %m", UsedShmemSegAddr);
+ UsedShmemSegAddr = NULL;
+ }
+
+ if (AnonymousShmem != NULL)
+ {
+ if (munmap(AnonymousShmem, AnonymousShmemSize) < 0)
+ elog(LOG, "munmap(%p, %zu) failed: %m",
+ AnonymousShmem, AnonymousShmemSize);
+ AnonymousShmem = NULL;
+ }
+}
diff --git a/contrib/libs/postgresql/src/backend/port/win32/crashdump.c b/contrib/libs/postgresql/src/backend/port/win32/crashdump.c
new file mode 100644
index 0000000000..45b6696ba1
--- /dev/null
+++ b/contrib/libs/postgresql/src/backend/port/win32/crashdump.c
@@ -0,0 +1,183 @@
+/*-------------------------------------------------------------------------
+ *
+ * crashdump.c
+ * Automatic crash dump creation for PostgreSQL on Windows
+ *
+ * The crashdump feature traps unhandled win32 exceptions produced by the
+ * backend, and tries to produce a Windows MiniDump crash
+ * dump for later debugging and analysis. The machine performing the dump
+ * doesn't need any special debugging tools; the user only needs to send
+ * the dump to somebody who has the same version of PostgreSQL and has debugging
+ * tools.
+ *
+ * crashdump module originally by Craig Ringer <ringerc@ringerc.id.au>
+ *
+ * LIMITATIONS
+ * ===========
+ * This *won't* work in hard OOM situations or stack overflows.
+ *
+ * For those, it'd be necessary to take a much more complicated approach where
+ * the handler switches to a new stack (if it can) and forks a helper process
+ * to debug it self.
+ *
+ * POSSIBLE FUTURE WORK
+ * ====================
+ * For bonus points, the crash dump format permits embedding of user-supplied
+ * data. If there's anything else that should always be supplied with a crash
+ * dump (postgresql.conf? Last few lines of a log file?), it could potentially
+ * be added, though at the cost of a greater chance of the crash dump failing.
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/backend/port/win32/crashdump.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#define WIN32_LEAN_AND_MEAN
+
+/*
+ * Some versions of the MS SDK contain "typedef enum { ... } ;" which the MS
+ * compiler quite sanely complains about. Well done, Microsoft.
+ * This pragma disables the warning just while we include the header.
+ * The pragma is known to work with all (as at the time of writing) supported
+ * versions of MSVC.
+ */
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable : 4091)
+#endif
+#include <dbghelp.h>
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+/*
+ * Much of the following code is based on CodeProject and MSDN examples,
+ * particularly
+ * http://www.codeproject.com/KB/debug/postmortemdebug_standalone1.aspx
+ *
+ * Useful MSDN articles:
+ *
+ * http://msdn.microsoft.com/en-us/library/ff805116(v=VS.85).aspx
+ * http://msdn.microsoft.com/en-us/library/ms679294(VS.85).aspx
+ *
+ * Other useful articles on working with minidumps:
+ * http://www.debuginfo.com/articles/effminidumps.html
+ */
+
+typedef BOOL (WINAPI * MINIDUMPWRITEDUMP) (HANDLE hProcess, DWORD dwPid, HANDLE hFile, MINIDUMP_TYPE DumpType,
+ CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
+ CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
+ CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam
+);
+
+
+/*
+ * This function is the exception handler passed to SetUnhandledExceptionFilter.
+ * It's invoked only if there's an unhandled exception. The handler will use
+ * dbghelp.dll to generate a crash dump, then resume the normal unhandled
+ * exception process, which will generally exit with an error message from
+ * the runtime.
+ *
+ * This function is run under the unhandled exception handler, effectively
+ * in a crash context, so it should be careful with memory and avoid using
+ * any PostgreSQL functions.
+ */
+static LONG WINAPI
+crashDumpHandler(struct _EXCEPTION_POINTERS *pExceptionInfo)
+{
+ /*
+ * We only write crash dumps if the "crashdumps" directory within the
+ * postgres data directory exists.
+ */
+ DWORD attribs = GetFileAttributesA("crashdumps");
+
+ if (attribs != INVALID_FILE_ATTRIBUTES && (attribs & FILE_ATTRIBUTE_DIRECTORY))
+ {
+ /* 'crashdumps' exists and is a directory. Try to write a dump' */
+ HMODULE hDll = NULL;
+ MINIDUMPWRITEDUMP pDump = NULL;
+ MINIDUMP_TYPE dumpType;
+ char dumpPath[_MAX_PATH];
+ HANDLE selfProcHandle = GetCurrentProcess();
+ DWORD selfPid = GetProcessId(selfProcHandle);
+ HANDLE dumpFile;
+ DWORD systemTicks;
+ struct _MINIDUMP_EXCEPTION_INFORMATION ExInfo;
+
+ ExInfo.ThreadId = GetCurrentThreadId();
+ ExInfo.ExceptionPointers = pExceptionInfo;
+ ExInfo.ClientPointers = FALSE;
+
+ /* Load the dbghelp.dll library and functions */
+ hDll = LoadLibrary("dbghelp.dll");
+ if (hDll == NULL)
+ {
+ write_stderr("could not load dbghelp.dll, cannot write crash dump\n");
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+
+ pDump = (MINIDUMPWRITEDUMP) (pg_funcptr_t) GetProcAddress(hDll, "MiniDumpWriteDump");
+
+ if (pDump == NULL)
+ {
+ write_stderr("could not load required functions in dbghelp.dll, cannot write crash dump\n");
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+
+ /*
+ * Dump as much as we can, except shared memory, code segments, and
+ * memory mapped files. Exactly what we can dump depends on the
+ * version of dbghelp.dll, see:
+ * http://msdn.microsoft.com/en-us/library/ms680519(v=VS.85).aspx
+ */
+ dumpType = MiniDumpNormal | MiniDumpWithHandleData |
+ MiniDumpWithDataSegs;
+
+ if (GetProcAddress(hDll, "EnumDirTree") != NULL)
+ {
+ /* If this function exists, we have version 5.2 or newer */
+ dumpType |= MiniDumpWithIndirectlyReferencedMemory |
+ MiniDumpWithPrivateReadWriteMemory;
+ }
+
+ systemTicks = GetTickCount();
+ snprintf(dumpPath, _MAX_PATH,
+ "crashdumps\\postgres-pid%0i-%0i.mdmp",
+ (int) selfPid, (int) systemTicks);
+ dumpPath[_MAX_PATH - 1] = '\0';
+
+ dumpFile = CreateFile(dumpPath, GENERIC_WRITE, FILE_SHARE_WRITE,
+ NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (dumpFile == INVALID_HANDLE_VALUE)
+ {
+ write_stderr("could not open crash dump file \"%s\" for writing: error code %lu\n",
+ dumpPath, GetLastError());
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+
+ if ((*pDump) (selfProcHandle, selfPid, dumpFile, dumpType, &ExInfo,
+ NULL, NULL))
+ write_stderr("wrote crash dump to file \"%s\"\n", dumpPath);
+ else
+ write_stderr("could not write crash dump to file \"%s\": error code %lu\n",
+ dumpPath, GetLastError());
+
+ CloseHandle(dumpFile);
+ }
+
+ return EXCEPTION_CONTINUE_SEARCH;
+}
+
+
+void
+pgwin32_install_crashdump_handler(void)
+{
+ SetUnhandledExceptionFilter(crashDumpHandler);
+}
diff --git a/contrib/libs/postgresql/src/backend/port/win32/signal.c b/contrib/libs/postgresql/src/backend/port/win32/signal.c
new file mode 100644
index 0000000000..580a517f3f
--- /dev/null
+++ b/contrib/libs/postgresql/src/backend/port/win32/signal.c
@@ -0,0 +1,344 @@
+/*-------------------------------------------------------------------------
+ *
+ * signal.c
+ * Microsoft Windows Win32 Signal Emulation Functions
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/backend/port/win32/signal.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "libpq/pqsignal.h"
+
+/*
+ * These are exported for use by the UNBLOCKED_SIGNAL_QUEUE() macro.
+ * pg_signal_queue must be volatile since it is changed by the signal
+ * handling thread and inspected without any lock by the main thread.
+ * pg_signal_mask is only changed by main thread so shouldn't need it.
+ */
+volatile int pg_signal_queue;
+int pg_signal_mask;
+
+HANDLE pgwin32_signal_event;
+HANDLE pgwin32_initial_signal_pipe = INVALID_HANDLE_VALUE;
+
+/*
+ * pg_signal_crit_sec is used to protect only pg_signal_queue. That is the only
+ * variable that can be accessed from the signal sending threads!
+ */
+static CRITICAL_SECTION pg_signal_crit_sec;
+
+/* Note that array elements 0 are unused since they correspond to signal 0 */
+static pqsigfunc pg_signal_array[PG_SIGNAL_COUNT];
+static pqsigfunc pg_signal_defaults[PG_SIGNAL_COUNT];
+
+
+/* Signal handling thread functions */
+static DWORD WINAPI pg_signal_thread(LPVOID param);
+static BOOL WINAPI pg_console_handler(DWORD dwCtrlType);
+
+
+/*
+ * pg_usleep --- delay the specified number of microseconds, but
+ * stop waiting if a signal arrives.
+ *
+ * This replaces the non-signal-aware version provided by src/port/pgsleep.c.
+ */
+void
+pg_usleep(long microsec)
+{
+ Assert(pgwin32_signal_event != NULL);
+ if (WaitForSingleObject(pgwin32_signal_event,
+ (microsec < 500 ? 1 : (microsec + 500) / 1000))
+ == WAIT_OBJECT_0)
+ {
+ pgwin32_dispatch_queued_signals();
+ errno = EINTR;
+ return;
+ }
+}
+
+
+/* Initialization */
+void
+pgwin32_signal_initialize(void)
+{
+ int i;
+ HANDLE signal_thread_handle;
+
+ InitializeCriticalSection(&pg_signal_crit_sec);
+
+ for (i = 0; i < PG_SIGNAL_COUNT; i++)
+ {
+ pg_signal_array[i] = SIG_DFL;
+ pg_signal_defaults[i] = SIG_IGN;
+ }
+ pg_signal_mask = 0;
+ pg_signal_queue = 0;
+
+ /* Create the global event handle used to flag signals */
+ pgwin32_signal_event = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (pgwin32_signal_event == NULL)
+ ereport(FATAL,
+ (errmsg_internal("could not create signal event: error code %lu", GetLastError())));
+
+ /* Create thread for handling signals */
+ signal_thread_handle = CreateThread(NULL, 0, pg_signal_thread, NULL, 0, NULL);
+ if (signal_thread_handle == NULL)
+ ereport(FATAL,
+ (errmsg_internal("could not create signal handler thread")));
+
+ /* Create console control handle to pick up Ctrl-C etc */
+ if (!SetConsoleCtrlHandler(pg_console_handler, TRUE))
+ ereport(FATAL,
+ (errmsg_internal("could not set console control handler")));
+}
+
+/*
+ * Dispatch all signals currently queued and not blocked
+ * Blocked signals are ignored, and will be fired at the time of
+ * the pqsigsetmask() call.
+ */
+void
+pgwin32_dispatch_queued_signals(void)
+{
+ int exec_mask;
+
+ Assert(pgwin32_signal_event != NULL);
+ EnterCriticalSection(&pg_signal_crit_sec);
+ while ((exec_mask = UNBLOCKED_SIGNAL_QUEUE()) != 0)
+ {
+ /* One or more unblocked signals queued for execution */
+ int i;
+
+ for (i = 1; i < PG_SIGNAL_COUNT; i++)
+ {
+ if (exec_mask & sigmask(i))
+ {
+ /* Execute this signal */
+ pqsigfunc sig = pg_signal_array[i];
+
+ if (sig == SIG_DFL)
+ sig = pg_signal_defaults[i];
+ pg_signal_queue &= ~sigmask(i);
+ if (sig != SIG_ERR && sig != SIG_IGN && sig != SIG_DFL)
+ {
+ LeaveCriticalSection(&pg_signal_crit_sec);
+ sig(i);
+ EnterCriticalSection(&pg_signal_crit_sec);
+ break; /* Restart outer loop, in case signal mask or
+ * queue has been modified inside signal
+ * handler */
+ }
+ }
+ }
+ }
+ ResetEvent(pgwin32_signal_event);
+ LeaveCriticalSection(&pg_signal_crit_sec);
+}
+
+/* signal masking. Only called on main thread, no sync required */
+int
+pqsigsetmask(int mask)
+{
+ int prevmask;
+
+ prevmask = pg_signal_mask;
+ pg_signal_mask = mask;
+
+ /*
+ * Dispatch any signals queued up right away, in case we have unblocked
+ * one or more signals previously queued
+ */
+ pgwin32_dispatch_queued_signals();
+
+ return prevmask;
+}
+
+
+/*
+ * Unix-like signal handler installation
+ *
+ * Only called on main thread, no sync required
+ */
+pqsigfunc
+pqsignal(int signum, pqsigfunc handler)
+{
+ pqsigfunc prevfunc;
+
+ if (signum >= PG_SIGNAL_COUNT || signum < 0)
+ return SIG_ERR;
+ prevfunc = pg_signal_array[signum];
+ pg_signal_array[signum] = handler;
+ return prevfunc;
+}
+
+/* Create the signal listener pipe for specified PID */
+HANDLE
+pgwin32_create_signal_listener(pid_t pid)
+{
+ char pipename[128];
+ HANDLE pipe;
+
+ snprintf(pipename, sizeof(pipename), "\\\\.\\pipe\\pgsignal_%u", (int) pid);
+
+ pipe = CreateNamedPipe(pipename, PIPE_ACCESS_DUPLEX,
+ PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
+ PIPE_UNLIMITED_INSTANCES, 16, 16, 1000, NULL);
+
+ if (pipe == INVALID_HANDLE_VALUE)
+ ereport(ERROR,
+ (errmsg("could not create signal listener pipe for PID %d: error code %lu",
+ (int) pid, GetLastError())));
+
+ return pipe;
+}
+
+
+/*
+ * All functions below execute on the signal handler thread
+ * and must be synchronized as such!
+ * NOTE! The only global variable that can be used is
+ * pg_signal_queue!
+ */
+
+
+/*
+ * Queue a signal for the main thread, by setting the flag bit and event.
+ */
+void
+pg_queue_signal(int signum)
+{
+ Assert(pgwin32_signal_event != NULL);
+ if (signum >= PG_SIGNAL_COUNT || signum <= 0)
+ return; /* ignore any bad signal number */
+
+ EnterCriticalSection(&pg_signal_crit_sec);
+ pg_signal_queue |= sigmask(signum);
+ LeaveCriticalSection(&pg_signal_crit_sec);
+
+ SetEvent(pgwin32_signal_event);
+}
+
+/* Signal handling thread */
+static DWORD WINAPI
+pg_signal_thread(LPVOID param)
+{
+ char pipename[128];
+ HANDLE pipe = pgwin32_initial_signal_pipe;
+
+ /* Set up pipe name, in case we have to re-create the pipe. */
+ snprintf(pipename, sizeof(pipename), "\\\\.\\pipe\\pgsignal_%lu", GetCurrentProcessId());
+
+ for (;;)
+ {
+ BOOL fConnected;
+
+ /* Create a new pipe instance if we don't have one. */
+ if (pipe == INVALID_HANDLE_VALUE)
+ {
+ pipe = CreateNamedPipe(pipename, PIPE_ACCESS_DUPLEX,
+ PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
+ PIPE_UNLIMITED_INSTANCES, 16, 16, 1000, NULL);
+
+ if (pipe == INVALID_HANDLE_VALUE)
+ {
+ write_stderr("could not create signal listener pipe: error code %lu; retrying\n", GetLastError());
+ SleepEx(500, FALSE);
+ continue;
+ }
+ }
+
+ /*
+ * Wait for a client to connect. If something connects before we
+ * reach here, we'll get back a "failure" with ERROR_PIPE_CONNECTED,
+ * which is actually a success (way to go, Microsoft).
+ */
+ fConnected = ConnectNamedPipe(pipe, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
+ if (fConnected)
+ {
+ /*
+ * We have a connection from a would-be signal sender. Process it.
+ */
+ BYTE sigNum;
+ DWORD bytes;
+
+ if (ReadFile(pipe, &sigNum, 1, &bytes, NULL) &&
+ bytes == 1)
+ {
+ /*
+ * Queue the signal before responding to the client. In this
+ * way, it's guaranteed that once kill() has returned in the
+ * signal sender, the next CHECK_FOR_INTERRUPTS() in the
+ * signal recipient will see the signal. (This is a stronger
+ * guarantee than POSIX makes; maybe we don't need it? But
+ * without it, we've seen timing bugs on Windows that do not
+ * manifest on any known Unix.)
+ */
+ pg_queue_signal(sigNum);
+
+ /*
+ * Write something back to the client, allowing its
+ * CallNamedPipe() call to terminate.
+ */
+ WriteFile(pipe, &sigNum, 1, &bytes, NULL); /* Don't care if it
+ * works or not */
+
+ /*
+ * We must wait for the client to read the data before we can
+ * disconnect, else the data will be lost. (If the WriteFile
+ * call failed, there'll be nothing in the buffer, so this
+ * shouldn't block.)
+ */
+ FlushFileBuffers(pipe);
+ }
+ else
+ {
+ /*
+ * If we fail to read a byte from the client, assume it's the
+ * client's problem and do nothing. Perhaps it'd be better to
+ * force a pipe close and reopen?
+ */
+ }
+
+ /* Disconnect from client so that we can re-use the pipe. */
+ DisconnectNamedPipe(pipe);
+ }
+ else
+ {
+ /*
+ * Connection failed. Cleanup and try again.
+ *
+ * This should never happen. If it does, there's a window where
+ * we'll miss signals until we manage to re-create the pipe.
+ * However, just trying to use the same pipe again is probably not
+ * going to work, so we have little choice.
+ */
+ CloseHandle(pipe);
+ pipe = INVALID_HANDLE_VALUE;
+ }
+ }
+ return 0;
+}
+
+
+/* Console control handler will execute on a thread created
+ by the OS at the time of invocation */
+static BOOL WINAPI
+pg_console_handler(DWORD dwCtrlType)
+{
+ if (dwCtrlType == CTRL_C_EVENT ||
+ dwCtrlType == CTRL_BREAK_EVENT ||
+ dwCtrlType == CTRL_CLOSE_EVENT ||
+ dwCtrlType == CTRL_SHUTDOWN_EVENT)
+ {
+ pg_queue_signal(SIGINT);
+ return TRUE;
+ }
+ return FALSE;
+}
diff --git a/contrib/libs/postgresql/src/backend/port/win32/socket.c b/contrib/libs/postgresql/src/backend/port/win32/socket.c
new file mode 100644
index 0000000000..af151e8470
--- /dev/null
+++ b/contrib/libs/postgresql/src/backend/port/win32/socket.c
@@ -0,0 +1,700 @@
+/*-------------------------------------------------------------------------
+ *
+ * socket.c
+ * Microsoft Windows Win32 Socket Functions
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/backend/port/win32/socket.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+/*
+ * Indicate if pgwin32_recv() and pgwin32_send() should operate
+ * in non-blocking mode.
+ *
+ * Since the socket emulation layer always sets the actual socket to
+ * non-blocking mode in order to be able to deliver signals, we must
+ * specify this in a separate flag if we actually need non-blocking
+ * operation.
+ *
+ * This flag changes the behaviour *globally* for all socket operations,
+ * so it should only be set for very short periods of time.
+ */
+int pgwin32_noblock = 0;
+
+/* Undef the macros defined in win32.h, so we can access system functions */
+#undef socket
+#undef bind
+#undef listen
+#undef accept
+#undef connect
+#undef select
+#undef recv
+#undef send
+
+/*
+ * Blocking socket functions implemented so they listen on both
+ * the socket and the signal event, required for signal handling.
+ */
+
+/*
+ * Convert the last socket error code into errno
+ *
+ * Note: where there is a direct correspondence between a WSAxxx error code
+ * and a Berkeley error symbol, this mapping is actually a no-op, because
+ * in win32.h we redefine the network-related Berkeley error symbols to have
+ * the values of their WSAxxx counterparts. The point of the switch is
+ * mostly to translate near-miss error codes into something that's sensible
+ * in the Berkeley universe.
+ */
+static void
+TranslateSocketError(void)
+{
+ switch (WSAGetLastError())
+ {
+ case WSAEINVAL:
+ case WSANOTINITIALISED:
+ case WSAEINVALIDPROVIDER:
+ case WSAEINVALIDPROCTABLE:
+ case WSAEDESTADDRREQ:
+ errno = EINVAL;
+ break;
+ case WSAEINPROGRESS:
+ errno = EINPROGRESS;
+ break;
+ case WSAEFAULT:
+ errno = EFAULT;
+ break;
+ case WSAEISCONN:
+ errno = EISCONN;
+ break;
+ case WSAEMSGSIZE:
+ errno = EMSGSIZE;
+ break;
+ case WSAEAFNOSUPPORT:
+ errno = EAFNOSUPPORT;
+ break;
+ case WSAEMFILE:
+ errno = EMFILE;
+ break;
+ case WSAENOBUFS:
+ errno = ENOBUFS;
+ break;
+ case WSAEPROTONOSUPPORT:
+ case WSAEPROTOTYPE:
+ case WSAESOCKTNOSUPPORT:
+ errno = EPROTONOSUPPORT;
+ break;
+ case WSAECONNABORTED:
+ errno = ECONNABORTED;
+ break;
+ case WSAECONNREFUSED:
+ errno = ECONNREFUSED;
+ break;
+ case WSAECONNRESET:
+ errno = ECONNRESET;
+ break;
+ case WSAEINTR:
+ errno = EINTR;
+ break;
+ case WSAENOTSOCK:
+ errno = ENOTSOCK;
+ break;
+ case WSAEOPNOTSUPP:
+ errno = EOPNOTSUPP;
+ break;
+ case WSAEWOULDBLOCK:
+ errno = EWOULDBLOCK;
+ break;
+ case WSAEACCES:
+ errno = EACCES;
+ break;
+ case WSAEADDRINUSE:
+ errno = EADDRINUSE;
+ break;
+ case WSAEADDRNOTAVAIL:
+ errno = EADDRNOTAVAIL;
+ break;
+ case WSAEHOSTDOWN:
+ errno = EHOSTDOWN;
+ break;
+ case WSAEHOSTUNREACH:
+ case WSAHOST_NOT_FOUND:
+ errno = EHOSTUNREACH;
+ break;
+ case WSAENETDOWN:
+ errno = ENETDOWN;
+ break;
+ case WSAENETUNREACH:
+ errno = ENETUNREACH;
+ break;
+ case WSAENETRESET:
+ errno = ENETRESET;
+ break;
+ case WSAENOTCONN:
+ case WSAESHUTDOWN:
+ case WSAEDISCON:
+ errno = ENOTCONN;
+ break;
+ default:
+ ereport(NOTICE,
+ (errmsg_internal("unrecognized win32 socket error code: %d", WSAGetLastError())));
+ errno = EINVAL;
+ }
+}
+
+static int
+pgwin32_poll_signals(void)
+{
+ if (UNBLOCKED_SIGNAL_QUEUE())
+ {
+ pgwin32_dispatch_queued_signals();
+ errno = EINTR;
+ return 1;
+ }
+ return 0;
+}
+
+static int
+isDataGram(SOCKET s)
+{
+ int type;
+ int typelen = sizeof(type);
+
+ if (getsockopt(s, SOL_SOCKET, SO_TYPE, (char *) &type, &typelen))
+ return 1;
+
+ return (type == SOCK_DGRAM) ? 1 : 0;
+}
+
+int
+pgwin32_waitforsinglesocket(SOCKET s, int what, int timeout)
+{
+ static HANDLE waitevent = INVALID_HANDLE_VALUE;
+ static SOCKET current_socket = INVALID_SOCKET;
+ static int isUDP = 0;
+ HANDLE events[2];
+ int r;
+
+ /* Create an event object just once and use it on all future calls */
+ if (waitevent == INVALID_HANDLE_VALUE)
+ {
+ waitevent = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+ if (waitevent == INVALID_HANDLE_VALUE)
+ ereport(ERROR,
+ (errmsg_internal("could not create socket waiting event: error code %lu", GetLastError())));
+ }
+ else if (!ResetEvent(waitevent))
+ ereport(ERROR,
+ (errmsg_internal("could not reset socket waiting event: error code %lu", GetLastError())));
+
+ /*
+ * Track whether socket is UDP or not. (NB: most likely, this is both
+ * useless and wrong; there is no reason to think that the behavior of
+ * WSAEventSelect is different for TCP and UDP.)
+ */
+ if (current_socket != s)
+ isUDP = isDataGram(s);
+ current_socket = s;
+
+ /*
+ * Attach event to socket. NOTE: we must detach it again before
+ * returning, since other bits of code may try to attach other events to
+ * the socket.
+ */
+ if (WSAEventSelect(s, waitevent, what) != 0)
+ {
+ TranslateSocketError();
+ return 0;
+ }
+
+ events[0] = pgwin32_signal_event;
+ events[1] = waitevent;
+
+ /*
+ * Just a workaround of unknown locking problem with writing in UDP socket
+ * under high load: Client's pgsql backend sleeps infinitely in
+ * WaitForMultipleObjectsEx, pgstat process sleeps in pgwin32_select().
+ * So, we will wait with small timeout(0.1 sec) and if socket is still
+ * blocked, try WSASend (see comments in pgwin32_select) and wait again.
+ */
+ if ((what & FD_WRITE) && isUDP)
+ {
+ for (;;)
+ {
+ r = WaitForMultipleObjectsEx(2, events, FALSE, 100, TRUE);
+
+ if (r == WAIT_TIMEOUT)
+ {
+ char c;
+ WSABUF buf;
+ DWORD sent;
+
+ buf.buf = &c;
+ buf.len = 0;
+
+ r = WSASend(s, &buf, 1, &sent, 0, NULL, NULL);
+ if (r == 0) /* Completed - means things are fine! */
+ {
+ WSAEventSelect(s, NULL, 0);
+ return 1;
+ }
+ else if (WSAGetLastError() != WSAEWOULDBLOCK)
+ {
+ TranslateSocketError();
+ WSAEventSelect(s, NULL, 0);
+ return 0;
+ }
+ }
+ else
+ break;
+ }
+ }
+ else
+ r = WaitForMultipleObjectsEx(2, events, FALSE, timeout, TRUE);
+
+ WSAEventSelect(s, NULL, 0);
+
+ if (r == WAIT_OBJECT_0 || r == WAIT_IO_COMPLETION)
+ {
+ pgwin32_dispatch_queued_signals();
+ errno = EINTR;
+ return 0;
+ }
+ if (r == WAIT_OBJECT_0 + 1)
+ return 1;
+ if (r == WAIT_TIMEOUT)
+ {
+ errno = EWOULDBLOCK;
+ return 0;
+ }
+ ereport(ERROR,
+ (errmsg_internal("unrecognized return value from WaitForMultipleObjects: %d (error code %lu)", r, GetLastError())));
+ return 0;
+}
+
+/*
+ * Create a socket, setting it to overlapped and non-blocking
+ */
+SOCKET
+pgwin32_socket(int af, int type, int protocol)
+{
+ SOCKET s;
+ unsigned long on = 1;
+
+ s = WSASocket(af, type, protocol, NULL, 0, WSA_FLAG_OVERLAPPED);
+ if (s == INVALID_SOCKET)
+ {
+ TranslateSocketError();
+ return INVALID_SOCKET;
+ }
+
+ if (ioctlsocket(s, FIONBIO, &on))
+ {
+ TranslateSocketError();
+ return INVALID_SOCKET;
+ }
+ errno = 0;
+
+ return s;
+}
+
+int
+pgwin32_bind(SOCKET s, struct sockaddr *addr, int addrlen)
+{
+ int res;
+
+ res = bind(s, addr, addrlen);
+ if (res < 0)
+ TranslateSocketError();
+ return res;
+}
+
+int
+pgwin32_listen(SOCKET s, int backlog)
+{
+ int res;
+
+ res = listen(s, backlog);
+ if (res < 0)
+ TranslateSocketError();
+ return res;
+}
+
+SOCKET
+pgwin32_accept(SOCKET s, struct sockaddr *addr, int *addrlen)
+{
+ SOCKET rs;
+
+ /*
+ * Poll for signals, but don't return with EINTR, since we don't handle
+ * that in pqcomm.c
+ */
+ pgwin32_poll_signals();
+
+ rs = WSAAccept(s, addr, addrlen, NULL, 0);
+ if (rs == INVALID_SOCKET)
+ {
+ TranslateSocketError();
+ return INVALID_SOCKET;
+ }
+ return rs;
+}
+
+
+/* No signal delivery during connect. */
+int
+pgwin32_connect(SOCKET s, const struct sockaddr *addr, int addrlen)
+{
+ int r;
+
+ r = WSAConnect(s, addr, addrlen, NULL, NULL, NULL, NULL);
+ if (r == 0)
+ return 0;
+
+ if (WSAGetLastError() != WSAEWOULDBLOCK)
+ {
+ TranslateSocketError();
+ return -1;
+ }
+
+ while (pgwin32_waitforsinglesocket(s, FD_CONNECT, INFINITE) == 0)
+ {
+ /* Loop endlessly as long as we are just delivering signals */
+ }
+
+ return 0;
+}
+
+int
+pgwin32_recv(SOCKET s, char *buf, int len, int f)
+{
+ WSABUF wbuf;
+ int r;
+ DWORD b;
+ DWORD flags = f;
+ int n;
+
+ if (pgwin32_poll_signals())
+ return -1;
+
+ wbuf.len = len;
+ wbuf.buf = buf;
+
+ r = WSARecv(s, &wbuf, 1, &b, &flags, NULL, NULL);
+ if (r != SOCKET_ERROR)
+ return b; /* success */
+
+ if (WSAGetLastError() != WSAEWOULDBLOCK)
+ {
+ TranslateSocketError();
+ return -1;
+ }
+
+ if (pgwin32_noblock)
+ {
+ /*
+ * No data received, and we are in "emulated non-blocking mode", so
+ * return indicating that we'd block if we were to continue.
+ */
+ errno = EWOULDBLOCK;
+ return -1;
+ }
+
+ /* We're in blocking mode, so wait for data */
+
+ for (n = 0; n < 5; n++)
+ {
+ if (pgwin32_waitforsinglesocket(s, FD_READ | FD_CLOSE | FD_ACCEPT,
+ INFINITE) == 0)
+ return -1; /* errno already set */
+
+ r = WSARecv(s, &wbuf, 1, &b, &flags, NULL, NULL);
+ if (r != SOCKET_ERROR)
+ return b; /* success */
+ if (WSAGetLastError() != WSAEWOULDBLOCK)
+ {
+ TranslateSocketError();
+ return -1;
+ }
+
+ /*
+ * There seem to be cases on win2k (at least) where WSARecv can return
+ * WSAEWOULDBLOCK even when pgwin32_waitforsinglesocket claims the
+ * socket is readable. In this case, just sleep for a moment and try
+ * again. We try up to 5 times - if it fails more than that it's not
+ * likely to ever come back.
+ */
+ pg_usleep(10000);
+ }
+ ereport(NOTICE,
+ (errmsg_internal("could not read from ready socket (after retries)")));
+ errno = EWOULDBLOCK;
+ return -1;
+}
+
+/*
+ * The second argument to send() is defined by SUS to be a "const void *"
+ * and so we use the same signature here to keep compilers happy when
+ * handling callers.
+ *
+ * But the buf member of a WSABUF struct is defined as "char *", so we cast
+ * the second argument to that here when assigning it, also to keep compilers
+ * happy.
+ */
+
+int
+pgwin32_send(SOCKET s, const void *buf, int len, int flags)
+{
+ WSABUF wbuf;
+ int r;
+ DWORD b;
+
+ if (pgwin32_poll_signals())
+ return -1;
+
+ wbuf.len = len;
+ wbuf.buf = (char *) buf;
+
+ /*
+ * Readiness of socket to send data to UDP socket may be not true: socket
+ * can become busy again! So loop until send or error occurs.
+ */
+ for (;;)
+ {
+ r = WSASend(s, &wbuf, 1, &b, flags, NULL, NULL);
+ if (r != SOCKET_ERROR && b > 0)
+ /* Write succeeded right away */
+ return b;
+
+ if (r == SOCKET_ERROR &&
+ WSAGetLastError() != WSAEWOULDBLOCK)
+ {
+ TranslateSocketError();
+ return -1;
+ }
+
+ if (pgwin32_noblock)
+ {
+ /*
+ * No data sent, and we are in "emulated non-blocking mode", so
+ * return indicating that we'd block if we were to continue.
+ */
+ errno = EWOULDBLOCK;
+ return -1;
+ }
+
+ /* No error, zero bytes (win2000+) or error+WSAEWOULDBLOCK (<=nt4) */
+
+ if (pgwin32_waitforsinglesocket(s, FD_WRITE | FD_CLOSE, INFINITE) == 0)
+ return -1;
+ }
+
+ return -1;
+}
+
+
+/*
+ * Wait for activity on one or more sockets.
+ * While waiting, allow signals to run
+ *
+ * NOTE! Currently does not implement exceptfds check,
+ * since it is not used in postgresql!
+ */
+int
+pgwin32_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timeval *timeout)
+{
+ WSAEVENT events[FD_SETSIZE * 2]; /* worst case is readfds totally
+ * different from writefds, so
+ * 2*FD_SETSIZE sockets */
+ SOCKET sockets[FD_SETSIZE * 2];
+ int numevents = 0;
+ int i;
+ int r;
+ DWORD timeoutval = WSA_INFINITE;
+ FD_SET outreadfds;
+ FD_SET outwritefds;
+ int nummatches = 0;
+
+ Assert(exceptfds == NULL);
+
+ if (pgwin32_poll_signals())
+ return -1;
+
+ FD_ZERO(&outreadfds);
+ FD_ZERO(&outwritefds);
+
+ /*
+ * Windows does not guarantee to log an FD_WRITE network event indicating
+ * that more data can be sent unless the previous send() failed with
+ * WSAEWOULDBLOCK. While our caller might well have made such a call, we
+ * cannot assume that here. Therefore, if waiting for write-ready, force
+ * the issue by doing a dummy send(). If the dummy send() succeeds,
+ * assume that the socket is in fact write-ready, and return immediately.
+ * Also, if it fails with something other than WSAEWOULDBLOCK, return a
+ * write-ready indication to let our caller deal with the error condition.
+ */
+ if (writefds != NULL)
+ {
+ for (i = 0; i < writefds->fd_count; i++)
+ {
+ char c;
+ WSABUF buf;
+ DWORD sent;
+
+ buf.buf = &c;
+ buf.len = 0;
+
+ r = WSASend(writefds->fd_array[i], &buf, 1, &sent, 0, NULL, NULL);
+ if (r == 0 || WSAGetLastError() != WSAEWOULDBLOCK)
+ FD_SET(writefds->fd_array[i], &outwritefds);
+ }
+
+ /* If we found any write-ready sockets, just return them immediately */
+ if (outwritefds.fd_count > 0)
+ {
+ memcpy(writefds, &outwritefds, sizeof(fd_set));
+ if (readfds)
+ FD_ZERO(readfds);
+ return outwritefds.fd_count;
+ }
+ }
+
+
+ /* Now set up for an actual select */
+
+ if (timeout != NULL)
+ {
+ /* timeoutval is in milliseconds */
+ timeoutval = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
+ }
+
+ if (readfds != NULL)
+ {
+ for (i = 0; i < readfds->fd_count; i++)
+ {
+ events[numevents] = WSACreateEvent();
+ sockets[numevents] = readfds->fd_array[i];
+ numevents++;
+ }
+ }
+ if (writefds != NULL)
+ {
+ for (i = 0; i < writefds->fd_count; i++)
+ {
+ if (!readfds ||
+ !FD_ISSET(writefds->fd_array[i], readfds))
+ {
+ /* If the socket is not in the read list */
+ events[numevents] = WSACreateEvent();
+ sockets[numevents] = writefds->fd_array[i];
+ numevents++;
+ }
+ }
+ }
+
+ for (i = 0; i < numevents; i++)
+ {
+ int flags = 0;
+
+ if (readfds && FD_ISSET(sockets[i], readfds))
+ flags |= FD_READ | FD_ACCEPT | FD_CLOSE;
+
+ if (writefds && FD_ISSET(sockets[i], writefds))
+ flags |= FD_WRITE | FD_CLOSE;
+
+ if (WSAEventSelect(sockets[i], events[i], flags) != 0)
+ {
+ TranslateSocketError();
+ /* release already-assigned event objects */
+ while (--i >= 0)
+ WSAEventSelect(sockets[i], NULL, 0);
+ for (i = 0; i < numevents; i++)
+ WSACloseEvent(events[i]);
+ return -1;
+ }
+ }
+
+ events[numevents] = pgwin32_signal_event;
+ r = WaitForMultipleObjectsEx(numevents + 1, events, FALSE, timeoutval, TRUE);
+ if (r != WAIT_TIMEOUT && r != WAIT_IO_COMPLETION && r != (WAIT_OBJECT_0 + numevents))
+ {
+ /*
+ * We scan all events, even those not signaled, in case more than one
+ * event has been tagged but Wait.. can only return one.
+ */
+ WSANETWORKEVENTS resEvents;
+
+ for (i = 0; i < numevents; i++)
+ {
+ ZeroMemory(&resEvents, sizeof(resEvents));
+ if (WSAEnumNetworkEvents(sockets[i], events[i], &resEvents) != 0)
+ elog(ERROR, "failed to enumerate network events: error code %d",
+ WSAGetLastError());
+ /* Read activity? */
+ if (readfds && FD_ISSET(sockets[i], readfds))
+ {
+ if ((resEvents.lNetworkEvents & FD_READ) ||
+ (resEvents.lNetworkEvents & FD_ACCEPT) ||
+ (resEvents.lNetworkEvents & FD_CLOSE))
+ {
+ FD_SET(sockets[i], &outreadfds);
+
+ nummatches++;
+ }
+ }
+ /* Write activity? */
+ if (writefds && FD_ISSET(sockets[i], writefds))
+ {
+ if ((resEvents.lNetworkEvents & FD_WRITE) ||
+ (resEvents.lNetworkEvents & FD_CLOSE))
+ {
+ FD_SET(sockets[i], &outwritefds);
+
+ nummatches++;
+ }
+ }
+ }
+ }
+
+ /* Clean up all the event objects */
+ for (i = 0; i < numevents; i++)
+ {
+ WSAEventSelect(sockets[i], NULL, 0);
+ WSACloseEvent(events[i]);
+ }
+
+ if (r == WSA_WAIT_TIMEOUT)
+ {
+ if (readfds)
+ FD_ZERO(readfds);
+ if (writefds)
+ FD_ZERO(writefds);
+ return 0;
+ }
+
+ /* Signal-like events. */
+ if (r == WAIT_OBJECT_0 + numevents || r == WAIT_IO_COMPLETION)
+ {
+ pgwin32_dispatch_queued_signals();
+ errno = EINTR;
+ if (readfds)
+ FD_ZERO(readfds);
+ if (writefds)
+ FD_ZERO(writefds);
+ return -1;
+ }
+
+ /* Overwrite socket sets with our resulting values */
+ if (readfds)
+ memcpy(readfds, &outreadfds, sizeof(fd_set));
+ if (writefds)
+ memcpy(writefds, &outwritefds, sizeof(fd_set));
+ return nummatches;
+}
diff --git a/contrib/libs/postgresql/src/backend/port/win32/timer.c b/contrib/libs/postgresql/src/backend/port/win32/timer.c
new file mode 100644
index 0000000000..53fdae9468
--- /dev/null
+++ b/contrib/libs/postgresql/src/backend/port/win32/timer.c
@@ -0,0 +1,121 @@
+/*-------------------------------------------------------------------------
+ *
+ * timer.c
+ * Microsoft Windows Win32 Timer Implementation
+ *
+ * Limitations of this implementation:
+ *
+ * - Does not support interval timer (value->it_interval)
+ * - Only supports ITIMER_REAL
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/backend/port/win32/timer.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+
+/* Communication area for inter-thread communication */
+typedef struct timerCA
+{
+ struct itimerval value;
+ HANDLE event;
+ CRITICAL_SECTION crit_sec;
+} timerCA;
+
+static timerCA timerCommArea;
+static HANDLE timerThreadHandle = INVALID_HANDLE_VALUE;
+
+
+/* Timer management thread */
+static DWORD WINAPI
+pg_timer_thread(LPVOID param)
+{
+ DWORD waittime;
+
+ Assert(param == NULL);
+
+ waittime = INFINITE;
+
+ for (;;)
+ {
+ int r;
+
+ r = WaitForSingleObjectEx(timerCommArea.event, waittime, FALSE);
+ if (r == WAIT_OBJECT_0)
+ {
+ /* Event signaled from main thread, change the timer */
+ EnterCriticalSection(&timerCommArea.crit_sec);
+ if (timerCommArea.value.it_value.tv_sec == 0 &&
+ timerCommArea.value.it_value.tv_usec == 0)
+ waittime = INFINITE; /* Cancel the interrupt */
+ else
+ {
+ /* WaitForSingleObjectEx() uses milliseconds, round up */
+ waittime = (timerCommArea.value.it_value.tv_usec + 999) / 1000 +
+ timerCommArea.value.it_value.tv_sec * 1000;
+ }
+ ResetEvent(timerCommArea.event);
+ LeaveCriticalSection(&timerCommArea.crit_sec);
+ }
+ else if (r == WAIT_TIMEOUT)
+ {
+ /* Timeout expired, signal SIGALRM and turn it off */
+ pg_queue_signal(SIGALRM);
+ waittime = INFINITE;
+ }
+ else
+ {
+ /* Should never happen */
+ Assert(false);
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Win32 setitimer emulation by creating a persistent thread
+ * to handle the timer setting and notification upon timeout.
+ */
+int
+setitimer(int which, const struct itimerval *value, struct itimerval *ovalue)
+{
+ Assert(value != NULL);
+ Assert(value->it_interval.tv_sec == 0 && value->it_interval.tv_usec == 0);
+ Assert(which == ITIMER_REAL);
+
+ if (timerThreadHandle == INVALID_HANDLE_VALUE)
+ {
+ /* First call in this backend, create event and the timer thread */
+ timerCommArea.event = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (timerCommArea.event == NULL)
+ ereport(FATAL,
+ (errmsg_internal("could not create timer event: error code %lu",
+ GetLastError())));
+
+ MemSet(&timerCommArea.value, 0, sizeof(struct itimerval));
+
+ InitializeCriticalSection(&timerCommArea.crit_sec);
+
+ timerThreadHandle = CreateThread(NULL, 0, pg_timer_thread, NULL, 0, NULL);
+ if (timerThreadHandle == INVALID_HANDLE_VALUE)
+ ereport(FATAL,
+ (errmsg_internal("could not create timer thread: error code %lu",
+ GetLastError())));
+ }
+
+ /* Request the timer thread to change settings */
+ EnterCriticalSection(&timerCommArea.crit_sec);
+ if (ovalue)
+ *ovalue = timerCommArea.value;
+ timerCommArea.value = *value;
+ LeaveCriticalSection(&timerCommArea.crit_sec);
+ SetEvent(timerCommArea.event);
+
+ return 0;
+}
diff --git a/contrib/libs/postgresql/src/backend/port/win32_sema.c b/contrib/libs/postgresql/src/backend/port/win32_sema.c
new file mode 100644
index 0000000000..858b88adae
--- /dev/null
+++ b/contrib/libs/postgresql/src/backend/port/win32_sema.c
@@ -0,0 +1,235 @@
+/*-------------------------------------------------------------------------
+ *
+ * win32_sema.c
+ * Microsoft Windows Win32 Semaphores Emulation
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/backend/port/win32_sema.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "miscadmin.h"
+#include "storage/ipc.h"
+#include "storage/pg_sema.h"
+
+static HANDLE *mySemSet; /* IDs of sema sets acquired so far */
+static int numSems; /* number of sema sets acquired so far */
+static int maxSems; /* allocated size of mySemaSet array */
+
+static void ReleaseSemaphores(int code, Datum arg);
+
+
+/*
+ * Report amount of shared memory needed for semaphores
+ */
+Size
+PGSemaphoreShmemSize(int maxSemas)
+{
+ /* No shared memory needed on Windows */
+ return 0;
+}
+
+/*
+ * PGReserveSemaphores --- initialize semaphore support
+ *
+ * In the Win32 implementation, we acquire semaphores on-demand; the
+ * maxSemas parameter is just used to size the array that keeps track of
+ * acquired semas for subsequent releasing. We use anonymous semaphores
+ * so the semaphores are automatically freed when the last referencing
+ * process exits.
+ */
+void
+PGReserveSemaphores(int maxSemas)
+{
+ mySemSet = (HANDLE *) malloc(maxSemas * sizeof(HANDLE));
+ if (mySemSet == NULL)
+ elog(PANIC, "out of memory");
+ numSems = 0;
+ maxSems = maxSemas;
+
+ on_shmem_exit(ReleaseSemaphores, 0);
+}
+
+/*
+ * Release semaphores at shutdown or shmem reinitialization
+ *
+ * (called as an on_shmem_exit callback, hence funny argument list)
+ */
+static void
+ReleaseSemaphores(int code, Datum arg)
+{
+ int i;
+
+ for (i = 0; i < numSems; i++)
+ CloseHandle(mySemSet[i]);
+ free(mySemSet);
+}
+
+/*
+ * PGSemaphoreCreate
+ *
+ * Allocate a PGSemaphore structure with initial count 1
+ */
+PGSemaphore
+PGSemaphoreCreate(void)
+{
+ HANDLE cur_handle;
+ SECURITY_ATTRIBUTES sec_attrs;
+
+ /* Can't do this in a backend, because static state is postmaster's */
+ Assert(!IsUnderPostmaster);
+
+ if (numSems >= maxSems)
+ elog(PANIC, "too many semaphores created");
+
+ ZeroMemory(&sec_attrs, sizeof(sec_attrs));
+ sec_attrs.nLength = sizeof(sec_attrs);
+ sec_attrs.lpSecurityDescriptor = NULL;
+ sec_attrs.bInheritHandle = TRUE;
+
+ /* We don't need a named semaphore */
+ cur_handle = CreateSemaphore(&sec_attrs, 1, 32767, NULL);
+ if (cur_handle)
+ {
+ /* Successfully done */
+ mySemSet[numSems++] = cur_handle;
+ }
+ else
+ ereport(PANIC,
+ (errmsg("could not create semaphore: error code %lu",
+ GetLastError())));
+
+ return (PGSemaphore) cur_handle;
+}
+
+/*
+ * PGSemaphoreReset
+ *
+ * Reset a previously-initialized PGSemaphore to have count 0
+ */
+void
+PGSemaphoreReset(PGSemaphore sema)
+{
+ /*
+ * There's no direct API for this in Win32, so we have to ratchet the
+ * semaphore down to 0 with repeated trylock's.
+ */
+ while (PGSemaphoreTryLock(sema))
+ /* loop */ ;
+}
+
+/*
+ * PGSemaphoreLock
+ *
+ * Lock a semaphore (decrement count), blocking if count would be < 0.
+ */
+void
+PGSemaphoreLock(PGSemaphore sema)
+{
+ HANDLE wh[2];
+ bool done = false;
+
+ /*
+ * Note: pgwin32_signal_event should be first to ensure that it will be
+ * reported when multiple events are set. We want to guarantee that
+ * pending signals are serviced.
+ */
+ wh[0] = pgwin32_signal_event;
+ wh[1] = sema;
+
+ /*
+ * As in other implementations of PGSemaphoreLock, we need to check for
+ * cancel/die interrupts each time through the loop. But here, there is
+ * no hidden magic about whether the syscall will internally service a
+ * signal --- we do that ourselves.
+ */
+ while (!done)
+ {
+ DWORD rc;
+
+ CHECK_FOR_INTERRUPTS();
+
+ rc = WaitForMultipleObjectsEx(2, wh, FALSE, INFINITE, TRUE);
+ switch (rc)
+ {
+ case WAIT_OBJECT_0:
+ /* Signal event is set - we have a signal to deliver */
+ pgwin32_dispatch_queued_signals();
+ break;
+ case WAIT_OBJECT_0 + 1:
+ /* We got it! */
+ done = true;
+ break;
+ case WAIT_IO_COMPLETION:
+
+ /*
+ * The system interrupted the wait to execute an I/O
+ * completion routine or asynchronous procedure call in this
+ * thread. PostgreSQL does not provoke either of these, but
+ * atypical loaded DLLs or even other processes might do so.
+ * Now, resume waiting.
+ */
+ break;
+ case WAIT_FAILED:
+ ereport(FATAL,
+ (errmsg("could not lock semaphore: error code %lu",
+ GetLastError())));
+ break;
+ default:
+ elog(FATAL, "unexpected return code from WaitForMultipleObjectsEx(): %lu", rc);
+ break;
+ }
+ }
+}
+
+/*
+ * PGSemaphoreUnlock
+ *
+ * Unlock a semaphore (increment count)
+ */
+void
+PGSemaphoreUnlock(PGSemaphore sema)
+{
+ if (!ReleaseSemaphore(sema, 1, NULL))
+ ereport(FATAL,
+ (errmsg("could not unlock semaphore: error code %lu",
+ GetLastError())));
+}
+
+/*
+ * PGSemaphoreTryLock
+ *
+ * Lock a semaphore only if able to do so without blocking
+ */
+bool
+PGSemaphoreTryLock(PGSemaphore sema)
+{
+ DWORD ret;
+
+ ret = WaitForSingleObject(sema, 0);
+
+ if (ret == WAIT_OBJECT_0)
+ {
+ /* We got it! */
+ return true;
+ }
+ else if (ret == WAIT_TIMEOUT)
+ {
+ /* Can't get it */
+ errno = EAGAIN;
+ return false;
+ }
+
+ /* Otherwise we are in trouble */
+ ereport(FATAL,
+ (errmsg("could not try-lock semaphore: error code %lu",
+ GetLastError())));
+
+ /* keep compiler quiet */
+ return false;
+}
diff --git a/contrib/libs/postgresql/src/backend/port/win32_shmem.c b/contrib/libs/postgresql/src/backend/port/win32_shmem.c
new file mode 100644
index 0000000000..d7a71992d8
--- /dev/null
+++ b/contrib/libs/postgresql/src/backend/port/win32_shmem.c
@@ -0,0 +1,607 @@
+/*-------------------------------------------------------------------------
+ *
+ * win32_shmem.c
+ * Implement shared memory using win32 facilities
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/backend/port/win32_shmem.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "miscadmin.h"
+#include "storage/dsm.h"
+#include "storage/ipc.h"
+#include "storage/pg_shmem.h"
+
+/*
+ * Early in a process's life, Windows asynchronously creates threads for the
+ * process's "default thread pool"
+ * (https://docs.microsoft.com/en-us/windows/desktop/ProcThread/thread-pools).
+ * Occasionally, thread creation allocates a stack after
+ * PGSharedMemoryReAttach() has released UsedShmemSegAddr and before it has
+ * mapped shared memory at UsedShmemSegAddr. This would cause mapping to fail
+ * if the allocator preferred the just-released region for allocating the new
+ * thread stack. We observed such failures in some Windows Server 2016
+ * configurations. To give the system another region to prefer, reserve and
+ * release an additional, protective region immediately before reserving or
+ * releasing shared memory. The idea is that, if the allocator handed out
+ * REGION1 pages before REGION2 pages at one occasion, it will do so whenever
+ * both regions are free. Windows Server 2016 exhibits that behavior, and a
+ * system behaving differently would have less need to protect
+ * UsedShmemSegAddr. The protective region must be at least large enough for
+ * one thread stack. However, ten times as much is less than 2% of the 32-bit
+ * address space and is negligible relative to the 64-bit address space.
+ */
+#define PROTECTIVE_REGION_SIZE (10 * WIN32_STACK_RLIMIT)
+void *ShmemProtectiveRegion = NULL;
+
+HANDLE UsedShmemSegID = INVALID_HANDLE_VALUE;
+void *UsedShmemSegAddr = NULL;
+static Size UsedShmemSegSize = 0;
+
+static bool EnableLockPagesPrivilege(int elevel);
+static void pgwin32_SharedMemoryDelete(int status, Datum shmId);
+
+/*
+ * Generate shared memory segment name. Expand the data directory, to generate
+ * an identifier unique for this data directory. Then replace all backslashes
+ * with forward slashes, since backslashes aren't permitted in global object names.
+ *
+ * Store the shared memory segment in the Global\ namespace (requires NT2 TSE or
+ * 2000, but that's all we support for other reasons as well), to make sure you can't
+ * open two postmasters in different sessions against the same data directory.
+ *
+ * XXX: What happens with junctions? It's only someone breaking things on purpose,
+ * and this is still better than before, but we might want to do something about
+ * that sometime in the future.
+ */
+static char *
+GetSharedMemName(void)
+{
+ char *retptr;
+ DWORD bufsize;
+ DWORD r;
+ char *cp;
+
+ bufsize = GetFullPathName(DataDir, 0, NULL, NULL);
+ if (bufsize == 0)
+ elog(FATAL, "could not get size for full pathname of datadir %s: error code %lu",
+ DataDir, GetLastError());
+
+ retptr = malloc(bufsize + 18); /* 18 for Global\PostgreSQL: */
+ if (retptr == NULL)
+ elog(FATAL, "could not allocate memory for shared memory name");
+
+ strcpy(retptr, "Global\\PostgreSQL:");
+ r = GetFullPathName(DataDir, bufsize, retptr + 18, NULL);
+ if (r == 0 || r > bufsize)
+ elog(FATAL, "could not generate full pathname for datadir %s: error code %lu",
+ DataDir, GetLastError());
+
+ /*
+ * XXX: Intentionally overwriting the Global\ part here. This was not the
+ * original approach, but putting it in the actual Global\ namespace
+ * causes permission errors in a lot of cases, so we leave it in the
+ * default namespace for now.
+ */
+ for (cp = retptr; *cp; cp++)
+ if (*cp == '\\')
+ *cp = '/';
+
+ return retptr;
+}
+
+
+/*
+ * PGSharedMemoryIsInUse
+ *
+ * Is a previously-existing shmem segment still existing and in use?
+ *
+ * The point of this exercise is to detect the case where a prior postmaster
+ * crashed, but it left child backends that are still running. Therefore
+ * we only care about shmem segments that are associated with the intended
+ * DataDir. This is an important consideration since accidental matches of
+ * shmem segment IDs are reasonably common.
+ */
+bool
+PGSharedMemoryIsInUse(unsigned long id1, unsigned long id2)
+{
+ char *szShareMem;
+ HANDLE hmap;
+
+ szShareMem = GetSharedMemName();
+
+ hmap = OpenFileMapping(FILE_MAP_READ, FALSE, szShareMem);
+
+ free(szShareMem);
+
+ if (hmap == NULL)
+ return false;
+
+ CloseHandle(hmap);
+ return true;
+}
+
+/*
+ * EnableLockPagesPrivilege
+ *
+ * Try to acquire SeLockMemoryPrivilege so we can use large pages.
+ */
+static bool
+EnableLockPagesPrivilege(int elevel)
+{
+ HANDLE hToken;
+ TOKEN_PRIVILEGES tp;
+ LUID luid;
+
+ if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
+ {
+ ereport(elevel,
+ (errmsg("could not enable user right \"%s\": error code %lu",
+
+ /*
+ * translator: This is a term from Windows and should be translated to
+ * match the Windows localization.
+ */
+ _("Lock pages in memory"),
+ GetLastError()),
+ errdetail("Failed system call was %s.", "OpenProcessToken")));
+ return FALSE;
+ }
+
+ if (!LookupPrivilegeValue(NULL, SE_LOCK_MEMORY_NAME, &luid))
+ {
+ ereport(elevel,
+ (errmsg("could not enable user right \"%s\": error code %lu", _("Lock pages in memory"), GetLastError()),
+ errdetail("Failed system call was %s.", "LookupPrivilegeValue")));
+ CloseHandle(hToken);
+ return FALSE;
+ }
+ tp.PrivilegeCount = 1;
+ tp.Privileges[0].Luid = luid;
+ tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+ if (!AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL))
+ {
+ ereport(elevel,
+ (errmsg("could not enable user right \"%s\": error code %lu", _("Lock pages in memory"), GetLastError()),
+ errdetail("Failed system call was %s.", "AdjustTokenPrivileges")));
+ CloseHandle(hToken);
+ return FALSE;
+ }
+
+ if (GetLastError() != ERROR_SUCCESS)
+ {
+ if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
+ ereport(elevel,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("could not enable user right \"%s\"", _("Lock pages in memory")),
+ errhint("Assign user right \"%s\" to the Windows user account which runs PostgreSQL.",
+ _("Lock pages in memory"))));
+ else
+ ereport(elevel,
+ (errmsg("could not enable user right \"%s\": error code %lu", _("Lock pages in memory"), GetLastError()),
+ errdetail("Failed system call was %s.", "AdjustTokenPrivileges")));
+ CloseHandle(hToken);
+ return FALSE;
+ }
+
+ CloseHandle(hToken);
+
+ return TRUE;
+}
+
+/*
+ * PGSharedMemoryCreate
+ *
+ * Create a shared memory segment of the given size and initialize its
+ * standard header.
+ */
+PGShmemHeader *
+PGSharedMemoryCreate(Size size,
+ PGShmemHeader **shim)
+{
+ void *memAddress;
+ PGShmemHeader *hdr;
+ HANDLE hmap,
+ hmap2;
+ char *szShareMem;
+ int i;
+ DWORD size_high;
+ DWORD size_low;
+ SIZE_T largePageSize = 0;
+ Size orig_size = size;
+ DWORD flProtect = PAGE_READWRITE;
+
+ ShmemProtectiveRegion = VirtualAlloc(NULL, PROTECTIVE_REGION_SIZE,
+ MEM_RESERVE, PAGE_NOACCESS);
+ if (ShmemProtectiveRegion == NULL)
+ elog(FATAL, "could not reserve memory region: error code %lu",
+ GetLastError());
+
+ /* Room for a header? */
+ Assert(size > MAXALIGN(sizeof(PGShmemHeader)));
+
+ szShareMem = GetSharedMemName();
+
+ UsedShmemSegAddr = NULL;
+
+ if (huge_pages == HUGE_PAGES_ON || huge_pages == HUGE_PAGES_TRY)
+ {
+ /* Does the processor support large pages? */
+ largePageSize = GetLargePageMinimum();
+ if (largePageSize == 0)
+ {
+ ereport(huge_pages == HUGE_PAGES_ON ? FATAL : DEBUG1,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("the processor does not support large pages")));
+ ereport(DEBUG1,
+ (errmsg_internal("disabling huge pages")));
+ }
+ else if (!EnableLockPagesPrivilege(huge_pages == HUGE_PAGES_ON ? FATAL : DEBUG1))
+ {
+ ereport(DEBUG1,
+ (errmsg_internal("disabling huge pages")));
+ }
+ else
+ {
+ /* Huge pages available and privilege enabled, so turn on */
+ flProtect = PAGE_READWRITE | SEC_COMMIT | SEC_LARGE_PAGES;
+
+ /* Round size up as appropriate. */
+ if (size % largePageSize != 0)
+ size += largePageSize - (size % largePageSize);
+ }
+ }
+
+retry:
+#ifdef _WIN64
+ size_high = size >> 32;
+#else
+ size_high = 0;
+#endif
+ size_low = (DWORD) size;
+
+ /*
+ * When recycling a shared memory segment, it may take a short while
+ * before it gets dropped from the global namespace. So re-try after
+ * sleeping for a second, and continue retrying 10 times. (both the 1
+ * second time and the 10 retries are completely arbitrary)
+ */
+ for (i = 0; i < 10; i++)
+ {
+ /*
+ * In case CreateFileMapping() doesn't set the error code to 0 on
+ * success
+ */
+ SetLastError(0);
+
+ hmap = CreateFileMapping(INVALID_HANDLE_VALUE, /* Use the pagefile */
+ NULL, /* Default security attrs */
+ flProtect,
+ size_high, /* Size Upper 32 Bits */
+ size_low, /* Size Lower 32 bits */
+ szShareMem);
+
+ if (!hmap)
+ {
+ if (GetLastError() == ERROR_NO_SYSTEM_RESOURCES &&
+ huge_pages == HUGE_PAGES_TRY &&
+ (flProtect & SEC_LARGE_PAGES) != 0)
+ {
+ elog(DEBUG1, "CreateFileMapping(%zu) with SEC_LARGE_PAGES failed, "
+ "huge pages disabled",
+ size);
+
+ /*
+ * Use the original size, not the rounded-up value, when
+ * falling back to non-huge pages.
+ */
+ size = orig_size;
+ flProtect = PAGE_READWRITE;
+ goto retry;
+ }
+ else
+ ereport(FATAL,
+ (errmsg("could not create shared memory segment: error code %lu", GetLastError()),
+ errdetail("Failed system call was CreateFileMapping(size=%zu, name=%s).",
+ size, szShareMem)));
+ }
+
+ /*
+ * If the segment already existed, CreateFileMapping() will return a
+ * handle to the existing one and set ERROR_ALREADY_EXISTS.
+ */
+ if (GetLastError() == ERROR_ALREADY_EXISTS)
+ {
+ CloseHandle(hmap); /* Close the handle, since we got a valid one
+ * to the previous segment. */
+ hmap = NULL;
+ Sleep(1000);
+ continue;
+ }
+ break;
+ }
+
+ /*
+ * If the last call in the loop still returned ERROR_ALREADY_EXISTS, this
+ * shared memory segment exists and we assume it belongs to somebody else.
+ */
+ if (!hmap)
+ ereport(FATAL,
+ (errmsg("pre-existing shared memory block is still in use"),
+ errhint("Check if there are any old server processes still running, and terminate them.")));
+
+ free(szShareMem);
+
+ /*
+ * Make the handle inheritable
+ */
+ if (!DuplicateHandle(GetCurrentProcess(), hmap, GetCurrentProcess(), &hmap2, 0, TRUE, DUPLICATE_SAME_ACCESS))
+ ereport(FATAL,
+ (errmsg("could not create shared memory segment: error code %lu", GetLastError()),
+ errdetail("Failed system call was DuplicateHandle.")));
+
+ /*
+ * Close the old, non-inheritable handle. If this fails we don't really
+ * care.
+ */
+ if (!CloseHandle(hmap))
+ elog(LOG, "could not close handle to shared memory: error code %lu", GetLastError());
+
+
+ /*
+ * Get a pointer to the new shared memory segment. Map the whole segment
+ * at once, and let the system decide on the initial address.
+ */
+ memAddress = MapViewOfFileEx(hmap2, FILE_MAP_WRITE | FILE_MAP_READ, 0, 0, 0, NULL);
+ if (!memAddress)
+ ereport(FATAL,
+ (errmsg("could not create shared memory segment: error code %lu", GetLastError()),
+ errdetail("Failed system call was MapViewOfFileEx.")));
+
+
+
+ /*
+ * OK, we created a new segment. Mark it as created by this process. The
+ * order of assignments here is critical so that another Postgres process
+ * can't see the header as valid but belonging to an invalid PID!
+ */
+ hdr = (PGShmemHeader *) memAddress;
+ hdr->creatorPID = getpid();
+ hdr->magic = PGShmemMagic;
+
+ /*
+ * Initialize space allocation status for segment.
+ */
+ hdr->totalsize = size;
+ hdr->freeoffset = MAXALIGN(sizeof(PGShmemHeader));
+ hdr->dsm_control = 0;
+
+ /* Save info for possible future use */
+ UsedShmemSegAddr = memAddress;
+ UsedShmemSegSize = size;
+ UsedShmemSegID = hmap2;
+
+ /* Register on-exit routine to delete the new segment */
+ on_shmem_exit(pgwin32_SharedMemoryDelete, PointerGetDatum(hmap2));
+
+ *shim = hdr;
+ return hdr;
+}
+
+/*
+ * PGSharedMemoryReAttach
+ *
+ * This is called during startup of a postmaster child process to re-attach to
+ * an already existing shared memory segment, using the handle inherited from
+ * the postmaster.
+ *
+ * ShmemProtectiveRegion, UsedShmemSegID and UsedShmemSegAddr are implicit
+ * parameters to this routine. The caller must have already restored them to
+ * the postmaster's values.
+ */
+void
+PGSharedMemoryReAttach(void)
+{
+ PGShmemHeader *hdr;
+ void *origUsedShmemSegAddr = UsedShmemSegAddr;
+
+ Assert(ShmemProtectiveRegion != NULL);
+ Assert(UsedShmemSegAddr != NULL);
+ Assert(IsUnderPostmaster);
+
+ /*
+ * Release memory region reservations made by the postmaster
+ */
+ if (VirtualFree(ShmemProtectiveRegion, 0, MEM_RELEASE) == 0)
+ elog(FATAL, "failed to release reserved memory region (addr=%p): error code %lu",
+ ShmemProtectiveRegion, GetLastError());
+ if (VirtualFree(UsedShmemSegAddr, 0, MEM_RELEASE) == 0)
+ elog(FATAL, "failed to release reserved memory region (addr=%p): error code %lu",
+ UsedShmemSegAddr, GetLastError());
+
+ hdr = (PGShmemHeader *) MapViewOfFileEx(UsedShmemSegID, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0, UsedShmemSegAddr);
+ if (!hdr)
+ elog(FATAL, "could not reattach to shared memory (key=%p, addr=%p): error code %lu",
+ UsedShmemSegID, UsedShmemSegAddr, GetLastError());
+ if (hdr != origUsedShmemSegAddr)
+ elog(FATAL, "reattaching to shared memory returned unexpected address (got %p, expected %p)",
+ hdr, origUsedShmemSegAddr);
+ if (hdr->magic != PGShmemMagic)
+ elog(FATAL, "reattaching to shared memory returned non-PostgreSQL memory");
+ dsm_set_control_handle(hdr->dsm_control);
+
+ UsedShmemSegAddr = hdr; /* probably redundant */
+}
+
+/*
+ * PGSharedMemoryNoReAttach
+ *
+ * This is called during startup of a postmaster child process when we choose
+ * *not* to re-attach to the existing shared memory segment. We must clean up
+ * to leave things in the appropriate state.
+ *
+ * The child process startup logic might or might not call PGSharedMemoryDetach
+ * after this; make sure that it will be a no-op if called.
+ *
+ * ShmemProtectiveRegion, UsedShmemSegID and UsedShmemSegAddr are implicit
+ * parameters to this routine. The caller must have already restored them to
+ * the postmaster's values.
+ */
+void
+PGSharedMemoryNoReAttach(void)
+{
+ Assert(ShmemProtectiveRegion != NULL);
+ Assert(UsedShmemSegAddr != NULL);
+ Assert(IsUnderPostmaster);
+
+ /*
+ * Under Windows we will not have mapped the segment, so we don't need to
+ * un-map it. Just reset UsedShmemSegAddr to show we're not attached.
+ */
+ UsedShmemSegAddr = NULL;
+
+ /*
+ * We *must* close the inherited shmem segment handle, else Windows will
+ * consider the existence of this process to mean it can't release the
+ * shmem segment yet. We can now use PGSharedMemoryDetach to do that.
+ */
+ PGSharedMemoryDetach();
+}
+
+/*
+ * PGSharedMemoryDetach
+ *
+ * Detach from the shared memory segment, if still attached. This is not
+ * intended to be called explicitly by the process that originally created the
+ * segment (it will have an on_shmem_exit callback registered to do that).
+ * Rather, this is for subprocesses that have inherited an attachment and want
+ * to get rid of it.
+ *
+ * ShmemProtectiveRegion, UsedShmemSegID and UsedShmemSegAddr are implicit
+ * parameters to this routine.
+ */
+void
+PGSharedMemoryDetach(void)
+{
+ /*
+ * Releasing the protective region liberates an unimportant quantity of
+ * address space, but be tidy.
+ */
+ if (ShmemProtectiveRegion != NULL)
+ {
+ if (VirtualFree(ShmemProtectiveRegion, 0, MEM_RELEASE) == 0)
+ elog(LOG, "failed to release reserved memory region (addr=%p): error code %lu",
+ ShmemProtectiveRegion, GetLastError());
+
+ ShmemProtectiveRegion = NULL;
+ }
+
+ /* Unmap the view, if it's mapped */
+ if (UsedShmemSegAddr != NULL)
+ {
+ if (!UnmapViewOfFile(UsedShmemSegAddr))
+ elog(LOG, "could not unmap view of shared memory: error code %lu",
+ GetLastError());
+
+ UsedShmemSegAddr = NULL;
+ }
+
+ /* And close the shmem handle, if we have one */
+ if (UsedShmemSegID != INVALID_HANDLE_VALUE)
+ {
+ if (!CloseHandle(UsedShmemSegID))
+ elog(LOG, "could not close handle to shared memory: error code %lu",
+ GetLastError());
+
+ UsedShmemSegID = INVALID_HANDLE_VALUE;
+ }
+}
+
+
+/*
+ * pgwin32_SharedMemoryDelete
+ *
+ * Detach from and delete the shared memory segment
+ * (called as an on_shmem_exit callback, hence funny argument list)
+ */
+static void
+pgwin32_SharedMemoryDelete(int status, Datum shmId)
+{
+ Assert(DatumGetPointer(shmId) == UsedShmemSegID);
+ PGSharedMemoryDetach();
+}
+
+/*
+ * pgwin32_ReserveSharedMemoryRegion(hChild)
+ *
+ * Reserve the memory region that will be used for shared memory in a child
+ * process. It is called before the child process starts, to make sure the
+ * memory is available.
+ *
+ * Once the child starts, DLLs loading in different order or threads getting
+ * scheduled differently may allocate memory which can conflict with the
+ * address space we need for our shared memory. By reserving the shared
+ * memory region before the child starts, and freeing it only just before we
+ * attempt to get access to the shared memory forces these allocations to
+ * be given different address ranges that don't conflict.
+ *
+ * NOTE! This function executes in the postmaster, and should for this
+ * reason not use elog(FATAL) since that would take down the postmaster.
+ */
+int
+pgwin32_ReserveSharedMemoryRegion(HANDLE hChild)
+{
+ void *address;
+
+ Assert(ShmemProtectiveRegion != NULL);
+ Assert(UsedShmemSegAddr != NULL);
+ Assert(UsedShmemSegSize != 0);
+
+ /* ShmemProtectiveRegion */
+ address = VirtualAllocEx(hChild, ShmemProtectiveRegion,
+ PROTECTIVE_REGION_SIZE,
+ MEM_RESERVE, PAGE_NOACCESS);
+ if (address == NULL)
+ {
+ /* Don't use FATAL since we're running in the postmaster */
+ elog(LOG, "could not reserve shared memory region (addr=%p) for child %p: error code %lu",
+ ShmemProtectiveRegion, hChild, GetLastError());
+ return false;
+ }
+ if (address != ShmemProtectiveRegion)
+ {
+ /*
+ * Should never happen - in theory if allocation granularity causes
+ * strange effects it could, so check just in case.
+ *
+ * Don't use FATAL since we're running in the postmaster.
+ */
+ elog(LOG, "reserved shared memory region got incorrect address %p, expected %p",
+ address, ShmemProtectiveRegion);
+ return false;
+ }
+
+ /* UsedShmemSegAddr */
+ address = VirtualAllocEx(hChild, UsedShmemSegAddr, UsedShmemSegSize,
+ MEM_RESERVE, PAGE_READWRITE);
+ if (address == NULL)
+ {
+ elog(LOG, "could not reserve shared memory region (addr=%p) for child %p: error code %lu",
+ UsedShmemSegAddr, hChild, GetLastError());
+ return false;
+ }
+ if (address != UsedShmemSegAddr)
+ {
+ elog(LOG, "reserved shared memory region got incorrect address %p, expected %p",
+ address, UsedShmemSegAddr);
+ return false;
+ }
+
+ return true;
+}
diff --git a/contrib/libs/postgresql/src/port/README b/contrib/libs/postgresql/src/port/README
new file mode 100644
index 0000000000..97f18a6233
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/README
@@ -0,0 +1,32 @@
+src/port/README
+
+libpgport
+=========
+
+libpgport must have special behavior. It supplies functions to both
+libraries and applications. However, there are two complexities:
+
+1) Libraries need to use object files that are compiled with exactly
+the same flags as the library. libpgport might not use the same flags,
+so it is necessary to recompile the object files for individual
+libraries. This is done by removing -lpgport from the link line:
+
+ # Need to recompile any libpgport object files
+ LIBS := $(filter-out -lpgport, $(LIBS))
+
+and adding infrastructure to recompile the object files:
+
+ OBJS= execute.o typename.o descriptor.o data.o error.o prepare.o memory.o \
+ connect.o misc.o path.o exec.o \
+ $(filter strlcat.o, $(LIBOBJS))
+
+The problem is that there is no testing of which object files need to be
+added, but missing functions usually show up when linking user
+applications.
+
+2) For applications, we use -lpgport before -lpq, so the static files
+from libpgport are linked first. This avoids having applications
+dependent on symbols that are _used_ by libpq, but not intended to be
+exported by libpq. libpq's libpgport usage changes over time, so such a
+dependency is a problem. Windows, Linux, AIX, and macOS use an export
+list to control the symbols exported by libpq.
diff --git a/contrib/libs/postgresql/src/port/bsearch_arg.c b/contrib/libs/postgresql/src/port/bsearch_arg.c
new file mode 100644
index 0000000000..8849bdffd2
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/bsearch_arg.c
@@ -0,0 +1,78 @@
+/*
+ * bsearch_arg.c: bsearch variant with a user-supplied pointer
+ *
+ * Copyright (c) 2021, PostgreSQL Global Development Group
+ * Copyright (c) 1990 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. [rescinded 22 July 1999]
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * src/port/bsearch_arg.c
+ */
+
+#include "c.h"
+
+/*
+ * Perform a binary search.
+ *
+ * The code below is a bit sneaky. After a comparison fails, we
+ * divide the work in half by moving either left or right. If lim
+ * is odd, moving left simply involves halving lim: e.g., when lim
+ * is 5 we look at item 2, so we change lim to 2 so that we will
+ * look at items 0 & 1. If lim is even, the same applies. If lim
+ * is odd, moving right again involves halving lim, this time moving
+ * the base up one item past p: e.g., when lim is 5 we change base
+ * to item 3 and make lim 2 so that we will look at items 3 and 4.
+ * If lim is even, however, we have to shrink it by one before
+ * halving: e.g., when lim is 4, we still looked at item 2, so we
+ * have to make lim 3, then halve, obtaining 1, so that we will only
+ * look at item 3.
+ */
+void *
+bsearch_arg(const void *key, const void *base0,
+ size_t nmemb, size_t size,
+ int (*compar) (const void *, const void *, void *),
+ void *arg)
+{
+ const char *base = (const char *) base0;
+ int lim,
+ cmp;
+ const void *p;
+
+ for (lim = nmemb; lim != 0; lim >>= 1)
+ {
+ p = base + (lim >> 1) * size;
+ cmp = (*compar) (key, p, arg);
+ if (cmp == 0)
+ return (void *) p;
+ if (cmp > 0)
+ { /* key > p: move right */
+ base = (const char *) p + size;
+ lim--;
+ } /* else move left */
+ }
+ return (NULL);
+}
diff --git a/contrib/libs/postgresql/src/port/chklocale.c b/contrib/libs/postgresql/src/port/chklocale.c
new file mode 100644
index 0000000000..3d47d37eae
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/chklocale.c
@@ -0,0 +1,457 @@
+/*-------------------------------------------------------------------------
+ *
+ * chklocale.c
+ * Functions for handling locale-related info
+ *
+ *
+ * Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ *
+ *
+ * IDENTIFICATION
+ * src/port/chklocale.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#ifdef HAVE_LANGINFO_H
+#include <langinfo.h>
+#endif
+
+#include "mb/pg_wchar.h"
+
+
+/*
+ * This table needs to recognize all the CODESET spellings for supported
+ * backend encodings, as well as frontend-only encodings where possible
+ * (the latter case is currently only needed for initdb to recognize
+ * error situations). On Windows, we rely on entries for codepage
+ * numbers (CPnnn).
+ *
+ * Note that we search the table with pg_strcasecmp(), so variant
+ * capitalizations don't need their own entries.
+ */
+struct encoding_match
+{
+ enum pg_enc pg_enc_code;
+ const char *system_enc_name;
+};
+
+static const struct encoding_match encoding_match_list[] = {
+ {PG_EUC_JP, "EUC-JP"},
+ {PG_EUC_JP, "eucJP"},
+ {PG_EUC_JP, "IBM-eucJP"},
+ {PG_EUC_JP, "sdeckanji"},
+ {PG_EUC_JP, "CP20932"},
+
+ {PG_EUC_CN, "EUC-CN"},
+ {PG_EUC_CN, "eucCN"},
+ {PG_EUC_CN, "IBM-eucCN"},
+ {PG_EUC_CN, "GB2312"},
+ {PG_EUC_CN, "dechanzi"},
+ {PG_EUC_CN, "CP20936"},
+
+ {PG_EUC_KR, "EUC-KR"},
+ {PG_EUC_KR, "eucKR"},
+ {PG_EUC_KR, "IBM-eucKR"},
+ {PG_EUC_KR, "deckorean"},
+ {PG_EUC_KR, "5601"},
+ {PG_EUC_KR, "CP51949"},
+
+ {PG_EUC_TW, "EUC-TW"},
+ {PG_EUC_TW, "eucTW"},
+ {PG_EUC_TW, "IBM-eucTW"},
+ {PG_EUC_TW, "cns11643"},
+ /* No codepage for EUC-TW ? */
+
+ {PG_UTF8, "UTF-8"},
+ {PG_UTF8, "utf8"},
+ {PG_UTF8, "CP65001"},
+
+ {PG_LATIN1, "ISO-8859-1"},
+ {PG_LATIN1, "ISO8859-1"},
+ {PG_LATIN1, "iso88591"},
+ {PG_LATIN1, "CP28591"},
+
+ {PG_LATIN2, "ISO-8859-2"},
+ {PG_LATIN2, "ISO8859-2"},
+ {PG_LATIN2, "iso88592"},
+ {PG_LATIN2, "CP28592"},
+
+ {PG_LATIN3, "ISO-8859-3"},
+ {PG_LATIN3, "ISO8859-3"},
+ {PG_LATIN3, "iso88593"},
+ {PG_LATIN3, "CP28593"},
+
+ {PG_LATIN4, "ISO-8859-4"},
+ {PG_LATIN4, "ISO8859-4"},
+ {PG_LATIN4, "iso88594"},
+ {PG_LATIN4, "CP28594"},
+
+ {PG_LATIN5, "ISO-8859-9"},
+ {PG_LATIN5, "ISO8859-9"},
+ {PG_LATIN5, "iso88599"},
+ {PG_LATIN5, "CP28599"},
+
+ {PG_LATIN6, "ISO-8859-10"},
+ {PG_LATIN6, "ISO8859-10"},
+ {PG_LATIN6, "iso885910"},
+
+ {PG_LATIN7, "ISO-8859-13"},
+ {PG_LATIN7, "ISO8859-13"},
+ {PG_LATIN7, "iso885913"},
+
+ {PG_LATIN8, "ISO-8859-14"},
+ {PG_LATIN8, "ISO8859-14"},
+ {PG_LATIN8, "iso885914"},
+
+ {PG_LATIN9, "ISO-8859-15"},
+ {PG_LATIN9, "ISO8859-15"},
+ {PG_LATIN9, "iso885915"},
+ {PG_LATIN9, "CP28605"},
+
+ {PG_LATIN10, "ISO-8859-16"},
+ {PG_LATIN10, "ISO8859-16"},
+ {PG_LATIN10, "iso885916"},
+
+ {PG_KOI8R, "KOI8-R"},
+ {PG_KOI8R, "CP20866"},
+
+ {PG_KOI8U, "KOI8-U"},
+ {PG_KOI8U, "CP21866"},
+
+ {PG_WIN866, "CP866"},
+ {PG_WIN874, "CP874"},
+ {PG_WIN1250, "CP1250"},
+ {PG_WIN1251, "CP1251"},
+ {PG_WIN1251, "ansi-1251"},
+ {PG_WIN1252, "CP1252"},
+ {PG_WIN1253, "CP1253"},
+ {PG_WIN1254, "CP1254"},
+ {PG_WIN1255, "CP1255"},
+ {PG_WIN1256, "CP1256"},
+ {PG_WIN1257, "CP1257"},
+ {PG_WIN1258, "CP1258"},
+
+ {PG_ISO_8859_5, "ISO-8859-5"},
+ {PG_ISO_8859_5, "ISO8859-5"},
+ {PG_ISO_8859_5, "iso88595"},
+ {PG_ISO_8859_5, "CP28595"},
+
+ {PG_ISO_8859_6, "ISO-8859-6"},
+ {PG_ISO_8859_6, "ISO8859-6"},
+ {PG_ISO_8859_6, "iso88596"},
+ {PG_ISO_8859_6, "CP28596"},
+
+ {PG_ISO_8859_7, "ISO-8859-7"},
+ {PG_ISO_8859_7, "ISO8859-7"},
+ {PG_ISO_8859_7, "iso88597"},
+ {PG_ISO_8859_7, "CP28597"},
+
+ {PG_ISO_8859_8, "ISO-8859-8"},
+ {PG_ISO_8859_8, "ISO8859-8"},
+ {PG_ISO_8859_8, "iso88598"},
+ {PG_ISO_8859_8, "CP28598"},
+
+ {PG_SJIS, "SJIS"},
+ {PG_SJIS, "PCK"},
+ {PG_SJIS, "CP932"},
+ {PG_SJIS, "SHIFT_JIS"},
+
+ {PG_BIG5, "BIG5"},
+ {PG_BIG5, "BIG5HKSCS"},
+ {PG_BIG5, "Big5-HKSCS"},
+ {PG_BIG5, "CP950"},
+
+ {PG_GBK, "GBK"},
+ {PG_GBK, "CP936"},
+
+ {PG_UHC, "UHC"},
+ {PG_UHC, "CP949"},
+
+ {PG_JOHAB, "JOHAB"},
+ {PG_JOHAB, "CP1361"},
+
+ {PG_GB18030, "GB18030"},
+ {PG_GB18030, "CP54936"},
+
+ {PG_SHIFT_JIS_2004, "SJIS_2004"},
+
+ {PG_SQL_ASCII, "US-ASCII"},
+
+ {PG_SQL_ASCII, NULL} /* end marker */
+};
+
+#ifdef WIN32
+/*
+ * On Windows, use CP<code page number> instead of the nl_langinfo() result
+ *
+ * Visual Studio 2012 expanded the set of valid LC_CTYPE values, so have its
+ * locale machinery determine the code page. See comments at IsoLocaleName().
+ * For other compilers, follow the locale's predictable format.
+ *
+ * Visual Studio 2015 should still be able to do the same, but the declaration
+ * of lc_codepage is missing in _locale_t, causing this code compilation to
+ * fail, hence this falls back instead on GetLocaleInfoEx. VS 2015 may be an
+ * exception and post-VS2015 versions should be able to handle properly the
+ * codepage number using _create_locale(). So, instead of the same logic as
+ * VS 2012 and VS 2013, this routine uses GetLocaleInfoEx to parse short
+ * locale names like "de-DE", "fr-FR", etc. If those cannot be parsed correctly
+ * process falls back to the pre-VS-2010 manual parsing done with
+ * using <Language>_<Country>.<CodePage> as a base.
+ *
+ * Returns a malloc()'d string for the caller to free.
+ */
+static char *
+win32_langinfo(const char *ctype)
+{
+ char *r = NULL;
+
+#if defined(_MSC_VER) && (_MSC_VER < 1900)
+ _locale_t loct = NULL;
+
+ loct = _create_locale(LC_CTYPE, ctype);
+ if (loct != NULL)
+ {
+ r = malloc(16); /* excess */
+ if (r != NULL)
+ sprintf(r, "CP%u", loct->locinfo->lc_codepage);
+ _free_locale(loct);
+ }
+#else
+ char *codepage;
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1900)
+ uint32 cp;
+ WCHAR wctype[LOCALE_NAME_MAX_LENGTH];
+
+ memset(wctype, 0, sizeof(wctype));
+ MultiByteToWideChar(CP_ACP, 0, ctype, -1, wctype, LOCALE_NAME_MAX_LENGTH);
+
+ if (GetLocaleInfoEx(wctype,
+ LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER,
+ (LPWSTR) &cp, sizeof(cp) / sizeof(WCHAR)) > 0)
+ {
+ r = malloc(16); /* excess */
+ if (r != NULL)
+ {
+ /*
+ * If the return value is CP_ACP that means no ANSI code page is
+ * available, so only Unicode can be used for the locale.
+ */
+ if (cp == CP_ACP)
+ strcpy(r, "utf8");
+ else
+ sprintf(r, "CP%u", cp);
+ }
+ }
+ else
+#endif
+ {
+ /*
+ * Locale format on Win32 is <Language>_<Country>.<CodePage>. For
+ * example, English_United States.1252. If we see digits after the
+ * last dot, assume it's a codepage number. Otherwise, we might be
+ * dealing with a Unix-style locale string; Windows' setlocale() will
+ * take those even though GetLocaleInfoEx() won't, so we end up here.
+ * In that case, just return what's after the last dot and hope we can
+ * find it in our table.
+ */
+ codepage = strrchr(ctype, '.');
+ if (codepage != NULL)
+ {
+ size_t ln;
+
+ codepage++;
+ ln = strlen(codepage);
+ r = malloc(ln + 3);
+ if (r != NULL)
+ {
+ if (strspn(codepage, "0123456789") == ln)
+ sprintf(r, "CP%s", codepage);
+ else
+ strcpy(r, codepage);
+ }
+ }
+
+ }
+#endif
+
+ return r;
+}
+
+#ifndef FRONTEND
+/*
+ * Given a Windows code page identifier, find the corresponding PostgreSQL
+ * encoding. Issue a warning and return -1 if none found.
+ */
+int
+pg_codepage_to_encoding(UINT cp)
+{
+ char sys[16];
+ int i;
+
+ sprintf(sys, "CP%u", cp);
+
+ /* Check the table */
+ for (i = 0; encoding_match_list[i].system_enc_name; i++)
+ if (pg_strcasecmp(sys, encoding_match_list[i].system_enc_name) == 0)
+ return encoding_match_list[i].pg_enc_code;
+
+ ereport(WARNING,
+ (errmsg("could not determine encoding for codeset \"%s\"", sys)));
+
+ return -1;
+}
+#endif
+#endif /* WIN32 */
+
+#if (defined(HAVE_LANGINFO_H) && defined(CODESET)) || defined(WIN32)
+
+/*
+ * Given a setting for LC_CTYPE, return the Postgres ID of the associated
+ * encoding, if we can determine it. Return -1 if we can't determine it.
+ *
+ * Pass in NULL to get the encoding for the current locale setting.
+ * Pass "" to get the encoding selected by the server's environment.
+ *
+ * If the result is PG_SQL_ASCII, callers should treat it as being compatible
+ * with any desired encoding.
+ *
+ * If running in the backend and write_message is false, this function must
+ * cope with the possibility that elog() and palloc() are not yet usable.
+ */
+int
+pg_get_encoding_from_locale(const char *ctype, bool write_message)
+{
+ char *sys;
+ int i;
+
+ /* Get the CODESET property, and also LC_CTYPE if not passed in */
+ if (ctype)
+ {
+ char *save;
+ char *name;
+
+ /* If locale is C or POSIX, we can allow all encodings */
+ if (pg_strcasecmp(ctype, "C") == 0 ||
+ pg_strcasecmp(ctype, "POSIX") == 0)
+ return PG_SQL_ASCII;
+
+ save = setlocale(LC_CTYPE, NULL);
+ if (!save)
+ return -1; /* setlocale() broken? */
+ /* must copy result, or it might change after setlocale */
+ save = strdup(save);
+ if (!save)
+ return -1; /* out of memory; unlikely */
+
+ name = setlocale(LC_CTYPE, ctype);
+ if (!name)
+ {
+ free(save);
+ return -1; /* bogus ctype passed in? */
+ }
+
+#ifndef WIN32
+ sys = nl_langinfo(CODESET);
+ if (sys)
+ sys = strdup(sys);
+#else
+ sys = win32_langinfo(name);
+#endif
+
+ setlocale(LC_CTYPE, save);
+ free(save);
+ }
+ else
+ {
+ /* much easier... */
+ ctype = setlocale(LC_CTYPE, NULL);
+ if (!ctype)
+ return -1; /* setlocale() broken? */
+
+ /* If locale is C or POSIX, we can allow all encodings */
+ if (pg_strcasecmp(ctype, "C") == 0 ||
+ pg_strcasecmp(ctype, "POSIX") == 0)
+ return PG_SQL_ASCII;
+
+#ifndef WIN32
+ sys = nl_langinfo(CODESET);
+ if (sys)
+ sys = strdup(sys);
+#else
+ sys = win32_langinfo(ctype);
+#endif
+ }
+
+ if (!sys)
+ return -1; /* out of memory; unlikely */
+
+ /* Check the table */
+ for (i = 0; encoding_match_list[i].system_enc_name; i++)
+ {
+ if (pg_strcasecmp(sys, encoding_match_list[i].system_enc_name) == 0)
+ {
+ free(sys);
+ return encoding_match_list[i].pg_enc_code;
+ }
+ }
+
+ /* Special-case kluges for particular platforms go here */
+
+#ifdef __darwin__
+
+ /*
+ * Current macOS has many locales that report an empty string for CODESET,
+ * but they all seem to actually use UTF-8.
+ */
+ if (strlen(sys) == 0)
+ {
+ free(sys);
+ return PG_UTF8;
+ }
+#endif
+
+ /*
+ * We print a warning if we got a CODESET string but couldn't recognize
+ * it. This means we need another entry in the table.
+ */
+ if (write_message)
+ {
+#ifdef FRONTEND
+ fprintf(stderr, _("could not determine encoding for locale \"%s\": codeset is \"%s\""),
+ ctype, sys);
+ /* keep newline separate so there's only one translatable string */
+ fputc('\n', stderr);
+#else
+ ereport(WARNING,
+ (errmsg("could not determine encoding for locale \"%s\": codeset is \"%s\"",
+ ctype, sys)));
+#endif
+ }
+
+ free(sys);
+ return -1;
+}
+#else /* (HAVE_LANGINFO_H && CODESET) || WIN32 */
+
+/*
+ * stub if no multi-language platform support
+ *
+ * Note: we could return -1 here, but that would have the effect of
+ * forcing users to specify an encoding to initdb on such platforms.
+ * It seems better to silently default to SQL_ASCII.
+ */
+int
+pg_get_encoding_from_locale(const char *ctype, bool write_message)
+{
+ return PG_SQL_ASCII;
+}
+
+#endif /* (HAVE_LANGINFO_H && CODESET) || WIN32 */
diff --git a/contrib/libs/postgresql/src/port/dirmod.c b/contrib/libs/postgresql/src/port/dirmod.c
new file mode 100644
index 0000000000..46c9c235c8
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/dirmod.c
@@ -0,0 +1,355 @@
+/*-------------------------------------------------------------------------
+ *
+ * dirmod.c
+ * directory handling functions
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * This includes replacement versions of functions that work on
+ * Win32 (NT4 and newer).
+ *
+ * IDENTIFICATION
+ * src/port/dirmod.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+/* Don't modify declarations in system headers */
+#if defined(WIN32) || defined(__CYGWIN__)
+#undef rename
+#undef unlink
+#endif
+
+#include <unistd.h>
+#include <sys/stat.h>
+
+#if defined(WIN32) || defined(__CYGWIN__)
+#ifndef __CYGWIN__
+#include <winioctl.h>
+#else
+#include <windows.h>
+#error #include <w32api/winioctl.h>
+#endif
+#endif
+
+#if defined(WIN32) || defined(__CYGWIN__)
+
+/*
+ * pgrename
+ */
+int
+pgrename(const char *from, const char *to)
+{
+ int loops = 0;
+
+ /*
+ * We need to loop because even though PostgreSQL uses flags that allow
+ * rename while the file is open, other applications might have the file
+ * open without those flags. However, we won't wait indefinitely for
+ * someone else to close the file, as the caller might be holding locks
+ * and blocking other backends.
+ */
+#if defined(WIN32) && !defined(__CYGWIN__)
+ while (!MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING))
+#else
+ while (rename(from, to) < 0)
+#endif
+ {
+#if defined(WIN32) && !defined(__CYGWIN__)
+ DWORD err = GetLastError();
+
+ _dosmaperr(err);
+
+ /*
+ * Modern NT-based Windows versions return ERROR_SHARING_VIOLATION if
+ * another process has the file open without FILE_SHARE_DELETE.
+ * ERROR_LOCK_VIOLATION has also been seen with some anti-virus
+ * software. This used to check for just ERROR_ACCESS_DENIED, so
+ * presumably you can get that too with some OS versions. We don't
+ * expect real permission errors where we currently use rename().
+ */
+ if (err != ERROR_ACCESS_DENIED &&
+ err != ERROR_SHARING_VIOLATION &&
+ err != ERROR_LOCK_VIOLATION)
+ return -1;
+#else
+ if (errno != EACCES)
+ return -1;
+#endif
+
+ if (++loops > 100) /* time out after 10 sec */
+ return -1;
+ pg_usleep(100000); /* us */
+ }
+ return 0;
+}
+
+
+/*
+ * pgunlink
+ */
+int
+pgunlink(const char *path)
+{
+ int loops = 0;
+
+ /*
+ * We need to loop because even though PostgreSQL uses flags that allow
+ * unlink while the file is open, other applications might have the file
+ * open without those flags. However, we won't wait indefinitely for
+ * someone else to close the file, as the caller might be holding locks
+ * and blocking other backends.
+ */
+ while (unlink(path))
+ {
+ if (errno != EACCES)
+ return -1;
+ if (++loops > 100) /* time out after 10 sec */
+ return -1;
+ pg_usleep(100000); /* us */
+ }
+ return 0;
+}
+
+/* We undefined these above; now redefine for possible use below */
+#define rename(from, to) pgrename(from, to)
+#define unlink(path) pgunlink(path)
+#endif /* defined(WIN32) || defined(__CYGWIN__) */
+
+
+#if defined(WIN32) && !defined(__CYGWIN__) /* Cygwin has its own symlinks */
+
+/*
+ * pgsymlink support:
+ *
+ * This struct is a replacement for REPARSE_DATA_BUFFER which is defined in VC6 winnt.h
+ * but omitted in later SDK functions.
+ * We only need the SymbolicLinkReparseBuffer part of the original struct's union.
+ */
+typedef struct
+{
+ DWORD ReparseTag;
+ WORD ReparseDataLength;
+ WORD Reserved;
+ /* SymbolicLinkReparseBuffer */
+ WORD SubstituteNameOffset;
+ WORD SubstituteNameLength;
+ WORD PrintNameOffset;
+ WORD PrintNameLength;
+ WCHAR PathBuffer[FLEXIBLE_ARRAY_MEMBER];
+} REPARSE_JUNCTION_DATA_BUFFER;
+
+#define REPARSE_JUNCTION_DATA_BUFFER_HEADER_SIZE \
+ FIELD_OFFSET(REPARSE_JUNCTION_DATA_BUFFER, SubstituteNameOffset)
+
+
+/*
+ * pgsymlink - uses Win32 junction points
+ *
+ * For reference: http://www.codeproject.com/KB/winsdk/junctionpoints.aspx
+ */
+int
+pgsymlink(const char *oldpath, const char *newpath)
+{
+ HANDLE dirhandle;
+ DWORD len;
+ char buffer[MAX_PATH * sizeof(WCHAR) + offsetof(REPARSE_JUNCTION_DATA_BUFFER, PathBuffer)];
+ char nativeTarget[MAX_PATH];
+ char *p = nativeTarget;
+ REPARSE_JUNCTION_DATA_BUFFER *reparseBuf = (REPARSE_JUNCTION_DATA_BUFFER *) buffer;
+
+ CreateDirectory(newpath, 0);
+ dirhandle = CreateFile(newpath, GENERIC_READ | GENERIC_WRITE,
+ 0, 0, OPEN_EXISTING,
+ FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, 0);
+
+ if (dirhandle == INVALID_HANDLE_VALUE)
+ return -1;
+
+ /* make sure we have an unparsed native win32 path */
+ if (memcmp("\\??\\", oldpath, 4) != 0)
+ snprintf(nativeTarget, sizeof(nativeTarget), "\\??\\%s", oldpath);
+ else
+ strlcpy(nativeTarget, oldpath, sizeof(nativeTarget));
+
+ while ((p = strchr(p, '/')) != NULL)
+ *p++ = '\\';
+
+ len = strlen(nativeTarget) * sizeof(WCHAR);
+ reparseBuf->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
+ reparseBuf->ReparseDataLength = len + 12;
+ reparseBuf->Reserved = 0;
+ reparseBuf->SubstituteNameOffset = 0;
+ reparseBuf->SubstituteNameLength = len;
+ reparseBuf->PrintNameOffset = len + sizeof(WCHAR);
+ reparseBuf->PrintNameLength = 0;
+ MultiByteToWideChar(CP_ACP, 0, nativeTarget, -1,
+ reparseBuf->PathBuffer, MAX_PATH);
+
+ /*
+ * FSCTL_SET_REPARSE_POINT is coded differently depending on SDK version;
+ * we use our own definition
+ */
+ if (!DeviceIoControl(dirhandle,
+ CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 41, METHOD_BUFFERED, FILE_ANY_ACCESS),
+ reparseBuf,
+ reparseBuf->ReparseDataLength + REPARSE_JUNCTION_DATA_BUFFER_HEADER_SIZE,
+ 0, 0, &len, 0))
+ {
+ LPSTR msg;
+
+ errno = 0;
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_IGNORE_INSERTS |
+ FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, GetLastError(),
+ MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
+ (LPSTR) &msg, 0, NULL);
+#ifndef FRONTEND
+ ereport(ERROR,
+ (errcode_for_file_access(),
+ errmsg("could not set junction for \"%s\": %s",
+ nativeTarget, msg)));
+#else
+ fprintf(stderr, _("could not set junction for \"%s\": %s\n"),
+ nativeTarget, msg);
+#endif
+ LocalFree(msg);
+
+ CloseHandle(dirhandle);
+ RemoveDirectory(newpath);
+ return -1;
+ }
+
+ CloseHandle(dirhandle);
+
+ return 0;
+}
+
+/*
+ * pgreadlink - uses Win32 junction points
+ */
+int
+pgreadlink(const char *path, char *buf, size_t size)
+{
+ DWORD attr;
+ HANDLE h;
+ char buffer[MAX_PATH * sizeof(WCHAR) + offsetof(REPARSE_JUNCTION_DATA_BUFFER, PathBuffer)];
+ REPARSE_JUNCTION_DATA_BUFFER *reparseBuf = (REPARSE_JUNCTION_DATA_BUFFER *) buffer;
+ DWORD len;
+ int r;
+
+ attr = GetFileAttributes(path);
+ if (attr == INVALID_FILE_ATTRIBUTES)
+ {
+ _dosmaperr(GetLastError());
+ return -1;
+ }
+ if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) == 0)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ h = CreateFile(path,
+ GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
+ 0);
+ if (h == INVALID_HANDLE_VALUE)
+ {
+ _dosmaperr(GetLastError());
+ return -1;
+ }
+
+ if (!DeviceIoControl(h,
+ FSCTL_GET_REPARSE_POINT,
+ NULL,
+ 0,
+ (LPVOID) reparseBuf,
+ sizeof(buffer),
+ &len,
+ NULL))
+ {
+ LPSTR msg;
+
+ errno = 0;
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_IGNORE_INSERTS |
+ FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, GetLastError(),
+ MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
+ (LPSTR) &msg, 0, NULL);
+#ifndef FRONTEND
+ ereport(ERROR,
+ (errcode_for_file_access(),
+ errmsg("could not get junction for \"%s\": %s",
+ path, msg)));
+#else
+ fprintf(stderr, _("could not get junction for \"%s\": %s\n"),
+ path, msg);
+#endif
+ LocalFree(msg);
+ CloseHandle(h);
+ errno = EINVAL;
+ return -1;
+ }
+ CloseHandle(h);
+
+ /* Got it, let's get some results from this */
+ if (reparseBuf->ReparseTag != IO_REPARSE_TAG_MOUNT_POINT)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ r = WideCharToMultiByte(CP_ACP, 0,
+ reparseBuf->PathBuffer, -1,
+ buf,
+ size,
+ NULL, NULL);
+
+ if (r <= 0)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /*
+ * If the path starts with "\??\", which it will do in most (all?) cases,
+ * strip those out.
+ */
+ if (r > 4 && strncmp(buf, "\\??\\", 4) == 0)
+ {
+ memmove(buf, buf + 4, strlen(buf + 4) + 1);
+ r -= 4;
+ }
+ return r;
+}
+
+/*
+ * Assumes the file exists, so will return false if it doesn't
+ * (since a nonexistent file is not a junction)
+ */
+bool
+pgwin32_is_junction(const char *path)
+{
+ DWORD attr = GetFileAttributes(path);
+
+ if (attr == INVALID_FILE_ATTRIBUTES)
+ {
+ _dosmaperr(GetLastError());
+ return false;
+ }
+ return ((attr & FILE_ATTRIBUTE_REPARSE_POINT) == FILE_ATTRIBUTE_REPARSE_POINT);
+}
+#endif /* defined(WIN32) && !defined(__CYGWIN__) */
diff --git a/contrib/libs/postgresql/src/port/dlopen.c b/contrib/libs/postgresql/src/port/dlopen.c
new file mode 100644
index 0000000000..f7948b861f
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/dlopen.c
@@ -0,0 +1,145 @@
+/*-------------------------------------------------------------------------
+ *
+ * dlopen.c
+ * dynamic loader for platforms without dlopen()
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/port/dlopen.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "c.h"
+
+#if defined(__hpux)
+
+/* System includes */
+#include <a.out.h>
+#include <dl.h>
+
+void *
+dlopen(const char *file, int mode)
+{
+ int flags = 0;
+
+ if (mode & RTLD_NOW)
+ flags |= BIND_IMMEDIATE;
+#ifdef NOT_USED
+ if (mode & RTLD_LAZY)
+ flags |= BIND_DEFERRED;
+#endif
+
+ return shl_load(file, flags | BIND_VERBOSE, 0L);
+}
+
+void *
+dlsym(void *handle, const char *symbol)
+{
+ void *value;
+
+ if (shl_findsym((shl_t *) & handle, symbol, TYPE_PROCEDURE, &value) == -1)
+ return NULL;
+ return value;
+}
+
+int
+dlclose(void *handle)
+{
+ return shl_unload((shl_t) handle);
+}
+
+char *
+dlerror(void)
+{
+ static char errmsg[] = "shl_load failed";
+
+ if (errno)
+ return strerror(errno);
+
+ return errmsg;
+}
+
+#elif defined(WIN32)
+
+static char last_dyn_error[512];
+
+static void
+set_dl_error(void)
+{
+ DWORD err = GetLastError();
+
+ if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS |
+ FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ err,
+ MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
+ last_dyn_error,
+ sizeof(last_dyn_error) - 1,
+ NULL) == 0)
+ {
+ snprintf(last_dyn_error, sizeof(last_dyn_error) - 1,
+ "unknown error %lu", err);
+ }
+}
+
+char *
+dlerror(void)
+{
+ if (last_dyn_error[0])
+ return last_dyn_error;
+ else
+ return NULL;
+}
+
+int
+dlclose(void *handle)
+{
+ if (!FreeLibrary((HMODULE) handle))
+ {
+ set_dl_error();
+ return 1;
+ }
+ last_dyn_error[0] = 0;
+ return 0;
+}
+
+void *
+dlsym(void *handle, const char *symbol)
+{
+ void *ptr;
+
+ ptr = GetProcAddress((HMODULE) handle, symbol);
+ if (!ptr)
+ {
+ set_dl_error();
+ return NULL;
+ }
+ last_dyn_error[0] = 0;
+ return ptr;
+}
+
+void *
+dlopen(const char *file, int mode)
+{
+ HMODULE h;
+ int prevmode;
+
+ /* Disable popup error messages when loading DLLs */
+ prevmode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
+ h = LoadLibrary(file);
+ SetErrorMode(prevmode);
+
+ if (!h)
+ {
+ set_dl_error();
+ return NULL;
+ }
+ last_dyn_error[0] = 0;
+ return (void *) h;
+}
+
+#endif
diff --git a/contrib/libs/postgresql/src/port/erand48.c b/contrib/libs/postgresql/src/port/erand48.c
new file mode 100644
index 0000000000..a82ea94220
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/erand48.c
@@ -0,0 +1,136 @@
+/*-------------------------------------------------------------------------
+ *
+ * erand48.c
+ *
+ * This file supplies pg_erand48() and related functions, which except
+ * for the names are just like the POSIX-standard erand48() family.
+ * (We don't supply the full set though, only the ones we have found use
+ * for in Postgres. In particular, we do *not* implement lcong48(), so
+ * that there is no need for the multiplier and addend to be variable.)
+ *
+ * We used to test for an operating system version rather than
+ * unconditionally using our own, but (1) some versions of Cygwin have a
+ * buggy erand48() that always returns zero and (2) as of 2011, glibc's
+ * erand48() is strangely coded to be almost-but-not-quite thread-safe,
+ * which doesn't matter for the backend but is important for pgbench.
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ *
+ * Portions Copyright (c) 1993 Martin Birgmeier
+ * All rights reserved.
+ *
+ * You may redistribute unmodified or modified versions of this source
+ * code provided that the above copyright notice and this and the
+ * following conditions are retained.
+ *
+ * This software is provided ``as is'', and comes with no warranties
+ * of any kind. I shall in no event be liable for anything that happens
+ * to anyone/anything when using this software.
+ *
+ * IDENTIFICATION
+ * src/port/erand48.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "c.h"
+
+#include <math.h>
+
+/* These values are specified by POSIX */
+#define RAND48_MULT UINT64CONST(0x0005deece66d)
+#define RAND48_ADD UINT64CONST(0x000b)
+
+/* POSIX specifies 0x330e's use in srand48, but the other bits are arbitrary */
+#define RAND48_SEED_0 (0x330e)
+#define RAND48_SEED_1 (0xabcd)
+#define RAND48_SEED_2 (0x1234)
+
+static unsigned short _rand48_seed[3] = {
+ RAND48_SEED_0,
+ RAND48_SEED_1,
+ RAND48_SEED_2
+};
+
+
+/*
+ * Advance the 48-bit value stored in xseed[] to the next "random" number.
+ *
+ * Also returns the value of that number --- without masking it to 48 bits.
+ * If caller uses the result, it must mask off the bits it wants.
+ */
+static uint64
+_dorand48(unsigned short xseed[3])
+{
+ /*
+ * We do the arithmetic in uint64; any type wider than 48 bits would work.
+ */
+ uint64 in;
+ uint64 out;
+
+ in = (uint64) xseed[2] << 32 | (uint64) xseed[1] << 16 | (uint64) xseed[0];
+
+ out = in * RAND48_MULT + RAND48_ADD;
+
+ xseed[0] = out & 0xFFFF;
+ xseed[1] = (out >> 16) & 0xFFFF;
+ xseed[2] = (out >> 32) & 0xFFFF;
+
+ return out;
+}
+
+
+/*
+ * Generate a random floating-point value using caller-supplied state.
+ * Values are uniformly distributed over the interval [0.0, 1.0).
+ */
+double
+pg_erand48(unsigned short xseed[3])
+{
+ uint64 x = _dorand48(xseed);
+
+ return ldexp((double) (x & UINT64CONST(0xFFFFFFFFFFFF)), -48);
+}
+
+/*
+ * Generate a random non-negative integral value using internal state.
+ * Values are uniformly distributed over the interval [0, 2^31).
+ */
+long
+pg_lrand48(void)
+{
+ uint64 x = _dorand48(_rand48_seed);
+
+ return (x >> 17) & UINT64CONST(0x7FFFFFFF);
+}
+
+/*
+ * Generate a random signed integral value using caller-supplied state.
+ * Values are uniformly distributed over the interval [-2^31, 2^31).
+ */
+long
+pg_jrand48(unsigned short xseed[3])
+{
+ uint64 x = _dorand48(xseed);
+
+ return (int32) ((x >> 16) & UINT64CONST(0xFFFFFFFF));
+}
+
+/*
+ * Initialize the internal state using the given seed.
+ *
+ * Per POSIX, this uses only 32 bits from "seed" even if "long" is wider.
+ * Hence, the set of possible seed values is smaller than it could be.
+ * Better practice is to use caller-supplied state and initialize it with
+ * random bits obtained from a high-quality source of random bits.
+ *
+ * Note: POSIX specifies a function seed48() that allows all 48 bits
+ * of the internal state to be set, but we don't currently support that.
+ */
+void
+pg_srand48(long seed)
+{
+ _rand48_seed[0] = RAND48_SEED_0;
+ _rand48_seed[1] = (unsigned short) seed;
+ _rand48_seed[2] = (unsigned short) (seed >> 16);
+}
diff --git a/contrib/libs/postgresql/src/port/fls.c b/contrib/libs/postgresql/src/port/fls.c
new file mode 100644
index 0000000000..2c622c51eb
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/fls.c
@@ -0,0 +1,64 @@
+/*-------------------------------------------------------------------------
+ *
+ * fls.c
+ * finds the last (most significant) bit that is set
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ *
+ *
+ * IDENTIFICATION
+ * src/port/fls.c
+ *
+ * This file was taken from FreeBSD to provide an implementation of fls()
+ * for platforms that lack it. Note that the operating system's version may
+ * be substantially more efficient than ours, since some platforms have an
+ * assembly instruction that does exactly this.
+ *
+ * The FreeBSD copyright terms follow.
+ */
+
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "c.h"
+
+/*
+ * Find Last Set bit
+ */
+int
+fls(int mask)
+{
+ int bit;
+
+ if (mask == 0)
+ return (0);
+ for (bit = 1; mask != 1; bit++)
+ mask = (unsigned int) mask >> 1;
+ return (bit);
+}
diff --git a/contrib/libs/postgresql/src/port/getaddrinfo.c b/contrib/libs/postgresql/src/port/getaddrinfo.c
new file mode 100644
index 0000000000..bb194da529
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/getaddrinfo.c
@@ -0,0 +1,396 @@
+/*-------------------------------------------------------------------------
+ *
+ * getaddrinfo.c
+ * Support getaddrinfo() on platforms that don't have it.
+ *
+ * We also supply getnameinfo() here, assuming that the platform will have
+ * it if and only if it has getaddrinfo(). If this proves false on some
+ * platform, we'll need to split this file and provide a separate configure
+ * test for getnameinfo().
+ *
+ * Windows may or may not have these routines, so we handle Windows specially
+ * by dynamically checking for their existence. If they already exist, we
+ * use the Windows native routines, but if not, we use our own.
+ *
+ *
+ * Copyright (c) 2003-2021, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/port/getaddrinfo.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/* This is intended to be used in both frontend and backend, so use c.h */
+#include "c.h"
+
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "getaddrinfo.h"
+#include "libpq/pqcomm.h" /* needed for struct sockaddr_storage */
+#include "port/pg_bswap.h"
+
+
+#ifdef WIN32
+/*
+ * The native routines may or may not exist on the Windows platform we are on,
+ * so we dynamically look up the routines, and call them via function pointers.
+ * Here we need to declare what the function pointers look like
+ */
+typedef int (__stdcall * getaddrinfo_ptr_t) (const char *nodename,
+ const char *servname,
+ const struct addrinfo *hints,
+ struct addrinfo **res);
+
+typedef void (__stdcall * freeaddrinfo_ptr_t) (struct addrinfo *ai);
+
+typedef int (__stdcall * getnameinfo_ptr_t) (const struct sockaddr *sa,
+ int salen,
+ char *node, int nodelen,
+ char *service, int servicelen,
+ int flags);
+
+/* static pointers to the native routines, so we only do the lookup once. */
+static getaddrinfo_ptr_t getaddrinfo_ptr = NULL;
+static freeaddrinfo_ptr_t freeaddrinfo_ptr = NULL;
+static getnameinfo_ptr_t getnameinfo_ptr = NULL;
+
+
+static bool
+haveNativeWindowsIPv6routines(void)
+{
+ void *hLibrary = NULL;
+ static bool alreadyLookedForIpv6routines = false;
+
+ if (alreadyLookedForIpv6routines)
+ return (getaddrinfo_ptr != NULL);
+
+ /*
+ * For Windows XP and later versions, the IPv6 routines are present in the
+ * WinSock 2 library (ws2_32.dll).
+ */
+ hLibrary = LoadLibraryA("ws2_32");
+
+ /* If hLibrary is null, we couldn't find a dll with functions */
+ if (hLibrary != NULL)
+ {
+ /* We found a dll, so now get the addresses of the routines */
+
+ getaddrinfo_ptr = (getaddrinfo_ptr_t) (pg_funcptr_t) GetProcAddress(hLibrary,
+ "getaddrinfo");
+ freeaddrinfo_ptr = (freeaddrinfo_ptr_t) (pg_funcptr_t) GetProcAddress(hLibrary,
+ "freeaddrinfo");
+ getnameinfo_ptr = (getnameinfo_ptr_t) (pg_funcptr_t) GetProcAddress(hLibrary,
+ "getnameinfo");
+
+ /*
+ * If any one of the routines is missing, let's play it safe and
+ * ignore them all
+ */
+ if (getaddrinfo_ptr == NULL ||
+ freeaddrinfo_ptr == NULL ||
+ getnameinfo_ptr == NULL)
+ {
+ FreeLibrary(hLibrary);
+ hLibrary = NULL;
+ getaddrinfo_ptr = NULL;
+ freeaddrinfo_ptr = NULL;
+ getnameinfo_ptr = NULL;
+ }
+ }
+
+ alreadyLookedForIpv6routines = true;
+ return (getaddrinfo_ptr != NULL);
+}
+#endif
+
+
+/*
+ * get address info for ipv4 sockets.
+ *
+ * Bugs: - only one addrinfo is set even though hintp is NULL or
+ * ai_socktype is 0
+ * - AI_CANONNAME is not supported.
+ * - servname can only be a number, not text.
+ */
+int
+getaddrinfo(const char *node, const char *service,
+ const struct addrinfo *hintp,
+ struct addrinfo **res)
+{
+ struct addrinfo *ai;
+ struct sockaddr_in sin,
+ *psin;
+ struct addrinfo hints;
+
+#ifdef WIN32
+
+ /*
+ * If Windows has native IPv6 support, use the native Windows routine.
+ * Otherwise, fall through and use our own code.
+ */
+ if (haveNativeWindowsIPv6routines())
+ return (*getaddrinfo_ptr) (node, service, hintp, res);
+#endif
+
+ if (hintp == NULL)
+ {
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_INET;
+ hints.ai_socktype = SOCK_STREAM;
+ }
+ else
+ memcpy(&hints, hintp, sizeof(hints));
+
+ if (hints.ai_family != AF_INET && hints.ai_family != AF_UNSPEC)
+ return EAI_FAMILY;
+
+ if (hints.ai_socktype == 0)
+ hints.ai_socktype = SOCK_STREAM;
+
+ if (!node && !service)
+ return EAI_NONAME;
+
+ memset(&sin, 0, sizeof(sin));
+
+ sin.sin_family = AF_INET;
+
+ if (node)
+ {
+ if (node[0] == '\0')
+ sin.sin_addr.s_addr = pg_hton32(INADDR_ANY);
+ else if (hints.ai_flags & AI_NUMERICHOST)
+ {
+ if (!inet_aton(node, &sin.sin_addr))
+ return EAI_NONAME;
+ }
+ else
+ {
+ struct hostent *hp;
+
+#ifdef FRONTEND
+ struct hostent hpstr;
+ char buf[BUFSIZ];
+ int herrno = 0;
+
+ pqGethostbyname(node, &hpstr, buf, sizeof(buf),
+ &hp, &herrno);
+#else
+ hp = gethostbyname(node);
+#endif
+ if (hp == NULL)
+ {
+ switch (h_errno)
+ {
+ case HOST_NOT_FOUND:
+ case NO_DATA:
+ return EAI_NONAME;
+ case TRY_AGAIN:
+ return EAI_AGAIN;
+ case NO_RECOVERY:
+ default:
+ return EAI_FAIL;
+ }
+ }
+ if (hp->h_addrtype != AF_INET)
+ return EAI_FAIL;
+
+ memcpy(&(sin.sin_addr), hp->h_addr, hp->h_length);
+ }
+ }
+ else
+ {
+ if (hints.ai_flags & AI_PASSIVE)
+ sin.sin_addr.s_addr = pg_hton32(INADDR_ANY);
+ else
+ sin.sin_addr.s_addr = pg_hton32(INADDR_LOOPBACK);
+ }
+
+ if (service)
+ sin.sin_port = pg_hton16((unsigned short) atoi(service));
+
+#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN
+ sin.sin_len = sizeof(sin);
+#endif
+
+ ai = malloc(sizeof(*ai));
+ if (!ai)
+ return EAI_MEMORY;
+
+ psin = malloc(sizeof(*psin));
+ if (!psin)
+ {
+ free(ai);
+ return EAI_MEMORY;
+ }
+
+ memcpy(psin, &sin, sizeof(*psin));
+
+ ai->ai_flags = 0;
+ ai->ai_family = AF_INET;
+ ai->ai_socktype = hints.ai_socktype;
+ ai->ai_protocol = hints.ai_protocol;
+ ai->ai_addrlen = sizeof(*psin);
+ ai->ai_addr = (struct sockaddr *) psin;
+ ai->ai_canonname = NULL;
+ ai->ai_next = NULL;
+
+ *res = ai;
+
+ return 0;
+}
+
+
+void
+freeaddrinfo(struct addrinfo *res)
+{
+ if (res)
+ {
+#ifdef WIN32
+
+ /*
+ * If Windows has native IPv6 support, use the native Windows routine.
+ * Otherwise, fall through and use our own code.
+ */
+ if (haveNativeWindowsIPv6routines())
+ {
+ (*freeaddrinfo_ptr) (res);
+ return;
+ }
+#endif
+
+ if (res->ai_addr)
+ free(res->ai_addr);
+ free(res);
+ }
+}
+
+
+const char *
+gai_strerror(int errcode)
+{
+#ifdef HAVE_HSTRERROR
+ int hcode;
+
+ switch (errcode)
+ {
+ case EAI_NONAME:
+ hcode = HOST_NOT_FOUND;
+ break;
+ case EAI_AGAIN:
+ hcode = TRY_AGAIN;
+ break;
+ case EAI_FAIL:
+ default:
+ hcode = NO_RECOVERY;
+ break;
+ }
+
+ return hstrerror(hcode);
+#else /* !HAVE_HSTRERROR */
+
+ switch (errcode)
+ {
+ case EAI_NONAME:
+ return "Unknown host";
+ case EAI_AGAIN:
+ return "Host name lookup failure";
+ /* Errors below are probably WIN32 only */
+#ifdef EAI_BADFLAGS
+ case EAI_BADFLAGS:
+ return "Invalid argument";
+#endif
+#ifdef EAI_FAMILY
+ case EAI_FAMILY:
+ return "Address family not supported";
+#endif
+#ifdef EAI_MEMORY
+ case EAI_MEMORY:
+ return "Not enough memory";
+#endif
+#if defined(EAI_NODATA) && EAI_NODATA != EAI_NONAME /* MSVC/WIN64 duplicate */
+ case EAI_NODATA:
+ return "No host data of that type was found";
+#endif
+#ifdef EAI_SERVICE
+ case EAI_SERVICE:
+ return "Class type not found";
+#endif
+#ifdef EAI_SOCKTYPE
+ case EAI_SOCKTYPE:
+ return "Socket type not supported";
+#endif
+ default:
+ return "Unknown server error";
+ }
+#endif /* HAVE_HSTRERROR */
+}
+
+/*
+ * Convert an ipv4 address to a hostname.
+ *
+ * Bugs: - Only supports NI_NUMERICHOST and NI_NUMERICSERV behavior.
+ * It will never resolve a hostname.
+ * - No IPv6 support.
+ */
+int
+getnameinfo(const struct sockaddr *sa, int salen,
+ char *node, int nodelen,
+ char *service, int servicelen, int flags)
+{
+#ifdef WIN32
+
+ /*
+ * If Windows has native IPv6 support, use the native Windows routine.
+ * Otherwise, fall through and use our own code.
+ */
+ if (haveNativeWindowsIPv6routines())
+ return (*getnameinfo_ptr) (sa, salen, node, nodelen,
+ service, servicelen, flags);
+#endif
+
+ /* Invalid arguments. */
+ if (sa == NULL || (node == NULL && service == NULL))
+ return EAI_FAIL;
+
+#ifdef HAVE_IPV6
+ if (sa->sa_family == AF_INET6)
+ return EAI_FAMILY;
+#endif
+
+ /* Unsupported flags. */
+ if (flags & NI_NAMEREQD)
+ return EAI_AGAIN;
+
+ if (node)
+ {
+ if (sa->sa_family == AF_INET)
+ {
+ if (pg_inet_net_ntop(AF_INET,
+ &((struct sockaddr_in *) sa)->sin_addr,
+ sa->sa_family == AF_INET ? 32 : 128,
+ node, nodelen) == NULL)
+ return EAI_MEMORY;
+ }
+ else
+ return EAI_MEMORY;
+ }
+
+ if (service)
+ {
+ int ret = -1;
+
+ if (sa->sa_family == AF_INET)
+ {
+ ret = snprintf(service, servicelen, "%d",
+ pg_ntoh16(((struct sockaddr_in *) sa)->sin_port));
+ }
+ if (ret < 0 || ret >= servicelen)
+ return EAI_MEMORY;
+ }
+
+ return 0;
+}
diff --git a/contrib/libs/postgresql/src/port/getopt.c b/contrib/libs/postgresql/src/port/getopt.c
new file mode 100644
index 0000000000..207c2836d3
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/getopt.c
@@ -0,0 +1,136 @@
+/* src/port/getopt.c */
+
+/*
+ * Copyright (c) 1987, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ */
+
+#include "c.h"
+
+#include "pg_getopt.h"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getopt.c 8.3 (Berkeley) 4/27/95";
+#endif /* LIBC_SCCS and not lint */
+
+
+/*
+ * On OpenBSD and some versions of Solaris, opterr and friends are defined in
+ * core libc rather than in a separate getopt module. Define these variables
+ * only if configure found they aren't there by default; otherwise, this
+ * module and its callers will just use libc's variables. (We assume that
+ * testing opterr is sufficient for all of these.)
+ */
+#ifndef HAVE_INT_OPTERR
+
+int opterr = 1, /* if error message should be printed */
+ optind = 1, /* index into parent argv vector */
+ optopt; /* character checked for validity */
+char *optarg; /* argument associated with option */
+
+#endif
+
+#define BADCH (int)'?'
+#define BADARG (int)':'
+#define EMSG ""
+
+/*
+ * getopt
+ * Parse argc/argv argument vector.
+ *
+ * This implementation does not use optreset. Instead, we guarantee that
+ * it can be restarted on a new argv array after a previous call returned -1,
+ * if the caller resets optind to 1 before the first call of the new series.
+ * (Internally, this means we must be sure to reset "place" to EMSG before
+ * returning -1.)
+ */
+int
+getopt(int nargc, char *const *nargv, const char *ostr)
+{
+ static char *place = EMSG; /* option letter processing */
+ char *oli; /* option letter list index */
+
+ if (!*place)
+ { /* update scanning pointer */
+ if (optind >= nargc || *(place = nargv[optind]) != '-')
+ {
+ place = EMSG;
+ return -1;
+ }
+ if (place[1] && *++place == '-' && place[1] == '\0')
+ { /* found "--" */
+ ++optind;
+ place = EMSG;
+ return -1;
+ }
+ } /* option letter okay? */
+ if ((optopt = (int) *place++) == (int) ':' ||
+ !(oli = strchr(ostr, optopt)))
+ {
+ /*
+ * if the user didn't specify '-' as an option, assume it means -1.
+ */
+ if (optopt == (int) '-')
+ {
+ place = EMSG;
+ return -1;
+ }
+ if (!*place)
+ ++optind;
+ if (opterr && *ostr != ':')
+ (void) fprintf(stderr,
+ "illegal option -- %c\n", optopt);
+ return BADCH;
+ }
+ if (*++oli != ':')
+ { /* don't need argument */
+ optarg = NULL;
+ if (!*place)
+ ++optind;
+ }
+ else
+ { /* need an argument */
+ if (*place) /* no white space */
+ optarg = place;
+ else if (nargc <= ++optind)
+ { /* no arg */
+ place = EMSG;
+ if (*ostr == ':')
+ return BADARG;
+ if (opterr)
+ (void) fprintf(stderr,
+ "option requires an argument -- %c\n",
+ optopt);
+ return BADCH;
+ }
+ else
+ /* white space */
+ optarg = nargv[optind];
+ place = EMSG;
+ ++optind;
+ }
+ return optopt; /* dump back option letter */
+}
diff --git a/contrib/libs/postgresql/src/port/getpeereid.c b/contrib/libs/postgresql/src/port/getpeereid.c
new file mode 100644
index 0000000000..d6aa755d30
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/getpeereid.c
@@ -0,0 +1,80 @@
+/*-------------------------------------------------------------------------
+ *
+ * getpeereid.c
+ * get peer userid for UNIX-domain socket connection
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ *
+ *
+ * IDENTIFICATION
+ * src/port/getpeereid.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "c.h"
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#ifdef HAVE_SYS_UN_H
+#include <sys/un.h>
+#endif
+#ifdef HAVE_UCRED_H
+#include <ucred.h>
+#endif
+#ifdef HAVE_SYS_UCRED_H
+#include <sys/ucred.h>
+#endif
+
+
+/*
+ * BSD-style getpeereid() for platforms that lack it.
+ */
+int
+getpeereid(int sock, uid_t *uid, gid_t *gid)
+{
+#if defined(SO_PEERCRED)
+ /* Linux: use getsockopt(SO_PEERCRED) */
+ struct ucred peercred;
+ ACCEPT_TYPE_ARG3 so_len = sizeof(peercred);
+
+ if (getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) != 0 ||
+ so_len != sizeof(peercred))
+ return -1;
+ *uid = peercred.uid;
+ *gid = peercred.gid;
+ return 0;
+#elif defined(LOCAL_PEERCRED)
+ /* Debian with FreeBSD kernel: use getsockopt(LOCAL_PEERCRED) */
+ struct xucred peercred;
+ ACCEPT_TYPE_ARG3 so_len = sizeof(peercred);
+
+ if (getsockopt(sock, 0, LOCAL_PEERCRED, &peercred, &so_len) != 0 ||
+ so_len != sizeof(peercred) ||
+ peercred.cr_version != XUCRED_VERSION)
+ return -1;
+ *uid = peercred.cr_uid;
+ *gid = peercred.cr_gid;
+ return 0;
+#elif defined(HAVE_GETPEERUCRED)
+ /* Solaris: use getpeerucred() */
+ ucred_t *ucred;
+
+ ucred = NULL; /* must be initialized to NULL */
+ if (getpeerucred(sock, &ucred) == -1)
+ return -1;
+
+ *uid = ucred_geteuid(ucred);
+ *gid = ucred_getegid(ucred);
+ ucred_free(ucred);
+
+ if (*uid == (uid_t) (-1) || *gid == (gid_t) (-1))
+ return -1;
+ return 0;
+#else
+ /* No implementation available on this platform */
+ errno = ENOSYS;
+ return -1;
+#endif
+}
diff --git a/contrib/libs/postgresql/src/port/getrusage.c b/contrib/libs/postgresql/src/port/getrusage.c
new file mode 100644
index 0000000000..99f240f6da
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/getrusage.c
@@ -0,0 +1,110 @@
+/*-------------------------------------------------------------------------
+ *
+ * getrusage.c
+ * get information about resource utilisation
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/port/getrusage.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "c.h"
+
+#include "rusagestub.h"
+
+/* This code works on:
+ * solaris_i386
+ * solaris_sparc
+ * hpux 9.*
+ * win32
+ * which currently is all the supported platforms that don't have a
+ * native version of getrusage(). So, if configure decides to compile
+ * this file at all, we just use this version unconditionally.
+ */
+
+int
+getrusage(int who, struct rusage *rusage)
+{
+#ifdef WIN32
+ FILETIME starttime;
+ FILETIME exittime;
+ FILETIME kerneltime;
+ FILETIME usertime;
+ ULARGE_INTEGER li;
+
+ if (who != RUSAGE_SELF)
+ {
+ /* Only RUSAGE_SELF is supported in this implementation for now */
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (rusage == (struct rusage *) NULL)
+ {
+ errno = EFAULT;
+ return -1;
+ }
+ memset(rusage, 0, sizeof(struct rusage));
+ if (GetProcessTimes(GetCurrentProcess(),
+ &starttime, &exittime, &kerneltime, &usertime) == 0)
+ {
+ _dosmaperr(GetLastError());
+ return -1;
+ }
+
+ /* Convert FILETIMEs (0.1 us) to struct timeval */
+ memcpy(&li, &kerneltime, sizeof(FILETIME));
+ li.QuadPart /= 10L; /* Convert to microseconds */
+ rusage->ru_stime.tv_sec = li.QuadPart / 1000000L;
+ rusage->ru_stime.tv_usec = li.QuadPart % 1000000L;
+
+ memcpy(&li, &usertime, sizeof(FILETIME));
+ li.QuadPart /= 10L; /* Convert to microseconds */
+ rusage->ru_utime.tv_sec = li.QuadPart / 1000000L;
+ rusage->ru_utime.tv_usec = li.QuadPart % 1000000L;
+#else /* all but WIN32 */
+
+ struct tms tms;
+ int tick_rate = CLK_TCK; /* ticks per second */
+ clock_t u,
+ s;
+
+ if (rusage == (struct rusage *) NULL)
+ {
+ errno = EFAULT;
+ return -1;
+ }
+ if (times(&tms) < 0)
+ {
+ /* errno set by times */
+ return -1;
+ }
+ switch (who)
+ {
+ case RUSAGE_SELF:
+ u = tms.tms_utime;
+ s = tms.tms_stime;
+ break;
+ case RUSAGE_CHILDREN:
+ u = tms.tms_cutime;
+ s = tms.tms_cstime;
+ break;
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+#define TICK_TO_SEC(T, RATE) ((T)/(RATE))
+#define TICK_TO_USEC(T,RATE) (((T)%(RATE)*1000000)/RATE)
+ rusage->ru_utime.tv_sec = TICK_TO_SEC(u, tick_rate);
+ rusage->ru_utime.tv_usec = TICK_TO_USEC(u, tick_rate);
+ rusage->ru_stime.tv_sec = TICK_TO_SEC(s, tick_rate);
+ rusage->ru_stime.tv_usec = TICK_TO_USEC(u, tick_rate);
+#endif /* WIN32 */
+
+ return 0;
+}
diff --git a/contrib/libs/postgresql/src/port/gettimeofday.c b/contrib/libs/postgresql/src/port/gettimeofday.c
new file mode 100644
index 0000000000..ee8fe82337
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/gettimeofday.c
@@ -0,0 +1,118 @@
+/*
+ * gettimeofday.c
+ * Win32 gettimeofday() replacement
+ *
+ * src/port/gettimeofday.c
+ *
+ * Copyright (c) 2003 SRA, Inc.
+ * Copyright (c) 2003 SKC, Inc.
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose, without fee, and without a
+ * written agreement is hereby granted, provided that the above
+ * copyright notice and this paragraph and the following two
+ * paragraphs appear in all copies.
+ *
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT,
+ * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
+ * LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
+ * DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS
+ * IS" BASIS, AND THE AUTHOR HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE,
+ * SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#include "c.h"
+
+#include <sys/time.h>
+
+/* FILETIME of Jan 1 1970 00:00:00, the PostgreSQL epoch */
+static const unsigned __int64 epoch = UINT64CONST(116444736000000000);
+
+/*
+ * FILETIME represents the number of 100-nanosecond intervals since
+ * January 1, 1601 (UTC).
+ */
+#define FILETIME_UNITS_PER_SEC 10000000L
+#define FILETIME_UNITS_PER_USEC 10
+
+/*
+ * Both GetSystemTimeAsFileTime and GetSystemTimePreciseAsFileTime share a
+ * signature, so we can just store a pointer to whichever we find. This
+ * is the pointer's type.
+ */
+typedef VOID(WINAPI * PgGetSystemTimeFn) (LPFILETIME);
+
+/* One-time initializer function, must match that signature. */
+static void WINAPI init_gettimeofday(LPFILETIME lpSystemTimeAsFileTime);
+
+/* Storage for the function we pick at runtime */
+static PgGetSystemTimeFn pg_get_system_time = &init_gettimeofday;
+
+/*
+ * One time initializer. Determine whether GetSystemTimePreciseAsFileTime
+ * is available and if so, plan to use it; if not, fall back to
+ * GetSystemTimeAsFileTime.
+ */
+static void WINAPI
+init_gettimeofday(LPFILETIME lpSystemTimeAsFileTime)
+{
+ /*
+ * Because it's guaranteed that kernel32.dll will be linked into our
+ * address space already, we don't need to LoadLibrary it and worry about
+ * closing it afterwards, so we're not using Pg's dlopen/dlsym() wrapper.
+ *
+ * We'll just look up the address of GetSystemTimePreciseAsFileTime if
+ * present.
+ *
+ * While we could look up the Windows version and skip this on Windows
+ * versions below Windows 8 / Windows Server 2012 there isn't much point,
+ * and determining the windows version is its self somewhat Windows
+ * version and development SDK specific...
+ */
+ pg_get_system_time = (PgGetSystemTimeFn) GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")),
+ "GetSystemTimePreciseAsFileTime");
+ if (pg_get_system_time == NULL)
+ {
+ /*
+ * The expected error from GetLastError() is ERROR_PROC_NOT_FOUND, if
+ * the function isn't present. No other error should occur.
+ *
+ * We can't report an error here because this might be running in
+ * frontend code; and even if we're in the backend, it's too early to
+ * elog(...) if we get some unexpected error. Also, it's not a
+ * serious problem, so just silently fall back to
+ * GetSystemTimeAsFileTime irrespective of why the failure occurred.
+ */
+ pg_get_system_time = &GetSystemTimeAsFileTime;
+ }
+
+ (*pg_get_system_time) (lpSystemTimeAsFileTime);
+}
+
+/*
+ * timezone information is stored outside the kernel so tzp isn't used anymore.
+ *
+ * Note: this function is not for Win32 high precision timing purposes. See
+ * elapsed_time().
+ */
+int
+gettimeofday(struct timeval *tp, struct timezone *tzp)
+{
+ FILETIME file_time;
+ ULARGE_INTEGER ularge;
+
+ (*pg_get_system_time) (&file_time);
+ ularge.LowPart = file_time.dwLowDateTime;
+ ularge.HighPart = file_time.dwHighDateTime;
+
+ tp->tv_sec = (long) ((ularge.QuadPart - epoch) / FILETIME_UNITS_PER_SEC);
+ tp->tv_usec = (long) (((ularge.QuadPart - epoch) % FILETIME_UNITS_PER_SEC)
+ / FILETIME_UNITS_PER_USEC);
+
+ return 0;
+}
diff --git a/contrib/libs/postgresql/src/port/inet_aton.c b/contrib/libs/postgresql/src/port/inet_aton.c
new file mode 100644
index 0000000000..adaf18adb3
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/inet_aton.c
@@ -0,0 +1,149 @@
+/* src/port/inet_aton.c
+ *
+ * This inet_aton() function was taken from the GNU C library and
+ * incorporated into Postgres for those systems which do not have this
+ * routine in their standard C libraries.
+ *
+ * The function was been extracted whole from the file inet_aton.c in
+ * Release 5.3.12 of the Linux C library, which is derived from the
+ * GNU C library, by Bryan Henderson in October 1996. The copyright
+ * notice from that file is below.
+ */
+
+/*
+ * Copyright (c) 1983, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE. */
+
+#include "c.h"
+
+#include <netinet/in.h>
+#include <ctype.h>
+
+#include "port/pg_bswap.h"
+
+/*
+ * Check whether "cp" is a valid ascii representation
+ * of an Internet address and convert to a binary address.
+ * Returns 1 if the address is valid, 0 if not.
+ * This replaces inet_addr, the return value from which
+ * cannot distinguish between failure and a local broadcast address.
+ */
+int
+inet_aton(const char *cp, struct in_addr *addr)
+{
+ unsigned int val;
+ int base,
+ n;
+ char c;
+ u_int parts[4];
+ u_int *pp = parts;
+
+ for (;;)
+ {
+ /*
+ * Collect number up to ``.''. Values are specified as for C: 0x=hex,
+ * 0=octal, other=decimal.
+ */
+ val = 0;
+ base = 10;
+ if (*cp == '0')
+ {
+ if (*++cp == 'x' || *cp == 'X')
+ base = 16, cp++;
+ else
+ base = 8;
+ }
+ while ((c = *cp) != '\0')
+ {
+ if (isdigit((unsigned char) c))
+ {
+ val = (val * base) + (c - '0');
+ cp++;
+ continue;
+ }
+ if (base == 16 && isxdigit((unsigned char) c))
+ {
+ val = (val << 4) +
+ (c + 10 - (islower((unsigned char) c) ? 'a' : 'A'));
+ cp++;
+ continue;
+ }
+ break;
+ }
+ if (*cp == '.')
+ {
+ /*
+ * Internet format: a.b.c.d a.b.c (with c treated as 16-bits)
+ * a.b (with b treated as 24 bits)
+ */
+ if (pp >= parts + 3 || val > 0xff)
+ return 0;
+ *pp++ = val, cp++;
+ }
+ else
+ break;
+ }
+
+ /*
+ * Check for trailing junk.
+ */
+ while (*cp)
+ if (!isspace((unsigned char) *cp++))
+ return 0;
+
+ /*
+ * Concoct the address according to the number of parts specified.
+ */
+ n = pp - parts + 1;
+ switch (n)
+ {
+
+ case 1: /* a -- 32 bits */
+ break;
+
+ case 2: /* a.b -- 8.24 bits */
+ if (val > 0xffffff)
+ return 0;
+ val |= parts[0] << 24;
+ break;
+
+ case 3: /* a.b.c -- 8.8.16 bits */
+ if (val > 0xffff)
+ return 0;
+ val |= (parts[0] << 24) | (parts[1] << 16);
+ break;
+
+ case 4: /* a.b.c.d -- 8.8.8.8 bits */
+ if (val > 0xff)
+ return 0;
+ val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
+ break;
+ }
+ if (addr)
+ addr->s_addr = pg_hton32(val);
+ return 1;
+}
diff --git a/contrib/libs/postgresql/src/port/inet_net_ntop.c b/contrib/libs/postgresql/src/port/inet_net_ntop.c
new file mode 100644
index 0000000000..b8ad69c390
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/inet_net_ntop.c
@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * src/port/inet_net_ntop.c
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "Id: inet_net_ntop.c,v 1.1.2.2 2004/03/09 09:17:27 marka Exp $";
+#endif
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#ifndef FRONTEND
+#include "utils/inet.h"
+#else
+/*
+ * In a frontend build, we can't include inet.h, but we still need to have
+ * sensible definitions of these two constants. Note that pg_inet_net_ntop()
+ * assumes that PGSQL_AF_INET is equal to AF_INET.
+ */
+#define PGSQL_AF_INET (AF_INET + 0)
+#define PGSQL_AF_INET6 (AF_INET + 1)
+#endif
+
+
+#define NS_IN6ADDRSZ 16
+#define NS_INT16SZ 2
+
+#ifdef SPRINTF_CHAR
+#define SPRINTF(x) strlen(sprintf/**/x)
+#else
+#define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+static char *inet_net_ntop_ipv4(const u_char *src, int bits,
+ char *dst, size_t size);
+static char *inet_net_ntop_ipv6(const u_char *src, int bits,
+ char *dst, size_t size);
+
+
+/*
+ * char *
+ * pg_inet_net_ntop(af, src, bits, dst, size)
+ * convert host/network address from network to presentation format.
+ * "src"'s size is determined from its "af".
+ * return:
+ * pointer to dst, or NULL if an error occurred (check errno).
+ * note:
+ * 192.5.5.1/28 has a nonzero host part, which means it isn't a network
+ * as called for by pg_inet_net_pton() but it can be a host address with
+ * an included netmask.
+ * author:
+ * Paul Vixie (ISC), October 1998
+ */
+char *
+pg_inet_net_ntop(int af, const void *src, int bits, char *dst, size_t size)
+{
+ /*
+ * We need to cover both the address family constants used by the PG inet
+ * type (PGSQL_AF_INET and PGSQL_AF_INET6) and those used by the system
+ * libraries (AF_INET and AF_INET6). We can safely assume PGSQL_AF_INET
+ * == AF_INET, but the INET6 constants are very likely to be different. If
+ * AF_INET6 isn't defined, silently ignore it.
+ */
+ switch (af)
+ {
+ case PGSQL_AF_INET:
+ return (inet_net_ntop_ipv4(src, bits, dst, size));
+ case PGSQL_AF_INET6:
+#if defined(AF_INET6) && AF_INET6 != PGSQL_AF_INET6
+ case AF_INET6:
+#endif
+ return (inet_net_ntop_ipv6(src, bits, dst, size));
+ default:
+ errno = EAFNOSUPPORT;
+ return (NULL);
+ }
+}
+
+/*
+ * static char *
+ * inet_net_ntop_ipv4(src, bits, dst, size)
+ * convert IPv4 network address from network to presentation format.
+ * "src"'s size is determined from its "af".
+ * return:
+ * pointer to dst, or NULL if an error occurred (check errno).
+ * note:
+ * network byte order assumed. this means 192.5.5.240/28 has
+ * 0b11110000 in its fourth octet.
+ * author:
+ * Paul Vixie (ISC), October 1998
+ */
+static char *
+inet_net_ntop_ipv4(const u_char *src, int bits, char *dst, size_t size)
+{
+ char *odst = dst;
+ char *t;
+ int len = 4;
+ int b;
+
+ if (bits < 0 || bits > 32)
+ {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ /* Always format all four octets, regardless of mask length. */
+ for (b = len; b > 0; b--)
+ {
+ if (size <= sizeof ".255")
+ goto emsgsize;
+ t = dst;
+ if (dst != odst)
+ *dst++ = '.';
+ dst += SPRINTF((dst, "%u", *src++));
+ size -= (size_t) (dst - t);
+ }
+
+ /* don't print masklen if 32 bits */
+ if (bits != 32)
+ {
+ if (size <= sizeof "/32")
+ goto emsgsize;
+ dst += SPRINTF((dst, "/%u", bits));
+ }
+
+ return (odst);
+
+emsgsize:
+ errno = EMSGSIZE;
+ return (NULL);
+}
+
+static int
+decoct(const u_char *src, int bytes, char *dst, size_t size)
+{
+ char *odst = dst;
+ char *t;
+ int b;
+
+ for (b = 1; b <= bytes; b++)
+ {
+ if (size <= sizeof "255.")
+ return (0);
+ t = dst;
+ dst += SPRINTF((dst, "%u", *src++));
+ if (b != bytes)
+ {
+ *dst++ = '.';
+ *dst = '\0';
+ }
+ size -= (size_t) (dst - t);
+ }
+ return (dst - odst);
+}
+
+static char *
+inet_net_ntop_ipv6(const u_char *src, int bits, char *dst, size_t size)
+{
+ /*
+ * Note that int32_t and int16_t need only be "at least" large enough to
+ * contain a value of the specified size. On some systems, like Crays,
+ * there is no such thing as an integer variable with 16 bits. Keep this
+ * in mind if you think this function should have been coded to use
+ * pointer overlays. All the world's not a VAX.
+ */
+ char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255/128"];
+ char *tp;
+ struct
+ {
+ int base,
+ len;
+ } best, cur;
+ u_int words[NS_IN6ADDRSZ / NS_INT16SZ];
+ int i;
+
+ if ((bits < -1) || (bits > 128))
+ {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ /*
+ * Preprocess: Copy the input (bytewise) array into a wordwise array. Find
+ * the longest run of 0x00's in src[] for :: shorthanding.
+ */
+ memset(words, '\0', sizeof words);
+ for (i = 0; i < NS_IN6ADDRSZ; i++)
+ words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
+ best.base = -1;
+ cur.base = -1;
+ best.len = 0;
+ cur.len = 0;
+ for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++)
+ {
+ if (words[i] == 0)
+ {
+ if (cur.base == -1)
+ cur.base = i, cur.len = 1;
+ else
+ cur.len++;
+ }
+ else
+ {
+ if (cur.base != -1)
+ {
+ if (best.base == -1 || cur.len > best.len)
+ best = cur;
+ cur.base = -1;
+ }
+ }
+ }
+ if (cur.base != -1)
+ {
+ if (best.base == -1 || cur.len > best.len)
+ best = cur;
+ }
+ if (best.base != -1 && best.len < 2)
+ best.base = -1;
+
+ /*
+ * Format the result.
+ */
+ tp = tmp;
+ for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++)
+ {
+ /* Are we inside the best run of 0x00's? */
+ if (best.base != -1 && i >= best.base &&
+ i < (best.base + best.len))
+ {
+ if (i == best.base)
+ *tp++ = ':';
+ continue;
+ }
+ /* Are we following an initial run of 0x00s or any real hex? */
+ if (i != 0)
+ *tp++ = ':';
+ /* Is this address an encapsulated IPv4? */
+ if (i == 6 && best.base == 0 && (best.len == 6 ||
+ (best.len == 7 && words[7] != 0x0001) ||
+ (best.len == 5 && words[5] == 0xffff)))
+ {
+ int n;
+
+ n = decoct(src + 12, 4, tp, sizeof tmp - (tp - tmp));
+ if (n == 0)
+ {
+ errno = EMSGSIZE;
+ return (NULL);
+ }
+ tp += strlen(tp);
+ break;
+ }
+ tp += SPRINTF((tp, "%x", words[i]));
+ }
+
+ /* Was it a trailing run of 0x00's? */
+ if (best.base != -1 && (best.base + best.len) ==
+ (NS_IN6ADDRSZ / NS_INT16SZ))
+ *tp++ = ':';
+ *tp = '\0';
+
+ if (bits != -1 && bits != 128)
+ tp += SPRINTF((tp, "/%u", bits));
+
+ /*
+ * Check for overflow, copy, and we're done.
+ */
+ if ((size_t) (tp - tmp) > size)
+ {
+ errno = EMSGSIZE;
+ return (NULL);
+ }
+ strcpy(dst, tmp);
+ return (dst);
+}
diff --git a/contrib/libs/postgresql/src/port/kill.c b/contrib/libs/postgresql/src/port/kill.c
new file mode 100644
index 0000000000..99b35de45b
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/kill.c
@@ -0,0 +1,97 @@
+/*-------------------------------------------------------------------------
+ *
+ * kill.c
+ * kill()
+ *
+ * Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ *
+ * This is a replacement version of kill for Win32 which sends
+ * signals that the backend can recognize.
+ *
+ * IDENTIFICATION
+ * src/port/kill.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "c.h"
+
+#ifdef WIN32
+/* signal sending */
+int
+pgkill(int pid, int sig)
+{
+ char pipename[128];
+ BYTE sigData = sig;
+ BYTE sigRet = 0;
+ DWORD bytes;
+
+ /* we allow signal 0 here, but it will be ignored in pg_queue_signal */
+ if (sig >= PG_SIGNAL_COUNT || sig < 0)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ if (pid <= 0)
+ {
+ /* No support for process groups */
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* special case for SIGKILL: just ask the system to terminate the target */
+ if (sig == SIGKILL)
+ {
+ HANDLE prochandle;
+
+ if ((prochandle = OpenProcess(PROCESS_TERMINATE, FALSE, (DWORD) pid)) == NULL)
+ {
+ errno = ESRCH;
+ return -1;
+ }
+ if (!TerminateProcess(prochandle, 255))
+ {
+ _dosmaperr(GetLastError());
+ CloseHandle(prochandle);
+ return -1;
+ }
+ CloseHandle(prochandle);
+ return 0;
+ }
+ snprintf(pipename, sizeof(pipename), "\\\\.\\pipe\\pgsignal_%u", pid);
+
+ if (CallNamedPipe(pipename, &sigData, 1, &sigRet, 1, &bytes, 1000))
+ {
+ if (bytes != 1 || sigRet != sig)
+ {
+ errno = ESRCH;
+ return -1;
+ }
+ return 0;
+ }
+
+ switch (GetLastError())
+ {
+ case ERROR_BROKEN_PIPE:
+ case ERROR_BAD_PIPE:
+
+ /*
+ * These arise transiently as a process is exiting. Treat them
+ * like POSIX treats a zombie process, reporting success.
+ */
+ return 0;
+
+ case ERROR_FILE_NOT_FOUND:
+ /* pipe fully gone, so treat the process as gone */
+ errno = ESRCH;
+ return -1;
+ case ERROR_ACCESS_DENIED:
+ errno = EPERM;
+ return -1;
+ default:
+ errno = EINVAL; /* unexpected */
+ return -1;
+ }
+}
+
+#endif
diff --git a/contrib/libs/postgresql/src/port/noblock.c b/contrib/libs/postgresql/src/port/noblock.c
new file mode 100644
index 0000000000..b43222c338
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/noblock.c
@@ -0,0 +1,66 @@
+/*-------------------------------------------------------------------------
+ *
+ * noblock.c
+ * set a file descriptor as blocking or non-blocking
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/port/noblock.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "c.h"
+
+#include <fcntl.h>
+
+
+/*
+ * Put socket into nonblock mode.
+ * Returns true on success, false on failure.
+ */
+bool
+pg_set_noblock(pgsocket sock)
+{
+#if !defined(WIN32)
+ int flags;
+
+ flags = fcntl(sock, F_GETFL);
+ if (flags < 0)
+ return false;
+ if (fcntl(sock, F_SETFL, (flags | O_NONBLOCK)) == -1)
+ return false;
+ return true;
+#else
+ unsigned long ioctlsocket_ret = 1;
+
+ /* Returns non-0 on failure, while fcntl() returns -1 on failure */
+ return (ioctlsocket(sock, FIONBIO, &ioctlsocket_ret) == 0);
+#endif
+}
+
+/*
+ * Put socket into blocking mode.
+ * Returns true on success, false on failure.
+ */
+bool
+pg_set_block(pgsocket sock)
+{
+#if !defined(WIN32)
+ int flags;
+
+ flags = fcntl(sock, F_GETFL);
+ if (flags < 0)
+ return false;
+ if (fcntl(sock, F_SETFL, (flags & ~O_NONBLOCK)) == -1)
+ return false;
+ return true;
+#else
+ unsigned long ioctlsocket_ret = 0;
+
+ /* Returns non-0 on failure, while fcntl() returns -1 on failure */
+ return (ioctlsocket(sock, FIONBIO, &ioctlsocket_ret) == 0);
+#endif
+}
diff --git a/contrib/libs/postgresql/src/port/open.c b/contrib/libs/postgresql/src/port/open.c
new file mode 100644
index 0000000000..14c6debba9
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/open.c
@@ -0,0 +1,216 @@
+/*-------------------------------------------------------------------------
+ *
+ * open.c
+ * Win32 open() replacement
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ *
+ * src/port/open.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifdef WIN32
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include <fcntl.h>
+#include <assert.h>
+#include <sys/stat.h>
+
+
+static int
+openFlagsToCreateFileFlags(int openFlags)
+{
+ switch (openFlags & (O_CREAT | O_TRUNC | O_EXCL))
+ {
+ /* O_EXCL is meaningless without O_CREAT */
+ case 0:
+ case O_EXCL:
+ return OPEN_EXISTING;
+
+ case O_CREAT:
+ return OPEN_ALWAYS;
+
+ /* O_EXCL is meaningless without O_CREAT */
+ case O_TRUNC:
+ case O_TRUNC | O_EXCL:
+ return TRUNCATE_EXISTING;
+
+ case O_CREAT | O_TRUNC:
+ return CREATE_ALWAYS;
+
+ /* O_TRUNC is meaningless with O_CREAT */
+ case O_CREAT | O_EXCL:
+ case O_CREAT | O_TRUNC | O_EXCL:
+ return CREATE_NEW;
+ }
+
+ /* will never get here */
+ return 0;
+}
+
+/*
+ * - file attribute setting, based on fileMode?
+ */
+int
+pgwin32_open(const char *fileName, int fileFlags,...)
+{
+ int fd;
+ HANDLE h = INVALID_HANDLE_VALUE;
+ SECURITY_ATTRIBUTES sa;
+ int loops = 0;
+
+ /* Check that we can handle the request */
+ assert((fileFlags & ((O_RDONLY | O_WRONLY | O_RDWR) | O_APPEND |
+ (O_RANDOM | O_SEQUENTIAL | O_TEMPORARY) |
+ _O_SHORT_LIVED | O_DSYNC | O_DIRECT |
+ (O_CREAT | O_TRUNC | O_EXCL) | (O_TEXT | O_BINARY))) == fileFlags);
+#ifndef FRONTEND
+ Assert(pgwin32_signal_event != NULL); /* small chance of pg_usleep() */
+#endif
+
+#ifdef FRONTEND
+
+ /*
+ * Since PostgreSQL 12, those concurrent-safe versions of open() and
+ * fopen() can be used by frontends, having as side-effect to switch the
+ * file-translation mode from O_TEXT to O_BINARY if none is specified.
+ * Caller may want to enforce the binary or text mode, but if nothing is
+ * defined make sure that the default mode maps with what versions older
+ * than 12 have been doing.
+ */
+ if ((fileFlags & O_BINARY) == 0)
+ fileFlags |= O_TEXT;
+#endif
+
+ sa.nLength = sizeof(sa);
+ sa.bInheritHandle = TRUE;
+ sa.lpSecurityDescriptor = NULL;
+
+ while ((h = CreateFile(fileName,
+ /* cannot use O_RDONLY, as it == 0 */
+ (fileFlags & O_RDWR) ? (GENERIC_WRITE | GENERIC_READ) :
+ ((fileFlags & O_WRONLY) ? GENERIC_WRITE : GENERIC_READ),
+ /* These flags allow concurrent rename/unlink */
+ (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE),
+ &sa,
+ openFlagsToCreateFileFlags(fileFlags),
+ FILE_ATTRIBUTE_NORMAL |
+ ((fileFlags & O_RANDOM) ? FILE_FLAG_RANDOM_ACCESS : 0) |
+ ((fileFlags & O_SEQUENTIAL) ? FILE_FLAG_SEQUENTIAL_SCAN : 0) |
+ ((fileFlags & _O_SHORT_LIVED) ? FILE_ATTRIBUTE_TEMPORARY : 0) |
+ ((fileFlags & O_TEMPORARY) ? FILE_FLAG_DELETE_ON_CLOSE : 0) |
+ ((fileFlags & O_DIRECT) ? FILE_FLAG_NO_BUFFERING : 0) |
+ ((fileFlags & O_DSYNC) ? FILE_FLAG_WRITE_THROUGH : 0),
+ NULL)) == INVALID_HANDLE_VALUE)
+ {
+ /*
+ * Sharing violation or locking error can indicate antivirus, backup
+ * or similar software that's locking the file. Wait a bit and try
+ * again, giving up after 30 seconds.
+ */
+ DWORD err = GetLastError();
+
+ if (err == ERROR_SHARING_VIOLATION ||
+ err == ERROR_LOCK_VIOLATION)
+ {
+#ifndef FRONTEND
+ if (loops == 50)
+ ereport(LOG,
+ (errmsg("could not open file \"%s\": %s", fileName,
+ (err == ERROR_SHARING_VIOLATION) ? _("sharing violation") : _("lock violation")),
+ errdetail("Continuing to retry for 30 seconds."),
+ errhint("You might have antivirus, backup, or similar software interfering with the database system.")));
+#endif
+
+ if (loops < 300)
+ {
+ pg_usleep(100000);
+ loops++;
+ continue;
+ }
+ }
+
+ /*
+ * ERROR_ACCESS_DENIED is returned if the file is deleted but not yet
+ * gone (Windows NT status code is STATUS_DELETE_PENDING). In that
+ * case we want to wait a bit and try again, giving up after 1 second
+ * (since this condition should never persist very long). However,
+ * there are other commonly-hit cases that return ERROR_ACCESS_DENIED,
+ * so care is needed. In particular that happens if we try to open a
+ * directory, or of course if there's an actual file-permissions
+ * problem. To distinguish these cases, try a stat(). In the
+ * delete-pending case, it will either also get STATUS_DELETE_PENDING,
+ * or it will see the file as gone and fail with ENOENT. In other
+ * cases it will usually succeed. The only somewhat-likely case where
+ * this coding will uselessly wait is if there's a permissions problem
+ * with a containing directory, which we hope will never happen in any
+ * performance-critical code paths.
+ */
+ if (err == ERROR_ACCESS_DENIED)
+ {
+ if (loops < 10)
+ {
+ struct stat st;
+
+ if (stat(fileName, &st) != 0)
+ {
+ pg_usleep(100000);
+ loops++;
+ continue;
+ }
+ }
+ }
+
+ _dosmaperr(err);
+ return -1;
+ }
+
+ /* _open_osfhandle will, on error, set errno accordingly */
+ if ((fd = _open_osfhandle((intptr_t) h, fileFlags & O_APPEND)) < 0)
+ CloseHandle(h); /* will not affect errno */
+ else if (fileFlags & (O_TEXT | O_BINARY) &&
+ _setmode(fd, fileFlags & (O_TEXT | O_BINARY)) < 0)
+ {
+ _close(fd);
+ return -1;
+ }
+
+ return fd;
+}
+
+FILE *
+pgwin32_fopen(const char *fileName, const char *mode)
+{
+ int openmode = 0;
+ int fd;
+
+ if (strstr(mode, "r+"))
+ openmode |= O_RDWR;
+ else if (strchr(mode, 'r'))
+ openmode |= O_RDONLY;
+ if (strstr(mode, "w+"))
+ openmode |= O_RDWR | O_CREAT | O_TRUNC;
+ else if (strchr(mode, 'w'))
+ openmode |= O_WRONLY | O_CREAT | O_TRUNC;
+ if (strchr(mode, 'a'))
+ openmode |= O_WRONLY | O_CREAT | O_APPEND;
+
+ if (strchr(mode, 'b'))
+ openmode |= O_BINARY;
+ if (strchr(mode, 't'))
+ openmode |= O_TEXT;
+
+ fd = pgwin32_open(fileName, openmode);
+ if (fd == -1)
+ return NULL;
+ return _fdopen(fd, mode);
+}
+
+#endif
diff --git a/contrib/libs/postgresql/src/port/path.c b/contrib/libs/postgresql/src/port/path.c
new file mode 100644
index 0000000000..a695cc4e2f
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/path.c
@@ -0,0 +1,916 @@
+/*-------------------------------------------------------------------------
+ *
+ * path.c
+ * portable path handling routines
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/port/path.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include <ctype.h>
+#include <sys/stat.h>
+#ifdef WIN32
+#ifdef _WIN32_IE
+#undef _WIN32_IE
+#endif
+#define _WIN32_IE 0x0500
+#ifdef near
+#undef near
+#endif
+#define near
+#include <shlobj.h>
+#else
+#include <unistd.h>
+#endif
+
+#include "pg_config_paths.h"
+
+
+#ifndef WIN32
+#define IS_PATH_VAR_SEP(ch) ((ch) == ':')
+#else
+#define IS_PATH_VAR_SEP(ch) ((ch) == ';')
+#endif
+
+static void make_relative_path(char *ret_path, const char *target_path,
+ const char *bin_path, const char *my_exec_path);
+static void trim_directory(char *path);
+static void trim_trailing_separator(char *path);
+
+
+/*
+ * skip_drive
+ *
+ * On Windows, a path may begin with "C:" or "//network/". Advance over
+ * this and point to the effective start of the path.
+ */
+#ifdef WIN32
+
+static char *
+skip_drive(const char *path)
+{
+ if (IS_DIR_SEP(path[0]) && IS_DIR_SEP(path[1]))
+ {
+ path += 2;
+ while (*path && !IS_DIR_SEP(*path))
+ path++;
+ }
+ else if (isalpha((unsigned char) path[0]) && path[1] == ':')
+ {
+ path += 2;
+ }
+ return (char *) path;
+}
+#else
+
+#define skip_drive(path) (path)
+#endif
+
+/*
+ * has_drive_prefix
+ *
+ * Return true if the given pathname has a drive prefix.
+ */
+bool
+has_drive_prefix(const char *path)
+{
+#ifdef WIN32
+ return skip_drive(path) != path;
+#else
+ return false;
+#endif
+}
+
+/*
+ * first_dir_separator
+ *
+ * Find the location of the first directory separator, return
+ * NULL if not found.
+ */
+char *
+first_dir_separator(const char *filename)
+{
+ const char *p;
+
+ for (p = skip_drive(filename); *p; p++)
+ if (IS_DIR_SEP(*p))
+ return unconstify(char *, p);
+ return NULL;
+}
+
+/*
+ * first_path_var_separator
+ *
+ * Find the location of the first path separator (i.e. ':' on
+ * Unix, ';' on Windows), return NULL if not found.
+ */
+char *
+first_path_var_separator(const char *pathlist)
+{
+ const char *p;
+
+ /* skip_drive is not needed */
+ for (p = pathlist; *p; p++)
+ if (IS_PATH_VAR_SEP(*p))
+ return unconstify(char *, p);
+ return NULL;
+}
+
+/*
+ * last_dir_separator
+ *
+ * Find the location of the last directory separator, return
+ * NULL if not found.
+ */
+char *
+last_dir_separator(const char *filename)
+{
+ const char *p,
+ *ret = NULL;
+
+ for (p = skip_drive(filename); *p; p++)
+ if (IS_DIR_SEP(*p))
+ ret = p;
+ return unconstify(char *, ret);
+}
+
+
+/*
+ * make_native_path - on WIN32, change / to \ in the path
+ *
+ * This effectively undoes canonicalize_path.
+ *
+ * This is required because WIN32 COPY is an internal CMD.EXE
+ * command and doesn't process forward slashes in the same way
+ * as external commands. Quoting the first argument to COPY
+ * does not convert forward to backward slashes, but COPY does
+ * properly process quoted forward slashes in the second argument.
+ *
+ * COPY works with quoted forward slashes in the first argument
+ * only if the current directory is the same as the directory
+ * of the first argument.
+ */
+void
+make_native_path(char *filename)
+{
+#ifdef WIN32
+ char *p;
+
+ for (p = filename; *p; p++)
+ if (*p == '/')
+ *p = '\\';
+#endif
+}
+
+
+/*
+ * This function cleans up the paths for use with either cmd.exe or Msys
+ * on Windows. We need them to use filenames without spaces, for which a
+ * short filename is the safest equivalent, eg:
+ * C:/Progra~1/
+ */
+void
+cleanup_path(char *path)
+{
+#ifdef WIN32
+ char *ptr;
+
+ /*
+ * GetShortPathName() will fail if the path does not exist, or short names
+ * are disabled on this file system. In both cases, we just return the
+ * original path. This is particularly useful for --sysconfdir, which
+ * might not exist.
+ */
+ GetShortPathName(path, path, MAXPGPATH - 1);
+
+ /* Replace '\' with '/' */
+ for (ptr = path; *ptr; ptr++)
+ {
+ if (*ptr == '\\')
+ *ptr = '/';
+ }
+#endif
+}
+
+
+/*
+ * join_path_components - join two path components, inserting a slash
+ *
+ * We omit the slash if either given component is empty.
+ *
+ * ret_path is the output area (must be of size MAXPGPATH)
+ *
+ * ret_path can be the same as head, but not the same as tail.
+ */
+void
+join_path_components(char *ret_path,
+ const char *head, const char *tail)
+{
+ if (ret_path != head)
+ strlcpy(ret_path, head, MAXPGPATH);
+
+ /*
+ * Remove any leading "." in the tail component.
+ *
+ * Note: we used to try to remove ".." as well, but that's tricky to get
+ * right; now we just leave it to be done by canonicalize_path() later.
+ */
+ while (tail[0] == '.' && IS_DIR_SEP(tail[1]))
+ tail += 2;
+
+ if (*tail)
+ {
+ /* only separate with slash if head wasn't empty */
+ snprintf(ret_path + strlen(ret_path), MAXPGPATH - strlen(ret_path),
+ "%s%s",
+ (*(skip_drive(head)) != '\0') ? "/" : "",
+ tail);
+ }
+}
+
+
+/*
+ * Clean up path by:
+ * o make Win32 path use Unix slashes
+ * o remove trailing quote on Win32
+ * o remove trailing slash
+ * o remove duplicate adjacent separators
+ * o remove trailing '.'
+ * o process trailing '..' ourselves
+ */
+void
+canonicalize_path(char *path)
+{
+ char *p,
+ *to_p;
+ char *spath;
+ bool was_sep = false;
+ int pending_strips;
+
+#ifdef WIN32
+
+ /*
+ * The Windows command processor will accept suitably quoted paths with
+ * forward slashes, but barfs badly with mixed forward and back slashes.
+ */
+ for (p = path; *p; p++)
+ {
+ if (*p == '\\')
+ *p = '/';
+ }
+
+ /*
+ * In Win32, if you do: prog.exe "a b" "\c\d\" the system will pass \c\d"
+ * as argv[2], so trim off trailing quote.
+ */
+ if (p > path && *(p - 1) == '"')
+ *(p - 1) = '/';
+#endif
+
+ /*
+ * Removing the trailing slash on a path means we never get ugly double
+ * trailing slashes. Also, Win32 can't stat() a directory with a trailing
+ * slash. Don't remove a leading slash, though.
+ */
+ trim_trailing_separator(path);
+
+ /*
+ * Remove duplicate adjacent separators
+ */
+ p = path;
+#ifdef WIN32
+ /* Don't remove leading double-slash on Win32 */
+ if (*p)
+ p++;
+#endif
+ to_p = p;
+ for (; *p; p++, to_p++)
+ {
+ /* Handle many adjacent slashes, like "/a///b" */
+ while (*p == '/' && was_sep)
+ p++;
+ if (to_p != p)
+ *to_p = *p;
+ was_sep = (*p == '/');
+ }
+ *to_p = '\0';
+
+ /*
+ * Remove any trailing uses of "." and process ".." ourselves
+ *
+ * Note that "/../.." should reduce to just "/", while "../.." has to be
+ * kept as-is. In the latter case we put back mistakenly trimmed ".."
+ * components below. Also note that we want a Windows drive spec to be
+ * visible to trim_directory(), but it's not part of the logic that's
+ * looking at the name components; hence distinction between path and
+ * spath.
+ */
+ spath = skip_drive(path);
+ pending_strips = 0;
+ for (;;)
+ {
+ int len = strlen(spath);
+
+ if (len >= 2 && strcmp(spath + len - 2, "/.") == 0)
+ trim_directory(path);
+ else if (strcmp(spath, ".") == 0)
+ {
+ /* Want to leave "." alone, but "./.." has to become ".." */
+ if (pending_strips > 0)
+ *spath = '\0';
+ break;
+ }
+ else if ((len >= 3 && strcmp(spath + len - 3, "/..") == 0) ||
+ strcmp(spath, "..") == 0)
+ {
+ trim_directory(path);
+ pending_strips++;
+ }
+ else if (pending_strips > 0 && *spath != '\0')
+ {
+ /* trim a regular directory name canceled by ".." */
+ trim_directory(path);
+ pending_strips--;
+ /* foo/.. should become ".", not empty */
+ if (*spath == '\0')
+ strcpy(spath, ".");
+ }
+ else
+ break;
+ }
+
+ if (pending_strips > 0)
+ {
+ /*
+ * We could only get here if path is now totally empty (other than a
+ * possible drive specifier on Windows). We have to put back one or
+ * more ".."'s that we took off.
+ */
+ while (--pending_strips > 0)
+ strcat(path, "../");
+ strcat(path, "..");
+ }
+}
+
+/*
+ * Detect whether a path contains any parent-directory references ("..")
+ *
+ * The input *must* have been put through canonicalize_path previously.
+ *
+ * This is a bit tricky because we mustn't be fooled by "..a.." (legal)
+ * nor "C:.." (legal on Unix but not Windows).
+ */
+bool
+path_contains_parent_reference(const char *path)
+{
+ int path_len;
+
+ path = skip_drive(path); /* C: shouldn't affect our conclusion */
+
+ path_len = strlen(path);
+
+ /*
+ * ".." could be the whole path; otherwise, if it's present it must be at
+ * the beginning, in the middle, or at the end.
+ */
+ if (strcmp(path, "..") == 0 ||
+ strncmp(path, "../", 3) == 0 ||
+ strstr(path, "/../") != NULL ||
+ (path_len >= 3 && strcmp(path + path_len - 3, "/..") == 0))
+ return true;
+
+ return false;
+}
+
+/*
+ * Detect whether a path is only in or below the current working directory.
+ * An absolute path that matches the current working directory should
+ * return false (we only want relative to the cwd). We don't allow
+ * "/../" even if that would keep us under the cwd (it is too hard to
+ * track that).
+ */
+bool
+path_is_relative_and_below_cwd(const char *path)
+{
+ if (is_absolute_path(path))
+ return false;
+ /* don't allow anything above the cwd */
+ else if (path_contains_parent_reference(path))
+ return false;
+#ifdef WIN32
+
+ /*
+ * On Win32, a drive letter _not_ followed by a slash, e.g. 'E:abc', is
+ * relative to the cwd on that drive, or the drive's root directory if
+ * that drive has no cwd. Because the path itself cannot tell us which is
+ * the case, we have to assume the worst, i.e. that it is not below the
+ * cwd. We could use GetFullPathName() to find the full path but that
+ * could change if the current directory for the drive changes underneath
+ * us, so we just disallow it.
+ */
+ else if (isalpha((unsigned char) path[0]) && path[1] == ':' &&
+ !IS_DIR_SEP(path[2]))
+ return false;
+#endif
+ else
+ return true;
+}
+
+/*
+ * Detect whether path1 is a prefix of path2 (including equality).
+ *
+ * This is pretty trivial, but it seems better to export a function than
+ * to export IS_DIR_SEP.
+ */
+bool
+path_is_prefix_of_path(const char *path1, const char *path2)
+{
+ int path1_len = strlen(path1);
+
+ if (strncmp(path1, path2, path1_len) == 0 &&
+ (IS_DIR_SEP(path2[path1_len]) || path2[path1_len] == '\0'))
+ return true;
+ return false;
+}
+
+/*
+ * Extracts the actual name of the program as called -
+ * stripped of .exe suffix if any
+ */
+const char *
+get_progname(const char *argv0)
+{
+ const char *nodir_name;
+ char *progname;
+
+ nodir_name = last_dir_separator(argv0);
+ if (nodir_name)
+ nodir_name++;
+ else
+ nodir_name = skip_drive(argv0);
+
+ /*
+ * Make a copy in case argv[0] is modified by ps_status. Leaks memory, but
+ * called only once.
+ */
+ progname = strdup(nodir_name);
+ if (progname == NULL)
+ {
+ fprintf(stderr, "%s: out of memory\n", nodir_name);
+ abort(); /* This could exit the postmaster */
+ }
+
+#if defined(__CYGWIN__) || defined(WIN32)
+ /* strip ".exe" suffix, regardless of case */
+ if (strlen(progname) > sizeof(EXE) - 1 &&
+ pg_strcasecmp(progname + strlen(progname) - (sizeof(EXE) - 1), EXE) == 0)
+ progname[strlen(progname) - (sizeof(EXE) - 1)] = '\0';
+#endif
+
+ return progname;
+}
+
+
+/*
+ * dir_strcmp: strcmp except any two DIR_SEP characters are considered equal,
+ * and we honor filesystem case insensitivity if known
+ */
+static int
+dir_strcmp(const char *s1, const char *s2)
+{
+ while (*s1 && *s2)
+ {
+ if (
+#ifndef WIN32
+ *s1 != *s2
+#else
+ /* On windows, paths are case-insensitive */
+ pg_tolower((unsigned char) *s1) != pg_tolower((unsigned char) *s2)
+#endif
+ && !(IS_DIR_SEP(*s1) && IS_DIR_SEP(*s2)))
+ return (int) *s1 - (int) *s2;
+ s1++, s2++;
+ }
+ if (*s1)
+ return 1; /* s1 longer */
+ if (*s2)
+ return -1; /* s2 longer */
+ return 0;
+}
+
+
+/*
+ * make_relative_path - make a path relative to the actual binary location
+ *
+ * This function exists to support relocation of installation trees.
+ *
+ * ret_path is the output area (must be of size MAXPGPATH)
+ * target_path is the compiled-in path to the directory we want to find
+ * bin_path is the compiled-in path to the directory of executables
+ * my_exec_path is the actual location of my executable
+ *
+ * We determine the common prefix of target_path and bin_path, then compare
+ * the remainder of bin_path to the last directory component(s) of
+ * my_exec_path. If they match, build the result as the part of my_exec_path
+ * preceding the match, joined to the remainder of target_path. If no match,
+ * return target_path as-is.
+ *
+ * For example:
+ * target_path = '/usr/local/share/postgresql'
+ * bin_path = '/usr/local/bin'
+ * my_exec_path = '/opt/pgsql/bin/postmaster'
+ * Given these inputs, the common prefix is '/usr/local/', the tail of
+ * bin_path is 'bin' which does match the last directory component of
+ * my_exec_path, so we would return '/opt/pgsql/share/postgresql'
+ */
+static void
+make_relative_path(char *ret_path, const char *target_path,
+ const char *bin_path, const char *my_exec_path)
+{
+ int prefix_len;
+ int tail_start;
+ int tail_len;
+ int i;
+
+ /*
+ * Determine the common prefix --- note we require it to end on a
+ * directory separator, consider eg '/usr/lib' and '/usr/libexec'.
+ */
+ prefix_len = 0;
+ for (i = 0; target_path[i] && bin_path[i]; i++)
+ {
+ if (IS_DIR_SEP(target_path[i]) && IS_DIR_SEP(bin_path[i]))
+ prefix_len = i + 1;
+ else if (target_path[i] != bin_path[i])
+ break;
+ }
+ if (prefix_len == 0)
+ goto no_match; /* no common prefix? */
+ tail_len = strlen(bin_path) - prefix_len;
+
+ /*
+ * Set up my_exec_path without the actual executable name, and
+ * canonicalize to simplify comparison to bin_path.
+ */
+ strlcpy(ret_path, my_exec_path, MAXPGPATH);
+ trim_directory(ret_path); /* remove my executable name */
+ canonicalize_path(ret_path);
+
+ /*
+ * Tail match?
+ */
+ tail_start = (int) strlen(ret_path) - tail_len;
+ if (tail_start > 0 &&
+ IS_DIR_SEP(ret_path[tail_start - 1]) &&
+ dir_strcmp(ret_path + tail_start, bin_path + prefix_len) == 0)
+ {
+ ret_path[tail_start] = '\0';
+ trim_trailing_separator(ret_path);
+ join_path_components(ret_path, ret_path, target_path + prefix_len);
+ canonicalize_path(ret_path);
+ return;
+ }
+
+no_match:
+ strlcpy(ret_path, target_path, MAXPGPATH);
+ canonicalize_path(ret_path);
+}
+
+
+/*
+ * make_absolute_path
+ *
+ * If the given pathname isn't already absolute, make it so, interpreting
+ * it relative to the current working directory.
+ *
+ * Also canonicalizes the path. The result is always a malloc'd copy.
+ *
+ * In backend, failure cases result in ereport(ERROR); in frontend,
+ * we write a complaint on stderr and return NULL.
+ *
+ * Note: interpretation of relative-path arguments during postmaster startup
+ * should happen before doing ChangeToDataDir(), else the user will probably
+ * not like the results.
+ */
+char *
+make_absolute_path(const char *path)
+{
+ char *new;
+
+ /* Returning null for null input is convenient for some callers */
+ if (path == NULL)
+ return NULL;
+
+ if (!is_absolute_path(path))
+ {
+ char *buf;
+ size_t buflen;
+
+ buflen = MAXPGPATH;
+ for (;;)
+ {
+ buf = malloc(buflen);
+ if (!buf)
+ {
+#ifndef FRONTEND
+ ereport(ERROR,
+ (errcode(ERRCODE_OUT_OF_MEMORY),
+ errmsg("out of memory")));
+#else
+ fprintf(stderr, _("out of memory\n"));
+ return NULL;
+#endif
+ }
+
+ if (getcwd(buf, buflen))
+ break;
+ else if (errno == ERANGE)
+ {
+ free(buf);
+ buflen *= 2;
+ continue;
+ }
+ else
+ {
+ int save_errno = errno;
+
+ free(buf);
+ errno = save_errno;
+#ifndef FRONTEND
+ elog(ERROR, "could not get current working directory: %m");
+#else
+ fprintf(stderr, _("could not get current working directory: %s\n"),
+ strerror(errno));
+ return NULL;
+#endif
+ }
+ }
+
+ new = malloc(strlen(buf) + strlen(path) + 2);
+ if (!new)
+ {
+ free(buf);
+#ifndef FRONTEND
+ ereport(ERROR,
+ (errcode(ERRCODE_OUT_OF_MEMORY),
+ errmsg("out of memory")));
+#else
+ fprintf(stderr, _("out of memory\n"));
+ return NULL;
+#endif
+ }
+ sprintf(new, "%s/%s", buf, path);
+ free(buf);
+ }
+ else
+ {
+ new = strdup(path);
+ if (!new)
+ {
+#ifndef FRONTEND
+ ereport(ERROR,
+ (errcode(ERRCODE_OUT_OF_MEMORY),
+ errmsg("out of memory")));
+#else
+ fprintf(stderr, _("out of memory\n"));
+ return NULL;
+#endif
+ }
+ }
+
+ /* Make sure punctuation is canonical, too */
+ canonicalize_path(new);
+
+ return new;
+}
+
+
+/*
+ * get_share_path
+ */
+void
+get_share_path(const char *my_exec_path, char *ret_path)
+{
+ make_relative_path(ret_path, PGSHAREDIR, PGBINDIR, my_exec_path);
+}
+
+/*
+ * get_etc_path
+ */
+void
+get_etc_path(const char *my_exec_path, char *ret_path)
+{
+ make_relative_path(ret_path, SYSCONFDIR, PGBINDIR, my_exec_path);
+}
+
+/*
+ * get_include_path
+ */
+void
+get_include_path(const char *my_exec_path, char *ret_path)
+{
+ make_relative_path(ret_path, INCLUDEDIR, PGBINDIR, my_exec_path);
+}
+
+/*
+ * get_pkginclude_path
+ */
+void
+get_pkginclude_path(const char *my_exec_path, char *ret_path)
+{
+ make_relative_path(ret_path, PKGINCLUDEDIR, PGBINDIR, my_exec_path);
+}
+
+/*
+ * get_includeserver_path
+ */
+void
+get_includeserver_path(const char *my_exec_path, char *ret_path)
+{
+ make_relative_path(ret_path, INCLUDEDIRSERVER, PGBINDIR, my_exec_path);
+}
+
+/*
+ * get_lib_path
+ */
+void
+get_lib_path(const char *my_exec_path, char *ret_path)
+{
+ char const * const nix_pglibdir = getenv("NIX_PGLIBDIR");
+ if(nix_pglibdir == NULL)
+ make_relative_path(ret_path, LIBDIR, PGBINDIR, my_exec_path);
+ else
+ make_relative_path(ret_path, nix_pglibdir, PGBINDIR, my_exec_path);
+}
+
+/*
+ * get_pkglib_path
+ */
+void
+get_pkglib_path(const char *my_exec_path, char *ret_path)
+{
+ char const * const nix_pglibdir = getenv("NIX_PGLIBDIR");
+ if(nix_pglibdir == NULL)
+ make_relative_path(ret_path, PKGLIBDIR, PGBINDIR, my_exec_path);
+ else
+ make_relative_path(ret_path, nix_pglibdir, PGBINDIR, my_exec_path);
+}
+
+/*
+ * get_locale_path
+ */
+void
+get_locale_path(const char *my_exec_path, char *ret_path)
+{
+ make_relative_path(ret_path, LOCALEDIR, PGBINDIR, my_exec_path);
+}
+
+/*
+ * get_doc_path
+ */
+void
+get_doc_path(const char *my_exec_path, char *ret_path)
+{
+ make_relative_path(ret_path, DOCDIR, PGBINDIR, my_exec_path);
+}
+
+/*
+ * get_html_path
+ */
+void
+get_html_path(const char *my_exec_path, char *ret_path)
+{
+ make_relative_path(ret_path, HTMLDIR, PGBINDIR, my_exec_path);
+}
+
+/*
+ * get_man_path
+ */
+void
+get_man_path(const char *my_exec_path, char *ret_path)
+{
+ make_relative_path(ret_path, MANDIR, PGBINDIR, my_exec_path);
+}
+
+
+/*
+ * get_home_path
+ *
+ * On Unix, this actually returns the user's home directory. On Windows
+ * it returns the PostgreSQL-specific application data folder.
+ */
+bool
+get_home_path(char *ret_path)
+{
+#ifndef WIN32
+ char pwdbuf[BUFSIZ];
+ struct passwd pwdstr;
+ struct passwd *pwd = NULL;
+
+ (void) pqGetpwuid(geteuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd);
+ if (pwd == NULL)
+ return false;
+ strlcpy(ret_path, pwd->pw_dir, MAXPGPATH);
+ return true;
+#else
+ char *tmppath;
+
+ /*
+ * Note: We use getenv() here because the more modern SHGetFolderPath()
+ * would force the backend to link with shell32.lib, which eats valuable
+ * desktop heap. XXX This function is used only in psql, which already
+ * brings in shell32 via libpq. Moving this function to its own file
+ * would keep it out of the backend, freeing it from this concern.
+ */
+ tmppath = getenv("APPDATA");
+ if (!tmppath)
+ return false;
+ snprintf(ret_path, MAXPGPATH, "%s/postgresql", tmppath);
+ return true;
+#endif
+}
+
+
+/*
+ * get_parent_directory
+ *
+ * Modify the given string in-place to name the parent directory of the
+ * named file.
+ *
+ * If the input is just a file name with no directory part, the result is
+ * an empty string, not ".". This is appropriate when the next step is
+ * join_path_components(), but might need special handling otherwise.
+ *
+ * Caution: this will not produce desirable results if the string ends
+ * with "..". For most callers this is not a problem since the string
+ * is already known to name a regular file. If in doubt, apply
+ * canonicalize_path() first.
+ */
+void
+get_parent_directory(char *path)
+{
+ trim_directory(path);
+}
+
+
+/*
+ * trim_directory
+ *
+ * Trim trailing directory from path, that is, remove any trailing slashes,
+ * the last pathname component, and the slash just ahead of it --- but never
+ * remove a leading slash.
+ */
+static void
+trim_directory(char *path)
+{
+ char *p;
+
+ path = skip_drive(path);
+
+ if (path[0] == '\0')
+ return;
+
+ /* back up over trailing slash(es) */
+ for (p = path + strlen(path) - 1; IS_DIR_SEP(*p) && p > path; p--)
+ ;
+ /* back up over directory name */
+ for (; !IS_DIR_SEP(*p) && p > path; p--)
+ ;
+ /* if multiple slashes before directory name, remove 'em all */
+ for (; p > path && IS_DIR_SEP(*(p - 1)); p--)
+ ;
+ /* don't erase a leading slash */
+ if (p == path && IS_DIR_SEP(*p))
+ p++;
+ *p = '\0';
+}
+
+
+/*
+ * trim_trailing_separator
+ *
+ * trim off trailing slashes, but not a leading slash
+ */
+static void
+trim_trailing_separator(char *path)
+{
+ char *p;
+
+ path = skip_drive(path);
+ p = path + strlen(path);
+ if (p > path)
+ for (p--; p > path && IS_DIR_SEP(*p); p--)
+ *p = '\0';
+}
diff --git a/contrib/libs/postgresql/src/port/pg_bitutils.c b/contrib/libs/postgresql/src/port/pg_bitutils.c
new file mode 100644
index 0000000000..2252021854
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/pg_bitutils.c
@@ -0,0 +1,321 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_bitutils.c
+ * Miscellaneous functions for bit-wise operations.
+ *
+ * Copyright (c) 2019-2021, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/port/pg_bitutils.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "c.h"
+
+#ifdef HAVE__GET_CPUID
+#include <cpuid.h>
+#endif
+#ifdef HAVE__CPUID
+#include <intrin.h>
+#endif
+
+#include "port/pg_bitutils.h"
+
+
+/*
+ * Array giving the position of the left-most set bit for each possible
+ * byte value. We count the right-most position as the 0th bit, and the
+ * left-most the 7th bit. The 0th entry of the array should not be used.
+ *
+ * Note: this is not used by the functions in pg_bitutils.h when
+ * HAVE__BUILTIN_CLZ is defined, but we provide it anyway, so that
+ * extensions possibly compiled with a different compiler can use it.
+ */
+const uint8 pg_leftmost_one_pos[256] = {
+ 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+};
+
+/*
+ * Array giving the position of the right-most set bit for each possible
+ * byte value. We count the right-most position as the 0th bit, and the
+ * left-most the 7th bit. The 0th entry of the array should not be used.
+ *
+ * Note: this is not used by the functions in pg_bitutils.h when
+ * HAVE__BUILTIN_CTZ is defined, but we provide it anyway, so that
+ * extensions possibly compiled with a different compiler can use it.
+ */
+const uint8 pg_rightmost_one_pos[256] = {
+ 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
+};
+
+/*
+ * Array giving the number of 1-bits in each possible byte value.
+ *
+ * Note: we export this for use by functions in which explicit use
+ * of the popcount functions seems unlikely to be a win.
+ */
+const uint8 pg_number_of_ones[256] = {
+ 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
+};
+
+/*
+ * On x86_64, we can use the hardware popcount instruction, but only if
+ * we can verify that the CPU supports it via the cpuid instruction.
+ *
+ * Otherwise, we fall back to __builtin_popcount if the compiler has that,
+ * or a hand-rolled implementation if not.
+ */
+#ifdef HAVE_X86_64_POPCNTQ
+#if defined(HAVE__GET_CPUID) || defined(HAVE__CPUID)
+#define USE_POPCNT_ASM 1
+#endif
+#endif
+
+static int pg_popcount32_slow(uint32 word);
+static int pg_popcount64_slow(uint64 word);
+
+#ifdef USE_POPCNT_ASM
+static bool pg_popcount_available(void);
+static int pg_popcount32_choose(uint32 word);
+static int pg_popcount64_choose(uint64 word);
+static int pg_popcount32_asm(uint32 word);
+static int pg_popcount64_asm(uint64 word);
+
+int (*pg_popcount32) (uint32 word) = pg_popcount32_choose;
+int (*pg_popcount64) (uint64 word) = pg_popcount64_choose;
+#else
+int (*pg_popcount32) (uint32 word) = pg_popcount32_slow;
+int (*pg_popcount64) (uint64 word) = pg_popcount64_slow;
+#endif /* USE_POPCNT_ASM */
+
+#ifdef USE_POPCNT_ASM
+
+/*
+ * Return true if CPUID indicates that the POPCNT instruction is available.
+ */
+static bool
+pg_popcount_available(void)
+{
+ unsigned int exx[4] = {0, 0, 0, 0};
+
+#if defined(HAVE__GET_CPUID)
+ __get_cpuid(1, &exx[0], &exx[1], &exx[2], &exx[3]);
+#elif defined(HAVE__CPUID)
+ __cpuid(exx, 1);
+#else
+#error cpuid instruction not available
+#endif
+
+ return (exx[2] & (1 << 23)) != 0; /* POPCNT */
+}
+
+/*
+ * These functions get called on the first call to pg_popcount32 etc.
+ * They detect whether we can use the asm implementations, and replace
+ * the function pointers so that subsequent calls are routed directly to
+ * the chosen implementation.
+ */
+static int
+pg_popcount32_choose(uint32 word)
+{
+ if (pg_popcount_available())
+ {
+ pg_popcount32 = pg_popcount32_asm;
+ pg_popcount64 = pg_popcount64_asm;
+ }
+ else
+ {
+ pg_popcount32 = pg_popcount32_slow;
+ pg_popcount64 = pg_popcount64_slow;
+ }
+
+ return pg_popcount32(word);
+}
+
+static int
+pg_popcount64_choose(uint64 word)
+{
+ if (pg_popcount_available())
+ {
+ pg_popcount32 = pg_popcount32_asm;
+ pg_popcount64 = pg_popcount64_asm;
+ }
+ else
+ {
+ pg_popcount32 = pg_popcount32_slow;
+ pg_popcount64 = pg_popcount64_slow;
+ }
+
+ return pg_popcount64(word);
+}
+
+/*
+ * pg_popcount32_asm
+ * Return the number of 1 bits set in word
+ */
+static int
+pg_popcount32_asm(uint32 word)
+{
+ uint32 res;
+
+__asm__ __volatile__(" popcntl %1,%0\n":"=q"(res):"rm"(word):"cc");
+ return (int) res;
+}
+
+/*
+ * pg_popcount64_asm
+ * Return the number of 1 bits set in word
+ */
+static int
+pg_popcount64_asm(uint64 word)
+{
+ uint64 res;
+
+__asm__ __volatile__(" popcntq %1,%0\n":"=q"(res):"rm"(word):"cc");
+ return (int) res;
+}
+
+#endif /* USE_POPCNT_ASM */
+
+
+/*
+ * pg_popcount32_slow
+ * Return the number of 1 bits set in word
+ */
+static int
+pg_popcount32_slow(uint32 word)
+{
+#ifdef HAVE__BUILTIN_POPCOUNT
+ return __builtin_popcount(word);
+#else /* !HAVE__BUILTIN_POPCOUNT */
+ int result = 0;
+
+ while (word != 0)
+ {
+ result += pg_number_of_ones[word & 255];
+ word >>= 8;
+ }
+
+ return result;
+#endif /* HAVE__BUILTIN_POPCOUNT */
+}
+
+/*
+ * pg_popcount64_slow
+ * Return the number of 1 bits set in word
+ */
+static int
+pg_popcount64_slow(uint64 word)
+{
+#ifdef HAVE__BUILTIN_POPCOUNT
+#if defined(HAVE_LONG_INT_64)
+ return __builtin_popcountl(word);
+#elif defined(HAVE_LONG_LONG_INT_64)
+ return __builtin_popcountll(word);
+#else
+#error must have a working 64-bit integer datatype
+#endif
+#else /* !HAVE__BUILTIN_POPCOUNT */
+ int result = 0;
+
+ while (word != 0)
+ {
+ result += pg_number_of_ones[word & 255];
+ word >>= 8;
+ }
+
+ return result;
+#endif /* HAVE__BUILTIN_POPCOUNT */
+}
+
+
+/*
+ * pg_popcount
+ * Returns the number of 1-bits in buf
+ */
+uint64
+pg_popcount(const char *buf, int bytes)
+{
+ uint64 popcnt = 0;
+
+#if SIZEOF_VOID_P >= 8
+ /* Process in 64-bit chunks if the buffer is aligned. */
+ if (buf == (const char *) TYPEALIGN(8, buf))
+ {
+ const uint64 *words = (const uint64 *) buf;
+
+ while (bytes >= 8)
+ {
+ popcnt += pg_popcount64(*words++);
+ bytes -= 8;
+ }
+
+ buf = (const char *) words;
+ }
+#else
+ /* Process in 32-bit chunks if the buffer is aligned. */
+ if (buf == (const char *) TYPEALIGN(4, buf))
+ {
+ const uint32 *words = (const uint32 *) buf;
+
+ while (bytes >= 4)
+ {
+ popcnt += pg_popcount32(*words++);
+ bytes -= 4;
+ }
+
+ buf = (const char *) words;
+ }
+#endif
+
+ /* Process any remaining bytes */
+ while (bytes--)
+ popcnt += pg_number_of_ones[(unsigned char) *buf++];
+
+ return popcnt;
+}
diff --git a/contrib/libs/postgresql/src/port/pg_config_paths.h b/contrib/libs/postgresql/src/port/pg_config_paths.h
new file mode 100644
index 0000000000..d9c45851c9
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/pg_config_paths.h
@@ -0,0 +1,12 @@
+#define PGBINDIR "/var/empty/postgresql-14.2/bin"
+#define PGSHAREDIR "/var/empty/postgresql-14.2/share/postgresql"
+#define SYSCONFDIR "/etc/postgresql"
+#define INCLUDEDIR "/var/empty/postgresql-14.2/include"
+#define PKGINCLUDEDIR "/var/empty/postgresql-14.2/include"
+#define INCLUDEDIRSERVER "/var/empty/postgresql-14.2/include/server"
+#define LIBDIR "/var/empty/tmp/out/lib"
+#define PKGLIBDIR "/var/empty/tmp/out/lib"
+#define LOCALEDIR "/var/empty/postgresql-14.2/share/locale"
+#define DOCDIR "/var/empty/postgresql-14.2/share/doc//postgresql"
+#define HTMLDIR "/var/empty/postgresql-14.2/share/doc//postgresql"
+#define MANDIR "/var/empty/postgresql-14.2/share/man"
diff --git a/contrib/libs/postgresql/src/port/pg_crc32c_sb8.c b/contrib/libs/postgresql/src/port/pg_crc32c_sb8.c
new file mode 100644
index 0000000000..98da86cdd3
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/pg_crc32c_sb8.c
@@ -0,0 +1,1169 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_crc32c_sb8.c
+ * Compute CRC-32C checksum using slicing-by-8 algorithm.
+ *
+ * Michael E. Kounavis, Frank L. Berry,
+ * "Novel Table Lookup-Based Algorithms for High-Performance CRC
+ * Generation", IEEE Transactions on Computers, vol.57, no. 11,
+ * pp. 1550-1560, November 2008, doi:10.1109/TC.2008.85
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/port/pg_crc32c_sb8.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "c.h"
+
+#include "port/pg_crc32c.h"
+
+static const uint32 pg_crc32c_table[8][256];
+
+/* Accumulate one input byte */
+#ifdef WORDS_BIGENDIAN
+#define CRC8(x) pg_crc32c_table[0][((crc >> 24) ^ (x)) & 0xFF] ^ (crc << 8)
+#else
+#define CRC8(x) pg_crc32c_table[0][(crc ^ (x)) & 0xFF] ^ (crc >> 8)
+#endif
+
+pg_crc32c
+pg_comp_crc32c_sb8(pg_crc32c crc, const void *data, size_t len)
+{
+ const unsigned char *p = data;
+ const uint32 *p4;
+
+ /*
+ * Handle 0-3 initial bytes one at a time, so that the loop below starts
+ * with a pointer aligned to four bytes.
+ */
+ while (len > 0 && ((uintptr_t) p & 3))
+ {
+ crc = CRC8(*p++);
+ len--;
+ }
+
+ /*
+ * Process eight bytes of data at a time.
+ */
+ p4 = (const uint32 *) p;
+ while (len >= 8)
+ {
+ uint32 a = *p4++ ^ crc;
+ uint32 b = *p4++;
+
+#ifdef WORDS_BIGENDIAN
+ const uint8 c0 = b;
+ const uint8 c1 = b >> 8;
+ const uint8 c2 = b >> 16;
+ const uint8 c3 = b >> 24;
+ const uint8 c4 = a;
+ const uint8 c5 = a >> 8;
+ const uint8 c6 = a >> 16;
+ const uint8 c7 = a >> 24;
+#else
+ const uint8 c0 = b >> 24;
+ const uint8 c1 = b >> 16;
+ const uint8 c2 = b >> 8;
+ const uint8 c3 = b;
+ const uint8 c4 = a >> 24;
+ const uint8 c5 = a >> 16;
+ const uint8 c6 = a >> 8;
+ const uint8 c7 = a;
+#endif
+
+ crc =
+ pg_crc32c_table[0][c0] ^ pg_crc32c_table[1][c1] ^
+ pg_crc32c_table[2][c2] ^ pg_crc32c_table[3][c3] ^
+ pg_crc32c_table[4][c4] ^ pg_crc32c_table[5][c5] ^
+ pg_crc32c_table[6][c6] ^ pg_crc32c_table[7][c7];
+
+ len -= 8;
+ }
+
+ /*
+ * Handle any remaining bytes one at a time.
+ */
+ p = (const unsigned char *) p4;
+ while (len > 0)
+ {
+ crc = CRC8(*p++);
+ len--;
+ }
+
+ return crc;
+}
+
+/*
+ * Lookup tables for the slicing-by-8 algorithm, for the so-called Castagnoli
+ * polynomial (the same that is used e.g. in iSCSI), 0x1EDC6F41. Using
+ * Williams' terms, this is the "normal", not "reflected" version. However, on
+ * big-endian systems the values in the tables are stored in byte-reversed
+ * order (IOW, the tables are stored in little-endian order even on big-endian
+ * systems).
+ */
+static const uint32 pg_crc32c_table[8][256] = {
+#ifndef WORDS_BIGENDIAN
+ {
+ 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
+ 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
+ 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
+ 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
+ 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
+ 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
+ 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
+ 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
+ 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
+ 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
+ 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
+ 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
+ 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
+ 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
+ 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
+ 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
+ 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
+ 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
+ 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
+ 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
+ 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
+ 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
+ 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
+ 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
+ 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
+ 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
+ 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
+ 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
+ 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
+ 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
+ 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
+ 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
+ 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
+ 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
+ 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
+ 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
+ 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
+ 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
+ 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
+ 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
+ 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
+ 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
+ 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
+ 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
+ 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
+ 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
+ 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
+ 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
+ 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
+ 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
+ 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
+ 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
+ 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
+ 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
+ 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
+ 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
+ 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
+ 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
+ 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
+ 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
+ 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
+ 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
+ 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
+ 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351
+ },
+ {
+ 0x00000000, 0x13A29877, 0x274530EE, 0x34E7A899,
+ 0x4E8A61DC, 0x5D28F9AB, 0x69CF5132, 0x7A6DC945,
+ 0x9D14C3B8, 0x8EB65BCF, 0xBA51F356, 0xA9F36B21,
+ 0xD39EA264, 0xC03C3A13, 0xF4DB928A, 0xE7790AFD,
+ 0x3FC5F181, 0x2C6769F6, 0x1880C16F, 0x0B225918,
+ 0x714F905D, 0x62ED082A, 0x560AA0B3, 0x45A838C4,
+ 0xA2D13239, 0xB173AA4E, 0x859402D7, 0x96369AA0,
+ 0xEC5B53E5, 0xFFF9CB92, 0xCB1E630B, 0xD8BCFB7C,
+ 0x7F8BE302, 0x6C297B75, 0x58CED3EC, 0x4B6C4B9B,
+ 0x310182DE, 0x22A31AA9, 0x1644B230, 0x05E62A47,
+ 0xE29F20BA, 0xF13DB8CD, 0xC5DA1054, 0xD6788823,
+ 0xAC154166, 0xBFB7D911, 0x8B507188, 0x98F2E9FF,
+ 0x404E1283, 0x53EC8AF4, 0x670B226D, 0x74A9BA1A,
+ 0x0EC4735F, 0x1D66EB28, 0x298143B1, 0x3A23DBC6,
+ 0xDD5AD13B, 0xCEF8494C, 0xFA1FE1D5, 0xE9BD79A2,
+ 0x93D0B0E7, 0x80722890, 0xB4958009, 0xA737187E,
+ 0xFF17C604, 0xECB55E73, 0xD852F6EA, 0xCBF06E9D,
+ 0xB19DA7D8, 0xA23F3FAF, 0x96D89736, 0x857A0F41,
+ 0x620305BC, 0x71A19DCB, 0x45463552, 0x56E4AD25,
+ 0x2C896460, 0x3F2BFC17, 0x0BCC548E, 0x186ECCF9,
+ 0xC0D23785, 0xD370AFF2, 0xE797076B, 0xF4359F1C,
+ 0x8E585659, 0x9DFACE2E, 0xA91D66B7, 0xBABFFEC0,
+ 0x5DC6F43D, 0x4E646C4A, 0x7A83C4D3, 0x69215CA4,
+ 0x134C95E1, 0x00EE0D96, 0x3409A50F, 0x27AB3D78,
+ 0x809C2506, 0x933EBD71, 0xA7D915E8, 0xB47B8D9F,
+ 0xCE1644DA, 0xDDB4DCAD, 0xE9537434, 0xFAF1EC43,
+ 0x1D88E6BE, 0x0E2A7EC9, 0x3ACDD650, 0x296F4E27,
+ 0x53028762, 0x40A01F15, 0x7447B78C, 0x67E52FFB,
+ 0xBF59D487, 0xACFB4CF0, 0x981CE469, 0x8BBE7C1E,
+ 0xF1D3B55B, 0xE2712D2C, 0xD69685B5, 0xC5341DC2,
+ 0x224D173F, 0x31EF8F48, 0x050827D1, 0x16AABFA6,
+ 0x6CC776E3, 0x7F65EE94, 0x4B82460D, 0x5820DE7A,
+ 0xFBC3FAF9, 0xE861628E, 0xDC86CA17, 0xCF245260,
+ 0xB5499B25, 0xA6EB0352, 0x920CABCB, 0x81AE33BC,
+ 0x66D73941, 0x7575A136, 0x419209AF, 0x523091D8,
+ 0x285D589D, 0x3BFFC0EA, 0x0F186873, 0x1CBAF004,
+ 0xC4060B78, 0xD7A4930F, 0xE3433B96, 0xF0E1A3E1,
+ 0x8A8C6AA4, 0x992EF2D3, 0xADC95A4A, 0xBE6BC23D,
+ 0x5912C8C0, 0x4AB050B7, 0x7E57F82E, 0x6DF56059,
+ 0x1798A91C, 0x043A316B, 0x30DD99F2, 0x237F0185,
+ 0x844819FB, 0x97EA818C, 0xA30D2915, 0xB0AFB162,
+ 0xCAC27827, 0xD960E050, 0xED8748C9, 0xFE25D0BE,
+ 0x195CDA43, 0x0AFE4234, 0x3E19EAAD, 0x2DBB72DA,
+ 0x57D6BB9F, 0x447423E8, 0x70938B71, 0x63311306,
+ 0xBB8DE87A, 0xA82F700D, 0x9CC8D894, 0x8F6A40E3,
+ 0xF50789A6, 0xE6A511D1, 0xD242B948, 0xC1E0213F,
+ 0x26992BC2, 0x353BB3B5, 0x01DC1B2C, 0x127E835B,
+ 0x68134A1E, 0x7BB1D269, 0x4F567AF0, 0x5CF4E287,
+ 0x04D43CFD, 0x1776A48A, 0x23910C13, 0x30339464,
+ 0x4A5E5D21, 0x59FCC556, 0x6D1B6DCF, 0x7EB9F5B8,
+ 0x99C0FF45, 0x8A626732, 0xBE85CFAB, 0xAD2757DC,
+ 0xD74A9E99, 0xC4E806EE, 0xF00FAE77, 0xE3AD3600,
+ 0x3B11CD7C, 0x28B3550B, 0x1C54FD92, 0x0FF665E5,
+ 0x759BACA0, 0x663934D7, 0x52DE9C4E, 0x417C0439,
+ 0xA6050EC4, 0xB5A796B3, 0x81403E2A, 0x92E2A65D,
+ 0xE88F6F18, 0xFB2DF76F, 0xCFCA5FF6, 0xDC68C781,
+ 0x7B5FDFFF, 0x68FD4788, 0x5C1AEF11, 0x4FB87766,
+ 0x35D5BE23, 0x26772654, 0x12908ECD, 0x013216BA,
+ 0xE64B1C47, 0xF5E98430, 0xC10E2CA9, 0xD2ACB4DE,
+ 0xA8C17D9B, 0xBB63E5EC, 0x8F844D75, 0x9C26D502,
+ 0x449A2E7E, 0x5738B609, 0x63DF1E90, 0x707D86E7,
+ 0x0A104FA2, 0x19B2D7D5, 0x2D557F4C, 0x3EF7E73B,
+ 0xD98EEDC6, 0xCA2C75B1, 0xFECBDD28, 0xED69455F,
+ 0x97048C1A, 0x84A6146D, 0xB041BCF4, 0xA3E32483
+ },
+ {
+ 0x00000000, 0xA541927E, 0x4F6F520D, 0xEA2EC073,
+ 0x9EDEA41A, 0x3B9F3664, 0xD1B1F617, 0x74F06469,
+ 0x38513EC5, 0x9D10ACBB, 0x773E6CC8, 0xD27FFEB6,
+ 0xA68F9ADF, 0x03CE08A1, 0xE9E0C8D2, 0x4CA15AAC,
+ 0x70A27D8A, 0xD5E3EFF4, 0x3FCD2F87, 0x9A8CBDF9,
+ 0xEE7CD990, 0x4B3D4BEE, 0xA1138B9D, 0x045219E3,
+ 0x48F3434F, 0xEDB2D131, 0x079C1142, 0xA2DD833C,
+ 0xD62DE755, 0x736C752B, 0x9942B558, 0x3C032726,
+ 0xE144FB14, 0x4405696A, 0xAE2BA919, 0x0B6A3B67,
+ 0x7F9A5F0E, 0xDADBCD70, 0x30F50D03, 0x95B49F7D,
+ 0xD915C5D1, 0x7C5457AF, 0x967A97DC, 0x333B05A2,
+ 0x47CB61CB, 0xE28AF3B5, 0x08A433C6, 0xADE5A1B8,
+ 0x91E6869E, 0x34A714E0, 0xDE89D493, 0x7BC846ED,
+ 0x0F382284, 0xAA79B0FA, 0x40577089, 0xE516E2F7,
+ 0xA9B7B85B, 0x0CF62A25, 0xE6D8EA56, 0x43997828,
+ 0x37691C41, 0x92288E3F, 0x78064E4C, 0xDD47DC32,
+ 0xC76580D9, 0x622412A7, 0x880AD2D4, 0x2D4B40AA,
+ 0x59BB24C3, 0xFCFAB6BD, 0x16D476CE, 0xB395E4B0,
+ 0xFF34BE1C, 0x5A752C62, 0xB05BEC11, 0x151A7E6F,
+ 0x61EA1A06, 0xC4AB8878, 0x2E85480B, 0x8BC4DA75,
+ 0xB7C7FD53, 0x12866F2D, 0xF8A8AF5E, 0x5DE93D20,
+ 0x29195949, 0x8C58CB37, 0x66760B44, 0xC337993A,
+ 0x8F96C396, 0x2AD751E8, 0xC0F9919B, 0x65B803E5,
+ 0x1148678C, 0xB409F5F2, 0x5E273581, 0xFB66A7FF,
+ 0x26217BCD, 0x8360E9B3, 0x694E29C0, 0xCC0FBBBE,
+ 0xB8FFDFD7, 0x1DBE4DA9, 0xF7908DDA, 0x52D11FA4,
+ 0x1E704508, 0xBB31D776, 0x511F1705, 0xF45E857B,
+ 0x80AEE112, 0x25EF736C, 0xCFC1B31F, 0x6A802161,
+ 0x56830647, 0xF3C29439, 0x19EC544A, 0xBCADC634,
+ 0xC85DA25D, 0x6D1C3023, 0x8732F050, 0x2273622E,
+ 0x6ED23882, 0xCB93AAFC, 0x21BD6A8F, 0x84FCF8F1,
+ 0xF00C9C98, 0x554D0EE6, 0xBF63CE95, 0x1A225CEB,
+ 0x8B277743, 0x2E66E53D, 0xC448254E, 0x6109B730,
+ 0x15F9D359, 0xB0B84127, 0x5A968154, 0xFFD7132A,
+ 0xB3764986, 0x1637DBF8, 0xFC191B8B, 0x595889F5,
+ 0x2DA8ED9C, 0x88E97FE2, 0x62C7BF91, 0xC7862DEF,
+ 0xFB850AC9, 0x5EC498B7, 0xB4EA58C4, 0x11ABCABA,
+ 0x655BAED3, 0xC01A3CAD, 0x2A34FCDE, 0x8F756EA0,
+ 0xC3D4340C, 0x6695A672, 0x8CBB6601, 0x29FAF47F,
+ 0x5D0A9016, 0xF84B0268, 0x1265C21B, 0xB7245065,
+ 0x6A638C57, 0xCF221E29, 0x250CDE5A, 0x804D4C24,
+ 0xF4BD284D, 0x51FCBA33, 0xBBD27A40, 0x1E93E83E,
+ 0x5232B292, 0xF77320EC, 0x1D5DE09F, 0xB81C72E1,
+ 0xCCEC1688, 0x69AD84F6, 0x83834485, 0x26C2D6FB,
+ 0x1AC1F1DD, 0xBF8063A3, 0x55AEA3D0, 0xF0EF31AE,
+ 0x841F55C7, 0x215EC7B9, 0xCB7007CA, 0x6E3195B4,
+ 0x2290CF18, 0x87D15D66, 0x6DFF9D15, 0xC8BE0F6B,
+ 0xBC4E6B02, 0x190FF97C, 0xF321390F, 0x5660AB71,
+ 0x4C42F79A, 0xE90365E4, 0x032DA597, 0xA66C37E9,
+ 0xD29C5380, 0x77DDC1FE, 0x9DF3018D, 0x38B293F3,
+ 0x7413C95F, 0xD1525B21, 0x3B7C9B52, 0x9E3D092C,
+ 0xEACD6D45, 0x4F8CFF3B, 0xA5A23F48, 0x00E3AD36,
+ 0x3CE08A10, 0x99A1186E, 0x738FD81D, 0xD6CE4A63,
+ 0xA23E2E0A, 0x077FBC74, 0xED517C07, 0x4810EE79,
+ 0x04B1B4D5, 0xA1F026AB, 0x4BDEE6D8, 0xEE9F74A6,
+ 0x9A6F10CF, 0x3F2E82B1, 0xD50042C2, 0x7041D0BC,
+ 0xAD060C8E, 0x08479EF0, 0xE2695E83, 0x4728CCFD,
+ 0x33D8A894, 0x96993AEA, 0x7CB7FA99, 0xD9F668E7,
+ 0x9557324B, 0x3016A035, 0xDA386046, 0x7F79F238,
+ 0x0B899651, 0xAEC8042F, 0x44E6C45C, 0xE1A75622,
+ 0xDDA47104, 0x78E5E37A, 0x92CB2309, 0x378AB177,
+ 0x437AD51E, 0xE63B4760, 0x0C158713, 0xA954156D,
+ 0xE5F54FC1, 0x40B4DDBF, 0xAA9A1DCC, 0x0FDB8FB2,
+ 0x7B2BEBDB, 0xDE6A79A5, 0x3444B9D6, 0x91052BA8
+ },
+ {
+ 0x00000000, 0xDD45AAB8, 0xBF672381, 0x62228939,
+ 0x7B2231F3, 0xA6679B4B, 0xC4451272, 0x1900B8CA,
+ 0xF64463E6, 0x2B01C95E, 0x49234067, 0x9466EADF,
+ 0x8D665215, 0x5023F8AD, 0x32017194, 0xEF44DB2C,
+ 0xE964B13D, 0x34211B85, 0x560392BC, 0x8B463804,
+ 0x924680CE, 0x4F032A76, 0x2D21A34F, 0xF06409F7,
+ 0x1F20D2DB, 0xC2657863, 0xA047F15A, 0x7D025BE2,
+ 0x6402E328, 0xB9474990, 0xDB65C0A9, 0x06206A11,
+ 0xD725148B, 0x0A60BE33, 0x6842370A, 0xB5079DB2,
+ 0xAC072578, 0x71428FC0, 0x136006F9, 0xCE25AC41,
+ 0x2161776D, 0xFC24DDD5, 0x9E0654EC, 0x4343FE54,
+ 0x5A43469E, 0x8706EC26, 0xE524651F, 0x3861CFA7,
+ 0x3E41A5B6, 0xE3040F0E, 0x81268637, 0x5C632C8F,
+ 0x45639445, 0x98263EFD, 0xFA04B7C4, 0x27411D7C,
+ 0xC805C650, 0x15406CE8, 0x7762E5D1, 0xAA274F69,
+ 0xB327F7A3, 0x6E625D1B, 0x0C40D422, 0xD1057E9A,
+ 0xABA65FE7, 0x76E3F55F, 0x14C17C66, 0xC984D6DE,
+ 0xD0846E14, 0x0DC1C4AC, 0x6FE34D95, 0xB2A6E72D,
+ 0x5DE23C01, 0x80A796B9, 0xE2851F80, 0x3FC0B538,
+ 0x26C00DF2, 0xFB85A74A, 0x99A72E73, 0x44E284CB,
+ 0x42C2EEDA, 0x9F874462, 0xFDA5CD5B, 0x20E067E3,
+ 0x39E0DF29, 0xE4A57591, 0x8687FCA8, 0x5BC25610,
+ 0xB4868D3C, 0x69C32784, 0x0BE1AEBD, 0xD6A40405,
+ 0xCFA4BCCF, 0x12E11677, 0x70C39F4E, 0xAD8635F6,
+ 0x7C834B6C, 0xA1C6E1D4, 0xC3E468ED, 0x1EA1C255,
+ 0x07A17A9F, 0xDAE4D027, 0xB8C6591E, 0x6583F3A6,
+ 0x8AC7288A, 0x57828232, 0x35A00B0B, 0xE8E5A1B3,
+ 0xF1E51979, 0x2CA0B3C1, 0x4E823AF8, 0x93C79040,
+ 0x95E7FA51, 0x48A250E9, 0x2A80D9D0, 0xF7C57368,
+ 0xEEC5CBA2, 0x3380611A, 0x51A2E823, 0x8CE7429B,
+ 0x63A399B7, 0xBEE6330F, 0xDCC4BA36, 0x0181108E,
+ 0x1881A844, 0xC5C402FC, 0xA7E68BC5, 0x7AA3217D,
+ 0x52A0C93F, 0x8FE56387, 0xEDC7EABE, 0x30824006,
+ 0x2982F8CC, 0xF4C75274, 0x96E5DB4D, 0x4BA071F5,
+ 0xA4E4AAD9, 0x79A10061, 0x1B838958, 0xC6C623E0,
+ 0xDFC69B2A, 0x02833192, 0x60A1B8AB, 0xBDE41213,
+ 0xBBC47802, 0x6681D2BA, 0x04A35B83, 0xD9E6F13B,
+ 0xC0E649F1, 0x1DA3E349, 0x7F816A70, 0xA2C4C0C8,
+ 0x4D801BE4, 0x90C5B15C, 0xF2E73865, 0x2FA292DD,
+ 0x36A22A17, 0xEBE780AF, 0x89C50996, 0x5480A32E,
+ 0x8585DDB4, 0x58C0770C, 0x3AE2FE35, 0xE7A7548D,
+ 0xFEA7EC47, 0x23E246FF, 0x41C0CFC6, 0x9C85657E,
+ 0x73C1BE52, 0xAE8414EA, 0xCCA69DD3, 0x11E3376B,
+ 0x08E38FA1, 0xD5A62519, 0xB784AC20, 0x6AC10698,
+ 0x6CE16C89, 0xB1A4C631, 0xD3864F08, 0x0EC3E5B0,
+ 0x17C35D7A, 0xCA86F7C2, 0xA8A47EFB, 0x75E1D443,
+ 0x9AA50F6F, 0x47E0A5D7, 0x25C22CEE, 0xF8878656,
+ 0xE1873E9C, 0x3CC29424, 0x5EE01D1D, 0x83A5B7A5,
+ 0xF90696D8, 0x24433C60, 0x4661B559, 0x9B241FE1,
+ 0x8224A72B, 0x5F610D93, 0x3D4384AA, 0xE0062E12,
+ 0x0F42F53E, 0xD2075F86, 0xB025D6BF, 0x6D607C07,
+ 0x7460C4CD, 0xA9256E75, 0xCB07E74C, 0x16424DF4,
+ 0x106227E5, 0xCD278D5D, 0xAF050464, 0x7240AEDC,
+ 0x6B401616, 0xB605BCAE, 0xD4273597, 0x09629F2F,
+ 0xE6264403, 0x3B63EEBB, 0x59416782, 0x8404CD3A,
+ 0x9D0475F0, 0x4041DF48, 0x22635671, 0xFF26FCC9,
+ 0x2E238253, 0xF36628EB, 0x9144A1D2, 0x4C010B6A,
+ 0x5501B3A0, 0x88441918, 0xEA669021, 0x37233A99,
+ 0xD867E1B5, 0x05224B0D, 0x6700C234, 0xBA45688C,
+ 0xA345D046, 0x7E007AFE, 0x1C22F3C7, 0xC167597F,
+ 0xC747336E, 0x1A0299D6, 0x782010EF, 0xA565BA57,
+ 0xBC65029D, 0x6120A825, 0x0302211C, 0xDE478BA4,
+ 0x31035088, 0xEC46FA30, 0x8E647309, 0x5321D9B1,
+ 0x4A21617B, 0x9764CBC3, 0xF54642FA, 0x2803E842
+ },
+ {
+ 0x00000000, 0x38116FAC, 0x7022DF58, 0x4833B0F4,
+ 0xE045BEB0, 0xD854D11C, 0x906761E8, 0xA8760E44,
+ 0xC5670B91, 0xFD76643D, 0xB545D4C9, 0x8D54BB65,
+ 0x2522B521, 0x1D33DA8D, 0x55006A79, 0x6D1105D5,
+ 0x8F2261D3, 0xB7330E7F, 0xFF00BE8B, 0xC711D127,
+ 0x6F67DF63, 0x5776B0CF, 0x1F45003B, 0x27546F97,
+ 0x4A456A42, 0x725405EE, 0x3A67B51A, 0x0276DAB6,
+ 0xAA00D4F2, 0x9211BB5E, 0xDA220BAA, 0xE2336406,
+ 0x1BA8B557, 0x23B9DAFB, 0x6B8A6A0F, 0x539B05A3,
+ 0xFBED0BE7, 0xC3FC644B, 0x8BCFD4BF, 0xB3DEBB13,
+ 0xDECFBEC6, 0xE6DED16A, 0xAEED619E, 0x96FC0E32,
+ 0x3E8A0076, 0x069B6FDA, 0x4EA8DF2E, 0x76B9B082,
+ 0x948AD484, 0xAC9BBB28, 0xE4A80BDC, 0xDCB96470,
+ 0x74CF6A34, 0x4CDE0598, 0x04EDB56C, 0x3CFCDAC0,
+ 0x51EDDF15, 0x69FCB0B9, 0x21CF004D, 0x19DE6FE1,
+ 0xB1A861A5, 0x89B90E09, 0xC18ABEFD, 0xF99BD151,
+ 0x37516AAE, 0x0F400502, 0x4773B5F6, 0x7F62DA5A,
+ 0xD714D41E, 0xEF05BBB2, 0xA7360B46, 0x9F2764EA,
+ 0xF236613F, 0xCA270E93, 0x8214BE67, 0xBA05D1CB,
+ 0x1273DF8F, 0x2A62B023, 0x625100D7, 0x5A406F7B,
+ 0xB8730B7D, 0x806264D1, 0xC851D425, 0xF040BB89,
+ 0x5836B5CD, 0x6027DA61, 0x28146A95, 0x10050539,
+ 0x7D1400EC, 0x45056F40, 0x0D36DFB4, 0x3527B018,
+ 0x9D51BE5C, 0xA540D1F0, 0xED736104, 0xD5620EA8,
+ 0x2CF9DFF9, 0x14E8B055, 0x5CDB00A1, 0x64CA6F0D,
+ 0xCCBC6149, 0xF4AD0EE5, 0xBC9EBE11, 0x848FD1BD,
+ 0xE99ED468, 0xD18FBBC4, 0x99BC0B30, 0xA1AD649C,
+ 0x09DB6AD8, 0x31CA0574, 0x79F9B580, 0x41E8DA2C,
+ 0xA3DBBE2A, 0x9BCAD186, 0xD3F96172, 0xEBE80EDE,
+ 0x439E009A, 0x7B8F6F36, 0x33BCDFC2, 0x0BADB06E,
+ 0x66BCB5BB, 0x5EADDA17, 0x169E6AE3, 0x2E8F054F,
+ 0x86F90B0B, 0xBEE864A7, 0xF6DBD453, 0xCECABBFF,
+ 0x6EA2D55C, 0x56B3BAF0, 0x1E800A04, 0x269165A8,
+ 0x8EE76BEC, 0xB6F60440, 0xFEC5B4B4, 0xC6D4DB18,
+ 0xABC5DECD, 0x93D4B161, 0xDBE70195, 0xE3F66E39,
+ 0x4B80607D, 0x73910FD1, 0x3BA2BF25, 0x03B3D089,
+ 0xE180B48F, 0xD991DB23, 0x91A26BD7, 0xA9B3047B,
+ 0x01C50A3F, 0x39D46593, 0x71E7D567, 0x49F6BACB,
+ 0x24E7BF1E, 0x1CF6D0B2, 0x54C56046, 0x6CD40FEA,
+ 0xC4A201AE, 0xFCB36E02, 0xB480DEF6, 0x8C91B15A,
+ 0x750A600B, 0x4D1B0FA7, 0x0528BF53, 0x3D39D0FF,
+ 0x954FDEBB, 0xAD5EB117, 0xE56D01E3, 0xDD7C6E4F,
+ 0xB06D6B9A, 0x887C0436, 0xC04FB4C2, 0xF85EDB6E,
+ 0x5028D52A, 0x6839BA86, 0x200A0A72, 0x181B65DE,
+ 0xFA2801D8, 0xC2396E74, 0x8A0ADE80, 0xB21BB12C,
+ 0x1A6DBF68, 0x227CD0C4, 0x6A4F6030, 0x525E0F9C,
+ 0x3F4F0A49, 0x075E65E5, 0x4F6DD511, 0x777CBABD,
+ 0xDF0AB4F9, 0xE71BDB55, 0xAF286BA1, 0x9739040D,
+ 0x59F3BFF2, 0x61E2D05E, 0x29D160AA, 0x11C00F06,
+ 0xB9B60142, 0x81A76EEE, 0xC994DE1A, 0xF185B1B6,
+ 0x9C94B463, 0xA485DBCF, 0xECB66B3B, 0xD4A70497,
+ 0x7CD10AD3, 0x44C0657F, 0x0CF3D58B, 0x34E2BA27,
+ 0xD6D1DE21, 0xEEC0B18D, 0xA6F30179, 0x9EE26ED5,
+ 0x36946091, 0x0E850F3D, 0x46B6BFC9, 0x7EA7D065,
+ 0x13B6D5B0, 0x2BA7BA1C, 0x63940AE8, 0x5B856544,
+ 0xF3F36B00, 0xCBE204AC, 0x83D1B458, 0xBBC0DBF4,
+ 0x425B0AA5, 0x7A4A6509, 0x3279D5FD, 0x0A68BA51,
+ 0xA21EB415, 0x9A0FDBB9, 0xD23C6B4D, 0xEA2D04E1,
+ 0x873C0134, 0xBF2D6E98, 0xF71EDE6C, 0xCF0FB1C0,
+ 0x6779BF84, 0x5F68D028, 0x175B60DC, 0x2F4A0F70,
+ 0xCD796B76, 0xF56804DA, 0xBD5BB42E, 0x854ADB82,
+ 0x2D3CD5C6, 0x152DBA6A, 0x5D1E0A9E, 0x650F6532,
+ 0x081E60E7, 0x300F0F4B, 0x783CBFBF, 0x402DD013,
+ 0xE85BDE57, 0xD04AB1FB, 0x9879010F, 0xA0686EA3
+ },
+ {
+ 0x00000000, 0xEF306B19, 0xDB8CA0C3, 0x34BCCBDA,
+ 0xB2F53777, 0x5DC55C6E, 0x697997B4, 0x8649FCAD,
+ 0x6006181F, 0x8F367306, 0xBB8AB8DC, 0x54BAD3C5,
+ 0xD2F32F68, 0x3DC34471, 0x097F8FAB, 0xE64FE4B2,
+ 0xC00C303E, 0x2F3C5B27, 0x1B8090FD, 0xF4B0FBE4,
+ 0x72F90749, 0x9DC96C50, 0xA975A78A, 0x4645CC93,
+ 0xA00A2821, 0x4F3A4338, 0x7B8688E2, 0x94B6E3FB,
+ 0x12FF1F56, 0xFDCF744F, 0xC973BF95, 0x2643D48C,
+ 0x85F4168D, 0x6AC47D94, 0x5E78B64E, 0xB148DD57,
+ 0x370121FA, 0xD8314AE3, 0xEC8D8139, 0x03BDEA20,
+ 0xE5F20E92, 0x0AC2658B, 0x3E7EAE51, 0xD14EC548,
+ 0x570739E5, 0xB83752FC, 0x8C8B9926, 0x63BBF23F,
+ 0x45F826B3, 0xAAC84DAA, 0x9E748670, 0x7144ED69,
+ 0xF70D11C4, 0x183D7ADD, 0x2C81B107, 0xC3B1DA1E,
+ 0x25FE3EAC, 0xCACE55B5, 0xFE729E6F, 0x1142F576,
+ 0x970B09DB, 0x783B62C2, 0x4C87A918, 0xA3B7C201,
+ 0x0E045BEB, 0xE13430F2, 0xD588FB28, 0x3AB89031,
+ 0xBCF16C9C, 0x53C10785, 0x677DCC5F, 0x884DA746,
+ 0x6E0243F4, 0x813228ED, 0xB58EE337, 0x5ABE882E,
+ 0xDCF77483, 0x33C71F9A, 0x077BD440, 0xE84BBF59,
+ 0xCE086BD5, 0x213800CC, 0x1584CB16, 0xFAB4A00F,
+ 0x7CFD5CA2, 0x93CD37BB, 0xA771FC61, 0x48419778,
+ 0xAE0E73CA, 0x413E18D3, 0x7582D309, 0x9AB2B810,
+ 0x1CFB44BD, 0xF3CB2FA4, 0xC777E47E, 0x28478F67,
+ 0x8BF04D66, 0x64C0267F, 0x507CEDA5, 0xBF4C86BC,
+ 0x39057A11, 0xD6351108, 0xE289DAD2, 0x0DB9B1CB,
+ 0xEBF65579, 0x04C63E60, 0x307AF5BA, 0xDF4A9EA3,
+ 0x5903620E, 0xB6330917, 0x828FC2CD, 0x6DBFA9D4,
+ 0x4BFC7D58, 0xA4CC1641, 0x9070DD9B, 0x7F40B682,
+ 0xF9094A2F, 0x16392136, 0x2285EAEC, 0xCDB581F5,
+ 0x2BFA6547, 0xC4CA0E5E, 0xF076C584, 0x1F46AE9D,
+ 0x990F5230, 0x763F3929, 0x4283F2F3, 0xADB399EA,
+ 0x1C08B7D6, 0xF338DCCF, 0xC7841715, 0x28B47C0C,
+ 0xAEFD80A1, 0x41CDEBB8, 0x75712062, 0x9A414B7B,
+ 0x7C0EAFC9, 0x933EC4D0, 0xA7820F0A, 0x48B26413,
+ 0xCEFB98BE, 0x21CBF3A7, 0x1577387D, 0xFA475364,
+ 0xDC0487E8, 0x3334ECF1, 0x0788272B, 0xE8B84C32,
+ 0x6EF1B09F, 0x81C1DB86, 0xB57D105C, 0x5A4D7B45,
+ 0xBC029FF7, 0x5332F4EE, 0x678E3F34, 0x88BE542D,
+ 0x0EF7A880, 0xE1C7C399, 0xD57B0843, 0x3A4B635A,
+ 0x99FCA15B, 0x76CCCA42, 0x42700198, 0xAD406A81,
+ 0x2B09962C, 0xC439FD35, 0xF08536EF, 0x1FB55DF6,
+ 0xF9FAB944, 0x16CAD25D, 0x22761987, 0xCD46729E,
+ 0x4B0F8E33, 0xA43FE52A, 0x90832EF0, 0x7FB345E9,
+ 0x59F09165, 0xB6C0FA7C, 0x827C31A6, 0x6D4C5ABF,
+ 0xEB05A612, 0x0435CD0B, 0x308906D1, 0xDFB96DC8,
+ 0x39F6897A, 0xD6C6E263, 0xE27A29B9, 0x0D4A42A0,
+ 0x8B03BE0D, 0x6433D514, 0x508F1ECE, 0xBFBF75D7,
+ 0x120CEC3D, 0xFD3C8724, 0xC9804CFE, 0x26B027E7,
+ 0xA0F9DB4A, 0x4FC9B053, 0x7B757B89, 0x94451090,
+ 0x720AF422, 0x9D3A9F3B, 0xA98654E1, 0x46B63FF8,
+ 0xC0FFC355, 0x2FCFA84C, 0x1B736396, 0xF443088F,
+ 0xD200DC03, 0x3D30B71A, 0x098C7CC0, 0xE6BC17D9,
+ 0x60F5EB74, 0x8FC5806D, 0xBB794BB7, 0x544920AE,
+ 0xB206C41C, 0x5D36AF05, 0x698A64DF, 0x86BA0FC6,
+ 0x00F3F36B, 0xEFC39872, 0xDB7F53A8, 0x344F38B1,
+ 0x97F8FAB0, 0x78C891A9, 0x4C745A73, 0xA344316A,
+ 0x250DCDC7, 0xCA3DA6DE, 0xFE816D04, 0x11B1061D,
+ 0xF7FEE2AF, 0x18CE89B6, 0x2C72426C, 0xC3422975,
+ 0x450BD5D8, 0xAA3BBEC1, 0x9E87751B, 0x71B71E02,
+ 0x57F4CA8E, 0xB8C4A197, 0x8C786A4D, 0x63480154,
+ 0xE501FDF9, 0x0A3196E0, 0x3E8D5D3A, 0xD1BD3623,
+ 0x37F2D291, 0xD8C2B988, 0xEC7E7252, 0x034E194B,
+ 0x8507E5E6, 0x6A378EFF, 0x5E8B4525, 0xB1BB2E3C
+ },
+ {
+ 0x00000000, 0x68032CC8, 0xD0065990, 0xB8057558,
+ 0xA5E0C5D1, 0xCDE3E919, 0x75E69C41, 0x1DE5B089,
+ 0x4E2DFD53, 0x262ED19B, 0x9E2BA4C3, 0xF628880B,
+ 0xEBCD3882, 0x83CE144A, 0x3BCB6112, 0x53C84DDA,
+ 0x9C5BFAA6, 0xF458D66E, 0x4C5DA336, 0x245E8FFE,
+ 0x39BB3F77, 0x51B813BF, 0xE9BD66E7, 0x81BE4A2F,
+ 0xD27607F5, 0xBA752B3D, 0x02705E65, 0x6A7372AD,
+ 0x7796C224, 0x1F95EEEC, 0xA7909BB4, 0xCF93B77C,
+ 0x3D5B83BD, 0x5558AF75, 0xED5DDA2D, 0x855EF6E5,
+ 0x98BB466C, 0xF0B86AA4, 0x48BD1FFC, 0x20BE3334,
+ 0x73767EEE, 0x1B755226, 0xA370277E, 0xCB730BB6,
+ 0xD696BB3F, 0xBE9597F7, 0x0690E2AF, 0x6E93CE67,
+ 0xA100791B, 0xC90355D3, 0x7106208B, 0x19050C43,
+ 0x04E0BCCA, 0x6CE39002, 0xD4E6E55A, 0xBCE5C992,
+ 0xEF2D8448, 0x872EA880, 0x3F2BDDD8, 0x5728F110,
+ 0x4ACD4199, 0x22CE6D51, 0x9ACB1809, 0xF2C834C1,
+ 0x7AB7077A, 0x12B42BB2, 0xAAB15EEA, 0xC2B27222,
+ 0xDF57C2AB, 0xB754EE63, 0x0F519B3B, 0x6752B7F3,
+ 0x349AFA29, 0x5C99D6E1, 0xE49CA3B9, 0x8C9F8F71,
+ 0x917A3FF8, 0xF9791330, 0x417C6668, 0x297F4AA0,
+ 0xE6ECFDDC, 0x8EEFD114, 0x36EAA44C, 0x5EE98884,
+ 0x430C380D, 0x2B0F14C5, 0x930A619D, 0xFB094D55,
+ 0xA8C1008F, 0xC0C22C47, 0x78C7591F, 0x10C475D7,
+ 0x0D21C55E, 0x6522E996, 0xDD279CCE, 0xB524B006,
+ 0x47EC84C7, 0x2FEFA80F, 0x97EADD57, 0xFFE9F19F,
+ 0xE20C4116, 0x8A0F6DDE, 0x320A1886, 0x5A09344E,
+ 0x09C17994, 0x61C2555C, 0xD9C72004, 0xB1C40CCC,
+ 0xAC21BC45, 0xC422908D, 0x7C27E5D5, 0x1424C91D,
+ 0xDBB77E61, 0xB3B452A9, 0x0BB127F1, 0x63B20B39,
+ 0x7E57BBB0, 0x16549778, 0xAE51E220, 0xC652CEE8,
+ 0x959A8332, 0xFD99AFFA, 0x459CDAA2, 0x2D9FF66A,
+ 0x307A46E3, 0x58796A2B, 0xE07C1F73, 0x887F33BB,
+ 0xF56E0EF4, 0x9D6D223C, 0x25685764, 0x4D6B7BAC,
+ 0x508ECB25, 0x388DE7ED, 0x808892B5, 0xE88BBE7D,
+ 0xBB43F3A7, 0xD340DF6F, 0x6B45AA37, 0x034686FF,
+ 0x1EA33676, 0x76A01ABE, 0xCEA56FE6, 0xA6A6432E,
+ 0x6935F452, 0x0136D89A, 0xB933ADC2, 0xD130810A,
+ 0xCCD53183, 0xA4D61D4B, 0x1CD36813, 0x74D044DB,
+ 0x27180901, 0x4F1B25C9, 0xF71E5091, 0x9F1D7C59,
+ 0x82F8CCD0, 0xEAFBE018, 0x52FE9540, 0x3AFDB988,
+ 0xC8358D49, 0xA036A181, 0x1833D4D9, 0x7030F811,
+ 0x6DD54898, 0x05D66450, 0xBDD31108, 0xD5D03DC0,
+ 0x8618701A, 0xEE1B5CD2, 0x561E298A, 0x3E1D0542,
+ 0x23F8B5CB, 0x4BFB9903, 0xF3FEEC5B, 0x9BFDC093,
+ 0x546E77EF, 0x3C6D5B27, 0x84682E7F, 0xEC6B02B7,
+ 0xF18EB23E, 0x998D9EF6, 0x2188EBAE, 0x498BC766,
+ 0x1A438ABC, 0x7240A674, 0xCA45D32C, 0xA246FFE4,
+ 0xBFA34F6D, 0xD7A063A5, 0x6FA516FD, 0x07A63A35,
+ 0x8FD9098E, 0xE7DA2546, 0x5FDF501E, 0x37DC7CD6,
+ 0x2A39CC5F, 0x423AE097, 0xFA3F95CF, 0x923CB907,
+ 0xC1F4F4DD, 0xA9F7D815, 0x11F2AD4D, 0x79F18185,
+ 0x6414310C, 0x0C171DC4, 0xB412689C, 0xDC114454,
+ 0x1382F328, 0x7B81DFE0, 0xC384AAB8, 0xAB878670,
+ 0xB66236F9, 0xDE611A31, 0x66646F69, 0x0E6743A1,
+ 0x5DAF0E7B, 0x35AC22B3, 0x8DA957EB, 0xE5AA7B23,
+ 0xF84FCBAA, 0x904CE762, 0x2849923A, 0x404ABEF2,
+ 0xB2828A33, 0xDA81A6FB, 0x6284D3A3, 0x0A87FF6B,
+ 0x17624FE2, 0x7F61632A, 0xC7641672, 0xAF673ABA,
+ 0xFCAF7760, 0x94AC5BA8, 0x2CA92EF0, 0x44AA0238,
+ 0x594FB2B1, 0x314C9E79, 0x8949EB21, 0xE14AC7E9,
+ 0x2ED97095, 0x46DA5C5D, 0xFEDF2905, 0x96DC05CD,
+ 0x8B39B544, 0xE33A998C, 0x5B3FECD4, 0x333CC01C,
+ 0x60F48DC6, 0x08F7A10E, 0xB0F2D456, 0xD8F1F89E,
+ 0xC5144817, 0xAD1764DF, 0x15121187, 0x7D113D4F
+ },
+ {
+ 0x00000000, 0x493C7D27, 0x9278FA4E, 0xDB448769,
+ 0x211D826D, 0x6821FF4A, 0xB3657823, 0xFA590504,
+ 0x423B04DA, 0x0B0779FD, 0xD043FE94, 0x997F83B3,
+ 0x632686B7, 0x2A1AFB90, 0xF15E7CF9, 0xB86201DE,
+ 0x847609B4, 0xCD4A7493, 0x160EF3FA, 0x5F328EDD,
+ 0xA56B8BD9, 0xEC57F6FE, 0x37137197, 0x7E2F0CB0,
+ 0xC64D0D6E, 0x8F717049, 0x5435F720, 0x1D098A07,
+ 0xE7508F03, 0xAE6CF224, 0x7528754D, 0x3C14086A,
+ 0x0D006599, 0x443C18BE, 0x9F789FD7, 0xD644E2F0,
+ 0x2C1DE7F4, 0x65219AD3, 0xBE651DBA, 0xF759609D,
+ 0x4F3B6143, 0x06071C64, 0xDD439B0D, 0x947FE62A,
+ 0x6E26E32E, 0x271A9E09, 0xFC5E1960, 0xB5626447,
+ 0x89766C2D, 0xC04A110A, 0x1B0E9663, 0x5232EB44,
+ 0xA86BEE40, 0xE1579367, 0x3A13140E, 0x732F6929,
+ 0xCB4D68F7, 0x827115D0, 0x593592B9, 0x1009EF9E,
+ 0xEA50EA9A, 0xA36C97BD, 0x782810D4, 0x31146DF3,
+ 0x1A00CB32, 0x533CB615, 0x8878317C, 0xC1444C5B,
+ 0x3B1D495F, 0x72213478, 0xA965B311, 0xE059CE36,
+ 0x583BCFE8, 0x1107B2CF, 0xCA4335A6, 0x837F4881,
+ 0x79264D85, 0x301A30A2, 0xEB5EB7CB, 0xA262CAEC,
+ 0x9E76C286, 0xD74ABFA1, 0x0C0E38C8, 0x453245EF,
+ 0xBF6B40EB, 0xF6573DCC, 0x2D13BAA5, 0x642FC782,
+ 0xDC4DC65C, 0x9571BB7B, 0x4E353C12, 0x07094135,
+ 0xFD504431, 0xB46C3916, 0x6F28BE7F, 0x2614C358,
+ 0x1700AEAB, 0x5E3CD38C, 0x857854E5, 0xCC4429C2,
+ 0x361D2CC6, 0x7F2151E1, 0xA465D688, 0xED59ABAF,
+ 0x553BAA71, 0x1C07D756, 0xC743503F, 0x8E7F2D18,
+ 0x7426281C, 0x3D1A553B, 0xE65ED252, 0xAF62AF75,
+ 0x9376A71F, 0xDA4ADA38, 0x010E5D51, 0x48322076,
+ 0xB26B2572, 0xFB575855, 0x2013DF3C, 0x692FA21B,
+ 0xD14DA3C5, 0x9871DEE2, 0x4335598B, 0x0A0924AC,
+ 0xF05021A8, 0xB96C5C8F, 0x6228DBE6, 0x2B14A6C1,
+ 0x34019664, 0x7D3DEB43, 0xA6796C2A, 0xEF45110D,
+ 0x151C1409, 0x5C20692E, 0x8764EE47, 0xCE589360,
+ 0x763A92BE, 0x3F06EF99, 0xE44268F0, 0xAD7E15D7,
+ 0x572710D3, 0x1E1B6DF4, 0xC55FEA9D, 0x8C6397BA,
+ 0xB0779FD0, 0xF94BE2F7, 0x220F659E, 0x6B3318B9,
+ 0x916A1DBD, 0xD856609A, 0x0312E7F3, 0x4A2E9AD4,
+ 0xF24C9B0A, 0xBB70E62D, 0x60346144, 0x29081C63,
+ 0xD3511967, 0x9A6D6440, 0x4129E329, 0x08159E0E,
+ 0x3901F3FD, 0x703D8EDA, 0xAB7909B3, 0xE2457494,
+ 0x181C7190, 0x51200CB7, 0x8A648BDE, 0xC358F6F9,
+ 0x7B3AF727, 0x32068A00, 0xE9420D69, 0xA07E704E,
+ 0x5A27754A, 0x131B086D, 0xC85F8F04, 0x8163F223,
+ 0xBD77FA49, 0xF44B876E, 0x2F0F0007, 0x66337D20,
+ 0x9C6A7824, 0xD5560503, 0x0E12826A, 0x472EFF4D,
+ 0xFF4CFE93, 0xB67083B4, 0x6D3404DD, 0x240879FA,
+ 0xDE517CFE, 0x976D01D9, 0x4C2986B0, 0x0515FB97,
+ 0x2E015D56, 0x673D2071, 0xBC79A718, 0xF545DA3F,
+ 0x0F1CDF3B, 0x4620A21C, 0x9D642575, 0xD4585852,
+ 0x6C3A598C, 0x250624AB, 0xFE42A3C2, 0xB77EDEE5,
+ 0x4D27DBE1, 0x041BA6C6, 0xDF5F21AF, 0x96635C88,
+ 0xAA7754E2, 0xE34B29C5, 0x380FAEAC, 0x7133D38B,
+ 0x8B6AD68F, 0xC256ABA8, 0x19122CC1, 0x502E51E6,
+ 0xE84C5038, 0xA1702D1F, 0x7A34AA76, 0x3308D751,
+ 0xC951D255, 0x806DAF72, 0x5B29281B, 0x1215553C,
+ 0x230138CF, 0x6A3D45E8, 0xB179C281, 0xF845BFA6,
+ 0x021CBAA2, 0x4B20C785, 0x906440EC, 0xD9583DCB,
+ 0x613A3C15, 0x28064132, 0xF342C65B, 0xBA7EBB7C,
+ 0x4027BE78, 0x091BC35F, 0xD25F4436, 0x9B633911,
+ 0xA777317B, 0xEE4B4C5C, 0x350FCB35, 0x7C33B612,
+ 0x866AB316, 0xCF56CE31, 0x14124958, 0x5D2E347F,
+ 0xE54C35A1, 0xAC704886, 0x7734CFEF, 0x3E08B2C8,
+ 0xC451B7CC, 0x8D6DCAEB, 0x56294D82, 0x1F1530A5
+ }
+#else /* !WORDS_BIGENDIAN */
+ {
+ 0x00000000, 0x03836BF2, 0xF7703BE1, 0xF4F35013,
+ 0x1F979AC7, 0x1C14F135, 0xE8E7A126, 0xEB64CAD4,
+ 0xCF58D98A, 0xCCDBB278, 0x3828E26B, 0x3BAB8999,
+ 0xD0CF434D, 0xD34C28BF, 0x27BF78AC, 0x243C135E,
+ 0x6FC75E10, 0x6C4435E2, 0x98B765F1, 0x9B340E03,
+ 0x7050C4D7, 0x73D3AF25, 0x8720FF36, 0x84A394C4,
+ 0xA09F879A, 0xA31CEC68, 0x57EFBC7B, 0x546CD789,
+ 0xBF081D5D, 0xBC8B76AF, 0x487826BC, 0x4BFB4D4E,
+ 0xDE8EBD20, 0xDD0DD6D2, 0x29FE86C1, 0x2A7DED33,
+ 0xC11927E7, 0xC29A4C15, 0x36691C06, 0x35EA77F4,
+ 0x11D664AA, 0x12550F58, 0xE6A65F4B, 0xE52534B9,
+ 0x0E41FE6D, 0x0DC2959F, 0xF931C58C, 0xFAB2AE7E,
+ 0xB149E330, 0xB2CA88C2, 0x4639D8D1, 0x45BAB323,
+ 0xAEDE79F7, 0xAD5D1205, 0x59AE4216, 0x5A2D29E4,
+ 0x7E113ABA, 0x7D925148, 0x8961015B, 0x8AE26AA9,
+ 0x6186A07D, 0x6205CB8F, 0x96F69B9C, 0x9575F06E,
+ 0xBC1D7B41, 0xBF9E10B3, 0x4B6D40A0, 0x48EE2B52,
+ 0xA38AE186, 0xA0098A74, 0x54FADA67, 0x5779B195,
+ 0x7345A2CB, 0x70C6C939, 0x8435992A, 0x87B6F2D8,
+ 0x6CD2380C, 0x6F5153FE, 0x9BA203ED, 0x9821681F,
+ 0xD3DA2551, 0xD0594EA3, 0x24AA1EB0, 0x27297542,
+ 0xCC4DBF96, 0xCFCED464, 0x3B3D8477, 0x38BEEF85,
+ 0x1C82FCDB, 0x1F019729, 0xEBF2C73A, 0xE871ACC8,
+ 0x0315661C, 0x00960DEE, 0xF4655DFD, 0xF7E6360F,
+ 0x6293C661, 0x6110AD93, 0x95E3FD80, 0x96609672,
+ 0x7D045CA6, 0x7E873754, 0x8A746747, 0x89F70CB5,
+ 0xADCB1FEB, 0xAE487419, 0x5ABB240A, 0x59384FF8,
+ 0xB25C852C, 0xB1DFEEDE, 0x452CBECD, 0x46AFD53F,
+ 0x0D549871, 0x0ED7F383, 0xFA24A390, 0xF9A7C862,
+ 0x12C302B6, 0x11406944, 0xE5B33957, 0xE63052A5,
+ 0xC20C41FB, 0xC18F2A09, 0x357C7A1A, 0x36FF11E8,
+ 0xDD9BDB3C, 0xDE18B0CE, 0x2AEBE0DD, 0x29688B2F,
+ 0x783BF682, 0x7BB89D70, 0x8F4BCD63, 0x8CC8A691,
+ 0x67AC6C45, 0x642F07B7, 0x90DC57A4, 0x935F3C56,
+ 0xB7632F08, 0xB4E044FA, 0x401314E9, 0x43907F1B,
+ 0xA8F4B5CF, 0xAB77DE3D, 0x5F848E2E, 0x5C07E5DC,
+ 0x17FCA892, 0x147FC360, 0xE08C9373, 0xE30FF881,
+ 0x086B3255, 0x0BE859A7, 0xFF1B09B4, 0xFC986246,
+ 0xD8A47118, 0xDB271AEA, 0x2FD44AF9, 0x2C57210B,
+ 0xC733EBDF, 0xC4B0802D, 0x3043D03E, 0x33C0BBCC,
+ 0xA6B54BA2, 0xA5362050, 0x51C57043, 0x52461BB1,
+ 0xB922D165, 0xBAA1BA97, 0x4E52EA84, 0x4DD18176,
+ 0x69ED9228, 0x6A6EF9DA, 0x9E9DA9C9, 0x9D1EC23B,
+ 0x767A08EF, 0x75F9631D, 0x810A330E, 0x828958FC,
+ 0xC97215B2, 0xCAF17E40, 0x3E022E53, 0x3D8145A1,
+ 0xD6E58F75, 0xD566E487, 0x2195B494, 0x2216DF66,
+ 0x062ACC38, 0x05A9A7CA, 0xF15AF7D9, 0xF2D99C2B,
+ 0x19BD56FF, 0x1A3E3D0D, 0xEECD6D1E, 0xED4E06EC,
+ 0xC4268DC3, 0xC7A5E631, 0x3356B622, 0x30D5DDD0,
+ 0xDBB11704, 0xD8327CF6, 0x2CC12CE5, 0x2F424717,
+ 0x0B7E5449, 0x08FD3FBB, 0xFC0E6FA8, 0xFF8D045A,
+ 0x14E9CE8E, 0x176AA57C, 0xE399F56F, 0xE01A9E9D,
+ 0xABE1D3D3, 0xA862B821, 0x5C91E832, 0x5F1283C0,
+ 0xB4764914, 0xB7F522E6, 0x430672F5, 0x40851907,
+ 0x64B90A59, 0x673A61AB, 0x93C931B8, 0x904A5A4A,
+ 0x7B2E909E, 0x78ADFB6C, 0x8C5EAB7F, 0x8FDDC08D,
+ 0x1AA830E3, 0x192B5B11, 0xEDD80B02, 0xEE5B60F0,
+ 0x053FAA24, 0x06BCC1D6, 0xF24F91C5, 0xF1CCFA37,
+ 0xD5F0E969, 0xD673829B, 0x2280D288, 0x2103B97A,
+ 0xCA6773AE, 0xC9E4185C, 0x3D17484F, 0x3E9423BD,
+ 0x756F6EF3, 0x76EC0501, 0x821F5512, 0x819C3EE0,
+ 0x6AF8F434, 0x697B9FC6, 0x9D88CFD5, 0x9E0BA427,
+ 0xBA37B779, 0xB9B4DC8B, 0x4D478C98, 0x4EC4E76A,
+ 0xA5A02DBE, 0xA623464C, 0x52D0165F, 0x51537DAD,
+ },
+ {
+ 0x00000000, 0x7798A213, 0xEE304527, 0x99A8E734,
+ 0xDC618A4E, 0xABF9285D, 0x3251CF69, 0x45C96D7A,
+ 0xB8C3149D, 0xCF5BB68E, 0x56F351BA, 0x216BF3A9,
+ 0x64A29ED3, 0x133A3CC0, 0x8A92DBF4, 0xFD0A79E7,
+ 0x81F1C53F, 0xF669672C, 0x6FC18018, 0x1859220B,
+ 0x5D904F71, 0x2A08ED62, 0xB3A00A56, 0xC438A845,
+ 0x3932D1A2, 0x4EAA73B1, 0xD7029485, 0xA09A3696,
+ 0xE5535BEC, 0x92CBF9FF, 0x0B631ECB, 0x7CFBBCD8,
+ 0x02E38B7F, 0x757B296C, 0xECD3CE58, 0x9B4B6C4B,
+ 0xDE820131, 0xA91AA322, 0x30B24416, 0x472AE605,
+ 0xBA209FE2, 0xCDB83DF1, 0x5410DAC5, 0x238878D6,
+ 0x664115AC, 0x11D9B7BF, 0x8871508B, 0xFFE9F298,
+ 0x83124E40, 0xF48AEC53, 0x6D220B67, 0x1ABAA974,
+ 0x5F73C40E, 0x28EB661D, 0xB1438129, 0xC6DB233A,
+ 0x3BD15ADD, 0x4C49F8CE, 0xD5E11FFA, 0xA279BDE9,
+ 0xE7B0D093, 0x90287280, 0x098095B4, 0x7E1837A7,
+ 0x04C617FF, 0x735EB5EC, 0xEAF652D8, 0x9D6EF0CB,
+ 0xD8A79DB1, 0xAF3F3FA2, 0x3697D896, 0x410F7A85,
+ 0xBC050362, 0xCB9DA171, 0x52354645, 0x25ADE456,
+ 0x6064892C, 0x17FC2B3F, 0x8E54CC0B, 0xF9CC6E18,
+ 0x8537D2C0, 0xF2AF70D3, 0x6B0797E7, 0x1C9F35F4,
+ 0x5956588E, 0x2ECEFA9D, 0xB7661DA9, 0xC0FEBFBA,
+ 0x3DF4C65D, 0x4A6C644E, 0xD3C4837A, 0xA45C2169,
+ 0xE1954C13, 0x960DEE00, 0x0FA50934, 0x783DAB27,
+ 0x06259C80, 0x71BD3E93, 0xE815D9A7, 0x9F8D7BB4,
+ 0xDA4416CE, 0xADDCB4DD, 0x347453E9, 0x43ECF1FA,
+ 0xBEE6881D, 0xC97E2A0E, 0x50D6CD3A, 0x274E6F29,
+ 0x62870253, 0x151FA040, 0x8CB74774, 0xFB2FE567,
+ 0x87D459BF, 0xF04CFBAC, 0x69E41C98, 0x1E7CBE8B,
+ 0x5BB5D3F1, 0x2C2D71E2, 0xB58596D6, 0xC21D34C5,
+ 0x3F174D22, 0x488FEF31, 0xD1270805, 0xA6BFAA16,
+ 0xE376C76C, 0x94EE657F, 0x0D46824B, 0x7ADE2058,
+ 0xF9FAC3FB, 0x8E6261E8, 0x17CA86DC, 0x605224CF,
+ 0x259B49B5, 0x5203EBA6, 0xCBAB0C92, 0xBC33AE81,
+ 0x4139D766, 0x36A17575, 0xAF099241, 0xD8913052,
+ 0x9D585D28, 0xEAC0FF3B, 0x7368180F, 0x04F0BA1C,
+ 0x780B06C4, 0x0F93A4D7, 0x963B43E3, 0xE1A3E1F0,
+ 0xA46A8C8A, 0xD3F22E99, 0x4A5AC9AD, 0x3DC26BBE,
+ 0xC0C81259, 0xB750B04A, 0x2EF8577E, 0x5960F56D,
+ 0x1CA99817, 0x6B313A04, 0xF299DD30, 0x85017F23,
+ 0xFB194884, 0x8C81EA97, 0x15290DA3, 0x62B1AFB0,
+ 0x2778C2CA, 0x50E060D9, 0xC94887ED, 0xBED025FE,
+ 0x43DA5C19, 0x3442FE0A, 0xADEA193E, 0xDA72BB2D,
+ 0x9FBBD657, 0xE8237444, 0x718B9370, 0x06133163,
+ 0x7AE88DBB, 0x0D702FA8, 0x94D8C89C, 0xE3406A8F,
+ 0xA68907F5, 0xD111A5E6, 0x48B942D2, 0x3F21E0C1,
+ 0xC22B9926, 0xB5B33B35, 0x2C1BDC01, 0x5B837E12,
+ 0x1E4A1368, 0x69D2B17B, 0xF07A564F, 0x87E2F45C,
+ 0xFD3CD404, 0x8AA47617, 0x130C9123, 0x64943330,
+ 0x215D5E4A, 0x56C5FC59, 0xCF6D1B6D, 0xB8F5B97E,
+ 0x45FFC099, 0x3267628A, 0xABCF85BE, 0xDC5727AD,
+ 0x999E4AD7, 0xEE06E8C4, 0x77AE0FF0, 0x0036ADE3,
+ 0x7CCD113B, 0x0B55B328, 0x92FD541C, 0xE565F60F,
+ 0xA0AC9B75, 0xD7343966, 0x4E9CDE52, 0x39047C41,
+ 0xC40E05A6, 0xB396A7B5, 0x2A3E4081, 0x5DA6E292,
+ 0x186F8FE8, 0x6FF72DFB, 0xF65FCACF, 0x81C768DC,
+ 0xFFDF5F7B, 0x8847FD68, 0x11EF1A5C, 0x6677B84F,
+ 0x23BED535, 0x54267726, 0xCD8E9012, 0xBA163201,
+ 0x471C4BE6, 0x3084E9F5, 0xA92C0EC1, 0xDEB4ACD2,
+ 0x9B7DC1A8, 0xECE563BB, 0x754D848F, 0x02D5269C,
+ 0x7E2E9A44, 0x09B63857, 0x901EDF63, 0xE7867D70,
+ 0xA24F100A, 0xD5D7B219, 0x4C7F552D, 0x3BE7F73E,
+ 0xC6ED8ED9, 0xB1752CCA, 0x28DDCBFE, 0x5F4569ED,
+ 0x1A8C0497, 0x6D14A684, 0xF4BC41B0, 0x8324E3A3,
+ },
+ {
+ 0x00000000, 0x7E9241A5, 0x0D526F4F, 0x73C02EEA,
+ 0x1AA4DE9E, 0x64369F3B, 0x17F6B1D1, 0x6964F074,
+ 0xC53E5138, 0xBBAC109D, 0xC86C3E77, 0xB6FE7FD2,
+ 0xDF9A8FA6, 0xA108CE03, 0xD2C8E0E9, 0xAC5AA14C,
+ 0x8A7DA270, 0xF4EFE3D5, 0x872FCD3F, 0xF9BD8C9A,
+ 0x90D97CEE, 0xEE4B3D4B, 0x9D8B13A1, 0xE3195204,
+ 0x4F43F348, 0x31D1B2ED, 0x42119C07, 0x3C83DDA2,
+ 0x55E72DD6, 0x2B756C73, 0x58B54299, 0x2627033C,
+ 0x14FB44E1, 0x6A690544, 0x19A92BAE, 0x673B6A0B,
+ 0x0E5F9A7F, 0x70CDDBDA, 0x030DF530, 0x7D9FB495,
+ 0xD1C515D9, 0xAF57547C, 0xDC977A96, 0xA2053B33,
+ 0xCB61CB47, 0xB5F38AE2, 0xC633A408, 0xB8A1E5AD,
+ 0x9E86E691, 0xE014A734, 0x93D489DE, 0xED46C87B,
+ 0x8422380F, 0xFAB079AA, 0x89705740, 0xF7E216E5,
+ 0x5BB8B7A9, 0x252AF60C, 0x56EAD8E6, 0x28789943,
+ 0x411C6937, 0x3F8E2892, 0x4C4E0678, 0x32DC47DD,
+ 0xD98065C7, 0xA7122462, 0xD4D20A88, 0xAA404B2D,
+ 0xC324BB59, 0xBDB6FAFC, 0xCE76D416, 0xB0E495B3,
+ 0x1CBE34FF, 0x622C755A, 0x11EC5BB0, 0x6F7E1A15,
+ 0x061AEA61, 0x7888ABC4, 0x0B48852E, 0x75DAC48B,
+ 0x53FDC7B7, 0x2D6F8612, 0x5EAFA8F8, 0x203DE95D,
+ 0x49591929, 0x37CB588C, 0x440B7666, 0x3A9937C3,
+ 0x96C3968F, 0xE851D72A, 0x9B91F9C0, 0xE503B865,
+ 0x8C674811, 0xF2F509B4, 0x8135275E, 0xFFA766FB,
+ 0xCD7B2126, 0xB3E96083, 0xC0294E69, 0xBEBB0FCC,
+ 0xD7DFFFB8, 0xA94DBE1D, 0xDA8D90F7, 0xA41FD152,
+ 0x0845701E, 0x76D731BB, 0x05171F51, 0x7B855EF4,
+ 0x12E1AE80, 0x6C73EF25, 0x1FB3C1CF, 0x6121806A,
+ 0x47068356, 0x3994C2F3, 0x4A54EC19, 0x34C6ADBC,
+ 0x5DA25DC8, 0x23301C6D, 0x50F03287, 0x2E627322,
+ 0x8238D26E, 0xFCAA93CB, 0x8F6ABD21, 0xF1F8FC84,
+ 0x989C0CF0, 0xE60E4D55, 0x95CE63BF, 0xEB5C221A,
+ 0x4377278B, 0x3DE5662E, 0x4E2548C4, 0x30B70961,
+ 0x59D3F915, 0x2741B8B0, 0x5481965A, 0x2A13D7FF,
+ 0x864976B3, 0xF8DB3716, 0x8B1B19FC, 0xF5895859,
+ 0x9CEDA82D, 0xE27FE988, 0x91BFC762, 0xEF2D86C7,
+ 0xC90A85FB, 0xB798C45E, 0xC458EAB4, 0xBACAAB11,
+ 0xD3AE5B65, 0xAD3C1AC0, 0xDEFC342A, 0xA06E758F,
+ 0x0C34D4C3, 0x72A69566, 0x0166BB8C, 0x7FF4FA29,
+ 0x16900A5D, 0x68024BF8, 0x1BC26512, 0x655024B7,
+ 0x578C636A, 0x291E22CF, 0x5ADE0C25, 0x244C4D80,
+ 0x4D28BDF4, 0x33BAFC51, 0x407AD2BB, 0x3EE8931E,
+ 0x92B23252, 0xEC2073F7, 0x9FE05D1D, 0xE1721CB8,
+ 0x8816ECCC, 0xF684AD69, 0x85448383, 0xFBD6C226,
+ 0xDDF1C11A, 0xA36380BF, 0xD0A3AE55, 0xAE31EFF0,
+ 0xC7551F84, 0xB9C75E21, 0xCA0770CB, 0xB495316E,
+ 0x18CF9022, 0x665DD187, 0x159DFF6D, 0x6B0FBEC8,
+ 0x026B4EBC, 0x7CF90F19, 0x0F3921F3, 0x71AB6056,
+ 0x9AF7424C, 0xE46503E9, 0x97A52D03, 0xE9376CA6,
+ 0x80539CD2, 0xFEC1DD77, 0x8D01F39D, 0xF393B238,
+ 0x5FC91374, 0x215B52D1, 0x529B7C3B, 0x2C093D9E,
+ 0x456DCDEA, 0x3BFF8C4F, 0x483FA2A5, 0x36ADE300,
+ 0x108AE03C, 0x6E18A199, 0x1DD88F73, 0x634ACED6,
+ 0x0A2E3EA2, 0x74BC7F07, 0x077C51ED, 0x79EE1048,
+ 0xD5B4B104, 0xAB26F0A1, 0xD8E6DE4B, 0xA6749FEE,
+ 0xCF106F9A, 0xB1822E3F, 0xC24200D5, 0xBCD04170,
+ 0x8E0C06AD, 0xF09E4708, 0x835E69E2, 0xFDCC2847,
+ 0x94A8D833, 0xEA3A9996, 0x99FAB77C, 0xE768F6D9,
+ 0x4B325795, 0x35A01630, 0x466038DA, 0x38F2797F,
+ 0x5196890B, 0x2F04C8AE, 0x5CC4E644, 0x2256A7E1,
+ 0x0471A4DD, 0x7AE3E578, 0x0923CB92, 0x77B18A37,
+ 0x1ED57A43, 0x60473BE6, 0x1387150C, 0x6D1554A9,
+ 0xC14FF5E5, 0xBFDDB440, 0xCC1D9AAA, 0xB28FDB0F,
+ 0xDBEB2B7B, 0xA5796ADE, 0xD6B94434, 0xA82B0591,
+ },
+ {
+ 0x00000000, 0xB8AA45DD, 0x812367BF, 0x39892262,
+ 0xF331227B, 0x4B9B67A6, 0x721245C4, 0xCAB80019,
+ 0xE66344F6, 0x5EC9012B, 0x67402349, 0xDFEA6694,
+ 0x1552668D, 0xADF82350, 0x94710132, 0x2CDB44EF,
+ 0x3DB164E9, 0x851B2134, 0xBC920356, 0x0438468B,
+ 0xCE804692, 0x762A034F, 0x4FA3212D, 0xF70964F0,
+ 0xDBD2201F, 0x637865C2, 0x5AF147A0, 0xE25B027D,
+ 0x28E30264, 0x904947B9, 0xA9C065DB, 0x116A2006,
+ 0x8B1425D7, 0x33BE600A, 0x0A374268, 0xB29D07B5,
+ 0x782507AC, 0xC08F4271, 0xF9066013, 0x41AC25CE,
+ 0x6D776121, 0xD5DD24FC, 0xEC54069E, 0x54FE4343,
+ 0x9E46435A, 0x26EC0687, 0x1F6524E5, 0xA7CF6138,
+ 0xB6A5413E, 0x0E0F04E3, 0x37862681, 0x8F2C635C,
+ 0x45946345, 0xFD3E2698, 0xC4B704FA, 0x7C1D4127,
+ 0x50C605C8, 0xE86C4015, 0xD1E56277, 0x694F27AA,
+ 0xA3F727B3, 0x1B5D626E, 0x22D4400C, 0x9A7E05D1,
+ 0xE75FA6AB, 0x5FF5E376, 0x667CC114, 0xDED684C9,
+ 0x146E84D0, 0xACC4C10D, 0x954DE36F, 0x2DE7A6B2,
+ 0x013CE25D, 0xB996A780, 0x801F85E2, 0x38B5C03F,
+ 0xF20DC026, 0x4AA785FB, 0x732EA799, 0xCB84E244,
+ 0xDAEEC242, 0x6244879F, 0x5BCDA5FD, 0xE367E020,
+ 0x29DFE039, 0x9175A5E4, 0xA8FC8786, 0x1056C25B,
+ 0x3C8D86B4, 0x8427C369, 0xBDAEE10B, 0x0504A4D6,
+ 0xCFBCA4CF, 0x7716E112, 0x4E9FC370, 0xF63586AD,
+ 0x6C4B837C, 0xD4E1C6A1, 0xED68E4C3, 0x55C2A11E,
+ 0x9F7AA107, 0x27D0E4DA, 0x1E59C6B8, 0xA6F38365,
+ 0x8A28C78A, 0x32828257, 0x0B0BA035, 0xB3A1E5E8,
+ 0x7919E5F1, 0xC1B3A02C, 0xF83A824E, 0x4090C793,
+ 0x51FAE795, 0xE950A248, 0xD0D9802A, 0x6873C5F7,
+ 0xA2CBC5EE, 0x1A618033, 0x23E8A251, 0x9B42E78C,
+ 0xB799A363, 0x0F33E6BE, 0x36BAC4DC, 0x8E108101,
+ 0x44A88118, 0xFC02C4C5, 0xC58BE6A7, 0x7D21A37A,
+ 0x3FC9A052, 0x8763E58F, 0xBEEAC7ED, 0x06408230,
+ 0xCCF88229, 0x7452C7F4, 0x4DDBE596, 0xF571A04B,
+ 0xD9AAE4A4, 0x6100A179, 0x5889831B, 0xE023C6C6,
+ 0x2A9BC6DF, 0x92318302, 0xABB8A160, 0x1312E4BD,
+ 0x0278C4BB, 0xBAD28166, 0x835BA304, 0x3BF1E6D9,
+ 0xF149E6C0, 0x49E3A31D, 0x706A817F, 0xC8C0C4A2,
+ 0xE41B804D, 0x5CB1C590, 0x6538E7F2, 0xDD92A22F,
+ 0x172AA236, 0xAF80E7EB, 0x9609C589, 0x2EA38054,
+ 0xB4DD8585, 0x0C77C058, 0x35FEE23A, 0x8D54A7E7,
+ 0x47ECA7FE, 0xFF46E223, 0xC6CFC041, 0x7E65859C,
+ 0x52BEC173, 0xEA1484AE, 0xD39DA6CC, 0x6B37E311,
+ 0xA18FE308, 0x1925A6D5, 0x20AC84B7, 0x9806C16A,
+ 0x896CE16C, 0x31C6A4B1, 0x084F86D3, 0xB0E5C30E,
+ 0x7A5DC317, 0xC2F786CA, 0xFB7EA4A8, 0x43D4E175,
+ 0x6F0FA59A, 0xD7A5E047, 0xEE2CC225, 0x568687F8,
+ 0x9C3E87E1, 0x2494C23C, 0x1D1DE05E, 0xA5B7A583,
+ 0xD89606F9, 0x603C4324, 0x59B56146, 0xE11F249B,
+ 0x2BA72482, 0x930D615F, 0xAA84433D, 0x122E06E0,
+ 0x3EF5420F, 0x865F07D2, 0xBFD625B0, 0x077C606D,
+ 0xCDC46074, 0x756E25A9, 0x4CE707CB, 0xF44D4216,
+ 0xE5276210, 0x5D8D27CD, 0x640405AF, 0xDCAE4072,
+ 0x1616406B, 0xAEBC05B6, 0x973527D4, 0x2F9F6209,
+ 0x034426E6, 0xBBEE633B, 0x82674159, 0x3ACD0484,
+ 0xF075049D, 0x48DF4140, 0x71566322, 0xC9FC26FF,
+ 0x5382232E, 0xEB2866F3, 0xD2A14491, 0x6A0B014C,
+ 0xA0B30155, 0x18194488, 0x219066EA, 0x993A2337,
+ 0xB5E167D8, 0x0D4B2205, 0x34C20067, 0x8C6845BA,
+ 0x46D045A3, 0xFE7A007E, 0xC7F3221C, 0x7F5967C1,
+ 0x6E3347C7, 0xD699021A, 0xEF102078, 0x57BA65A5,
+ 0x9D0265BC, 0x25A82061, 0x1C210203, 0xA48B47DE,
+ 0x88500331, 0x30FA46EC, 0x0973648E, 0xB1D92153,
+ 0x7B61214A, 0xC3CB6497, 0xFA4246F5, 0x42E80328,
+ },
+ {
+ 0x00000000, 0xAC6F1138, 0x58DF2270, 0xF4B03348,
+ 0xB0BE45E0, 0x1CD154D8, 0xE8616790, 0x440E76A8,
+ 0x910B67C5, 0x3D6476FD, 0xC9D445B5, 0x65BB548D,
+ 0x21B52225, 0x8DDA331D, 0x796A0055, 0xD505116D,
+ 0xD361228F, 0x7F0E33B7, 0x8BBE00FF, 0x27D111C7,
+ 0x63DF676F, 0xCFB07657, 0x3B00451F, 0x976F5427,
+ 0x426A454A, 0xEE055472, 0x1AB5673A, 0xB6DA7602,
+ 0xF2D400AA, 0x5EBB1192, 0xAA0B22DA, 0x066433E2,
+ 0x57B5A81B, 0xFBDAB923, 0x0F6A8A6B, 0xA3059B53,
+ 0xE70BEDFB, 0x4B64FCC3, 0xBFD4CF8B, 0x13BBDEB3,
+ 0xC6BECFDE, 0x6AD1DEE6, 0x9E61EDAE, 0x320EFC96,
+ 0x76008A3E, 0xDA6F9B06, 0x2EDFA84E, 0x82B0B976,
+ 0x84D48A94, 0x28BB9BAC, 0xDC0BA8E4, 0x7064B9DC,
+ 0x346ACF74, 0x9805DE4C, 0x6CB5ED04, 0xC0DAFC3C,
+ 0x15DFED51, 0xB9B0FC69, 0x4D00CF21, 0xE16FDE19,
+ 0xA561A8B1, 0x090EB989, 0xFDBE8AC1, 0x51D19BF9,
+ 0xAE6A5137, 0x0205400F, 0xF6B57347, 0x5ADA627F,
+ 0x1ED414D7, 0xB2BB05EF, 0x460B36A7, 0xEA64279F,
+ 0x3F6136F2, 0x930E27CA, 0x67BE1482, 0xCBD105BA,
+ 0x8FDF7312, 0x23B0622A, 0xD7005162, 0x7B6F405A,
+ 0x7D0B73B8, 0xD1646280, 0x25D451C8, 0x89BB40F0,
+ 0xCDB53658, 0x61DA2760, 0x956A1428, 0x39050510,
+ 0xEC00147D, 0x406F0545, 0xB4DF360D, 0x18B02735,
+ 0x5CBE519D, 0xF0D140A5, 0x046173ED, 0xA80E62D5,
+ 0xF9DFF92C, 0x55B0E814, 0xA100DB5C, 0x0D6FCA64,
+ 0x4961BCCC, 0xE50EADF4, 0x11BE9EBC, 0xBDD18F84,
+ 0x68D49EE9, 0xC4BB8FD1, 0x300BBC99, 0x9C64ADA1,
+ 0xD86ADB09, 0x7405CA31, 0x80B5F979, 0x2CDAE841,
+ 0x2ABEDBA3, 0x86D1CA9B, 0x7261F9D3, 0xDE0EE8EB,
+ 0x9A009E43, 0x366F8F7B, 0xC2DFBC33, 0x6EB0AD0B,
+ 0xBBB5BC66, 0x17DAAD5E, 0xE36A9E16, 0x4F058F2E,
+ 0x0B0BF986, 0xA764E8BE, 0x53D4DBF6, 0xFFBBCACE,
+ 0x5CD5A26E, 0xF0BAB356, 0x040A801E, 0xA8659126,
+ 0xEC6BE78E, 0x4004F6B6, 0xB4B4C5FE, 0x18DBD4C6,
+ 0xCDDEC5AB, 0x61B1D493, 0x9501E7DB, 0x396EF6E3,
+ 0x7D60804B, 0xD10F9173, 0x25BFA23B, 0x89D0B303,
+ 0x8FB480E1, 0x23DB91D9, 0xD76BA291, 0x7B04B3A9,
+ 0x3F0AC501, 0x9365D439, 0x67D5E771, 0xCBBAF649,
+ 0x1EBFE724, 0xB2D0F61C, 0x4660C554, 0xEA0FD46C,
+ 0xAE01A2C4, 0x026EB3FC, 0xF6DE80B4, 0x5AB1918C,
+ 0x0B600A75, 0xA70F1B4D, 0x53BF2805, 0xFFD0393D,
+ 0xBBDE4F95, 0x17B15EAD, 0xE3016DE5, 0x4F6E7CDD,
+ 0x9A6B6DB0, 0x36047C88, 0xC2B44FC0, 0x6EDB5EF8,
+ 0x2AD52850, 0x86BA3968, 0x720A0A20, 0xDE651B18,
+ 0xD80128FA, 0x746E39C2, 0x80DE0A8A, 0x2CB11BB2,
+ 0x68BF6D1A, 0xC4D07C22, 0x30604F6A, 0x9C0F5E52,
+ 0x490A4F3F, 0xE5655E07, 0x11D56D4F, 0xBDBA7C77,
+ 0xF9B40ADF, 0x55DB1BE7, 0xA16B28AF, 0x0D043997,
+ 0xF2BFF359, 0x5ED0E261, 0xAA60D129, 0x060FC011,
+ 0x4201B6B9, 0xEE6EA781, 0x1ADE94C9, 0xB6B185F1,
+ 0x63B4949C, 0xCFDB85A4, 0x3B6BB6EC, 0x9704A7D4,
+ 0xD30AD17C, 0x7F65C044, 0x8BD5F30C, 0x27BAE234,
+ 0x21DED1D6, 0x8DB1C0EE, 0x7901F3A6, 0xD56EE29E,
+ 0x91609436, 0x3D0F850E, 0xC9BFB646, 0x65D0A77E,
+ 0xB0D5B613, 0x1CBAA72B, 0xE80A9463, 0x4465855B,
+ 0x006BF3F3, 0xAC04E2CB, 0x58B4D183, 0xF4DBC0BB,
+ 0xA50A5B42, 0x09654A7A, 0xFDD57932, 0x51BA680A,
+ 0x15B41EA2, 0xB9DB0F9A, 0x4D6B3CD2, 0xE1042DEA,
+ 0x34013C87, 0x986E2DBF, 0x6CDE1EF7, 0xC0B10FCF,
+ 0x84BF7967, 0x28D0685F, 0xDC605B17, 0x700F4A2F,
+ 0x766B79CD, 0xDA0468F5, 0x2EB45BBD, 0x82DB4A85,
+ 0xC6D53C2D, 0x6ABA2D15, 0x9E0A1E5D, 0x32650F65,
+ 0xE7601E08, 0x4B0F0F30, 0xBFBF3C78, 0x13D02D40,
+ 0x57DE5BE8, 0xFBB14AD0, 0x0F017998, 0xA36E68A0,
+ },
+ {
+ 0x00000000, 0x196B30EF, 0xC3A08CDB, 0xDACBBC34,
+ 0x7737F5B2, 0x6E5CC55D, 0xB4977969, 0xADFC4986,
+ 0x1F180660, 0x0673368F, 0xDCB88ABB, 0xC5D3BA54,
+ 0x682FF3D2, 0x7144C33D, 0xAB8F7F09, 0xB2E44FE6,
+ 0x3E300CC0, 0x275B3C2F, 0xFD90801B, 0xE4FBB0F4,
+ 0x4907F972, 0x506CC99D, 0x8AA775A9, 0x93CC4546,
+ 0x21280AA0, 0x38433A4F, 0xE288867B, 0xFBE3B694,
+ 0x561FFF12, 0x4F74CFFD, 0x95BF73C9, 0x8CD44326,
+ 0x8D16F485, 0x947DC46A, 0x4EB6785E, 0x57DD48B1,
+ 0xFA210137, 0xE34A31D8, 0x39818DEC, 0x20EABD03,
+ 0x920EF2E5, 0x8B65C20A, 0x51AE7E3E, 0x48C54ED1,
+ 0xE5390757, 0xFC5237B8, 0x26998B8C, 0x3FF2BB63,
+ 0xB326F845, 0xAA4DC8AA, 0x7086749E, 0x69ED4471,
+ 0xC4110DF7, 0xDD7A3D18, 0x07B1812C, 0x1EDAB1C3,
+ 0xAC3EFE25, 0xB555CECA, 0x6F9E72FE, 0x76F54211,
+ 0xDB090B97, 0xC2623B78, 0x18A9874C, 0x01C2B7A3,
+ 0xEB5B040E, 0xF23034E1, 0x28FB88D5, 0x3190B83A,
+ 0x9C6CF1BC, 0x8507C153, 0x5FCC7D67, 0x46A74D88,
+ 0xF443026E, 0xED283281, 0x37E38EB5, 0x2E88BE5A,
+ 0x8374F7DC, 0x9A1FC733, 0x40D47B07, 0x59BF4BE8,
+ 0xD56B08CE, 0xCC003821, 0x16CB8415, 0x0FA0B4FA,
+ 0xA25CFD7C, 0xBB37CD93, 0x61FC71A7, 0x78974148,
+ 0xCA730EAE, 0xD3183E41, 0x09D38275, 0x10B8B29A,
+ 0xBD44FB1C, 0xA42FCBF3, 0x7EE477C7, 0x678F4728,
+ 0x664DF08B, 0x7F26C064, 0xA5ED7C50, 0xBC864CBF,
+ 0x117A0539, 0x081135D6, 0xD2DA89E2, 0xCBB1B90D,
+ 0x7955F6EB, 0x603EC604, 0xBAF57A30, 0xA39E4ADF,
+ 0x0E620359, 0x170933B6, 0xCDC28F82, 0xD4A9BF6D,
+ 0x587DFC4B, 0x4116CCA4, 0x9BDD7090, 0x82B6407F,
+ 0x2F4A09F9, 0x36213916, 0xECEA8522, 0xF581B5CD,
+ 0x4765FA2B, 0x5E0ECAC4, 0x84C576F0, 0x9DAE461F,
+ 0x30520F99, 0x29393F76, 0xF3F28342, 0xEA99B3AD,
+ 0xD6B7081C, 0xCFDC38F3, 0x151784C7, 0x0C7CB428,
+ 0xA180FDAE, 0xB8EBCD41, 0x62207175, 0x7B4B419A,
+ 0xC9AF0E7C, 0xD0C43E93, 0x0A0F82A7, 0x1364B248,
+ 0xBE98FBCE, 0xA7F3CB21, 0x7D387715, 0x645347FA,
+ 0xE88704DC, 0xF1EC3433, 0x2B278807, 0x324CB8E8,
+ 0x9FB0F16E, 0x86DBC181, 0x5C107DB5, 0x457B4D5A,
+ 0xF79F02BC, 0xEEF43253, 0x343F8E67, 0x2D54BE88,
+ 0x80A8F70E, 0x99C3C7E1, 0x43087BD5, 0x5A634B3A,
+ 0x5BA1FC99, 0x42CACC76, 0x98017042, 0x816A40AD,
+ 0x2C96092B, 0x35FD39C4, 0xEF3685F0, 0xF65DB51F,
+ 0x44B9FAF9, 0x5DD2CA16, 0x87197622, 0x9E7246CD,
+ 0x338E0F4B, 0x2AE53FA4, 0xF02E8390, 0xE945B37F,
+ 0x6591F059, 0x7CFAC0B6, 0xA6317C82, 0xBF5A4C6D,
+ 0x12A605EB, 0x0BCD3504, 0xD1068930, 0xC86DB9DF,
+ 0x7A89F639, 0x63E2C6D6, 0xB9297AE2, 0xA0424A0D,
+ 0x0DBE038B, 0x14D53364, 0xCE1E8F50, 0xD775BFBF,
+ 0x3DEC0C12, 0x24873CFD, 0xFE4C80C9, 0xE727B026,
+ 0x4ADBF9A0, 0x53B0C94F, 0x897B757B, 0x90104594,
+ 0x22F40A72, 0x3B9F3A9D, 0xE15486A9, 0xF83FB646,
+ 0x55C3FFC0, 0x4CA8CF2F, 0x9663731B, 0x8F0843F4,
+ 0x03DC00D2, 0x1AB7303D, 0xC07C8C09, 0xD917BCE6,
+ 0x74EBF560, 0x6D80C58F, 0xB74B79BB, 0xAE204954,
+ 0x1CC406B2, 0x05AF365D, 0xDF648A69, 0xC60FBA86,
+ 0x6BF3F300, 0x7298C3EF, 0xA8537FDB, 0xB1384F34,
+ 0xB0FAF897, 0xA991C878, 0x735A744C, 0x6A3144A3,
+ 0xC7CD0D25, 0xDEA63DCA, 0x046D81FE, 0x1D06B111,
+ 0xAFE2FEF7, 0xB689CE18, 0x6C42722C, 0x752942C3,
+ 0xD8D50B45, 0xC1BE3BAA, 0x1B75879E, 0x021EB771,
+ 0x8ECAF457, 0x97A1C4B8, 0x4D6A788C, 0x54014863,
+ 0xF9FD01E5, 0xE096310A, 0x3A5D8D3E, 0x2336BDD1,
+ 0x91D2F237, 0x88B9C2D8, 0x52727EEC, 0x4B194E03,
+ 0xE6E50785, 0xFF8E376A, 0x25458B5E, 0x3C2EBBB1,
+ },
+ {
+ 0x00000000, 0xC82C0368, 0x905906D0, 0x587505B8,
+ 0xD1C5E0A5, 0x19E9E3CD, 0x419CE675, 0x89B0E51D,
+ 0x53FD2D4E, 0x9BD12E26, 0xC3A42B9E, 0x0B8828F6,
+ 0x8238CDEB, 0x4A14CE83, 0x1261CB3B, 0xDA4DC853,
+ 0xA6FA5B9C, 0x6ED658F4, 0x36A35D4C, 0xFE8F5E24,
+ 0x773FBB39, 0xBF13B851, 0xE766BDE9, 0x2F4ABE81,
+ 0xF50776D2, 0x3D2B75BA, 0x655E7002, 0xAD72736A,
+ 0x24C29677, 0xECEE951F, 0xB49B90A7, 0x7CB793CF,
+ 0xBD835B3D, 0x75AF5855, 0x2DDA5DED, 0xE5F65E85,
+ 0x6C46BB98, 0xA46AB8F0, 0xFC1FBD48, 0x3433BE20,
+ 0xEE7E7673, 0x2652751B, 0x7E2770A3, 0xB60B73CB,
+ 0x3FBB96D6, 0xF79795BE, 0xAFE29006, 0x67CE936E,
+ 0x1B7900A1, 0xD35503C9, 0x8B200671, 0x430C0519,
+ 0xCABCE004, 0x0290E36C, 0x5AE5E6D4, 0x92C9E5BC,
+ 0x48842DEF, 0x80A82E87, 0xD8DD2B3F, 0x10F12857,
+ 0x9941CD4A, 0x516DCE22, 0x0918CB9A, 0xC134C8F2,
+ 0x7A07B77A, 0xB22BB412, 0xEA5EB1AA, 0x2272B2C2,
+ 0xABC257DF, 0x63EE54B7, 0x3B9B510F, 0xF3B75267,
+ 0x29FA9A34, 0xE1D6995C, 0xB9A39CE4, 0x718F9F8C,
+ 0xF83F7A91, 0x301379F9, 0x68667C41, 0xA04A7F29,
+ 0xDCFDECE6, 0x14D1EF8E, 0x4CA4EA36, 0x8488E95E,
+ 0x0D380C43, 0xC5140F2B, 0x9D610A93, 0x554D09FB,
+ 0x8F00C1A8, 0x472CC2C0, 0x1F59C778, 0xD775C410,
+ 0x5EC5210D, 0x96E92265, 0xCE9C27DD, 0x06B024B5,
+ 0xC784EC47, 0x0FA8EF2F, 0x57DDEA97, 0x9FF1E9FF,
+ 0x16410CE2, 0xDE6D0F8A, 0x86180A32, 0x4E34095A,
+ 0x9479C109, 0x5C55C261, 0x0420C7D9, 0xCC0CC4B1,
+ 0x45BC21AC, 0x8D9022C4, 0xD5E5277C, 0x1DC92414,
+ 0x617EB7DB, 0xA952B4B3, 0xF127B10B, 0x390BB263,
+ 0xB0BB577E, 0x78975416, 0x20E251AE, 0xE8CE52C6,
+ 0x32839A95, 0xFAAF99FD, 0xA2DA9C45, 0x6AF69F2D,
+ 0xE3467A30, 0x2B6A7958, 0x731F7CE0, 0xBB337F88,
+ 0xF40E6EF5, 0x3C226D9D, 0x64576825, 0xAC7B6B4D,
+ 0x25CB8E50, 0xEDE78D38, 0xB5928880, 0x7DBE8BE8,
+ 0xA7F343BB, 0x6FDF40D3, 0x37AA456B, 0xFF864603,
+ 0x7636A31E, 0xBE1AA076, 0xE66FA5CE, 0x2E43A6A6,
+ 0x52F43569, 0x9AD83601, 0xC2AD33B9, 0x0A8130D1,
+ 0x8331D5CC, 0x4B1DD6A4, 0x1368D31C, 0xDB44D074,
+ 0x01091827, 0xC9251B4F, 0x91501EF7, 0x597C1D9F,
+ 0xD0CCF882, 0x18E0FBEA, 0x4095FE52, 0x88B9FD3A,
+ 0x498D35C8, 0x81A136A0, 0xD9D43318, 0x11F83070,
+ 0x9848D56D, 0x5064D605, 0x0811D3BD, 0xC03DD0D5,
+ 0x1A701886, 0xD25C1BEE, 0x8A291E56, 0x42051D3E,
+ 0xCBB5F823, 0x0399FB4B, 0x5BECFEF3, 0x93C0FD9B,
+ 0xEF776E54, 0x275B6D3C, 0x7F2E6884, 0xB7026BEC,
+ 0x3EB28EF1, 0xF69E8D99, 0xAEEB8821, 0x66C78B49,
+ 0xBC8A431A, 0x74A64072, 0x2CD345CA, 0xE4FF46A2,
+ 0x6D4FA3BF, 0xA563A0D7, 0xFD16A56F, 0x353AA607,
+ 0x8E09D98F, 0x4625DAE7, 0x1E50DF5F, 0xD67CDC37,
+ 0x5FCC392A, 0x97E03A42, 0xCF953FFA, 0x07B93C92,
+ 0xDDF4F4C1, 0x15D8F7A9, 0x4DADF211, 0x8581F179,
+ 0x0C311464, 0xC41D170C, 0x9C6812B4, 0x544411DC,
+ 0x28F38213, 0xE0DF817B, 0xB8AA84C3, 0x708687AB,
+ 0xF93662B6, 0x311A61DE, 0x696F6466, 0xA143670E,
+ 0x7B0EAF5D, 0xB322AC35, 0xEB57A98D, 0x237BAAE5,
+ 0xAACB4FF8, 0x62E74C90, 0x3A924928, 0xF2BE4A40,
+ 0x338A82B2, 0xFBA681DA, 0xA3D38462, 0x6BFF870A,
+ 0xE24F6217, 0x2A63617F, 0x721664C7, 0xBA3A67AF,
+ 0x6077AFFC, 0xA85BAC94, 0xF02EA92C, 0x3802AA44,
+ 0xB1B24F59, 0x799E4C31, 0x21EB4989, 0xE9C74AE1,
+ 0x9570D92E, 0x5D5CDA46, 0x0529DFFE, 0xCD05DC96,
+ 0x44B5398B, 0x8C993AE3, 0xD4EC3F5B, 0x1CC03C33,
+ 0xC68DF460, 0x0EA1F708, 0x56D4F2B0, 0x9EF8F1D8,
+ 0x174814C5, 0xDF6417AD, 0x87111215, 0x4F3D117D,
+ },
+ {
+ 0x00000000, 0x277D3C49, 0x4EFA7892, 0x698744DB,
+ 0x6D821D21, 0x4AFF2168, 0x237865B3, 0x040559FA,
+ 0xDA043B42, 0xFD79070B, 0x94FE43D0, 0xB3837F99,
+ 0xB7862663, 0x90FB1A2A, 0xF97C5EF1, 0xDE0162B8,
+ 0xB4097684, 0x93744ACD, 0xFAF30E16, 0xDD8E325F,
+ 0xD98B6BA5, 0xFEF657EC, 0x97711337, 0xB00C2F7E,
+ 0x6E0D4DC6, 0x4970718F, 0x20F73554, 0x078A091D,
+ 0x038F50E7, 0x24F26CAE, 0x4D752875, 0x6A08143C,
+ 0x9965000D, 0xBE183C44, 0xD79F789F, 0xF0E244D6,
+ 0xF4E71D2C, 0xD39A2165, 0xBA1D65BE, 0x9D6059F7,
+ 0x43613B4F, 0x641C0706, 0x0D9B43DD, 0x2AE67F94,
+ 0x2EE3266E, 0x099E1A27, 0x60195EFC, 0x476462B5,
+ 0x2D6C7689, 0x0A114AC0, 0x63960E1B, 0x44EB3252,
+ 0x40EE6BA8, 0x679357E1, 0x0E14133A, 0x29692F73,
+ 0xF7684DCB, 0xD0157182, 0xB9923559, 0x9EEF0910,
+ 0x9AEA50EA, 0xBD976CA3, 0xD4102878, 0xF36D1431,
+ 0x32CB001A, 0x15B63C53, 0x7C317888, 0x5B4C44C1,
+ 0x5F491D3B, 0x78342172, 0x11B365A9, 0x36CE59E0,
+ 0xE8CF3B58, 0xCFB20711, 0xA63543CA, 0x81487F83,
+ 0x854D2679, 0xA2301A30, 0xCBB75EEB, 0xECCA62A2,
+ 0x86C2769E, 0xA1BF4AD7, 0xC8380E0C, 0xEF453245,
+ 0xEB406BBF, 0xCC3D57F6, 0xA5BA132D, 0x82C72F64,
+ 0x5CC64DDC, 0x7BBB7195, 0x123C354E, 0x35410907,
+ 0x314450FD, 0x16396CB4, 0x7FBE286F, 0x58C31426,
+ 0xABAE0017, 0x8CD33C5E, 0xE5547885, 0xC22944CC,
+ 0xC62C1D36, 0xE151217F, 0x88D665A4, 0xAFAB59ED,
+ 0x71AA3B55, 0x56D7071C, 0x3F5043C7, 0x182D7F8E,
+ 0x1C282674, 0x3B551A3D, 0x52D25EE6, 0x75AF62AF,
+ 0x1FA77693, 0x38DA4ADA, 0x515D0E01, 0x76203248,
+ 0x72256BB2, 0x555857FB, 0x3CDF1320, 0x1BA22F69,
+ 0xC5A34DD1, 0xE2DE7198, 0x8B593543, 0xAC24090A,
+ 0xA82150F0, 0x8F5C6CB9, 0xE6DB2862, 0xC1A6142B,
+ 0x64960134, 0x43EB3D7D, 0x2A6C79A6, 0x0D1145EF,
+ 0x09141C15, 0x2E69205C, 0x47EE6487, 0x609358CE,
+ 0xBE923A76, 0x99EF063F, 0xF06842E4, 0xD7157EAD,
+ 0xD3102757, 0xF46D1B1E, 0x9DEA5FC5, 0xBA97638C,
+ 0xD09F77B0, 0xF7E24BF9, 0x9E650F22, 0xB918336B,
+ 0xBD1D6A91, 0x9A6056D8, 0xF3E71203, 0xD49A2E4A,
+ 0x0A9B4CF2, 0x2DE670BB, 0x44613460, 0x631C0829,
+ 0x671951D3, 0x40646D9A, 0x29E32941, 0x0E9E1508,
+ 0xFDF30139, 0xDA8E3D70, 0xB30979AB, 0x947445E2,
+ 0x90711C18, 0xB70C2051, 0xDE8B648A, 0xF9F658C3,
+ 0x27F73A7B, 0x008A0632, 0x690D42E9, 0x4E707EA0,
+ 0x4A75275A, 0x6D081B13, 0x048F5FC8, 0x23F26381,
+ 0x49FA77BD, 0x6E874BF4, 0x07000F2F, 0x207D3366,
+ 0x24786A9C, 0x030556D5, 0x6A82120E, 0x4DFF2E47,
+ 0x93FE4CFF, 0xB48370B6, 0xDD04346D, 0xFA790824,
+ 0xFE7C51DE, 0xD9016D97, 0xB086294C, 0x97FB1505,
+ 0x565D012E, 0x71203D67, 0x18A779BC, 0x3FDA45F5,
+ 0x3BDF1C0F, 0x1CA22046, 0x7525649D, 0x525858D4,
+ 0x8C593A6C, 0xAB240625, 0xC2A342FE, 0xE5DE7EB7,
+ 0xE1DB274D, 0xC6A61B04, 0xAF215FDF, 0x885C6396,
+ 0xE25477AA, 0xC5294BE3, 0xACAE0F38, 0x8BD33371,
+ 0x8FD66A8B, 0xA8AB56C2, 0xC12C1219, 0xE6512E50,
+ 0x38504CE8, 0x1F2D70A1, 0x76AA347A, 0x51D70833,
+ 0x55D251C9, 0x72AF6D80, 0x1B28295B, 0x3C551512,
+ 0xCF380123, 0xE8453D6A, 0x81C279B1, 0xA6BF45F8,
+ 0xA2BA1C02, 0x85C7204B, 0xEC406490, 0xCB3D58D9,
+ 0x153C3A61, 0x32410628, 0x5BC642F3, 0x7CBB7EBA,
+ 0x78BE2740, 0x5FC31B09, 0x36445FD2, 0x1139639B,
+ 0x7B3177A7, 0x5C4C4BEE, 0x35CB0F35, 0x12B6337C,
+ 0x16B36A86, 0x31CE56CF, 0x58491214, 0x7F342E5D,
+ 0xA1354CE5, 0x864870AC, 0xEFCF3477, 0xC8B2083E,
+ 0xCCB751C4, 0xEBCA6D8D, 0x824D2956, 0xA530151F
+ }
+#endif /* WORDS_BIGENDIAN */
+};
diff --git a/contrib/libs/postgresql/src/port/pg_crc32c_sse42.c b/contrib/libs/postgresql/src/port/pg_crc32c_sse42.c
new file mode 100644
index 0000000000..10fc01e1f0
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/pg_crc32c_sse42.c
@@ -0,0 +1,69 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_crc32c_sse42.c
+ * Compute CRC-32C checksum using Intel SSE 4.2 instructions.
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/port/pg_crc32c_sse42.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "c.h"
+
+#include <nmmintrin.h>
+
+#include "port/pg_crc32c.h"
+
+pg_attribute_no_sanitize_alignment()
+pg_crc32c
+pg_comp_crc32c_sse42(pg_crc32c crc, const void *data, size_t len)
+{
+ const unsigned char *p = data;
+ const unsigned char *pend = p + len;
+
+ /*
+ * Process eight bytes of data at a time.
+ *
+ * NB: We do unaligned accesses here. The Intel architecture allows that,
+ * and performance testing didn't show any performance gain from aligning
+ * the begin address.
+ */
+#ifdef __x86_64__
+ while (p + 8 <= pend)
+ {
+ crc = (uint32) _mm_crc32_u64(crc, *((const uint64 *) p));
+ p += 8;
+ }
+
+ /* Process remaining full four bytes if any */
+ if (p + 4 <= pend)
+ {
+ crc = _mm_crc32_u32(crc, *((const unsigned int *) p));
+ p += 4;
+ }
+#else
+
+ /*
+ * Process four bytes at a time. (The eight byte instruction is not
+ * available on the 32-bit x86 architecture).
+ */
+ while (p + 4 <= pend)
+ {
+ crc = _mm_crc32_u32(crc, *((const unsigned int *) p));
+ p += 4;
+ }
+#endif /* __x86_64__ */
+
+ /* Process any remaining bytes one at a time. */
+ while (p < pend)
+ {
+ crc = _mm_crc32_u8(crc, *p);
+ p++;
+ }
+
+ return crc;
+}
diff --git a/contrib/libs/postgresql/src/port/pg_crc32c_sse42_choose.c b/contrib/libs/postgresql/src/port/pg_crc32c_sse42_choose.c
new file mode 100644
index 0000000000..0608e02011
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/pg_crc32c_sse42_choose.c
@@ -0,0 +1,64 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_crc32c_sse42_choose.c
+ * Choose between Intel SSE 4.2 and software CRC-32C implementation.
+ *
+ * On first call, checks if the CPU we're running on supports Intel SSE
+ * 4.2. If it does, use the special SSE instructions for CRC-32C
+ * computation. Otherwise, fall back to the pure software implementation
+ * (slicing-by-8).
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/port/pg_crc32c_sse42_choose.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "c.h"
+
+#ifdef HAVE__GET_CPUID
+#include <cpuid.h>
+#endif
+
+#ifdef HAVE__CPUID
+#include <intrin.h>
+#endif
+
+#include "port/pg_crc32c.h"
+
+static bool
+pg_crc32c_sse42_available(void)
+{
+ unsigned int exx[4] = {0, 0, 0, 0};
+
+#if defined(HAVE__GET_CPUID)
+ __get_cpuid(1, &exx[0], &exx[1], &exx[2], &exx[3]);
+#elif defined(HAVE__CPUID)
+ __cpuid(exx, 1);
+#else
+#error cpuid instruction not available
+#endif
+
+ return (exx[2] & (1 << 20)) != 0; /* SSE 4.2 */
+}
+
+/*
+ * This gets called on the first call. It replaces the function pointer
+ * so that subsequent calls are routed directly to the chosen implementation.
+ */
+static pg_crc32c
+pg_comp_crc32c_choose(pg_crc32c crc, const void *data, size_t len)
+{
+ if (pg_crc32c_sse42_available())
+ pg_comp_crc32c = pg_comp_crc32c_sse42;
+ else
+ pg_comp_crc32c = pg_comp_crc32c_sb8;
+
+ return pg_comp_crc32c(crc, data, len);
+}
+
+pg_crc32c (*pg_comp_crc32c) (pg_crc32c crc, const void *data, size_t len) = pg_comp_crc32c_choose;
diff --git a/contrib/libs/postgresql/src/port/pg_strong_random.c b/contrib/libs/postgresql/src/port/pg_strong_random.c
new file mode 100644
index 0000000000..07f24c0089
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/pg_strong_random.c
@@ -0,0 +1,182 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_strong_random.c
+ * generate a cryptographically secure random number
+ *
+ * Our definition of "strong" is that it's suitable for generating random
+ * salts and query cancellation keys, during authentication.
+ *
+ * Note: this code is run quite early in postmaster and backend startup;
+ * therefore, even when built for backend, it cannot rely on backend
+ * infrastructure such as elog() or palloc().
+ *
+ * Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/port/pg_strong_random.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "c.h"
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+/*
+ * pg_strong_random & pg_strong_random_init
+ *
+ * Generate requested number of random bytes. The returned bytes are
+ * cryptographically secure, suitable for use e.g. in authentication.
+ *
+ * Before pg_strong_random is called in any process, the generator must first
+ * be initialized by calling pg_strong_random_init().
+ *
+ * We rely on system facilities for actually generating the numbers.
+ * We support a number of sources:
+ *
+ * 1. OpenSSL's RAND_bytes()
+ * 2. Windows' CryptGenRandom() function
+ * 3. /dev/urandom
+ *
+ * Returns true on success, and false if none of the sources
+ * were available. NB: It is important to check the return value!
+ * Proceeding with key generation when no random data was available
+ * would lead to predictable keys and security issues.
+ */
+
+
+
+#ifdef USE_OPENSSL
+
+#include <openssl/rand.h>
+
+void
+pg_strong_random_init(void)
+{
+ /*
+ * Make sure processes do not share OpenSSL randomness state. This is no
+ * longer required in OpenSSL 1.1.1 and later versions, but until we drop
+ * support for version < 1.1.1 we need to do this.
+ */
+ RAND_poll();
+}
+
+bool
+pg_strong_random(void *buf, size_t len)
+{
+ int i;
+
+ /*
+ * Check that OpenSSL's CSPRNG has been sufficiently seeded, and if not
+ * add more seed data using RAND_poll(). With some older versions of
+ * OpenSSL, it may be necessary to call RAND_poll() a number of times. If
+ * RAND_poll() fails to generate seed data within the given amount of
+ * retries, subsequent RAND_bytes() calls will fail, but we allow that to
+ * happen to let pg_strong_random() callers handle that with appropriate
+ * error handling.
+ */
+#define NUM_RAND_POLL_RETRIES 8
+
+ for (i = 0; i < NUM_RAND_POLL_RETRIES; i++)
+ {
+ if (RAND_status() == 1)
+ {
+ /* The CSPRNG is sufficiently seeded */
+ break;
+ }
+
+ RAND_poll();
+ }
+
+ if (RAND_bytes(buf, len) == 1)
+ return true;
+ return false;
+}
+
+#elif WIN32
+
+#include <wincrypt.h>
+/*
+ * Cache a global crypto provider that only gets freed when the process
+ * exits, in case we need random numbers more than once.
+ */
+static HCRYPTPROV hProvider = 0;
+
+void
+pg_strong_random_init(void)
+{
+ /* No initialization needed on WIN32 */
+}
+
+bool
+pg_strong_random(void *buf, size_t len)
+{
+ if (hProvider == 0)
+ {
+ if (!CryptAcquireContext(&hProvider,
+ NULL,
+ MS_DEF_PROV,
+ PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
+ {
+ /*
+ * On failure, set back to 0 in case the value was for some reason
+ * modified.
+ */
+ hProvider = 0;
+ }
+ }
+ /* Re-check in case we just retrieved the provider */
+ if (hProvider != 0)
+ {
+ if (CryptGenRandom(hProvider, len, buf))
+ return true;
+ }
+ return false;
+}
+
+#else /* not USE_OPENSSL or WIN32 */
+
+/*
+ * Without OpenSSL or Win32 support, just read /dev/urandom ourselves.
+ */
+
+void
+pg_strong_random_init(void)
+{
+ /* No initialization needed */
+}
+
+bool
+pg_strong_random(void *buf, size_t len)
+{
+ int f;
+ char *p = buf;
+ ssize_t res;
+
+ f = open("/dev/urandom", O_RDONLY, 0);
+ if (f == -1)
+ return false;
+
+ while (len)
+ {
+ res = read(f, p, len);
+ if (res <= 0)
+ {
+ if (errno == EINTR)
+ continue; /* interrupted by signal, just retry */
+
+ close(f);
+ return false;
+ }
+
+ p += res;
+ len -= res;
+ }
+
+ close(f);
+ return true;
+}
+#endif
diff --git a/contrib/libs/postgresql/src/port/pgcheckdir.c b/contrib/libs/postgresql/src/port/pgcheckdir.c
new file mode 100644
index 0000000000..9fb2f23bdd
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/pgcheckdir.c
@@ -0,0 +1,90 @@
+/*-------------------------------------------------------------------------
+ *
+ * src/port/pgcheckdir.c
+ *
+ * A simple subroutine to check whether a directory exists and is empty or not.
+ * Useful in both initdb and the backend.
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "c.h"
+
+#include <dirent.h>
+
+
+/*
+ * Test to see if a directory exists and is empty or not.
+ *
+ * Returns:
+ * 0 if nonexistent
+ * 1 if exists and empty
+ * 2 if exists and contains _only_ dot files
+ * 3 if exists and contains a mount point
+ * 4 if exists and not empty
+ * -1 if trouble accessing directory (errno reflects the error)
+ */
+int
+pg_check_dir(const char *dir)
+{
+ int result = 1;
+ DIR *chkdir;
+ struct dirent *file;
+ bool dot_found = false;
+ bool mount_found = false;
+ int readdir_errno;
+
+ chkdir = opendir(dir);
+ if (chkdir == NULL)
+ return (errno == ENOENT) ? 0 : -1;
+
+ while (errno = 0, (file = readdir(chkdir)) != NULL)
+ {
+ if (strcmp(".", file->d_name) == 0 ||
+ strcmp("..", file->d_name) == 0)
+ {
+ /* skip this and parent directory */
+ continue;
+ }
+#ifndef WIN32
+ /* file starts with "." */
+ else if (file->d_name[0] == '.')
+ {
+ dot_found = true;
+ }
+ /* lost+found directory */
+ else if (strcmp("lost+found", file->d_name) == 0)
+ {
+ mount_found = true;
+ }
+#endif
+ else
+ {
+ result = 4; /* not empty */
+ break;
+ }
+ }
+
+ if (errno)
+ result = -1; /* some kind of I/O error? */
+
+ /* Close chkdir and avoid overwriting the readdir errno on success */
+ readdir_errno = errno;
+ if (closedir(chkdir))
+ result = -1; /* error executing closedir */
+ else
+ errno = readdir_errno;
+
+ /* We report on mount point if we find a lost+found directory */
+ if (result == 1 && mount_found)
+ result = 3;
+
+ /* We report on dot-files if we _only_ find dot files */
+ if (result == 1 && dot_found)
+ result = 2;
+
+ return result;
+}
diff --git a/contrib/libs/postgresql/src/port/pgmkdirp.c b/contrib/libs/postgresql/src/port/pgmkdirp.c
new file mode 100644
index 0000000000..d943559760
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/pgmkdirp.c
@@ -0,0 +1,148 @@
+/*
+ * This is adapted from FreeBSD's src/bin/mkdir/mkdir.c, which bears
+ * the following copyright notice:
+ *
+ * Copyright (c) 1983, 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "c.h"
+
+#include <sys/stat.h>
+
+
+/*
+ * pg_mkdir_p --- create a directory and, if necessary, parent directories
+ *
+ * This is equivalent to "mkdir -p" except we don't complain if the target
+ * directory already exists.
+ *
+ * We assume the path is in canonical form, i.e., uses / as the separator.
+ *
+ * omode is the file permissions bits for the target directory. Note that any
+ * parent directories that have to be created get permissions according to the
+ * prevailing umask, but with u+wx forced on to ensure we can create there.
+ * (We declare omode as int, not mode_t, to minimize dependencies for port.h.)
+ *
+ * Returns 0 on success, -1 (with errno set) on failure.
+ *
+ * Note that on failure, the path arg has been modified to show the particular
+ * directory level we had problems with.
+ */
+int
+pg_mkdir_p(char *path, int omode)
+{
+ struct stat sb;
+ mode_t numask,
+ oumask;
+ int last,
+ retval;
+ char *p;
+
+ retval = 0;
+ p = path;
+
+#ifdef WIN32
+ /* skip network and drive specifiers for win32 */
+ if (strlen(p) >= 2)
+ {
+ if (p[0] == '/' && p[1] == '/')
+ {
+ /* network drive */
+ p = strstr(p + 2, "/");
+ if (p == NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ }
+ else if (p[1] == ':' &&
+ ((p[0] >= 'a' && p[0] <= 'z') ||
+ (p[0] >= 'A' && p[0] <= 'Z')))
+ {
+ /* local drive */
+ p += 2;
+ }
+ }
+#endif
+
+ /*
+ * POSIX 1003.2: For each dir operand that does not name an existing
+ * directory, effects equivalent to those caused by the following command
+ * shall occur:
+ *
+ * mkdir -p -m $(umask -S),u+wx $(dirname dir) && mkdir [-m mode] dir
+ *
+ * We change the user's umask and then restore it, instead of doing
+ * chmod's. Note we assume umask() can't change errno.
+ */
+ oumask = umask(0);
+ numask = oumask & ~(S_IWUSR | S_IXUSR);
+ (void) umask(numask);
+
+ if (p[0] == '/') /* Skip leading '/'. */
+ ++p;
+ for (last = 0; !last; ++p)
+ {
+ if (p[0] == '\0')
+ last = 1;
+ else if (p[0] != '/')
+ continue;
+ *p = '\0';
+ if (!last && p[1] == '\0')
+ last = 1;
+
+ if (last)
+ (void) umask(oumask);
+
+ /* check for pre-existing directory */
+ if (stat(path, &sb) == 0)
+ {
+ if (!S_ISDIR(sb.st_mode))
+ {
+ if (last)
+ errno = EEXIST;
+ else
+ errno = ENOTDIR;
+ retval = -1;
+ break;
+ }
+ }
+ else if (mkdir(path, last ? omode : S_IRWXU | S_IRWXG | S_IRWXO) < 0)
+ {
+ retval = -1;
+ break;
+ }
+ if (!last)
+ *p = '/';
+ }
+
+ /* ensure we restored umask */
+ (void) umask(oumask);
+
+ return retval;
+}
diff --git a/contrib/libs/postgresql/src/port/pgsleep.c b/contrib/libs/postgresql/src/port/pgsleep.c
new file mode 100644
index 0000000000..d6d51363e7
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/pgsleep.c
@@ -0,0 +1,63 @@
+/*-------------------------------------------------------------------------
+ *
+ * pgsleep.c
+ * Portable delay handling.
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ *
+ * src/port/pgsleep.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "c.h"
+
+#include <unistd.h>
+#include <sys/time.h>
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+/*
+ * In a Windows backend, we don't use this implementation, but rather
+ * the signal-aware version in src/backend/port/win32/signal.c.
+ */
+#if defined(FRONTEND) || !defined(WIN32)
+
+/*
+ * pg_usleep --- delay the specified number of microseconds.
+ *
+ * NOTE: although the delay is specified in microseconds, the effective
+ * resolution is only 1/HZ, or 10 milliseconds, on most Unixen. Expect
+ * the requested delay to be rounded up to the next resolution boundary.
+ *
+ * On machines where "long" is 32 bits, the maximum delay is ~2000 seconds.
+ *
+ * CAUTION: the behavior when a signal arrives during the sleep is platform
+ * dependent. On most Unix-ish platforms, a signal does not terminate the
+ * sleep; but on some, it will (the Windows implementation also allows signals
+ * to terminate pg_usleep). And there are platforms where not only does a
+ * signal not terminate the sleep, but it actually resets the timeout counter
+ * so that the sleep effectively starts over! It is therefore rather hazardous
+ * to use this for long sleeps; a continuing stream of signal events could
+ * prevent the sleep from ever terminating. Better practice for long sleeps
+ * is to use WaitLatch() with a timeout.
+ */
+void
+pg_usleep(long microsec)
+{
+ if (microsec > 0)
+ {
+#ifndef WIN32
+ struct timeval delay;
+
+ delay.tv_sec = microsec / 1000000L;
+ delay.tv_usec = microsec % 1000000L;
+ (void) select(0, NULL, NULL, NULL, &delay);
+#else
+ SleepEx((microsec < 500 ? 1 : (microsec + 500) / 1000), FALSE);
+#endif
+ }
+}
+
+#endif /* defined(FRONTEND) || !defined(WIN32) */
diff --git a/contrib/libs/postgresql/src/port/pgstrcasecmp.c b/contrib/libs/postgresql/src/port/pgstrcasecmp.c
new file mode 100644
index 0000000000..98e1aedfee
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/pgstrcasecmp.c
@@ -0,0 +1,151 @@
+/*-------------------------------------------------------------------------
+ *
+ * pgstrcasecmp.c
+ * Portable SQL-like case-independent comparisons and conversions.
+ *
+ * SQL99 specifies Unicode-aware case normalization, which we don't yet
+ * have the infrastructure for. Instead we use tolower() to provide a
+ * locale-aware translation. However, there are some locales where this
+ * is not right either (eg, Turkish may do strange things with 'i' and
+ * 'I'). Our current compromise is to use tolower() for characters with
+ * the high bit set, and use an ASCII-only downcasing for 7-bit
+ * characters.
+ *
+ * NB: this code should match downcase_truncate_identifier() in scansup.c.
+ *
+ * We also provide strict ASCII-only case conversion functions, which can
+ * be used to implement C/POSIX case folding semantics no matter what the
+ * C library thinks the locale is.
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ *
+ * src/port/pgstrcasecmp.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "c.h"
+
+#include <ctype.h>
+
+
+/*
+ * Case-independent comparison of two null-terminated strings.
+ */
+int
+pg_strcasecmp(const char *s1, const char *s2)
+{
+ for (;;)
+ {
+ unsigned char ch1 = (unsigned char) *s1++;
+ unsigned char ch2 = (unsigned char) *s2++;
+
+ if (ch1 != ch2)
+ {
+ if (ch1 >= 'A' && ch1 <= 'Z')
+ ch1 += 'a' - 'A';
+ else if (IS_HIGHBIT_SET(ch1) && isupper(ch1))
+ ch1 = tolower(ch1);
+
+ if (ch2 >= 'A' && ch2 <= 'Z')
+ ch2 += 'a' - 'A';
+ else if (IS_HIGHBIT_SET(ch2) && isupper(ch2))
+ ch2 = tolower(ch2);
+
+ if (ch1 != ch2)
+ return (int) ch1 - (int) ch2;
+ }
+ if (ch1 == 0)
+ break;
+ }
+ return 0;
+}
+
+/*
+ * Case-independent comparison of two not-necessarily-null-terminated strings.
+ * At most n bytes will be examined from each string.
+ */
+int
+pg_strncasecmp(const char *s1, const char *s2, size_t n)
+{
+ while (n-- > 0)
+ {
+ unsigned char ch1 = (unsigned char) *s1++;
+ unsigned char ch2 = (unsigned char) *s2++;
+
+ if (ch1 != ch2)
+ {
+ if (ch1 >= 'A' && ch1 <= 'Z')
+ ch1 += 'a' - 'A';
+ else if (IS_HIGHBIT_SET(ch1) && isupper(ch1))
+ ch1 = tolower(ch1);
+
+ if (ch2 >= 'A' && ch2 <= 'Z')
+ ch2 += 'a' - 'A';
+ else if (IS_HIGHBIT_SET(ch2) && isupper(ch2))
+ ch2 = tolower(ch2);
+
+ if (ch1 != ch2)
+ return (int) ch1 - (int) ch2;
+ }
+ if (ch1 == 0)
+ break;
+ }
+ return 0;
+}
+
+/*
+ * Fold a character to upper case.
+ *
+ * Unlike some versions of toupper(), this is safe to apply to characters
+ * that aren't lower case letters. Note however that the whole thing is
+ * a bit bogus for multibyte character sets.
+ */
+unsigned char
+pg_toupper(unsigned char ch)
+{
+ if (ch >= 'a' && ch <= 'z')
+ ch += 'A' - 'a';
+ else if (IS_HIGHBIT_SET(ch) && islower(ch))
+ ch = toupper(ch);
+ return ch;
+}
+
+/*
+ * Fold a character to lower case.
+ *
+ * Unlike some versions of tolower(), this is safe to apply to characters
+ * that aren't upper case letters. Note however that the whole thing is
+ * a bit bogus for multibyte character sets.
+ */
+unsigned char
+pg_tolower(unsigned char ch)
+{
+ if (ch >= 'A' && ch <= 'Z')
+ ch += 'a' - 'A';
+ else if (IS_HIGHBIT_SET(ch) && isupper(ch))
+ ch = tolower(ch);
+ return ch;
+}
+
+/*
+ * Fold a character to upper case, following C/POSIX locale rules.
+ */
+unsigned char
+pg_ascii_toupper(unsigned char ch)
+{
+ if (ch >= 'a' && ch <= 'z')
+ ch += 'A' - 'a';
+ return ch;
+}
+
+/*
+ * Fold a character to lower case, following C/POSIX locale rules.
+ */
+unsigned char
+pg_ascii_tolower(unsigned char ch)
+{
+ if (ch >= 'A' && ch <= 'Z')
+ ch += 'a' - 'A';
+ return ch;
+}
diff --git a/contrib/libs/postgresql/src/port/pgstrsignal.c b/contrib/libs/postgresql/src/port/pgstrsignal.c
new file mode 100644
index 0000000000..0f3b5da04f
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/pgstrsignal.c
@@ -0,0 +1,64 @@
+/*-------------------------------------------------------------------------
+ *
+ * pgstrsignal.c
+ * Identify a Unix signal number
+ *
+ * On platforms compliant with modern POSIX, this just wraps strsignal(3).
+ * Elsewhere, we do the best we can.
+ *
+ * This file is not currently built in MSVC builds, since it's useless
+ * on non-Unix platforms.
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/port/pgstrsignal.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "c.h"
+
+
+/*
+ * pg_strsignal
+ *
+ * Return a string identifying the given Unix signal number.
+ *
+ * The result is declared "const char *" because callers should not
+ * modify the string. Note, however, that POSIX does not promise that
+ * the string will remain valid across later calls to strsignal().
+ *
+ * This version guarantees to return a non-NULL pointer, although
+ * some platforms' versions of strsignal() reputedly do not.
+ *
+ * Note that the fallback cases just return constant strings such as
+ * "unrecognized signal". Project style is for callers to print the
+ * numeric signal value along with the result of this function, so
+ * there's no need to work harder than that.
+ */
+const char *
+pg_strsignal(int signum)
+{
+ const char *result;
+
+ /*
+ * If we have strsignal(3), use that --- but check its result for NULL.
+ */
+#ifdef HAVE_STRSIGNAL
+ result = strsignal(signum);
+ if (result == NULL)
+ result = "unrecognized signal";
+#else
+
+ /*
+ * We used to have code here to try to use sys_siglist[] if available.
+ * However, it seems that all platforms with sys_siglist[] have also had
+ * strsignal() for many years now, so that was just a waste of code.
+ */
+ result = "(signal names not available on this platform)";
+#endif
+
+ return result;
+}
diff --git a/contrib/libs/postgresql/src/port/pqsignal.c b/contrib/libs/postgresql/src/port/pqsignal.c
new file mode 100644
index 0000000000..a373b48093
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/pqsignal.c
@@ -0,0 +1,61 @@
+/*-------------------------------------------------------------------------
+ *
+ * pqsignal.c
+ * reliable BSD-style signal(2) routine stolen from RWW who stole it
+ * from Stevens...
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/port/pqsignal.c
+ *
+ * We now assume that all Unix-oid systems have POSIX sigaction(2)
+ * with support for restartable signals (SA_RESTART). We used to also
+ * support BSD-style signal(2), but there really shouldn't be anything
+ * out there anymore that doesn't have the POSIX API.
+ *
+ * Windows, of course, is resolutely in a class by itself. In the backend,
+ * we don't use this file at all; src/backend/port/win32/signal.c provides
+ * pqsignal() for the backend environment. Frontend programs can use
+ * this version of pqsignal() if they wish, but beware that this does
+ * not provide restartable signals on Windows.
+ *
+ * ------------------------------------------------------------------------
+ */
+
+#include "c.h"
+
+#include <signal.h>
+
+#if !defined(WIN32) || defined(FRONTEND)
+
+/*
+ * Set up a signal handler, with SA_RESTART, for signal "signo"
+ *
+ * Returns the previous handler.
+ */
+pqsigfunc
+pqsignal(int signo, pqsigfunc func)
+{
+#ifndef WIN32
+ struct sigaction act,
+ oact;
+
+ act.sa_handler = func;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_RESTART;
+#ifdef SA_NOCLDSTOP
+ if (signo == SIGCHLD)
+ act.sa_flags |= SA_NOCLDSTOP;
+#endif
+ if (sigaction(signo, &act, &oact) < 0)
+ return SIG_ERR;
+ return oact.sa_handler;
+#else /* WIN32 */
+ return signal(signo, func);
+#endif
+}
+
+#endif /* !defined(WIN32) || defined(FRONTEND) */
diff --git a/contrib/libs/postgresql/src/port/pread.c b/contrib/libs/postgresql/src/port/pread.c
new file mode 100644
index 0000000000..486f07a7df
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/pread.c
@@ -0,0 +1,58 @@
+/*-------------------------------------------------------------------------
+ *
+ * pread.c
+ * Implementation of pread(2) for platforms that lack one.
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/port/pread.c
+ *
+ * Note that this implementation changes the current file position, unlike
+ * the POSIX function, so we use the name pg_pread().
+ *
+ *-------------------------------------------------------------------------
+ */
+
+
+#include "postgres.h"
+
+#ifdef WIN32
+#include <windows.h>
+#else
+#include <unistd.h>
+#endif
+
+ssize_t
+pg_pread(int fd, void *buf, size_t size, off_t offset)
+{
+#ifdef WIN32
+ OVERLAPPED overlapped = {0};
+ HANDLE handle;
+ DWORD result;
+
+ handle = (HANDLE) _get_osfhandle(fd);
+ if (handle == INVALID_HANDLE_VALUE)
+ {
+ errno = EBADF;
+ return -1;
+ }
+
+ overlapped.Offset = offset;
+ if (!ReadFile(handle, buf, size, &result, &overlapped))
+ {
+ if (GetLastError() == ERROR_HANDLE_EOF)
+ return 0;
+
+ _dosmaperr(GetLastError());
+ return -1;
+ }
+
+ return result;
+#else
+ if (lseek(fd, offset, SEEK_SET) < 0)
+ return -1;
+
+ return read(fd, buf, size);
+#endif
+}
diff --git a/contrib/libs/postgresql/src/port/pwrite.c b/contrib/libs/postgresql/src/port/pwrite.c
new file mode 100644
index 0000000000..282b27115e
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/pwrite.c
@@ -0,0 +1,55 @@
+/*-------------------------------------------------------------------------
+ *
+ * pwrite.c
+ * Implementation of pwrite(2) for platforms that lack one.
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/port/pwrite.c
+ *
+ * Note that this implementation changes the current file position, unlike
+ * the POSIX function, so we use the name pg_pwrite().
+ *
+ *-------------------------------------------------------------------------
+ */
+
+
+#include "postgres.h"
+
+#ifdef WIN32
+#include <windows.h>
+#else
+#include <unistd.h>
+#endif
+
+ssize_t
+pg_pwrite(int fd, const void *buf, size_t size, off_t offset)
+{
+#ifdef WIN32
+ OVERLAPPED overlapped = {0};
+ HANDLE handle;
+ DWORD result;
+
+ handle = (HANDLE) _get_osfhandle(fd);
+ if (handle == INVALID_HANDLE_VALUE)
+ {
+ errno = EBADF;
+ return -1;
+ }
+
+ overlapped.Offset = offset;
+ if (!WriteFile(handle, buf, size, &result, &overlapped))
+ {
+ _dosmaperr(GetLastError());
+ return -1;
+ }
+
+ return result;
+#else
+ if (lseek(fd, offset, SEEK_SET) < 0)
+ return -1;
+
+ return write(fd, buf, size);
+#endif
+}
diff --git a/contrib/libs/postgresql/src/port/pwritev.c b/contrib/libs/postgresql/src/port/pwritev.c
new file mode 100644
index 0000000000..2e8ef7e378
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/pwritev.c
@@ -0,0 +1,58 @@
+/*-------------------------------------------------------------------------
+ *
+ * pwritev.c
+ * Implementation of pwritev(2) for platforms that lack one.
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/port/pwritev.c
+ *
+ * Note that this implementation changes the current file position, unlike
+ * the POSIX-like function, so we use the name pg_pwritev().
+ *
+ *-------------------------------------------------------------------------
+ */
+
+
+#include "postgres.h"
+
+#ifdef WIN32
+#include <windows.h>
+#else
+#include <unistd.h>
+#endif
+
+#include "port/pg_iovec.h"
+
+ssize_t
+pg_pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset)
+{
+#ifdef HAVE_WRITEV
+ if (iovcnt == 1)
+ return pg_pwrite(fd, iov[0].iov_base, iov[0].iov_len, offset);
+ if (lseek(fd, offset, SEEK_SET) < 0)
+ return -1;
+ return writev(fd, iov, iovcnt);
+#else
+ ssize_t sum = 0;
+ ssize_t part;
+
+ for (int i = 0; i < iovcnt; ++i)
+ {
+ part = pg_pwrite(fd, iov[i].iov_base, iov[i].iov_len, offset);
+ if (part < 0)
+ {
+ if (i == 0)
+ return -1;
+ else
+ return sum;
+ }
+ sum += part;
+ offset += part;
+ if (part < iov[i].iov_len)
+ return sum;
+ }
+ return sum;
+#endif
+}
diff --git a/contrib/libs/postgresql/src/port/qsort.c b/contrib/libs/postgresql/src/port/qsort.c
new file mode 100644
index 0000000000..7879e6cd56
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/qsort.c
@@ -0,0 +1,22 @@
+/*
+ * qsort.c: standard quicksort algorithm
+ */
+
+#include "c.h"
+
+#define ST_SORT pg_qsort
+#define ST_ELEMENT_TYPE_VOID
+#define ST_COMPARE_RUNTIME_POINTER
+#define ST_SCOPE
+#define ST_DECLARE
+#define ST_DEFINE
+#include "lib/sort_template.h"
+
+/*
+ * qsort comparator wrapper for strcmp.
+ */
+int
+pg_qsort_strcmp(const void *a, const void *b)
+{
+ return strcmp(*(const char *const *) a, *(const char *const *) b);
+}
diff --git a/contrib/libs/postgresql/src/port/qsort_arg.c b/contrib/libs/postgresql/src/port/qsort_arg.c
new file mode 100644
index 0000000000..fa7e11a3b8
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/qsort_arg.c
@@ -0,0 +1,14 @@
+/*
+ * qsort_arg.c: qsort with a passthrough "void *" argument
+ */
+
+#include "c.h"
+
+#define ST_SORT qsort_arg
+#define ST_ELEMENT_TYPE_VOID
+#define ST_COMPARATOR_TYPE_NAME qsort_arg_comparator
+#define ST_COMPARE_RUNTIME_POINTER
+#define ST_COMPARE_ARG_TYPE void
+#define ST_SCOPE
+#define ST_DEFINE
+#include "lib/sort_template.h"
diff --git a/contrib/libs/postgresql/src/port/quotes.c b/contrib/libs/postgresql/src/port/quotes.c
new file mode 100644
index 0000000000..63a219f5f4
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/quotes.c
@@ -0,0 +1,51 @@
+/*-------------------------------------------------------------------------
+ *
+ * quotes.c
+ * string quoting and escaping functions
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/port/quotes.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "c.h"
+
+/*
+ * Escape (by doubling) any single quotes or backslashes in given string
+ *
+ * Note: this is used to process postgresql.conf entries and to quote
+ * string literals in pg_basebackup for writing the recovery configuration.
+ * Since postgresql.conf strings are defined to treat backslashes as escapes,
+ * we have to double backslashes here.
+ *
+ * Since this function is only used for parsing or creating configuration
+ * files, we do not care about encoding considerations.
+ *
+ * Returns a malloced() string that it's the responsibility of the caller
+ * to free.
+ */
+char *
+escape_single_quotes_ascii(const char *src)
+{
+ int len = strlen(src),
+ i,
+ j;
+ char *result = malloc(len * 2 + 1);
+
+ if (!result)
+ return NULL;
+
+ for (i = 0, j = 0; i < len; i++)
+ {
+ if (SQL_STR_DOUBLE(src[i], true))
+ result[j++] = src[i];
+ result[j++] = src[i];
+ }
+ result[j] = '\0';
+ return result;
+}
diff --git a/contrib/libs/postgresql/src/port/snprintf.c b/contrib/libs/postgresql/src/port/snprintf.c
new file mode 100644
index 0000000000..7c21429369
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/snprintf.c
@@ -0,0 +1,1515 @@
+/*
+ * Copyright (c) 1983, 1995, 1996 Eric P. Allman
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * src/port/snprintf.c
+ */
+
+#include "c.h"
+
+#include <math.h>
+
+/*
+ * We used to use the platform's NL_ARGMAX here, but that's a bad idea,
+ * first because the point of this module is to remove platform dependencies
+ * not perpetuate them, and second because some platforms use ridiculously
+ * large values, leading to excessive stack consumption in dopr().
+ */
+#define PG_NL_ARGMAX 31
+
+
+/*
+ * SNPRINTF, VSNPRINTF and friends
+ *
+ * These versions have been grabbed off the net. They have been
+ * cleaned up to compile properly and support for most of the C99
+ * specification has been added. Remaining unimplemented features are:
+ *
+ * 1. No locale support: the radix character is always '.' and the '
+ * (single quote) format flag is ignored.
+ *
+ * 2. No support for the "%n" format specification.
+ *
+ * 3. No support for wide characters ("lc" and "ls" formats).
+ *
+ * 4. No support for "long double" ("Lf" and related formats).
+ *
+ * 5. Space and '#' flags are not implemented.
+ *
+ * In addition, we support some extensions over C99:
+ *
+ * 1. Argument order control through "%n$" and "*n$", as required by POSIX.
+ *
+ * 2. "%m" expands to the value of strerror(errno), where errno is the
+ * value that variable had at the start of the call. This is a glibc
+ * extension, but a very useful one.
+ *
+ *
+ * Historically the result values of sprintf/snprintf varied across platforms.
+ * This implementation now follows the C99 standard:
+ *
+ * 1. -1 is returned if an error is detected in the format string, or if
+ * a write to the target stream fails (as reported by fwrite). Note that
+ * overrunning snprintf's target buffer is *not* an error.
+ *
+ * 2. For successful writes to streams, the actual number of bytes written
+ * to the stream is returned.
+ *
+ * 3. For successful sprintf/snprintf, the number of bytes that would have
+ * been written to an infinite-size buffer (excluding the trailing '\0')
+ * is returned. snprintf will truncate its output to fit in the buffer
+ * (ensuring a trailing '\0' unless count == 0), but this is not reflected
+ * in the function result.
+ *
+ * snprintf buffer overrun can be detected by checking for function result
+ * greater than or equal to the supplied count.
+ */
+
+/**************************************************************
+ * Original:
+ * Patrick Powell Tue Apr 11 09:48:21 PDT 1995
+ * A bombproof version of doprnt (dopr) included.
+ * Sigh. This sort of thing is always nasty do deal with. Note that
+ * the version here does not include floating point. (now it does ... tgl)
+ **************************************************************/
+
+/* Prevent recursion */
+#undef vsnprintf
+#undef snprintf
+#undef vsprintf
+#undef sprintf
+#undef vfprintf
+#undef fprintf
+#undef vprintf
+#undef printf
+
+/*
+ * Info about where the formatted output is going.
+ *
+ * dopr and subroutines will not write at/past bufend, but snprintf
+ * reserves one byte, ensuring it may place the trailing '\0' there.
+ *
+ * In snprintf, we use nchars to count the number of bytes dropped on the
+ * floor due to buffer overrun. The correct result of snprintf is thus
+ * (bufptr - bufstart) + nchars. (This isn't as inconsistent as it might
+ * seem: nchars is the number of emitted bytes that are not in the buffer now,
+ * either because we sent them to the stream or because we couldn't fit them
+ * into the buffer to begin with.)
+ */
+typedef struct
+{
+ char *bufptr; /* next buffer output position */
+ char *bufstart; /* first buffer element */
+ char *bufend; /* last+1 buffer element, or NULL */
+ /* bufend == NULL is for sprintf, where we assume buf is big enough */
+ FILE *stream; /* eventual output destination, or NULL */
+ int nchars; /* # chars sent to stream, or dropped */
+ bool failed; /* call is a failure; errno is set */
+} PrintfTarget;
+
+/*
+ * Info about the type and value of a formatting parameter. Note that we
+ * don't currently support "long double", "wint_t", or "wchar_t *" data,
+ * nor the '%n' formatting code; else we'd need more types. Also, at this
+ * level we need not worry about signed vs unsigned values.
+ */
+typedef enum
+{
+ ATYPE_NONE = 0,
+ ATYPE_INT,
+ ATYPE_LONG,
+ ATYPE_LONGLONG,
+ ATYPE_DOUBLE,
+ ATYPE_CHARPTR
+} PrintfArgType;
+
+typedef union
+{
+ int i;
+ long l;
+ long long ll;
+ double d;
+ char *cptr;
+} PrintfArgValue;
+
+
+static void flushbuffer(PrintfTarget *target);
+static void dopr(PrintfTarget *target, const char *format, va_list args);
+
+
+/*
+ * Externally visible entry points.
+ *
+ * All of these are just wrappers around dopr(). Note it's essential that
+ * they not change the value of "errno" before reaching dopr().
+ */
+
+int
+pg_vsnprintf(char *str, size_t count, const char *fmt, va_list args)
+{
+ PrintfTarget target;
+ char onebyte[1];
+
+ /*
+ * C99 allows the case str == NULL when count == 0. Rather than
+ * special-casing this situation further down, we substitute a one-byte
+ * local buffer. Callers cannot tell, since the function result doesn't
+ * depend on count.
+ */
+ if (count == 0)
+ {
+ str = onebyte;
+ count = 1;
+ }
+ target.bufstart = target.bufptr = str;
+ target.bufend = str + count - 1;
+ target.stream = NULL;
+ target.nchars = 0;
+ target.failed = false;
+ dopr(&target, fmt, args);
+ *(target.bufptr) = '\0';
+ return target.failed ? -1 : (target.bufptr - target.bufstart
+ + target.nchars);
+}
+
+int
+pg_snprintf(char *str, size_t count, const char *fmt,...)
+{
+ int len;
+ va_list args;
+
+ va_start(args, fmt);
+ len = pg_vsnprintf(str, count, fmt, args);
+ va_end(args);
+ return len;
+}
+
+int
+pg_vsprintf(char *str, const char *fmt, va_list args)
+{
+ PrintfTarget target;
+
+ target.bufstart = target.bufptr = str;
+ target.bufend = NULL;
+ target.stream = NULL;
+ target.nchars = 0; /* not really used in this case */
+ target.failed = false;
+ dopr(&target, fmt, args);
+ *(target.bufptr) = '\0';
+ return target.failed ? -1 : (target.bufptr - target.bufstart
+ + target.nchars);
+}
+
+int
+pg_sprintf(char *str, const char *fmt,...)
+{
+ int len;
+ va_list args;
+
+ va_start(args, fmt);
+ len = pg_vsprintf(str, fmt, args);
+ va_end(args);
+ return len;
+}
+
+int
+pg_vfprintf(FILE *stream, const char *fmt, va_list args)
+{
+ PrintfTarget target;
+ char buffer[1024]; /* size is arbitrary */
+
+ if (stream == NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ target.bufstart = target.bufptr = buffer;
+ target.bufend = buffer + sizeof(buffer); /* use the whole buffer */
+ target.stream = stream;
+ target.nchars = 0;
+ target.failed = false;
+ dopr(&target, fmt, args);
+ /* dump any remaining buffer contents */
+ flushbuffer(&target);
+ return target.failed ? -1 : target.nchars;
+}
+
+int
+pg_fprintf(FILE *stream, const char *fmt,...)
+{
+ int len;
+ va_list args;
+
+ va_start(args, fmt);
+ len = pg_vfprintf(stream, fmt, args);
+ va_end(args);
+ return len;
+}
+
+int
+pg_vprintf(const char *fmt, va_list args)
+{
+ return pg_vfprintf(stdout, fmt, args);
+}
+
+int
+pg_printf(const char *fmt,...)
+{
+ int len;
+ va_list args;
+
+ va_start(args, fmt);
+ len = pg_vfprintf(stdout, fmt, args);
+ va_end(args);
+ return len;
+}
+
+/*
+ * Attempt to write the entire buffer to target->stream; discard the entire
+ * buffer in any case. Call this only when target->stream is defined.
+ */
+static void
+flushbuffer(PrintfTarget *target)
+{
+ size_t nc = target->bufptr - target->bufstart;
+
+ /*
+ * Don't write anything if we already failed; this is to ensure we
+ * preserve the original failure's errno.
+ */
+ if (!target->failed && nc > 0)
+ {
+ size_t written;
+
+ written = fwrite(target->bufstart, 1, nc, target->stream);
+ target->nchars += written;
+ if (written != nc)
+ target->failed = true;
+ }
+ target->bufptr = target->bufstart;
+}
+
+
+static bool find_arguments(const char *format, va_list args,
+ PrintfArgValue *argvalues);
+static void fmtstr(const char *value, int leftjust, int minlen, int maxwidth,
+ int pointflag, PrintfTarget *target);
+static void fmtptr(const void *value, PrintfTarget *target);
+static void fmtint(long long value, char type, int forcesign,
+ int leftjust, int minlen, int zpad, int precision, int pointflag,
+ PrintfTarget *target);
+static void fmtchar(int value, int leftjust, int minlen, PrintfTarget *target);
+static void fmtfloat(double value, char type, int forcesign,
+ int leftjust, int minlen, int zpad, int precision, int pointflag,
+ PrintfTarget *target);
+static void dostr(const char *str, int slen, PrintfTarget *target);
+static void dopr_outch(int c, PrintfTarget *target);
+static void dopr_outchmulti(int c, int slen, PrintfTarget *target);
+static int adjust_sign(int is_negative, int forcesign, int *signvalue);
+static int compute_padlen(int minlen, int vallen, int leftjust);
+static void leading_pad(int zpad, int signvalue, int *padlen,
+ PrintfTarget *target);
+static void trailing_pad(int padlen, PrintfTarget *target);
+
+/*
+ * If strchrnul exists (it's a glibc-ism), it's a good bit faster than the
+ * equivalent manual loop. If it doesn't exist, provide a replacement.
+ *
+ * Note: glibc declares this as returning "char *", but that would require
+ * casting away const internally, so we don't follow that detail.
+ */
+#ifndef HAVE_STRCHRNUL
+
+static inline const char *
+strchrnul(const char *s, int c)
+{
+ while (*s != '\0' && *s != c)
+ s++;
+ return s;
+}
+
+#else
+
+/*
+ * glibc's <string.h> declares strchrnul only if _GNU_SOURCE is defined.
+ * While we typically use that on glibc platforms, configure will set
+ * HAVE_STRCHRNUL whether it's used or not. Fill in the missing declaration
+ * so that this file will compile cleanly with or without _GNU_SOURCE.
+ */
+#ifndef _GNU_SOURCE
+extern char *strchrnul(const char *s, int c);
+#endif
+
+#endif /* HAVE_STRCHRNUL */
+
+
+/*
+ * dopr(): the guts of *printf for all cases.
+ */
+static void
+dopr(PrintfTarget *target, const char *format, va_list args)
+{
+ int save_errno = errno;
+ const char *first_pct = NULL;
+ int ch;
+ bool have_dollar;
+ bool have_star;
+ bool afterstar;
+ int accum;
+ int longlongflag;
+ int longflag;
+ int pointflag;
+ int leftjust;
+ int fieldwidth;
+ int precision;
+ int zpad;
+ int forcesign;
+ int fmtpos;
+ int cvalue;
+ long long numvalue;
+ double fvalue;
+ const char *strvalue;
+ PrintfArgValue argvalues[PG_NL_ARGMAX + 1];
+
+ /*
+ * Initially, we suppose the format string does not use %n$. The first
+ * time we come to a conversion spec that has that, we'll call
+ * find_arguments() to check for consistent use of %n$ and fill the
+ * argvalues array with the argument values in the correct order.
+ */
+ have_dollar = false;
+
+ while (*format != '\0')
+ {
+ /* Locate next conversion specifier */
+ if (*format != '%')
+ {
+ /* Scan to next '%' or end of string */
+ const char *next_pct = strchrnul(format + 1, '%');
+
+ /* Dump literal data we just scanned over */
+ dostr(format, next_pct - format, target);
+ if (target->failed)
+ break;
+
+ if (*next_pct == '\0')
+ break;
+ format = next_pct;
+ }
+
+ /*
+ * Remember start of first conversion spec; if we find %n$, then it's
+ * sufficient for find_arguments() to start here, without rescanning
+ * earlier literal text.
+ */
+ if (first_pct == NULL)
+ first_pct = format;
+
+ /* Process conversion spec starting at *format */
+ format++;
+
+ /* Fast path for conversion spec that is exactly %s */
+ if (*format == 's')
+ {
+ format++;
+ strvalue = va_arg(args, char *);
+ if (strvalue == NULL)
+ strvalue = "(null)";
+ dostr(strvalue, strlen(strvalue), target);
+ if (target->failed)
+ break;
+ continue;
+ }
+
+ fieldwidth = precision = zpad = leftjust = forcesign = 0;
+ longflag = longlongflag = pointflag = 0;
+ fmtpos = accum = 0;
+ have_star = afterstar = false;
+nextch2:
+ ch = *format++;
+ switch (ch)
+ {
+ case '-':
+ leftjust = 1;
+ goto nextch2;
+ case '+':
+ forcesign = 1;
+ goto nextch2;
+ case '0':
+ /* set zero padding if no nonzero digits yet */
+ if (accum == 0 && !pointflag)
+ zpad = '0';
+ /* FALL THRU */
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ accum = accum * 10 + (ch - '0');
+ goto nextch2;
+ case '.':
+ if (have_star)
+ have_star = false;
+ else
+ fieldwidth = accum;
+ pointflag = 1;
+ accum = 0;
+ goto nextch2;
+ case '*':
+ if (have_dollar)
+ {
+ /*
+ * We'll process value after reading n$. Note it's OK to
+ * assume have_dollar is set correctly, because in a valid
+ * format string the initial % must have had n$ if * does.
+ */
+ afterstar = true;
+ }
+ else
+ {
+ /* fetch and process value now */
+ int starval = va_arg(args, int);
+
+ if (pointflag)
+ {
+ precision = starval;
+ if (precision < 0)
+ {
+ precision = 0;
+ pointflag = 0;
+ }
+ }
+ else
+ {
+ fieldwidth = starval;
+ if (fieldwidth < 0)
+ {
+ leftjust = 1;
+ fieldwidth = -fieldwidth;
+ }
+ }
+ }
+ have_star = true;
+ accum = 0;
+ goto nextch2;
+ case '$':
+ /* First dollar sign? */
+ if (!have_dollar)
+ {
+ /* Yup, so examine all conversion specs in format */
+ if (!find_arguments(first_pct, args, argvalues))
+ goto bad_format;
+ have_dollar = true;
+ }
+ if (afterstar)
+ {
+ /* fetch and process star value */
+ int starval = argvalues[accum].i;
+
+ if (pointflag)
+ {
+ precision = starval;
+ if (precision < 0)
+ {
+ precision = 0;
+ pointflag = 0;
+ }
+ }
+ else
+ {
+ fieldwidth = starval;
+ if (fieldwidth < 0)
+ {
+ leftjust = 1;
+ fieldwidth = -fieldwidth;
+ }
+ }
+ afterstar = false;
+ }
+ else
+ fmtpos = accum;
+ accum = 0;
+ goto nextch2;
+ case 'l':
+ if (longflag)
+ longlongflag = 1;
+ else
+ longflag = 1;
+ goto nextch2;
+ case 'z':
+#if SIZEOF_SIZE_T == 8
+#ifdef HAVE_LONG_INT_64
+ longflag = 1;
+#elif defined(HAVE_LONG_LONG_INT_64)
+ longlongflag = 1;
+#else
+#error "Don't know how to print 64bit integers"
+#endif
+#else
+ /* assume size_t is same size as int */
+#endif
+ goto nextch2;
+ case 'h':
+ case '\'':
+ /* ignore these */
+ goto nextch2;
+ case 'd':
+ case 'i':
+ if (!have_star)
+ {
+ if (pointflag)
+ precision = accum;
+ else
+ fieldwidth = accum;
+ }
+ if (have_dollar)
+ {
+ if (longlongflag)
+ numvalue = argvalues[fmtpos].ll;
+ else if (longflag)
+ numvalue = argvalues[fmtpos].l;
+ else
+ numvalue = argvalues[fmtpos].i;
+ }
+ else
+ {
+ if (longlongflag)
+ numvalue = va_arg(args, long long);
+ else if (longflag)
+ numvalue = va_arg(args, long);
+ else
+ numvalue = va_arg(args, int);
+ }
+ fmtint(numvalue, ch, forcesign, leftjust, fieldwidth, zpad,
+ precision, pointflag, target);
+ break;
+ case 'o':
+ case 'u':
+ case 'x':
+ case 'X':
+ if (!have_star)
+ {
+ if (pointflag)
+ precision = accum;
+ else
+ fieldwidth = accum;
+ }
+ if (have_dollar)
+ {
+ if (longlongflag)
+ numvalue = (unsigned long long) argvalues[fmtpos].ll;
+ else if (longflag)
+ numvalue = (unsigned long) argvalues[fmtpos].l;
+ else
+ numvalue = (unsigned int) argvalues[fmtpos].i;
+ }
+ else
+ {
+ if (longlongflag)
+ numvalue = (unsigned long long) va_arg(args, long long);
+ else if (longflag)
+ numvalue = (unsigned long) va_arg(args, long);
+ else
+ numvalue = (unsigned int) va_arg(args, int);
+ }
+ fmtint(numvalue, ch, forcesign, leftjust, fieldwidth, zpad,
+ precision, pointflag, target);
+ break;
+ case 'c':
+ if (!have_star)
+ {
+ if (pointflag)
+ precision = accum;
+ else
+ fieldwidth = accum;
+ }
+ if (have_dollar)
+ cvalue = (unsigned char) argvalues[fmtpos].i;
+ else
+ cvalue = (unsigned char) va_arg(args, int);
+ fmtchar(cvalue, leftjust, fieldwidth, target);
+ break;
+ case 's':
+ if (!have_star)
+ {
+ if (pointflag)
+ precision = accum;
+ else
+ fieldwidth = accum;
+ }
+ if (have_dollar)
+ strvalue = argvalues[fmtpos].cptr;
+ else
+ strvalue = va_arg(args, char *);
+ /* If string is NULL, silently substitute "(null)" */
+ if (strvalue == NULL)
+ strvalue = "(null)";
+ fmtstr(strvalue, leftjust, fieldwidth, precision, pointflag,
+ target);
+ break;
+ case 'p':
+ /* fieldwidth/leftjust are ignored ... */
+ if (have_dollar)
+ strvalue = argvalues[fmtpos].cptr;
+ else
+ strvalue = va_arg(args, char *);
+ fmtptr((const void *) strvalue, target);
+ break;
+ case 'e':
+ case 'E':
+ case 'f':
+ case 'g':
+ case 'G':
+ if (!have_star)
+ {
+ if (pointflag)
+ precision = accum;
+ else
+ fieldwidth = accum;
+ }
+ if (have_dollar)
+ fvalue = argvalues[fmtpos].d;
+ else
+ fvalue = va_arg(args, double);
+ fmtfloat(fvalue, ch, forcesign, leftjust,
+ fieldwidth, zpad,
+ precision, pointflag,
+ target);
+ break;
+ case 'm':
+ {
+ char errbuf[PG_STRERROR_R_BUFLEN];
+ const char *errm = strerror_r(save_errno,
+ errbuf, sizeof(errbuf));
+
+ dostr(errm, strlen(errm), target);
+ }
+ break;
+ case '%':
+ dopr_outch('%', target);
+ break;
+ default:
+
+ /*
+ * Anything else --- in particular, '\0' indicating end of
+ * format string --- is bogus.
+ */
+ goto bad_format;
+ }
+
+ /* Check for failure after each conversion spec */
+ if (target->failed)
+ break;
+ }
+
+ return;
+
+bad_format:
+ errno = EINVAL;
+ target->failed = true;
+}
+
+/*
+ * find_arguments(): sort out the arguments for a format spec with %n$
+ *
+ * If format is valid, return true and fill argvalues[i] with the value
+ * for the conversion spec that has %i$ or *i$. Else return false.
+ */
+static bool
+find_arguments(const char *format, va_list args,
+ PrintfArgValue *argvalues)
+{
+ int ch;
+ bool afterstar;
+ int accum;
+ int longlongflag;
+ int longflag;
+ int fmtpos;
+ int i;
+ int last_dollar;
+ PrintfArgType argtypes[PG_NL_ARGMAX + 1];
+
+ /* Initialize to "no dollar arguments known" */
+ last_dollar = 0;
+ MemSet(argtypes, 0, sizeof(argtypes));
+
+ /*
+ * This loop must accept the same format strings as the one in dopr().
+ * However, we don't need to analyze them to the same level of detail.
+ *
+ * Since we're only called if there's a dollar-type spec somewhere, we can
+ * fail immediately if we find a non-dollar spec. Per the C99 standard,
+ * all argument references in the format string must be one or the other.
+ */
+ while (*format != '\0')
+ {
+ /* Locate next conversion specifier */
+ if (*format != '%')
+ {
+ /* Unlike dopr, we can just quit if there's no more specifiers */
+ format = strchr(format + 1, '%');
+ if (format == NULL)
+ break;
+ }
+
+ /* Process conversion spec starting at *format */
+ format++;
+ longflag = longlongflag = 0;
+ fmtpos = accum = 0;
+ afterstar = false;
+nextch1:
+ ch = *format++;
+ switch (ch)
+ {
+ case '-':
+ case '+':
+ goto nextch1;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ accum = accum * 10 + (ch - '0');
+ goto nextch1;
+ case '.':
+ accum = 0;
+ goto nextch1;
+ case '*':
+ if (afterstar)
+ return false; /* previous star missing dollar */
+ afterstar = true;
+ accum = 0;
+ goto nextch1;
+ case '$':
+ if (accum <= 0 || accum > PG_NL_ARGMAX)
+ return false;
+ if (afterstar)
+ {
+ if (argtypes[accum] &&
+ argtypes[accum] != ATYPE_INT)
+ return false;
+ argtypes[accum] = ATYPE_INT;
+ last_dollar = Max(last_dollar, accum);
+ afterstar = false;
+ }
+ else
+ fmtpos = accum;
+ accum = 0;
+ goto nextch1;
+ case 'l':
+ if (longflag)
+ longlongflag = 1;
+ else
+ longflag = 1;
+ goto nextch1;
+ case 'z':
+#if SIZEOF_SIZE_T == 8
+#ifdef HAVE_LONG_INT_64
+ longflag = 1;
+#elif defined(HAVE_LONG_LONG_INT_64)
+ longlongflag = 1;
+#else
+#error "Don't know how to print 64bit integers"
+#endif
+#else
+ /* assume size_t is same size as int */
+#endif
+ goto nextch1;
+ case 'h':
+ case '\'':
+ /* ignore these */
+ goto nextch1;
+ case 'd':
+ case 'i':
+ case 'o':
+ case 'u':
+ case 'x':
+ case 'X':
+ if (fmtpos)
+ {
+ PrintfArgType atype;
+
+ if (longlongflag)
+ atype = ATYPE_LONGLONG;
+ else if (longflag)
+ atype = ATYPE_LONG;
+ else
+ atype = ATYPE_INT;
+ if (argtypes[fmtpos] &&
+ argtypes[fmtpos] != atype)
+ return false;
+ argtypes[fmtpos] = atype;
+ last_dollar = Max(last_dollar, fmtpos);
+ }
+ else
+ return false; /* non-dollar conversion spec */
+ break;
+ case 'c':
+ if (fmtpos)
+ {
+ if (argtypes[fmtpos] &&
+ argtypes[fmtpos] != ATYPE_INT)
+ return false;
+ argtypes[fmtpos] = ATYPE_INT;
+ last_dollar = Max(last_dollar, fmtpos);
+ }
+ else
+ return false; /* non-dollar conversion spec */
+ break;
+ case 's':
+ case 'p':
+ if (fmtpos)
+ {
+ if (argtypes[fmtpos] &&
+ argtypes[fmtpos] != ATYPE_CHARPTR)
+ return false;
+ argtypes[fmtpos] = ATYPE_CHARPTR;
+ last_dollar = Max(last_dollar, fmtpos);
+ }
+ else
+ return false; /* non-dollar conversion spec */
+ break;
+ case 'e':
+ case 'E':
+ case 'f':
+ case 'g':
+ case 'G':
+ if (fmtpos)
+ {
+ if (argtypes[fmtpos] &&
+ argtypes[fmtpos] != ATYPE_DOUBLE)
+ return false;
+ argtypes[fmtpos] = ATYPE_DOUBLE;
+ last_dollar = Max(last_dollar, fmtpos);
+ }
+ else
+ return false; /* non-dollar conversion spec */
+ break;
+ case 'm':
+ case '%':
+ break;
+ default:
+ return false; /* bogus format string */
+ }
+
+ /*
+ * If we finish the spec with afterstar still set, there's a
+ * non-dollar star in there.
+ */
+ if (afterstar)
+ return false; /* non-dollar conversion spec */
+ }
+
+ /*
+ * Format appears valid so far, so collect the arguments in physical
+ * order. (Since we rejected any non-dollar specs that would have
+ * collected arguments, we know that dopr() hasn't collected any yet.)
+ */
+ for (i = 1; i <= last_dollar; i++)
+ {
+ switch (argtypes[i])
+ {
+ case ATYPE_NONE:
+ return false;
+ case ATYPE_INT:
+ argvalues[i].i = va_arg(args, int);
+ break;
+ case ATYPE_LONG:
+ argvalues[i].l = va_arg(args, long);
+ break;
+ case ATYPE_LONGLONG:
+ argvalues[i].ll = va_arg(args, long long);
+ break;
+ case ATYPE_DOUBLE:
+ argvalues[i].d = va_arg(args, double);
+ break;
+ case ATYPE_CHARPTR:
+ argvalues[i].cptr = va_arg(args, char *);
+ break;
+ }
+ }
+
+ return true;
+}
+
+static void
+fmtstr(const char *value, int leftjust, int minlen, int maxwidth,
+ int pointflag, PrintfTarget *target)
+{
+ int padlen,
+ vallen; /* amount to pad */
+
+ /*
+ * If a maxwidth (precision) is specified, we must not fetch more bytes
+ * than that.
+ */
+ if (pointflag)
+ vallen = strnlen(value, maxwidth);
+ else
+ vallen = strlen(value);
+
+ padlen = compute_padlen(minlen, vallen, leftjust);
+
+ if (padlen > 0)
+ {
+ dopr_outchmulti(' ', padlen, target);
+ padlen = 0;
+ }
+
+ dostr(value, vallen, target);
+
+ trailing_pad(padlen, target);
+}
+
+static void
+fmtptr(const void *value, PrintfTarget *target)
+{
+ int vallen;
+ char convert[64];
+
+ /* we rely on regular C library's sprintf to do the basic conversion */
+ vallen = sprintf(convert, "%p", value);
+ if (vallen < 0)
+ target->failed = true;
+ else
+ dostr(convert, vallen, target);
+}
+
+static void
+fmtint(long long value, char type, int forcesign, int leftjust,
+ int minlen, int zpad, int precision, int pointflag,
+ PrintfTarget *target)
+{
+ unsigned long long base;
+ unsigned long long uvalue;
+ int dosign;
+ const char *cvt = "0123456789abcdef";
+ int signvalue = 0;
+ char convert[64];
+ int vallen = 0;
+ int padlen; /* amount to pad */
+ int zeropad; /* extra leading zeroes */
+
+ switch (type)
+ {
+ case 'd':
+ case 'i':
+ base = 10;
+ dosign = 1;
+ break;
+ case 'o':
+ base = 8;
+ dosign = 0;
+ break;
+ case 'u':
+ base = 10;
+ dosign = 0;
+ break;
+ case 'x':
+ base = 16;
+ dosign = 0;
+ break;
+ case 'X':
+ cvt = "0123456789ABCDEF";
+ base = 16;
+ dosign = 0;
+ break;
+ default:
+ return; /* keep compiler quiet */
+ }
+
+ /* disable MSVC warning about applying unary minus to an unsigned value */
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4146)
+#endif
+ /* Handle +/- */
+ if (dosign && adjust_sign((value < 0), forcesign, &signvalue))
+ uvalue = -(unsigned long long) value;
+ else
+ uvalue = (unsigned long long) value;
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+ /*
+ * SUS: the result of converting 0 with an explicit precision of 0 is no
+ * characters
+ */
+ if (value == 0 && pointflag && precision == 0)
+ vallen = 0;
+ else
+ {
+ /* make integer string */
+ do
+ {
+ convert[sizeof(convert) - (++vallen)] = cvt[uvalue % base];
+ uvalue = uvalue / base;
+ } while (uvalue);
+ }
+
+ zeropad = Max(0, precision - vallen);
+
+ padlen = compute_padlen(minlen, vallen + zeropad, leftjust);
+
+ leading_pad(zpad, signvalue, &padlen, target);
+
+ if (zeropad > 0)
+ dopr_outchmulti('0', zeropad, target);
+
+ dostr(convert + sizeof(convert) - vallen, vallen, target);
+
+ trailing_pad(padlen, target);
+}
+
+static void
+fmtchar(int value, int leftjust, int minlen, PrintfTarget *target)
+{
+ int padlen; /* amount to pad */
+
+ padlen = compute_padlen(minlen, 1, leftjust);
+
+ if (padlen > 0)
+ {
+ dopr_outchmulti(' ', padlen, target);
+ padlen = 0;
+ }
+
+ dopr_outch(value, target);
+
+ trailing_pad(padlen, target);
+}
+
+static void
+fmtfloat(double value, char type, int forcesign, int leftjust,
+ int minlen, int zpad, int precision, int pointflag,
+ PrintfTarget *target)
+{
+ int signvalue = 0;
+ int prec;
+ int vallen;
+ char fmt[8];
+ char convert[1024];
+ int zeropadlen = 0; /* amount to pad with zeroes */
+ int padlen; /* amount to pad with spaces */
+
+ /*
+ * We rely on the regular C library's sprintf to do the basic conversion,
+ * then handle padding considerations here.
+ *
+ * The dynamic range of "double" is about 1E+-308 for IEEE math, and not
+ * too wildly more than that with other hardware. In "f" format, sprintf
+ * could therefore generate at most 308 characters to the left of the
+ * decimal point; while we need to allow the precision to get as high as
+ * 308+17 to ensure that we don't truncate significant digits from very
+ * small values. To handle both these extremes, we use a buffer of 1024
+ * bytes and limit requested precision to 350 digits; this should prevent
+ * buffer overrun even with non-IEEE math. If the original precision
+ * request was more than 350, separately pad with zeroes.
+ *
+ * We handle infinities and NaNs specially to ensure platform-independent
+ * output.
+ */
+ if (precision < 0) /* cover possible overflow of "accum" */
+ precision = 0;
+ prec = Min(precision, 350);
+
+ if (isnan(value))
+ {
+ strcpy(convert, "NaN");
+ vallen = 3;
+ /* no zero padding, regardless of precision spec */
+ }
+ else
+ {
+ /*
+ * Handle sign (NaNs have no sign, so we don't do this in the case
+ * above). "value < 0.0" will not be true for IEEE minus zero, so we
+ * detect that by looking for the case where value equals 0.0
+ * according to == but not according to memcmp.
+ */
+ static const double dzero = 0.0;
+
+ if (adjust_sign((value < 0.0 ||
+ (value == 0.0 &&
+ memcmp(&value, &dzero, sizeof(double)) != 0)),
+ forcesign, &signvalue))
+ value = -value;
+
+ if (isinf(value))
+ {
+ strcpy(convert, "Infinity");
+ vallen = 8;
+ /* no zero padding, regardless of precision spec */
+ }
+ else if (pointflag)
+ {
+ zeropadlen = precision - prec;
+ fmt[0] = '%';
+ fmt[1] = '.';
+ fmt[2] = '*';
+ fmt[3] = type;
+ fmt[4] = '\0';
+ vallen = sprintf(convert, fmt, prec, value);
+ }
+ else
+ {
+ fmt[0] = '%';
+ fmt[1] = type;
+ fmt[2] = '\0';
+ vallen = sprintf(convert, fmt, value);
+ }
+ if (vallen < 0)
+ goto fail;
+
+ /*
+ * Windows, alone among our supported platforms, likes to emit
+ * three-digit exponent fields even when two digits would do. Hack
+ * such results to look like the way everyone else does it.
+ */
+#ifdef WIN32
+ if (vallen >= 6 &&
+ convert[vallen - 5] == 'e' &&
+ convert[vallen - 3] == '0')
+ {
+ convert[vallen - 3] = convert[vallen - 2];
+ convert[vallen - 2] = convert[vallen - 1];
+ vallen--;
+ }
+#endif
+ }
+
+ padlen = compute_padlen(minlen, vallen + zeropadlen, leftjust);
+
+ leading_pad(zpad, signvalue, &padlen, target);
+
+ if (zeropadlen > 0)
+ {
+ /* If 'e' or 'E' format, inject zeroes before the exponent */
+ char *epos = strrchr(convert, 'e');
+
+ if (!epos)
+ epos = strrchr(convert, 'E');
+ if (epos)
+ {
+ /* pad before exponent */
+ dostr(convert, epos - convert, target);
+ dopr_outchmulti('0', zeropadlen, target);
+ dostr(epos, vallen - (epos - convert), target);
+ }
+ else
+ {
+ /* no exponent, pad after the digits */
+ dostr(convert, vallen, target);
+ dopr_outchmulti('0', zeropadlen, target);
+ }
+ }
+ else
+ {
+ /* no zero padding, just emit the number as-is */
+ dostr(convert, vallen, target);
+ }
+
+ trailing_pad(padlen, target);
+ return;
+
+fail:
+ target->failed = true;
+}
+
+/*
+ * Nonstandard entry point to print a double value efficiently.
+ *
+ * This is approximately equivalent to strfromd(), but has an API more
+ * adapted to what float8out() wants. The behavior is like snprintf()
+ * with a format of "%.ng", where n is the specified precision.
+ * However, the target buffer must be nonempty (i.e. count > 0), and
+ * the precision is silently bounded to a sane range.
+ */
+int
+pg_strfromd(char *str, size_t count, int precision, double value)
+{
+ PrintfTarget target;
+ int signvalue = 0;
+ int vallen;
+ char fmt[8];
+ char convert[64];
+
+ /* Set up the target like pg_snprintf, but require nonempty buffer */
+ Assert(count > 0);
+ target.bufstart = target.bufptr = str;
+ target.bufend = str + count - 1;
+ target.stream = NULL;
+ target.nchars = 0;
+ target.failed = false;
+
+ /*
+ * We bound precision to a reasonable range; the combination of this and
+ * the knowledge that we're using "g" format without padding allows the
+ * convert[] buffer to be reasonably small.
+ */
+ if (precision < 1)
+ precision = 1;
+ else if (precision > 32)
+ precision = 32;
+
+ /*
+ * The rest is just an inlined version of the fmtfloat() logic above,
+ * simplified using the knowledge that no padding is wanted.
+ */
+ if (isnan(value))
+ {
+ strcpy(convert, "NaN");
+ vallen = 3;
+ }
+ else
+ {
+ static const double dzero = 0.0;
+
+ if (value < 0.0 ||
+ (value == 0.0 &&
+ memcmp(&value, &dzero, sizeof(double)) != 0))
+ {
+ signvalue = '-';
+ value = -value;
+ }
+
+ if (isinf(value))
+ {
+ strcpy(convert, "Infinity");
+ vallen = 8;
+ }
+ else
+ {
+ fmt[0] = '%';
+ fmt[1] = '.';
+ fmt[2] = '*';
+ fmt[3] = 'g';
+ fmt[4] = '\0';
+ vallen = sprintf(convert, fmt, precision, value);
+ if (vallen < 0)
+ {
+ target.failed = true;
+ goto fail;
+ }
+
+#ifdef WIN32
+ if (vallen >= 6 &&
+ convert[vallen - 5] == 'e' &&
+ convert[vallen - 3] == '0')
+ {
+ convert[vallen - 3] = convert[vallen - 2];
+ convert[vallen - 2] = convert[vallen - 1];
+ vallen--;
+ }
+#endif
+ }
+ }
+
+ if (signvalue)
+ dopr_outch(signvalue, &target);
+
+ dostr(convert, vallen, &target);
+
+fail:
+ *(target.bufptr) = '\0';
+ return target.failed ? -1 : (target.bufptr - target.bufstart
+ + target.nchars);
+}
+
+
+static void
+dostr(const char *str, int slen, PrintfTarget *target)
+{
+ /* fast path for common case of slen == 1 */
+ if (slen == 1)
+ {
+ dopr_outch(*str, target);
+ return;
+ }
+
+ while (slen > 0)
+ {
+ int avail;
+
+ if (target->bufend != NULL)
+ avail = target->bufend - target->bufptr;
+ else
+ avail = slen;
+ if (avail <= 0)
+ {
+ /* buffer full, can we dump to stream? */
+ if (target->stream == NULL)
+ {
+ target->nchars += slen; /* no, lose the data */
+ return;
+ }
+ flushbuffer(target);
+ continue;
+ }
+ avail = Min(avail, slen);
+ memmove(target->bufptr, str, avail);
+ target->bufptr += avail;
+ str += avail;
+ slen -= avail;
+ }
+}
+
+static void
+dopr_outch(int c, PrintfTarget *target)
+{
+ if (target->bufend != NULL && target->bufptr >= target->bufend)
+ {
+ /* buffer full, can we dump to stream? */
+ if (target->stream == NULL)
+ {
+ target->nchars++; /* no, lose the data */
+ return;
+ }
+ flushbuffer(target);
+ }
+ *(target->bufptr++) = c;
+}
+
+static void
+dopr_outchmulti(int c, int slen, PrintfTarget *target)
+{
+ /* fast path for common case of slen == 1 */
+ if (slen == 1)
+ {
+ dopr_outch(c, target);
+ return;
+ }
+
+ while (slen > 0)
+ {
+ int avail;
+
+ if (target->bufend != NULL)
+ avail = target->bufend - target->bufptr;
+ else
+ avail = slen;
+ if (avail <= 0)
+ {
+ /* buffer full, can we dump to stream? */
+ if (target->stream == NULL)
+ {
+ target->nchars += slen; /* no, lose the data */
+ return;
+ }
+ flushbuffer(target);
+ continue;
+ }
+ avail = Min(avail, slen);
+ memset(target->bufptr, c, avail);
+ target->bufptr += avail;
+ slen -= avail;
+ }
+}
+
+
+static int
+adjust_sign(int is_negative, int forcesign, int *signvalue)
+{
+ if (is_negative)
+ {
+ *signvalue = '-';
+ return true;
+ }
+ else if (forcesign)
+ *signvalue = '+';
+ return false;
+}
+
+
+static int
+compute_padlen(int minlen, int vallen, int leftjust)
+{
+ int padlen;
+
+ padlen = minlen - vallen;
+ if (padlen < 0)
+ padlen = 0;
+ if (leftjust)
+ padlen = -padlen;
+ return padlen;
+}
+
+
+static void
+leading_pad(int zpad, int signvalue, int *padlen, PrintfTarget *target)
+{
+ int maxpad;
+
+ if (*padlen > 0 && zpad)
+ {
+ if (signvalue)
+ {
+ dopr_outch(signvalue, target);
+ --(*padlen);
+ signvalue = 0;
+ }
+ if (*padlen > 0)
+ {
+ dopr_outchmulti(zpad, *padlen, target);
+ *padlen = 0;
+ }
+ }
+ maxpad = (signvalue != 0);
+ if (*padlen > maxpad)
+ {
+ dopr_outchmulti(' ', *padlen - maxpad, target);
+ *padlen = maxpad;
+ }
+ if (signvalue)
+ {
+ dopr_outch(signvalue, target);
+ if (*padlen > 0)
+ --(*padlen);
+ else if (*padlen < 0)
+ ++(*padlen);
+ }
+}
+
+
+static void
+trailing_pad(int padlen, PrintfTarget *target)
+{
+ if (padlen < 0)
+ dopr_outchmulti(' ', -padlen, target);
+}
diff --git a/contrib/libs/postgresql/src/port/strerror.c b/contrib/libs/postgresql/src/port/strerror.c
new file mode 100644
index 0000000000..c07c983e75
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/strerror.c
@@ -0,0 +1,314 @@
+/*-------------------------------------------------------------------------
+ *
+ * strerror.c
+ * Replacements for standard strerror() and strerror_r() functions
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/port/strerror.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "c.h"
+
+/*
+ * Within this file, "strerror" means the platform's function not pg_strerror,
+ * and likewise for "strerror_r"
+ */
+#undef strerror
+#undef strerror_r
+
+static char *gnuish_strerror_r(int errnum, char *buf, size_t buflen);
+static char *get_errno_symbol(int errnum);
+#ifdef WIN32
+static char *win32_socket_strerror(int errnum, char *buf, size_t buflen);
+#endif
+
+
+/*
+ * A slightly cleaned-up version of strerror()
+ */
+char *
+pg_strerror(int errnum)
+{
+ static char errorstr_buf[PG_STRERROR_R_BUFLEN];
+
+ return pg_strerror_r(errnum, errorstr_buf, sizeof(errorstr_buf));
+}
+
+/*
+ * A slightly cleaned-up version of strerror_r()
+ */
+char *
+pg_strerror_r(int errnum, char *buf, size_t buflen)
+{
+ char *str;
+
+ /* If it's a Windows Winsock error, that needs special handling */
+#ifdef WIN32
+ /* Winsock error code range, per WinError.h */
+ if (errnum >= 10000 && errnum <= 11999)
+ return win32_socket_strerror(errnum, buf, buflen);
+#endif
+
+ /* Try the platform's strerror_r(), or maybe just strerror() */
+ str = gnuish_strerror_r(errnum, buf, buflen);
+
+ /*
+ * Some strerror()s return an empty string for out-of-range errno. This
+ * is ANSI C spec compliant, but not exactly useful. Also, we may get
+ * back strings of question marks if libc cannot transcode the message to
+ * the codeset specified by LC_CTYPE. If we get nothing useful, first try
+ * get_errno_symbol(), and if that fails, print the numeric errno.
+ */
+ if (str == NULL || *str == '\0' || *str == '?')
+ str = get_errno_symbol(errnum);
+
+ if (str == NULL)
+ {
+ snprintf(buf, buflen, _("operating system error %d"), errnum);
+ str = buf;
+ }
+
+ return str;
+}
+
+/*
+ * Simple wrapper to emulate GNU strerror_r if what the platform provides is
+ * POSIX. Also, if platform lacks strerror_r altogether, fall back to plain
+ * strerror; it might not be very thread-safe, but tough luck.
+ */
+static char *
+gnuish_strerror_r(int errnum, char *buf, size_t buflen)
+{
+#ifdef HAVE_STRERROR_R
+#ifdef STRERROR_R_INT
+ /* POSIX API */
+ if (strerror_r(errnum, buf, buflen) == 0)
+ return buf;
+ return NULL; /* let caller deal with failure */
+#else
+ /* GNU API */
+ return strerror_r(errnum, buf, buflen);
+#endif
+#else /* !HAVE_STRERROR_R */
+ char *sbuf = strerror(errnum);
+
+ if (sbuf == NULL) /* can this still happen anywhere? */
+ return NULL;
+ /* To minimize thread-unsafety hazard, copy into caller's buffer */
+ strlcpy(buf, sbuf, buflen);
+ return buf;
+#endif
+}
+
+/*
+ * Returns a symbol (e.g. "ENOENT") for an errno code.
+ * Returns NULL if the code is unrecognized.
+ */
+static char *
+get_errno_symbol(int errnum)
+{
+ switch (errnum)
+ {
+ case E2BIG:
+ return "E2BIG";
+ case EACCES:
+ return "EACCES";
+ case EADDRINUSE:
+ return "EADDRINUSE";
+ case EADDRNOTAVAIL:
+ return "EADDRNOTAVAIL";
+ case EAFNOSUPPORT:
+ return "EAFNOSUPPORT";
+#ifdef EAGAIN
+ case EAGAIN:
+ return "EAGAIN";
+#endif
+#ifdef EALREADY
+ case EALREADY:
+ return "EALREADY";
+#endif
+ case EBADF:
+ return "EBADF";
+#ifdef EBADMSG
+ case EBADMSG:
+ return "EBADMSG";
+#endif
+ case EBUSY:
+ return "EBUSY";
+ case ECHILD:
+ return "ECHILD";
+ case ECONNABORTED:
+ return "ECONNABORTED";
+ case ECONNREFUSED:
+ return "ECONNREFUSED";
+ case ECONNRESET:
+ return "ECONNRESET";
+ case EDEADLK:
+ return "EDEADLK";
+ case EDOM:
+ return "EDOM";
+ case EEXIST:
+ return "EEXIST";
+ case EFAULT:
+ return "EFAULT";
+ case EFBIG:
+ return "EFBIG";
+ case EHOSTDOWN:
+ return "EHOSTDOWN";
+ case EHOSTUNREACH:
+ return "EHOSTUNREACH";
+ case EIDRM:
+ return "EIDRM";
+ case EINPROGRESS:
+ return "EINPROGRESS";
+ case EINTR:
+ return "EINTR";
+ case EINVAL:
+ return "EINVAL";
+ case EIO:
+ return "EIO";
+ case EISCONN:
+ return "EISCONN";
+ case EISDIR:
+ return "EISDIR";
+#ifdef ELOOP
+ case ELOOP:
+ return "ELOOP";
+#endif
+ case EMFILE:
+ return "EMFILE";
+ case EMLINK:
+ return "EMLINK";
+ case EMSGSIZE:
+ return "EMSGSIZE";
+ case ENAMETOOLONG:
+ return "ENAMETOOLONG";
+ case ENETDOWN:
+ return "ENETDOWN";
+ case ENETRESET:
+ return "ENETRESET";
+ case ENETUNREACH:
+ return "ENETUNREACH";
+ case ENFILE:
+ return "ENFILE";
+ case ENOBUFS:
+ return "ENOBUFS";
+ case ENODEV:
+ return "ENODEV";
+ case ENOENT:
+ return "ENOENT";
+ case ENOEXEC:
+ return "ENOEXEC";
+ case ENOMEM:
+ return "ENOMEM";
+ case ENOSPC:
+ return "ENOSPC";
+ case ENOSYS:
+ return "ENOSYS";
+ case ENOTCONN:
+ return "ENOTCONN";
+ case ENOTDIR:
+ return "ENOTDIR";
+#if defined(ENOTEMPTY) && (ENOTEMPTY != EEXIST) /* same code on AIX */
+ case ENOTEMPTY:
+ return "ENOTEMPTY";
+#endif
+ case ENOTSOCK:
+ return "ENOTSOCK";
+#ifdef ENOTSUP
+ case ENOTSUP:
+ return "ENOTSUP";
+#endif
+ case ENOTTY:
+ return "ENOTTY";
+ case ENXIO:
+ return "ENXIO";
+#if defined(EOPNOTSUPP) && (!defined(ENOTSUP) || (EOPNOTSUPP != ENOTSUP))
+ case EOPNOTSUPP:
+ return "EOPNOTSUPP";
+#endif
+#ifdef EOVERFLOW
+ case EOVERFLOW:
+ return "EOVERFLOW";
+#endif
+ case EPERM:
+ return "EPERM";
+ case EPIPE:
+ return "EPIPE";
+ case EPROTONOSUPPORT:
+ return "EPROTONOSUPPORT";
+ case ERANGE:
+ return "ERANGE";
+#ifdef EROFS
+ case EROFS:
+ return "EROFS";
+#endif
+ case ESRCH:
+ return "ESRCH";
+#ifdef ETIMEDOUT
+ case ETIMEDOUT:
+ return "ETIMEDOUT";
+#endif
+#ifdef ETXTBSY
+ case ETXTBSY:
+ return "ETXTBSY";
+#endif
+#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
+ case EWOULDBLOCK:
+ return "EWOULDBLOCK";
+#endif
+ case EXDEV:
+ return "EXDEV";
+ }
+
+ return NULL;
+}
+
+
+#ifdef WIN32
+
+/*
+ * Windows' strerror() doesn't know the Winsock codes, so handle them this way
+ */
+static char *
+win32_socket_strerror(int errnum, char *buf, size_t buflen)
+{
+ static HANDLE handleDLL = INVALID_HANDLE_VALUE;
+
+ if (handleDLL == INVALID_HANDLE_VALUE)
+ {
+ handleDLL = LoadLibraryEx("netmsg.dll", NULL,
+ DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE);
+ if (handleDLL == NULL)
+ {
+ snprintf(buf, buflen,
+ "winsock error %d (could not load netmsg.dll to translate: error code %lu)",
+ errnum, GetLastError());
+ return buf;
+ }
+ }
+
+ ZeroMemory(buf, buflen);
+ if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_FROM_HMODULE,
+ handleDLL,
+ errnum,
+ MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
+ buf,
+ buflen - 1,
+ NULL) == 0)
+ {
+ /* Failed to get id */
+ snprintf(buf, buflen, "unrecognized winsock error %d", errnum);
+ }
+
+ return buf;
+}
+
+#endif /* WIN32 */
diff --git a/contrib/libs/postgresql/src/port/system.c b/contrib/libs/postgresql/src/port/system.c
new file mode 100644
index 0000000000..8618e47f97
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/system.c
@@ -0,0 +1,117 @@
+/*-------------------------------------------------------------------------
+ *
+ * system.c
+ * Win32 system() and popen() replacements
+ *
+ *
+ * Win32 needs double quotes at the beginning and end of system()
+ * strings. If not, it gets confused with multiple quoted strings.
+ * It also requires double-quotes around the executable name and
+ * any files used for redirection. Filter other args through
+ * appendShellString() to quote them.
+ *
+ * Generated using Win32 "CMD /?":
+ *
+ * 1. If all of the following conditions are met, then quote characters
+ * on the command line are preserved:
+ *
+ * - no /S switch
+ * - exactly two quote characters
+ * - no special characters between the two quote characters, where special
+ * is one of: &<>()@^|
+ * - there are one or more whitespace characters between the two quote
+ * characters
+ * - the string between the two quote characters is the name of an
+ * executable file.
+ *
+ * 2. Otherwise, old behavior is to see if the first character is a quote
+ * character and if so, strip the leading character and remove the last
+ * quote character on the command line, preserving any text after the last
+ * quote character.
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ *
+ * src/port/system.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#if defined(WIN32) && !defined(__CYGWIN__)
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include <fcntl.h>
+
+#undef system
+#undef popen
+
+int
+pgwin32_system(const char *command)
+{
+ size_t cmdlen = strlen(command);
+ char *buf;
+ int save_errno;
+ int res;
+
+ /*
+ * Create a malloc'd copy of the command string, enclosed with an extra
+ * pair of quotes
+ */
+ buf = malloc(cmdlen + 2 + 1);
+ if (buf == NULL)
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+ buf[0] = '"';
+ memcpy(&buf[1], command, cmdlen);
+ buf[cmdlen + 1] = '"';
+ buf[cmdlen + 2] = '\0';
+
+ res = system(buf);
+
+ save_errno = errno;
+ free(buf);
+ errno = save_errno;
+
+ return res;
+}
+
+
+FILE *
+pgwin32_popen(const char *command, const char *type)
+{
+ size_t cmdlen = strlen(command);
+ char *buf;
+ int save_errno;
+ FILE *res;
+
+ /*
+ * Create a malloc'd copy of the command string, enclosed with an extra
+ * pair of quotes
+ */
+ buf = malloc(cmdlen + 2 + 1);
+ if (buf == NULL)
+ {
+ errno = ENOMEM;
+ return NULL;
+ }
+ buf[0] = '"';
+ memcpy(&buf[1], command, cmdlen);
+ buf[cmdlen + 1] = '"';
+ buf[cmdlen + 2] = '\0';
+
+ res = _popen(buf, type);
+
+ save_errno = errno;
+ free(buf);
+ errno = save_errno;
+
+ return res;
+}
+
+#endif
diff --git a/contrib/libs/postgresql/src/port/tar.c b/contrib/libs/postgresql/src/port/tar.c
new file mode 100644
index 0000000000..4afe9f2533
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/tar.c
@@ -0,0 +1,206 @@
+#include "c.h"
+
+#include <sys/stat.h>
+
+#include "pgtar.h"
+
+/*
+ * Print a numeric field in a tar header. The field starts at *s and is of
+ * length len; val is the value to be written.
+ *
+ * Per POSIX, the way to write a number is in octal with leading zeroes and
+ * one trailing space (or NUL, but we use space) at the end of the specified
+ * field width.
+ *
+ * However, the given value may not fit in the available space in octal form.
+ * If that's true, we use the GNU extension of writing \200 followed by the
+ * number in base-256 form (ie, stored in binary MSB-first). (Note: here we
+ * support only non-negative numbers, so we don't worry about the GNU rules
+ * for handling negative numbers.)
+ */
+void
+print_tar_number(char *s, int len, uint64 val)
+{
+ if (val < (((uint64) 1) << ((len - 1) * 3)))
+ {
+ /* Use octal with trailing space */
+ s[--len] = ' ';
+ while (len)
+ {
+ s[--len] = (val & 7) + '0';
+ val >>= 3;
+ }
+ }
+ else
+ {
+ /* Use base-256 with leading \200 */
+ s[0] = '\200';
+ while (len > 1)
+ {
+ s[--len] = (val & 255);
+ val >>= 8;
+ }
+ }
+}
+
+
+/*
+ * Read a numeric field in a tar header. The field starts at *s and is of
+ * length len.
+ *
+ * The POSIX-approved format for a number is octal, ending with a space or
+ * NUL. However, for values that don't fit, we recognize the GNU extension
+ * of \200 followed by the number in base-256 form (ie, stored in binary
+ * MSB-first). (Note: here we support only non-negative numbers, so we don't
+ * worry about the GNU rules for handling negative numbers.)
+ */
+uint64
+read_tar_number(const char *s, int len)
+{
+ uint64 result = 0;
+
+ if (*s == '\200')
+ {
+ /* base-256 */
+ while (--len)
+ {
+ result <<= 8;
+ result |= (unsigned char) (*++s);
+ }
+ }
+ else
+ {
+ /* octal */
+ while (len-- && *s >= '0' && *s <= '7')
+ {
+ result <<= 3;
+ result |= (*s - '0');
+ s++;
+ }
+ }
+ return result;
+}
+
+
+/*
+ * Calculate the tar checksum for a header. The header is assumed to always
+ * be 512 bytes, per the tar standard.
+ */
+int
+tarChecksum(char *header)
+{
+ int i,
+ sum;
+
+ /*
+ * Per POSIX, the checksum is the simple sum of all bytes in the header,
+ * treating the bytes as unsigned, and treating the checksum field (at
+ * offset 148) as though it contained 8 spaces.
+ */
+ sum = 8 * ' '; /* presumed value for checksum field */
+ for (i = 0; i < 512; i++)
+ if (i < 148 || i >= 156)
+ sum += 0xFF & header[i];
+ return sum;
+}
+
+
+/*
+ * Fill in the buffer pointed to by h with a tar format header. This buffer
+ * must always have space for 512 characters, which is a requirement of
+ * the tar format.
+ */
+enum tarError
+tarCreateHeader(char *h, const char *filename, const char *linktarget,
+ pgoff_t size, mode_t mode, uid_t uid, gid_t gid, time_t mtime)
+{
+ if (strlen(filename) > 99)
+ return TAR_NAME_TOO_LONG;
+
+ if (linktarget && strlen(linktarget) > 99)
+ return TAR_SYMLINK_TOO_LONG;
+
+ memset(h, 0, 512); /* assume tar header size */
+
+ /* Name 100 */
+ strlcpy(&h[0], filename, 100);
+ if (linktarget != NULL || S_ISDIR(mode))
+ {
+ /*
+ * We only support symbolic links to directories, and this is
+ * indicated in the tar format by adding a slash at the end of the
+ * name, the same as for regular directories.
+ */
+ int flen = strlen(filename);
+
+ flen = Min(flen, 99);
+ h[flen] = '/';
+ h[flen + 1] = '\0';
+ }
+
+ /* Mode 8 - this doesn't include the file type bits (S_IFMT) */
+ print_tar_number(&h[100], 8, (mode & 07777));
+
+ /* User ID 8 */
+ print_tar_number(&h[108], 8, uid);
+
+ /* Group 8 */
+ print_tar_number(&h[116], 8, gid);
+
+ /* File size 12 */
+ if (linktarget != NULL || S_ISDIR(mode))
+ /* Symbolic link or directory has size zero */
+ print_tar_number(&h[124], 12, 0);
+ else
+ print_tar_number(&h[124], 12, size);
+
+ /* Mod Time 12 */
+ print_tar_number(&h[136], 12, mtime);
+
+ /* Checksum 8 cannot be calculated until we've filled all other fields */
+
+ if (linktarget != NULL)
+ {
+ /* Type - Symbolic link */
+ h[156] = '2';
+ /* Link Name 100 */
+ strlcpy(&h[157], linktarget, 100);
+ }
+ else if (S_ISDIR(mode))
+ {
+ /* Type - directory */
+ h[156] = '5';
+ }
+ else
+ {
+ /* Type - regular file */
+ h[156] = '0';
+ }
+
+ /* Magic 6 */
+ strcpy(&h[257], "ustar");
+
+ /* Version 2 */
+ memcpy(&h[263], "00", 2);
+
+ /* User 32 */
+ /* XXX: Do we need to care about setting correct username? */
+ strlcpy(&h[265], "postgres", 32);
+
+ /* Group 32 */
+ /* XXX: Do we need to care about setting correct group name? */
+ strlcpy(&h[297], "postgres", 32);
+
+ /* Major Dev 8 */
+ print_tar_number(&h[329], 8, 0);
+
+ /* Minor Dev 8 */
+ print_tar_number(&h[337], 8, 0);
+
+ /* Prefix 155 - not used, leave as nulls */
+
+ /* Finally, compute and insert the checksum */
+ print_tar_number(&h[148], 8, tarChecksum(h));
+
+ return TAR_OK;
+}
diff --git a/contrib/libs/postgresql/src/port/thread.c b/contrib/libs/postgresql/src/port/thread.c
new file mode 100644
index 0000000000..1f3bcbd1c9
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/thread.c
@@ -0,0 +1,116 @@
+/*-------------------------------------------------------------------------
+ *
+ * thread.c
+ *
+ * Prototypes and macros around system calls, used to help make
+ * threaded libraries reentrant and safe to use from threaded applications.
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ *
+ * src/port/thread.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "c.h"
+
+#include <pwd.h>
+
+
+/*
+ * Threading sometimes requires specially-named versions of functions
+ * that return data in static buffers, like strerror_r() instead of
+ * strerror(). Other operating systems use pthread_setspecific()
+ * and pthread_getspecific() internally to allow standard library
+ * functions to return static data to threaded applications. And some
+ * operating systems have neither.
+ *
+ * Additional confusion exists because many operating systems that
+ * use pthread_setspecific/pthread_getspecific() also have *_r versions
+ * of standard library functions for compatibility with operating systems
+ * that require them. However, internally, these *_r functions merely
+ * call the thread-safe standard library functions.
+ *
+ * For example, BSD/OS 4.3 uses Bind 8.2.3 for getpwuid(). Internally,
+ * getpwuid() calls pthread_setspecific/pthread_getspecific() to return
+ * static data to the caller in a thread-safe manner. However, BSD/OS
+ * also has getpwuid_r(), which merely calls getpwuid() and shifts
+ * around the arguments to match the getpwuid_r() function declaration.
+ * Therefore, while BSD/OS has getpwuid_r(), it isn't required. It also
+ * doesn't have strerror_r(), so we can't fall back to only using *_r
+ * functions for threaded programs.
+ *
+ * The current setup is to try threading in this order:
+ *
+ * use *_r function names if they exit
+ * (*_THREADSAFE=yes)
+ * use non-*_r functions if they are thread-safe
+ *
+ * One thread-safe solution for gethostbyname() might be to use getaddrinfo().
+ */
+
+
+/*
+ * Wrapper around getpwuid() or getpwuid_r() to mimic POSIX getpwuid_r()
+ * behaviour, if that function is not available or required.
+ *
+ * Per POSIX, the possible cases are:
+ * success: returns zero, *result is non-NULL
+ * uid not found: returns zero, *result is NULL
+ * error during lookup: returns an errno code, *result is NULL
+ * (caller should *not* assume that the errno variable is set)
+ */
+#ifndef WIN32
+int
+pqGetpwuid(uid_t uid, struct passwd *resultbuf, char *buffer,
+ size_t buflen, struct passwd **result)
+{
+#if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && defined(HAVE_GETPWUID_R)
+ return getpwuid_r(uid, resultbuf, buffer, buflen, result);
+#else
+ /* no getpwuid_r() available, just use getpwuid() */
+ errno = 0;
+ *result = getpwuid(uid);
+ /* paranoia: ensure we return zero on success */
+ return (*result == NULL) ? errno : 0;
+#endif
+}
+#endif
+
+/*
+ * Wrapper around gethostbyname() or gethostbyname_r() to mimic
+ * POSIX gethostbyname_r() behaviour, if it is not available or required.
+ * This function is called _only_ by our getaddrinfo() portability function.
+ */
+#ifndef HAVE_GETADDRINFO
+int
+pqGethostbyname(const char *name,
+ struct hostent *resultbuf,
+ char *buffer, size_t buflen,
+ struct hostent **result,
+ int *herrno)
+{
+#if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && defined(HAVE_GETHOSTBYNAME_R)
+
+ /*
+ * broken (well early POSIX draft) gethostbyname_r() which returns 'struct
+ * hostent *'
+ */
+ *result = gethostbyname_r(name, resultbuf, buffer, buflen, herrno);
+ return (*result == NULL) ? -1 : 0;
+#else
+
+ /* no gethostbyname_r(), just use gethostbyname() */
+ *result = gethostbyname(name);
+
+ if (*result != NULL)
+ *herrno = h_errno;
+
+ if (*result != NULL)
+ return 0;
+ else
+ return -1;
+#endif
+}
+
+#endif
diff --git a/contrib/libs/postgresql/src/port/win32env.c b/contrib/libs/postgresql/src/port/win32env.c
new file mode 100644
index 0000000000..a03556078c
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/win32env.c
@@ -0,0 +1,163 @@
+/*-------------------------------------------------------------------------
+ *
+ * win32env.c
+ * putenv(), setenv(), and unsetenv() for win32.
+ *
+ * These functions update both the process environment and caches in
+ * (potentially multiple) C run-time library (CRT) versions.
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/port/win32env.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "c.h"
+
+
+/*
+ * Note that unlike POSIX putenv(), this doesn't use the passed-in string
+ * as permanent storage.
+ */
+int
+pgwin32_putenv(const char *envval)
+{
+ char *envcpy;
+ char *cp;
+ typedef int (_cdecl * PUTENVPROC) (const char *);
+ static const char *const modulenames[] = {
+ "msvcrt", /* Visual Studio 6.0 / MinGW */
+ "msvcrtd",
+ "msvcr70", /* Visual Studio 2002 */
+ "msvcr70d",
+ "msvcr71", /* Visual Studio 2003 */
+ "msvcr71d",
+ "msvcr80", /* Visual Studio 2005 */
+ "msvcr80d",
+ "msvcr90", /* Visual Studio 2008 */
+ "msvcr90d",
+ "msvcr100", /* Visual Studio 2010 */
+ "msvcr100d",
+ "msvcr110", /* Visual Studio 2012 */
+ "msvcr110d",
+ "msvcr120", /* Visual Studio 2013 */
+ "msvcr120d",
+ "ucrtbase", /* Visual Studio 2015 and later */
+ "ucrtbased",
+ NULL
+ };
+ int i;
+
+ /*
+ * Update process environment, making this change visible to child
+ * processes and to CRTs initializing in the future. Do this before the
+ * _putenv() loop, for the benefit of any CRT that initializes during this
+ * pgwin32_putenv() execution, after the loop checks that CRT.
+ *
+ * Need a copy of the string so we can modify it.
+ */
+ envcpy = strdup(envval);
+ if (!envcpy)
+ return -1;
+ cp = strchr(envcpy, '=');
+ if (cp == NULL)
+ {
+ free(envcpy);
+ return -1;
+ }
+ *cp = '\0';
+ cp++;
+ if (*cp)
+ {
+ /*
+ * Only call SetEnvironmentVariable() when we are adding a variable,
+ * not when removing it. Calling it on both crashes on at least
+ * certain versions of MinGW.
+ */
+ if (!SetEnvironmentVariable(envcpy, cp))
+ {
+ free(envcpy);
+ return -1;
+ }
+ }
+ free(envcpy);
+
+ /*
+ * Each CRT has its own _putenv() symbol and copy of the environment.
+ * Update the environment in each CRT module currently loaded, so every
+ * third-party library sees this change regardless of the CRT it links
+ * against. Addresses within these modules may become invalid the moment
+ * we call FreeLibrary(), so don't cache them.
+ */
+ for (i = 0; modulenames[i]; i++)
+ {
+ HMODULE hmodule = NULL;
+ BOOL res = GetModuleHandleEx(0, modulenames[i], &hmodule);
+
+ if (res != 0 && hmodule != NULL)
+ {
+ PUTENVPROC putenvFunc;
+
+ putenvFunc = (PUTENVPROC) (pg_funcptr_t) GetProcAddress(hmodule, "_putenv");
+ if (putenvFunc)
+ putenvFunc(envval);
+ FreeLibrary(hmodule);
+ }
+ }
+
+ /*
+ * Finally, update our "own" cache. This is redundant with the loop
+ * above, except when PostgreSQL itself links to a CRT not listed above.
+ * Ideally, the loop does visit all possible CRTs, making this redundant.
+ */
+ return _putenv(envval);
+}
+
+int
+pgwin32_setenv(const char *name, const char *value, int overwrite)
+{
+ int res;
+ char *envstr;
+
+ /* Error conditions, per POSIX */
+ if (name == NULL || name[0] == '\0' || strchr(name, '=') != NULL ||
+ value == NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* No work if variable exists and we're not to replace it */
+ if (overwrite == 0 && getenv(name) != NULL)
+ return 0;
+
+ envstr = (char *) malloc(strlen(name) + strlen(value) + 2);
+ if (!envstr) /* not much we can do if no memory */
+ return -1;
+
+ sprintf(envstr, "%s=%s", name, value);
+
+ res = pgwin32_putenv(envstr);
+ free(envstr);
+ return res;
+}
+
+int
+pgwin32_unsetenv(const char *name)
+{
+ int res;
+ char *envbuf;
+
+ envbuf = (char *) malloc(strlen(name) + 2);
+ if (!envbuf)
+ return -1;
+
+ sprintf(envbuf, "%s=", name);
+ res = pgwin32_putenv(envbuf);
+ free(envbuf);
+ return res;
+}
diff --git a/contrib/libs/postgresql/src/port/win32error.c b/contrib/libs/postgresql/src/port/win32error.c
new file mode 100644
index 0000000000..0e5f91adfa
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/win32error.c
@@ -0,0 +1,208 @@
+/*-------------------------------------------------------------------------
+ *
+ * win32error.c
+ * Map win32 error codes to errno values
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/port/win32error.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+static const struct
+{
+ DWORD winerr;
+ int doserr;
+} doserrors[] =
+
+{
+ {
+ ERROR_INVALID_FUNCTION, EINVAL
+ },
+ {
+ ERROR_FILE_NOT_FOUND, ENOENT
+ },
+ {
+ ERROR_PATH_NOT_FOUND, ENOENT
+ },
+ {
+ ERROR_TOO_MANY_OPEN_FILES, EMFILE
+ },
+ {
+ ERROR_ACCESS_DENIED, EACCES
+ },
+ {
+ ERROR_INVALID_HANDLE, EBADF
+ },
+ {
+ ERROR_ARENA_TRASHED, ENOMEM
+ },
+ {
+ ERROR_NOT_ENOUGH_MEMORY, ENOMEM
+ },
+ {
+ ERROR_INVALID_BLOCK, ENOMEM
+ },
+ {
+ ERROR_BAD_ENVIRONMENT, E2BIG
+ },
+ {
+ ERROR_BAD_FORMAT, ENOEXEC
+ },
+ {
+ ERROR_INVALID_ACCESS, EINVAL
+ },
+ {
+ ERROR_INVALID_DATA, EINVAL
+ },
+ {
+ ERROR_INVALID_DRIVE, ENOENT
+ },
+ {
+ ERROR_CURRENT_DIRECTORY, EACCES
+ },
+ {
+ ERROR_NOT_SAME_DEVICE, EXDEV
+ },
+ {
+ ERROR_NO_MORE_FILES, ENOENT
+ },
+ {
+ ERROR_LOCK_VIOLATION, EACCES
+ },
+ {
+ ERROR_SHARING_VIOLATION, EACCES
+ },
+ {
+ ERROR_BAD_NETPATH, ENOENT
+ },
+ {
+ ERROR_NETWORK_ACCESS_DENIED, EACCES
+ },
+ {
+ ERROR_BAD_NET_NAME, ENOENT
+ },
+ {
+ ERROR_FILE_EXISTS, EEXIST
+ },
+ {
+ ERROR_CANNOT_MAKE, EACCES
+ },
+ {
+ ERROR_FAIL_I24, EACCES
+ },
+ {
+ ERROR_INVALID_PARAMETER, EINVAL
+ },
+ {
+ ERROR_NO_PROC_SLOTS, EAGAIN
+ },
+ {
+ ERROR_DRIVE_LOCKED, EACCES
+ },
+ {
+ ERROR_BROKEN_PIPE, EPIPE
+ },
+ {
+ ERROR_DISK_FULL, ENOSPC
+ },
+ {
+ ERROR_INVALID_TARGET_HANDLE, EBADF
+ },
+ {
+ ERROR_INVALID_HANDLE, EINVAL
+ },
+ {
+ ERROR_WAIT_NO_CHILDREN, ECHILD
+ },
+ {
+ ERROR_CHILD_NOT_COMPLETE, ECHILD
+ },
+ {
+ ERROR_DIRECT_ACCESS_HANDLE, EBADF
+ },
+ {
+ ERROR_NEGATIVE_SEEK, EINVAL
+ },
+ {
+ ERROR_SEEK_ON_DEVICE, EACCES
+ },
+ {
+ ERROR_DIR_NOT_EMPTY, ENOTEMPTY
+ },
+ {
+ ERROR_NOT_LOCKED, EACCES
+ },
+ {
+ ERROR_BAD_PATHNAME, ENOENT
+ },
+ {
+ ERROR_MAX_THRDS_REACHED, EAGAIN
+ },
+ {
+ ERROR_LOCK_FAILED, EACCES
+ },
+ {
+ ERROR_ALREADY_EXISTS, EEXIST
+ },
+ {
+ ERROR_FILENAME_EXCED_RANGE, ENOENT
+ },
+ {
+ ERROR_NESTING_NOT_ALLOWED, EAGAIN
+ },
+ {
+ ERROR_NOT_ENOUGH_QUOTA, ENOMEM
+ },
+ {
+ ERROR_DELETE_PENDING, ENOENT
+ }
+};
+
+void
+_dosmaperr(unsigned long e)
+{
+ int i;
+
+ if (e == 0)
+ {
+ errno = 0;
+ return;
+ }
+
+ for (i = 0; i < lengthof(doserrors); i++)
+ {
+ if (doserrors[i].winerr == e)
+ {
+ int doserr = doserrors[i].doserr;
+
+#ifndef FRONTEND
+ ereport(DEBUG5,
+ (errmsg_internal("mapped win32 error code %lu to %d",
+ e, doserr)));
+#elif defined(FRONTEND_DEBUG)
+ fprintf(stderr, "mapped win32 error code %lu to %d", e, doserr);
+#endif
+ errno = doserr;
+ return;
+ }
+ }
+
+#ifndef FRONTEND
+ ereport(LOG,
+ (errmsg_internal("unrecognized win32 error code: %lu",
+ e)));
+#else
+ fprintf(stderr, "unrecognized win32 error code: %lu", e);
+#endif
+
+ errno = EINVAL;
+}
diff --git a/contrib/libs/postgresql/src/port/win32security.c b/contrib/libs/postgresql/src/port/win32security.c
new file mode 100644
index 0000000000..4a673fde19
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/win32security.c
@@ -0,0 +1,178 @@
+/*-------------------------------------------------------------------------
+ *
+ * win32security.c
+ * Microsoft Windows Win32 Security Support Functions
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/port/win32security.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+
+/*
+ * Utility wrapper for frontend and backend when reporting an error
+ * message.
+ */
+static
+pg_attribute_printf(1, 2)
+void
+log_error(const char *fmt,...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+#ifndef FRONTEND
+ write_stderr(fmt, ap);
+#else
+ fprintf(stderr, fmt, ap);
+#endif
+ va_end(ap);
+}
+
+/*
+ * Returns nonzero if the current user has administrative privileges,
+ * or zero if not.
+ *
+ * Note: this cannot use ereport() because it's called too early during
+ * startup.
+ */
+int
+pgwin32_is_admin(void)
+{
+ PSID AdministratorsSid;
+ PSID PowerUsersSid;
+ SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
+ BOOL IsAdministrators;
+ BOOL IsPowerUsers;
+
+ if (!AllocateAndInitializeSid(&NtAuthority, 2,
+ SECURITY_BUILTIN_DOMAIN_RID,
+ DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0,
+ 0, &AdministratorsSid))
+ {
+ log_error(_("could not get SID for Administrators group: error code %lu\n"),
+ GetLastError());
+ exit(1);
+ }
+
+ if (!AllocateAndInitializeSid(&NtAuthority, 2,
+ SECURITY_BUILTIN_DOMAIN_RID,
+ DOMAIN_ALIAS_RID_POWER_USERS, 0, 0, 0, 0, 0,
+ 0, &PowerUsersSid))
+ {
+ log_error(_("could not get SID for PowerUsers group: error code %lu\n"),
+ GetLastError());
+ exit(1);
+ }
+
+ if (!CheckTokenMembership(NULL, AdministratorsSid, &IsAdministrators) ||
+ !CheckTokenMembership(NULL, PowerUsersSid, &IsPowerUsers))
+ {
+ log_error(_("could not check access token membership: error code %lu\n"),
+ GetLastError());
+ exit(1);
+ }
+
+ FreeSid(AdministratorsSid);
+ FreeSid(PowerUsersSid);
+
+ if (IsAdministrators || IsPowerUsers)
+ return 1;
+ else
+ return 0;
+}
+
+/*
+ * We consider ourselves running as a service if one of the following is
+ * true:
+ *
+ * 1) We are running as LocalSystem (only used by services)
+ * 2) Our token contains SECURITY_SERVICE_RID (automatically added to the
+ * process token by the SCM when starting a service)
+ *
+ * The check for LocalSystem is needed, because surprisingly, if a service
+ * is running as LocalSystem, it does not have SECURITY_SERVICE_RID in its
+ * process token.
+ *
+ * Return values:
+ * 0 = Not service
+ * 1 = Service
+ * -1 = Error
+ *
+ * Note: we can't report errors via either ereport (we're called too early
+ * in the backend) or write_stderr (because that calls this). We are
+ * therefore reduced to writing directly on stderr, which sucks, but we
+ * have few alternatives.
+ */
+int
+pgwin32_is_service(void)
+{
+ static int _is_service = -1;
+ BOOL IsMember;
+ PSID ServiceSid;
+ PSID LocalSystemSid;
+ SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
+
+ /* Only check the first time */
+ if (_is_service != -1)
+ return _is_service;
+
+ /* First check for LocalSystem */
+ if (!AllocateAndInitializeSid(&NtAuthority, 1,
+ SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0,
+ &LocalSystemSid))
+ {
+ fprintf(stderr, "could not get SID for local system account\n");
+ return -1;
+ }
+
+ if (!CheckTokenMembership(NULL, LocalSystemSid, &IsMember))
+ {
+ fprintf(stderr, "could not check access token membership: error code %lu\n",
+ GetLastError());
+ FreeSid(LocalSystemSid);
+ return -1;
+ }
+ FreeSid(LocalSystemSid);
+
+ if (IsMember)
+ {
+ _is_service = 1;
+ return _is_service;
+ }
+
+ /* Check for service group membership */
+ if (!AllocateAndInitializeSid(&NtAuthority, 1,
+ SECURITY_SERVICE_RID, 0, 0, 0, 0, 0, 0, 0,
+ &ServiceSid))
+ {
+ fprintf(stderr, "could not get SID for service group: error code %lu\n",
+ GetLastError());
+ return -1;
+ }
+
+ if (!CheckTokenMembership(NULL, ServiceSid, &IsMember))
+ {
+ fprintf(stderr, "could not check access token membership: error code %lu\n",
+ GetLastError());
+ FreeSid(ServiceSid);
+ return -1;
+ }
+ FreeSid(ServiceSid);
+
+ if (IsMember)
+ _is_service = 1;
+ else
+ _is_service = 0;
+
+ return _is_service;
+}
diff --git a/contrib/libs/postgresql/src/port/win32setlocale.c b/contrib/libs/postgresql/src/port/win32setlocale.c
new file mode 100644
index 0000000000..4edae05bb7
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/win32setlocale.c
@@ -0,0 +1,193 @@
+/*-------------------------------------------------------------------------
+ *
+ * win32setlocale.c
+ * Wrapper to work around bugs in Windows setlocale() implementation
+ *
+ * Copyright (c) 2011-2021, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/port/win32setlocale.c
+ *
+ *
+ * The setlocale() function in Windows is broken in two ways. First, it
+ * has a problem with locale names that have a dot in the country name. For
+ * example:
+ *
+ * "Chinese (Traditional)_Hong Kong S.A.R..950"
+ *
+ * For some reason, setlocale() doesn't accept that as argument, even though
+ * setlocale(LC_ALL, NULL) returns exactly that. Fortunately, it accepts
+ * various alternative names for such countries, so to work around the broken
+ * setlocale() function, we map the troublemaking locale names to accepted
+ * aliases, before calling setlocale().
+ *
+ * The second problem is that the locale name for "Norwegian (Bokm&aring;l)"
+ * contains a non-ASCII character. That's problematic, because it's not clear
+ * what encoding the locale name itself is supposed to be in, when you
+ * haven't yet set a locale. Also, it causes problems when the cluster
+ * contains databases with different encodings, as the locale name is stored
+ * in the pg_database system catalog. To work around that, when setlocale()
+ * returns that locale name, map it to a pure-ASCII alias for the same
+ * locale.
+ *-------------------------------------------------------------------------
+ */
+
+#include "c.h"
+
+#undef setlocale
+
+struct locale_map
+{
+ /*
+ * String in locale name to replace. Can be a single string (end is NULL),
+ * or separate start and end strings. If two strings are given, the locale
+ * name must contain both of them, and everything between them is
+ * replaced. This is used for a poor-man's regexp search, allowing
+ * replacement of "start.*end".
+ */
+ const char *locale_name_start;
+ const char *locale_name_end;
+
+ const char *replacement; /* string to replace the match with */
+};
+
+/*
+ * Mappings applied before calling setlocale(), to the argument.
+ */
+static const struct locale_map locale_map_argument[] = {
+ /*
+ * "HKG" is listed here:
+ * http://msdn.microsoft.com/en-us/library/cdax410z%28v=vs.71%29.aspx
+ * (Country/Region Strings).
+ *
+ * "ARE" is the ISO-3166 three-letter code for U.A.E. It is not on the
+ * above list, but seems to work anyway.
+ */
+ {"Hong Kong S.A.R.", NULL, "HKG"},
+ {"U.A.E.", NULL, "ARE"},
+
+ /*
+ * The ISO-3166 country code for Macau S.A.R. is MAC, but Windows doesn't
+ * seem to recognize that. And Macau isn't listed in the table of accepted
+ * abbreviations linked above. Fortunately, "ZHM" seems to be accepted as
+ * an alias for "Chinese (Traditional)_Macau S.A.R..950". I'm not sure
+ * where "ZHM" comes from, must be some legacy naming scheme. But hey, it
+ * works.
+ *
+ * Note that unlike HKG and ARE, ZHM is an alias for the *whole* locale
+ * name, not just the country part.
+ *
+ * Some versions of Windows spell it "Macau", others "Macao".
+ */
+ {"Chinese (Traditional)_Macau S.A.R..950", NULL, "ZHM"},
+ {"Chinese_Macau S.A.R..950", NULL, "ZHM"},
+ {"Chinese (Traditional)_Macao S.A.R..950", NULL, "ZHM"},
+ {"Chinese_Macao S.A.R..950", NULL, "ZHM"},
+ {NULL, NULL, NULL}
+};
+
+/*
+ * Mappings applied after calling setlocale(), to its return value.
+ */
+static const struct locale_map locale_map_result[] = {
+ /*
+ * "Norwegian (Bokm&aring;l)" locale name contains the a-ring character.
+ * Map it to a pure-ASCII alias.
+ *
+ * It's not clear what encoding setlocale() uses when it returns the
+ * locale name, so to play it safe, we search for "Norwegian (Bok*l)".
+ *
+ * Just to make life even more complicated, some versions of Windows spell
+ * the locale name without parentheses. Translate that too.
+ */
+ {"Norwegian (Bokm", "l)_Norway", "Norwegian_Norway"},
+ {"Norwegian Bokm", "l_Norway", "Norwegian_Norway"},
+ {NULL, NULL, NULL}
+};
+
+#define MAX_LOCALE_NAME_LEN 100
+
+static const char *
+map_locale(const struct locale_map *map, const char *locale)
+{
+ static char aliasbuf[MAX_LOCALE_NAME_LEN];
+ int i;
+
+ /* Check if the locale name matches any of the problematic ones. */
+ for (i = 0; map[i].locale_name_start != NULL; i++)
+ {
+ const char *needle_start = map[i].locale_name_start;
+ const char *needle_end = map[i].locale_name_end;
+ const char *replacement = map[i].replacement;
+ char *match;
+ char *match_start = NULL;
+ char *match_end = NULL;
+
+ match = strstr(locale, needle_start);
+ if (match)
+ {
+ /*
+ * Found a match for the first part. If this was a two-part
+ * replacement, find the second part.
+ */
+ match_start = match;
+ if (needle_end)
+ {
+ match = strstr(match_start + strlen(needle_start), needle_end);
+ if (match)
+ match_end = match + strlen(needle_end);
+ else
+ match_start = NULL;
+ }
+ else
+ match_end = match_start + strlen(needle_start);
+ }
+
+ if (match_start)
+ {
+ /* Found a match. Replace the matched string. */
+ int matchpos = match_start - locale;
+ int replacementlen = strlen(replacement);
+ char *rest = match_end;
+ int restlen = strlen(rest);
+
+ /* check that the result fits in the static buffer */
+ if (matchpos + replacementlen + restlen + 1 > MAX_LOCALE_NAME_LEN)
+ return NULL;
+
+ memcpy(&aliasbuf[0], &locale[0], matchpos);
+ memcpy(&aliasbuf[matchpos], replacement, replacementlen);
+ /* includes null terminator */
+ memcpy(&aliasbuf[matchpos + replacementlen], rest, restlen + 1);
+
+ return aliasbuf;
+ }
+ }
+
+ /* no match, just return the original string */
+ return locale;
+}
+
+char *
+pgwin32_setlocale(int category, const char *locale)
+{
+ const char *argument;
+ char *result;
+
+ if (locale == NULL)
+ argument = NULL;
+ else
+ argument = map_locale(locale_map_argument, locale);
+
+ /* Call the real setlocale() function */
+ result = setlocale(category, argument);
+
+ /*
+ * setlocale() is specified to return a "char *" that the caller is
+ * forbidden to modify, so casting away the "const" is innocuous.
+ */
+ if (result)
+ result = unconstify(char *, map_locale(locale_map_result, result));
+
+ return result;
+}
diff --git a/contrib/libs/postgresql/src/port/win32stat.c b/contrib/libs/postgresql/src/port/win32stat.c
new file mode 100644
index 0000000000..426e01f0ef
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/win32stat.c
@@ -0,0 +1,327 @@
+/*-------------------------------------------------------------------------
+ *
+ * win32stat.c
+ * Replacements for <sys/stat.h> functions using GetFileInformationByHandle
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/port/win32stat.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifdef WIN32
+
+#include "c.h"
+#include <windows.h>
+
+/*
+ * In order to support MinGW and MSVC2013 we use NtQueryInformationFile as an
+ * alternative for GetFileInformationByHandleEx. It is loaded from the ntdll
+ * library.
+ */
+#if _WIN32_WINNT < 0x0600
+#include <winternl.h>
+
+#if !defined(__MINGW32__) && !defined(__MINGW64__)
+/* MinGW includes this in <winternl.h>, but it is missing in MSVC */
+typedef struct _FILE_STANDARD_INFORMATION
+{
+ LARGE_INTEGER AllocationSize;
+ LARGE_INTEGER EndOfFile;
+ ULONG NumberOfLinks;
+ BOOLEAN DeletePending;
+ BOOLEAN Directory;
+} FILE_STANDARD_INFORMATION;
+#define FileStandardInformation 5
+#endif /* !defined(__MINGW32__) &&
+ * !defined(__MINGW64__) */
+
+typedef NTSTATUS (NTAPI * PFN_NTQUERYINFORMATIONFILE)
+ (IN HANDLE FileHandle,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ OUT PVOID FileInformation,
+ IN ULONG Length,
+ IN FILE_INFORMATION_CLASS FileInformationClass);
+
+static PFN_NTQUERYINFORMATIONFILE _NtQueryInformationFile = NULL;
+
+static HMODULE ntdll = NULL;
+
+/*
+ * Load DLL file just once regardless of how many functions we load/call in it.
+ */
+static void
+LoadNtdll(void)
+{
+ if (ntdll != NULL)
+ return;
+ ntdll = LoadLibraryEx("ntdll.dll", NULL, 0);
+}
+
+#endif /* _WIN32_WINNT < 0x0600 */
+
+
+/*
+ * Convert a FILETIME struct into a 64 bit time_t.
+ */
+static __time64_t
+filetime_to_time(const FILETIME *ft)
+{
+ ULARGE_INTEGER unified_ft = {0};
+ static const uint64 EpochShift = UINT64CONST(116444736000000000);
+
+ unified_ft.LowPart = ft->dwLowDateTime;
+ unified_ft.HighPart = ft->dwHighDateTime;
+
+ if (unified_ft.QuadPart < EpochShift)
+ return -1;
+
+ unified_ft.QuadPart -= EpochShift;
+ unified_ft.QuadPart /= 10 * 1000 * 1000;
+
+ return unified_ft.QuadPart;
+}
+
+/*
+ * Convert WIN32 file attributes to a Unix-style mode.
+ *
+ * Only owner permissions are set.
+ */
+static unsigned short
+fileattr_to_unixmode(int attr)
+{
+ unsigned short uxmode = 0;
+
+ uxmode |= (unsigned short) ((attr & FILE_ATTRIBUTE_DIRECTORY) ?
+ (_S_IFDIR) : (_S_IFREG));
+
+ uxmode |= (unsigned short) ((attr & FILE_ATTRIBUTE_READONLY) ?
+ (_S_IREAD) : (_S_IREAD | _S_IWRITE));
+
+ /* there is no need to simulate _S_IEXEC using CMD's PATHEXT extensions */
+ uxmode |= _S_IEXEC;
+
+ return uxmode;
+}
+
+/*
+ * Convert WIN32 file information (from a HANDLE) to a struct stat.
+ */
+static int
+fileinfo_to_stat(HANDLE hFile, struct stat *buf)
+{
+ BY_HANDLE_FILE_INFORMATION fiData;
+
+ memset(buf, 0, sizeof(*buf));
+
+ /*
+ * GetFileInformationByHandle minimum supported version: Windows XP and
+ * Windows Server 2003, so it exists everywhere we care about.
+ */
+ if (!GetFileInformationByHandle(hFile, &fiData))
+ {
+ _dosmaperr(GetLastError());
+ return -1;
+ }
+
+ if (fiData.ftLastWriteTime.dwLowDateTime ||
+ fiData.ftLastWriteTime.dwHighDateTime)
+ buf->st_mtime = filetime_to_time(&fiData.ftLastWriteTime);
+
+ if (fiData.ftLastAccessTime.dwLowDateTime ||
+ fiData.ftLastAccessTime.dwHighDateTime)
+ buf->st_atime = filetime_to_time(&fiData.ftLastAccessTime);
+ else
+ buf->st_atime = buf->st_mtime;
+
+ if (fiData.ftCreationTime.dwLowDateTime ||
+ fiData.ftCreationTime.dwHighDateTime)
+ buf->st_ctime = filetime_to_time(&fiData.ftCreationTime);
+ else
+ buf->st_ctime = buf->st_mtime;
+
+ buf->st_mode = fileattr_to_unixmode(fiData.dwFileAttributes);
+ buf->st_nlink = fiData.nNumberOfLinks;
+
+ buf->st_size = ((((uint64) fiData.nFileSizeHigh) << 32) |
+ fiData.nFileSizeLow);
+
+ return 0;
+}
+
+/*
+ * Windows implementation of stat().
+ *
+ * This currently also implements lstat(), though perhaps that should change.
+ */
+int
+_pgstat64(const char *name, struct stat *buf)
+{
+ /*
+ * We must use a handle so lstat() returns the information of the target
+ * file. To have a reliable test for ERROR_DELETE_PENDING, we use
+ * NtQueryInformationFile from Windows 2000 or
+ * GetFileInformationByHandleEx from Server 2008 / Vista.
+ */
+ SECURITY_ATTRIBUTES sa;
+ HANDLE hFile;
+ int ret;
+#if _WIN32_WINNT < 0x0600
+ IO_STATUS_BLOCK ioStatus;
+ FILE_STANDARD_INFORMATION standardInfo;
+#else
+ FILE_STANDARD_INFO standardInfo;
+#endif
+
+ if (name == NULL || buf == NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* fast not-exists check */
+ if (GetFileAttributes(name) == INVALID_FILE_ATTRIBUTES)
+ {
+ _dosmaperr(GetLastError());
+ return -1;
+ }
+
+ /* get a file handle as lightweight as we can */
+ sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+ sa.bInheritHandle = TRUE;
+ sa.lpSecurityDescriptor = NULL;
+ hFile = CreateFile(name,
+ GENERIC_READ,
+ (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE),
+ &sa,
+ OPEN_EXISTING,
+ (FILE_FLAG_NO_BUFFERING | FILE_FLAG_BACKUP_SEMANTICS |
+ FILE_FLAG_OVERLAPPED),
+ NULL);
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ DWORD err = GetLastError();
+
+ CloseHandle(hFile);
+ _dosmaperr(err);
+ return -1;
+ }
+
+ memset(&standardInfo, 0, sizeof(standardInfo));
+
+#if _WIN32_WINNT < 0x0600
+ if (_NtQueryInformationFile == NULL)
+ {
+ /* First time through: load ntdll.dll and find NtQueryInformationFile */
+ LoadNtdll();
+ if (ntdll == NULL)
+ {
+ DWORD err = GetLastError();
+
+ CloseHandle(hFile);
+ _dosmaperr(err);
+ return -1;
+ }
+
+ _NtQueryInformationFile = (PFN_NTQUERYINFORMATIONFILE) (pg_funcptr_t)
+ GetProcAddress(ntdll, "NtQueryInformationFile");
+ if (_NtQueryInformationFile == NULL)
+ {
+ DWORD err = GetLastError();
+
+ CloseHandle(hFile);
+ _dosmaperr(err);
+ return -1;
+ }
+ }
+
+ if (!NT_SUCCESS(_NtQueryInformationFile(hFile, &ioStatus, &standardInfo,
+ sizeof(standardInfo),
+ FileStandardInformation)))
+ {
+ DWORD err = GetLastError();
+
+ CloseHandle(hFile);
+ _dosmaperr(err);
+ return -1;
+ }
+#else
+ if (!GetFileInformationByHandleEx(hFile, FileStandardInfo, &standardInfo,
+ sizeof(standardInfo)))
+ {
+ DWORD err = GetLastError();
+
+ CloseHandle(hFile);
+ _dosmaperr(err);
+ return -1;
+ }
+#endif /* _WIN32_WINNT < 0x0600 */
+
+ if (standardInfo.DeletePending)
+ {
+ /*
+ * File has been deleted, but is not gone from the filesystem yet.
+ * This can happen when some process with FILE_SHARE_DELETE has it
+ * open, and it will be fully removed once that handle is closed.
+ * Meanwhile, we can't open it, so indicate that the file just doesn't
+ * exist.
+ */
+ CloseHandle(hFile);
+ errno = ENOENT;
+ return -1;
+ }
+
+ /* At last we can invoke fileinfo_to_stat */
+ ret = fileinfo_to_stat(hFile, buf);
+
+ CloseHandle(hFile);
+ return ret;
+}
+
+/*
+ * Windows implementation of fstat().
+ */
+int
+_pgfstat64(int fileno, struct stat *buf)
+{
+ HANDLE hFile = (HANDLE) _get_osfhandle(fileno);
+ BY_HANDLE_FILE_INFORMATION fiData;
+
+ if (hFile == INVALID_HANDLE_VALUE || buf == NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /*
+ * Check if the fileno is a data stream. If so, unless it has been
+ * redirected to a file, getting information through its HANDLE will fail,
+ * so emulate its stat information in the most appropriate way and return
+ * it instead.
+ */
+ if ((fileno == _fileno(stdin) ||
+ fileno == _fileno(stdout) ||
+ fileno == _fileno(stderr)) &&
+ !GetFileInformationByHandle(hFile, &fiData))
+ {
+ memset(buf, 0, sizeof(*buf));
+ buf->st_mode = _S_IFCHR;
+ buf->st_dev = fileno;
+ buf->st_rdev = fileno;
+ buf->st_nlink = 1;
+ return 0;
+ }
+
+ /*
+ * Since we already have a file handle there is no need to check for
+ * ERROR_DELETE_PENDING.
+ */
+
+ return fileinfo_to_stat(hFile, buf);
+}
+
+#endif /* WIN32 */