diff options
author | vvvv <vvvv@ydb.tech> | 2023-10-20 18:42:40 +0300 |
---|---|---|
committer | vvvv <vvvv@ydb.tech> | 2023-10-20 19:40:38 +0300 |
commit | 6472d9635f006ec9dd8ae0189c9c3e940885ef2d (patch) | |
tree | c7b8541e14c22f74a7641368a5facad3de36bae2 /contrib/libs/postgresql/src | |
parent | babd49b87ac8b28d492552a48161080fae18a250 (diff) | |
download | ydb-6472d9635f006ec9dd8ae0189c9c3e940885ef2d.tar.gz |
Try to copy port .h/.c inside pg_wrapper
Diffstat (limited to 'contrib/libs/postgresql/src')
43 files changed, 0 insertions, 6913 deletions
diff --git a/contrib/libs/postgresql/src/backend/port/posix_sema.c b/contrib/libs/postgresql/src/backend/port/posix_sema.c deleted file mode 100644 index a97a3ed99ee..00000000000 --- a/contrib/libs/postgresql/src/backend/port/posix_sema.c +++ /dev/null @@ -1,388 +0,0 @@ -/*------------------------------------------------------------------------- - * - * 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-2022, 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 deleted file mode 100644 index ea287c733df..00000000000 --- a/contrib/libs/postgresql/src/backend/port/sysv_shmem.c +++ /dev/null @@ -1,963 +0,0 @@ -/*------------------------------------------------------------------------- - * - * 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-2022, 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((void *) 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((void *) 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; -} - -/* - * 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 if requested by the caller. If huge pages are not supported, - * *hugepagesize and *mmap_flags are set to 0. - */ -void -GetHugePageSize(Size *hugepagesize, int *mmap_flags) -{ -#ifdef MAP_HUGETLB - - Size default_hugepagesize = 0; - Size hugepagesize_local = 0; - int mmap_flags_local = 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_local = (Size) huge_page_size * 1024; - } - else if (default_hugepagesize != 0) - { - /* Otherwise use the system default, if we have it. */ - hugepagesize_local = 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_local = 2 * 1024 * 1024; - } - - mmap_flags_local = 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_local != default_hugepagesize) - { - int shift = pg_ceil_log2_64(hugepagesize_local); - - mmap_flags_local |= (shift & MAP_HUGE_MASK) << MAP_HUGE_SHIFT; - } -#endif - - /* assign the results found */ - if (mmap_flags) - *mmap_flags = mmap_flags_local; - if (hugepagesize) - *hugepagesize = hugepagesize_local; - -#else - - if (hugepagesize) - *hugepagesize = 0; - if (mmap_flags) - *mmap_flags = 0; - -#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((void *) 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 deleted file mode 100644 index cea7be2896c..00000000000 --- a/contrib/libs/postgresql/src/backend/port/win32/crashdump.c +++ /dev/null @@ -1,181 +0,0 @@ -/*------------------------------------------------------------------------- - * - * 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-2022, PostgreSQL Global Development Group - * - * IDENTIFICATION - * src/backend/port/win32/crashdump.c - * - *------------------------------------------------------------------------- - */ - -#include "postgres.h" - -/* - * 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 deleted file mode 100644 index b71164d8dbd..00000000000 --- a/contrib/libs/postgresql/src/backend/port/win32/signal.c +++ /dev/null @@ -1,354 +0,0 @@ -/*------------------------------------------------------------------------- - * - * signal.c - * Microsoft Windows Win32 Signal Emulation Functions - * - * Portions Copyright (c) 1996-2022, 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) -{ - if (unlikely(pgwin32_signal_event == NULL)) - { - /* - * If we're reached by pgwin32_open_handle() early in startup before - * the signal event is set up, just fall back to a regular - * non-interruptible sleep. - */ - SleepEx((microsec < 500 ? 1 : (microsec + 500) / 1000), FALSE); - return; - } - - 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 deleted file mode 100644 index 52944a0d332..00000000000 --- a/contrib/libs/postgresql/src/backend/port/win32/socket.c +++ /dev/null @@ -1,705 +0,0 @@ -/*------------------------------------------------------------------------- - * - * socket.c - * Microsoft Windows Win32 Socket Functions - * - * Portions Copyright (c) 1996-2022, 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_port.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; - case WSAETIMEDOUT: - errno = ETIMEDOUT; - break; - default: - ereport(NOTICE, - (errmsg_internal("unrecognized win32 socket error code: %d", - WSAGetLastError()))); - errno = EINVAL; - break; - } -} - -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 deleted file mode 100644 index 3405253af30..00000000000 --- a/contrib/libs/postgresql/src/backend/port/win32/timer.c +++ /dev/null @@ -1,121 +0,0 @@ -/*------------------------------------------------------------------------- - * - * 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-2022, 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 deleted file mode 100644 index 8e9c0f93074..00000000000 --- a/contrib/libs/postgresql/src/backend/port/win32_sema.c +++ /dev/null @@ -1,235 +0,0 @@ -/*------------------------------------------------------------------------- - * - * win32_sema.c - * Microsoft Windows Win32 Semaphores Emulation - * - * Portions Copyright (c) 1996-2022, 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 deleted file mode 100644 index 6cf69411db1..00000000000 --- a/contrib/libs/postgresql/src/backend/port/win32_shmem.c +++ /dev/null @@ -1,621 +0,0 @@ -/*------------------------------------------------------------------------- - * - * win32_shmem.c - * Implement shared memory using win32 facilities - * - * Portions Copyright (c) 1996-2022, 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; -} - -/* - * This function is provided for consistency with sysv_shmem.c and does not - * provide any useful information for Windows. To obtain the large page size, - * use GetLargePageMinimum() instead. - */ -void -GetHugePageSize(Size *hugepagesize, int *mmap_flags) -{ - if (hugepagesize) - *hugepagesize = 0; - if (mmap_flags) - *mmap_flags = 0; -} diff --git a/contrib/libs/postgresql/src/include/port/win32/arpa/inet.h b/contrib/libs/postgresql/src/include/port/win32/arpa/inet.h deleted file mode 100644 index ad1803179c7..00000000000 --- a/contrib/libs/postgresql/src/include/port/win32/arpa/inet.h +++ /dev/null @@ -1,3 +0,0 @@ -/* src/include/port/win32/arpa/inet.h */ - -#include <sys/socket.h> diff --git a/contrib/libs/postgresql/src/include/port/win32/grp.h b/contrib/libs/postgresql/src/include/port/win32/grp.h deleted file mode 100644 index 8b4f21310e9..00000000000 --- a/contrib/libs/postgresql/src/include/port/win32/grp.h +++ /dev/null @@ -1 +0,0 @@ -/* src/include/port/win32/grp.h */ diff --git a/contrib/libs/postgresql/src/include/port/win32/netdb.h b/contrib/libs/postgresql/src/include/port/win32/netdb.h deleted file mode 100644 index ad0627e9861..00000000000 --- a/contrib/libs/postgresql/src/include/port/win32/netdb.h +++ /dev/null @@ -1 +0,0 @@ -/* src/include/port/win32/netdb.h */ diff --git a/contrib/libs/postgresql/src/include/port/win32/netinet/in.h b/contrib/libs/postgresql/src/include/port/win32/netinet/in.h deleted file mode 100644 index a4e22f89f49..00000000000 --- a/contrib/libs/postgresql/src/include/port/win32/netinet/in.h +++ /dev/null @@ -1,3 +0,0 @@ -/* src/include/port/win32/netinet/in.h */ - -#include <sys/socket.h> diff --git a/contrib/libs/postgresql/src/include/port/win32/pwd.h b/contrib/libs/postgresql/src/include/port/win32/pwd.h deleted file mode 100644 index b8c7178fc06..00000000000 --- a/contrib/libs/postgresql/src/include/port/win32/pwd.h +++ /dev/null @@ -1,3 +0,0 @@ -/* - * src/include/port/win32/pwd.h - */ diff --git a/contrib/libs/postgresql/src/include/port/win32/sys/socket.h b/contrib/libs/postgresql/src/include/port/win32/sys/socket.h deleted file mode 100644 index 9b2cdf3b9bc..00000000000 --- a/contrib/libs/postgresql/src/include/port/win32/sys/socket.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * src/include/port/win32/sys/socket.h - */ -#ifndef WIN32_SYS_SOCKET_H -#define WIN32_SYS_SOCKET_H - -/* - * Unfortunately, <wingdi.h> of VC++ also defines ERROR. - * To avoid the conflict, we include <windows.h> here and undefine ERROR - * immediately. - * - * Note: Don't include <wingdi.h> directly. It causes compile errors. - */ -#include <winsock2.h> -#include <ws2tcpip.h> -#include <windows.h> - -#undef ERROR -#undef small - -/* Restore old ERROR value */ -#ifdef PGERROR -#define ERROR PGERROR -#endif - -/* - * we can't use the windows gai_strerror{AW} functions because - * they are defined inline in the MS header files. So we'll use our - * own - */ -#undef gai_strerror - -#endif /* WIN32_SYS_SOCKET_H */ diff --git a/contrib/libs/postgresql/src/include/port/win32/sys/wait.h b/contrib/libs/postgresql/src/include/port/win32/sys/wait.h deleted file mode 100644 index eaeb5661c98..00000000000 --- a/contrib/libs/postgresql/src/include/port/win32/sys/wait.h +++ /dev/null @@ -1,3 +0,0 @@ -/* - * src/include/port/win32/sys/wait.h - */ diff --git a/contrib/libs/postgresql/src/include/port/win32_msvc/dirent.h b/contrib/libs/postgresql/src/include/port/win32_msvc/dirent.h deleted file mode 100644 index 62799db0014..00000000000 --- a/contrib/libs/postgresql/src/include/port/win32_msvc/dirent.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Headers for port/dirent.c, win32 native implementation of dirent functions - * - * src/include/port/win32_msvc/dirent.h - */ - -#ifndef _WIN32VC_DIRENT_H -#define _WIN32VC_DIRENT_H -struct dirent -{ - long d_ino; - unsigned short d_reclen; - unsigned char d_type; - unsigned short d_namlen; - char d_name[MAX_PATH]; -}; - -typedef struct DIR DIR; - -DIR *opendir(const char *); -struct dirent *readdir(DIR *); -int closedir(DIR *); - -/* File types for 'd_type'. */ -#define DT_UNKNOWN 0 -#define DT_FIFO 1 -#define DT_CHR 2 -#define DT_DIR 4 -#define DT_BLK 6 -#define DT_REG 8 -#define DT_LNK 10 -#define DT_SOCK 12 -#define DT_WHT 14 -#endif diff --git a/contrib/libs/postgresql/src/include/port/win32_msvc/sys/file.h b/contrib/libs/postgresql/src/include/port/win32_msvc/sys/file.h deleted file mode 100644 index 76be3e77740..00000000000 --- a/contrib/libs/postgresql/src/include/port/win32_msvc/sys/file.h +++ /dev/null @@ -1 +0,0 @@ -/* src/include/port/win32_msvc/sys/file.h */ diff --git a/contrib/libs/postgresql/src/include/port/win32_msvc/sys/param.h b/contrib/libs/postgresql/src/include/port/win32_msvc/sys/param.h deleted file mode 100644 index 160df3b25e1..00000000000 --- a/contrib/libs/postgresql/src/include/port/win32_msvc/sys/param.h +++ /dev/null @@ -1 +0,0 @@ -/* src/include/port/win32_msvc/sys/param.h */ diff --git a/contrib/libs/postgresql/src/include/port/win32_msvc/sys/time.h b/contrib/libs/postgresql/src/include/port/win32_msvc/sys/time.h deleted file mode 100644 index 9d943ecc6fa..00000000000 --- a/contrib/libs/postgresql/src/include/port/win32_msvc/sys/time.h +++ /dev/null @@ -1 +0,0 @@ -/* src/include/port/win32_msvc/sys/time.h */ diff --git a/contrib/libs/postgresql/src/include/port/win32_msvc/unistd.h b/contrib/libs/postgresql/src/include/port/win32_msvc/unistd.h deleted file mode 100644 index b7795ba03c4..00000000000 --- a/contrib/libs/postgresql/src/include/port/win32_msvc/unistd.h +++ /dev/null @@ -1,9 +0,0 @@ -/* src/include/port/win32_msvc/unistd.h */ - -/* - * MSVC does not define these, nor does _fileno(stdin) etc reliably work - * (returns -1 if stdin/out/err are closed). - */ -#define STDIN_FILENO 0 -#define STDOUT_FILENO 1 -#define STDERR_FILENO 2 diff --git a/contrib/libs/postgresql/src/include/port/win32_msvc/utime.h b/contrib/libs/postgresql/src/include/port/win32_msvc/utime.h deleted file mode 100644 index c78e79c33d3..00000000000 --- a/contrib/libs/postgresql/src/include/port/win32_msvc/utime.h +++ /dev/null @@ -1,3 +0,0 @@ -/* src/include/port/win32_msvc/utime.h */ - -#include <sys/utime.h> /* for non-unicode version */ diff --git a/contrib/libs/postgresql/src/include/port/win32ntdll.h b/contrib/libs/postgresql/src/include/port/win32ntdll.h deleted file mode 100644 index 291b067ea4f..00000000000 --- a/contrib/libs/postgresql/src/include/port/win32ntdll.h +++ /dev/null @@ -1,32 +0,0 @@ -/*------------------------------------------------------------------------- - * - * win32ntdll.h - * Dynamically loaded Windows NT functions. - * - * Portions Copyright (c) 2021-2022, PostgreSQL Global Development Group - * Portions Copyright (c) 1994, Regents of the University of California - * - * src/include/port/win32ntdll.h - * - *------------------------------------------------------------------------- - */ - -#ifndef WIN32NTDLL_H -#define WIN32NTDLL_H - -/* - * Because this includes NT headers that normally conflict with Win32 headers, - * any translation unit that includes it should #define UMDF_USING_NTSTATUS - * before including <windows.h>. - */ - -#include <ntstatus.h> -#include <winternl.h> - -typedef NTSTATUS (__stdcall * RtlGetLastNtStatus_t) (void); - -extern PGDLLIMPORT RtlGetLastNtStatus_t pg_RtlGetLastNtStatus; - -extern int initialize_ntdll(void); - -#endif /* WIN32NTDLL_H */ diff --git a/contrib/libs/postgresql/src/port/dirmod.c b/contrib/libs/postgresql/src/port/dirmod.c deleted file mode 100644 index 62daec7af8a..00000000000 --- a/contrib/libs/postgresql/src/port/dirmod.c +++ /dev/null @@ -1,355 +0,0 @@ -/*------------------------------------------------------------------------- - * - * dirmod.c - * directory handling functions - * - * Portions Copyright (c) 1996-2022, 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 deleted file mode 100644 index d441dc8196a..00000000000 --- a/contrib/libs/postgresql/src/port/dlopen.c +++ /dev/null @@ -1,145 +0,0 @@ -/*------------------------------------------------------------------------- - * - * dlopen.c - * dynamic loader for platforms without dlopen() - * - * Portions Copyright (c) 1996-2022, 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/getaddrinfo.c b/contrib/libs/postgresql/src/port/getaddrinfo.c deleted file mode 100644 index 3284c6eb52a..00000000000 --- a/contrib/libs/postgresql/src/port/getaddrinfo.c +++ /dev/null @@ -1,440 +0,0 @@ -/*------------------------------------------------------------------------- - * - * 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-2022, 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 FRONTEND -static int pqGethostbyname(const char *name, - struct hostent *resultbuf, - char *buffer, size_t buflen, - struct hostent **result, - int *herrno); -#endif - -#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; -} - -/* - * Wrapper around gethostbyname() or gethostbyname_r() to mimic - * POSIX gethostbyname_r() behaviour, if it is not available or required. - */ -#ifdef FRONTEND -static int -pqGethostbyname(const char *name, - struct hostent *resultbuf, - char *buffer, size_t buflen, - struct hostent **result, - int *herrno) -{ -#if 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 /* FRONTEND */ diff --git a/contrib/libs/postgresql/src/port/getopt.c b/contrib/libs/postgresql/src/port/getopt.c deleted file mode 100644 index 207c2836d35..00000000000 --- a/contrib/libs/postgresql/src/port/getopt.c +++ /dev/null @@ -1,136 +0,0 @@ -/* 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/getrusage.c b/contrib/libs/postgresql/src/port/getrusage.c deleted file mode 100644 index 8369fd27938..00000000000 --- a/contrib/libs/postgresql/src/port/getrusage.c +++ /dev/null @@ -1,110 +0,0 @@ -/*------------------------------------------------------------------------- - * - * getrusage.c - * get information about resource utilisation - * - * Portions Copyright (c) 1996-2022, 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 deleted file mode 100644 index ee8fe823378..00000000000 --- a/contrib/libs/postgresql/src/port/gettimeofday.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * 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 deleted file mode 100644 index adaf18adb39..00000000000 --- a/contrib/libs/postgresql/src/port/inet_aton.c +++ /dev/null @@ -1,149 +0,0 @@ -/* 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/kill.c b/contrib/libs/postgresql/src/port/kill.c deleted file mode 100644 index ff0862683c1..00000000000 --- a/contrib/libs/postgresql/src/port/kill.c +++ /dev/null @@ -1,97 +0,0 @@ -/*------------------------------------------------------------------------- - * - * kill.c - * kill() - * - * Copyright (c) 1996-2022, 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/open.c b/contrib/libs/postgresql/src/port/open.c deleted file mode 100644 index 8c09c7c1f77..00000000000 --- a/contrib/libs/postgresql/src/port/open.c +++ /dev/null @@ -1,224 +0,0 @@ -/*------------------------------------------------------------------------- - * - * open.c - * Win32 open() replacement - * - * - * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group - * - * src/port/open.c - * - *------------------------------------------------------------------------- - */ - -#ifdef WIN32 - -#define UMDF_USING_NTSTATUS - -#ifndef FRONTEND -#include "postgres.h" -#else -#include "postgres_fe.h" -#endif - -#include "port/win32ntdll.h" - -#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; -} - -/* - * Internal function used by pgwin32_open() and _pgstat64(). When - * backup_semantics is true, directories may be opened (for limited uses). On - * failure, INVALID_HANDLE_VALUE is returned and errno is set. - */ -HANDLE -pgwin32_open_handle(const char *fileName, int fileFlags, bool backup_semantics) -{ - HANDLE h; - SECURITY_ATTRIBUTES sa; - int loops = 0; - - if (initialize_ntdll() < 0) - return INVALID_HANDLE_VALUE; - - /* 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); - - 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 | - (backup_semantics ? FILE_FLAG_BACKUP_SEMANTICS : 0) | - ((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'd better ask for the NT status too so we can translate it - * to a more Unix-like error. We hope that nothing clobbers the NT - * status in between the internal NtCreateFile() call and CreateFile() - * returning. - * - * If there's no O_CREAT flag, then we'll pretend the file is - * invisible. With O_CREAT, we have no choice but to report that - * there's a file in the way (which wouldn't happen on Unix). - */ - if (err == ERROR_ACCESS_DENIED && - pg_RtlGetLastNtStatus() == STATUS_DELETE_PENDING) - { - if (fileFlags & O_CREAT) - err = ERROR_FILE_EXISTS; - else - err = ERROR_FILE_NOT_FOUND; - } - - _dosmaperr(err); - return INVALID_HANDLE_VALUE; - } - - return h; -} - -int -pgwin32_open(const char *fileName, int fileFlags,...) -{ - HANDLE h; - int fd; - - h = pgwin32_open_handle(fileName, fileFlags, false); - if (h == INVALID_HANDLE_VALUE) - return -1; - -#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 - - /* _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/pread.c b/contrib/libs/postgresql/src/port/pread.c deleted file mode 100644 index bbf12ee0279..00000000000 --- a/contrib/libs/postgresql/src/port/pread.c +++ /dev/null @@ -1,58 +0,0 @@ -/*------------------------------------------------------------------------- - * - * pread.c - * Implementation of pread(2) for platforms that lack one. - * - * Portions Copyright (c) 1996-2022, 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 "c.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 deleted file mode 100644 index cadecc481c2..00000000000 --- a/contrib/libs/postgresql/src/port/pwrite.c +++ /dev/null @@ -1,55 +0,0 @@ -/*------------------------------------------------------------------------- - * - * pwrite.c - * Implementation of pwrite(2) for platforms that lack one. - * - * Portions Copyright (c) 1996-2022, 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 "c.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 deleted file mode 100644 index bc53704ef79..00000000000 --- a/contrib/libs/postgresql/src/port/pwritev.c +++ /dev/null @@ -1,58 +0,0 @@ -/*------------------------------------------------------------------------- - * - * pwritev.c - * Implementation of pwritev(2) for platforms that lack one. - * - * Portions Copyright (c) 1996-2022, 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 "c.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/system.c b/contrib/libs/postgresql/src/port/system.c deleted file mode 100644 index 20a830fd5ce..00000000000 --- a/contrib/libs/postgresql/src/port/system.c +++ /dev/null @@ -1,117 +0,0 @@ -/*------------------------------------------------------------------------- - * - * 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-2022, 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/win32common.c b/contrib/libs/postgresql/src/port/win32common.c deleted file mode 100644 index 2fd78f7f936..00000000000 --- a/contrib/libs/postgresql/src/port/win32common.c +++ /dev/null @@ -1,68 +0,0 @@ -/*------------------------------------------------------------------------- - * - * win32common.c - * Common routines shared among the win32*.c ports. - * - * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group - * Portions Copyright (c) 1994, Regents of the University of California - * - * - * IDENTIFICATION - * src/port/win32common.c - * - *------------------------------------------------------------------------- - */ - -#ifdef FRONTEND -#include "postgres_fe.h" -#else -#include "postgres.h" -#endif - -#ifdef WIN32 - -/* - * pgwin32_get_file_type - * - * Convenience wrapper for GetFileType() with specific error handling for all the - * port implementations. Returns the file type associated with a HANDLE. - * - * On error, sets errno with FILE_TYPE_UNKNOWN as file type. - */ -DWORD -pgwin32_get_file_type(HANDLE hFile) -{ - DWORD fileType = FILE_TYPE_UNKNOWN; - DWORD lastError; - - errno = 0; - - /* - * When stdin, stdout, and stderr aren't associated with a stream the - * special value -2 is returned: - * https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/get-osfhandle - */ - if (hFile == INVALID_HANDLE_VALUE || hFile == (HANDLE) -2) - { - errno = EINVAL; - return FILE_TYPE_UNKNOWN; - } - - fileType = GetFileType(hFile); - lastError = GetLastError(); - - /* - * Invoke GetLastError in order to distinguish between a "valid" return of - * FILE_TYPE_UNKNOWN and its return due to a calling error. In case of - * success, GetLastError() returns NO_ERROR. - */ - if (fileType == FILE_TYPE_UNKNOWN && lastError != NO_ERROR) - { - _dosmaperr(lastError); - return FILE_TYPE_UNKNOWN; - } - - return fileType; -} - -#endif /* WIN32 */ diff --git a/contrib/libs/postgresql/src/port/win32env.c b/contrib/libs/postgresql/src/port/win32env.c deleted file mode 100644 index 7aa5a3081e3..00000000000 --- a/contrib/libs/postgresql/src/port/win32env.c +++ /dev/null @@ -1,163 +0,0 @@ -/*------------------------------------------------------------------------- - * - * 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-2022, 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 deleted file mode 100644 index fca867ba3d5..00000000000 --- a/contrib/libs/postgresql/src/port/win32error.c +++ /dev/null @@ -1,208 +0,0 @@ -/*------------------------------------------------------------------------- - * - * win32error.c - * Map win32 error codes to errno values - * - * Portions Copyright (c) 1996-2022, 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/win32fseek.c b/contrib/libs/postgresql/src/port/win32fseek.c deleted file mode 100644 index 985313c825f..00000000000 --- a/contrib/libs/postgresql/src/port/win32fseek.c +++ /dev/null @@ -1,75 +0,0 @@ -/*------------------------------------------------------------------------- - * - * win32fseek.c - * Replacements for fseeko() and ftello(). - * - * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group - * - * IDENTIFICATION - * src/port/win32fseek.c - * - *------------------------------------------------------------------------- - */ - -#ifdef FRONTEND -#include "postgres_fe.h" -#else -#include "postgres.h" -#endif - -#if defined(WIN32) && defined(_MSC_VER) - -/* - * _pgfseeko64 - * - * Calling fseek() on a handle to a non-seeking device such as a pipe or - * a communications device is not supported, and fseek() may not return - * an error. This wrapper relies on the file type to check which cases - * are supported. - */ -int -_pgfseeko64(FILE *stream, pgoff_t offset, int origin) -{ - DWORD fileType; - HANDLE hFile = (HANDLE) _get_osfhandle(_fileno(stream)); - - fileType = pgwin32_get_file_type(hFile); - if (errno != 0) - return -1; - - if (fileType == FILE_TYPE_DISK) - return _fseeki64(stream, offset, origin); - else if (fileType == FILE_TYPE_CHAR || fileType == FILE_TYPE_PIPE) - errno = ESPIPE; - else - errno = EINVAL; - - return -1; -} - -/* - * _pgftello64 - * - * Same as _pgfseeko64(). - */ -pgoff_t -_pgftello64(FILE *stream) -{ - DWORD fileType; - HANDLE hFile = (HANDLE) _get_osfhandle(_fileno(stream)); - - fileType = pgwin32_get_file_type(hFile); - if (errno != 0) - return -1; - - if (fileType == FILE_TYPE_DISK) - return _ftelli64(stream); - else if (fileType == FILE_TYPE_CHAR || fileType == FILE_TYPE_PIPE) - errno = ESPIPE; - else - errno = EINVAL; - - return -1; -} - -#endif /* defined(WIN32) && defined(_MSC_VER) */ diff --git a/contrib/libs/postgresql/src/port/win32ntdll.c b/contrib/libs/postgresql/src/port/win32ntdll.c deleted file mode 100644 index 10c33c6a01d..00000000000 --- a/contrib/libs/postgresql/src/port/win32ntdll.c +++ /dev/null @@ -1,69 +0,0 @@ -/*------------------------------------------------------------------------- - * - * win32ntdll.c - * Dynamically loaded Windows NT functions. - * - * Portions Copyright (c) 2021-2022, PostgreSQL Global Development Group - * Portions Copyright (c) 1994, Regents of the University of California - * - * - * IDENTIFICATION - * src/port/win32ntdll.c - * - *------------------------------------------------------------------------- - */ - -#define UMDF_USING_NTSTATUS - -#include "c.h" - -#include "port/win32ntdll.h" - -RtlGetLastNtStatus_t pg_RtlGetLastNtStatus; - -typedef struct NtDllRoutine -{ - const char *name; - pg_funcptr_t *address; -} NtDllRoutine; - -static const NtDllRoutine routines[] = { - {"RtlGetLastNtStatus", (pg_funcptr_t *) &pg_RtlGetLastNtStatus} -}; - -static bool initialized; - -int -initialize_ntdll(void) -{ - HMODULE module; - - if (initialized) - return 0; - - if (!(module = LoadLibraryEx("ntdll.dll", NULL, 0))) - { - _dosmaperr(GetLastError()); - return -1; - } - - for (int i = 0; i < lengthof(routines); ++i) - { - pg_funcptr_t address; - - address = (pg_funcptr_t) GetProcAddress(module, routines[i].name); - if (!address) - { - _dosmaperr(GetLastError()); - FreeLibrary(module); - - return -1; - } - - *(pg_funcptr_t *) routines[i].address = address; - } - - initialized = true; - - return 0; -} diff --git a/contrib/libs/postgresql/src/port/win32security.c b/contrib/libs/postgresql/src/port/win32security.c deleted file mode 100644 index 1235199f2fb..00000000000 --- a/contrib/libs/postgresql/src/port/win32security.c +++ /dev/null @@ -1,190 +0,0 @@ -/*------------------------------------------------------------------------- - * - * win32security.c - * Microsoft Windows Win32 Security Support Functions - * - * Portions Copyright (c) 1996-2022, 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) Standard error is not valid (always the case for services, and pg_ctl - * running as a service "passes" that down to postgres, - * c.f. CreateRestrictedProcess()) - * 2) We are running as LocalSystem (only used by services) - * 3) 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}; - HANDLE stderr_handle; - - /* Only check the first time */ - if (_is_service != -1) - return _is_service; - - /* Check if standard error is not valid */ - stderr_handle = GetStdHandle(STD_ERROR_HANDLE); - if (stderr_handle != INVALID_HANDLE_VALUE && stderr_handle != NULL) - { - _is_service = 0; - return _is_service; - } - - /* Check if running as 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 deleted file mode 100644 index aadd09a4e9a..00000000000 --- a/contrib/libs/postgresql/src/port/win32setlocale.c +++ /dev/null @@ -1,193 +0,0 @@ -/*------------------------------------------------------------------------- - * - * win32setlocale.c - * Wrapper to work around bugs in Windows setlocale() implementation - * - * Copyright (c) 2011-2022, 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å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å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 deleted file mode 100644 index e25811d290e..00000000000 --- a/contrib/libs/postgresql/src/port/win32stat.c +++ /dev/null @@ -1,189 +0,0 @@ -/*------------------------------------------------------------------------- - * - * win32stat.c - * Replacements for <sys/stat.h> functions using GetFileInformationByHandle - * - * Portions Copyright (c) 1996-2022, 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> - -/* - * 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) -{ - /* - * Our open wrapper will report STATUS_DELETE_PENDING as ENOENT. We - * request FILE_FLAG_BACKUP_SEMANTICS so that we can open directories too, - * for limited purposes. We use the private handle-based version, so we - * don't risk running out of fds. - */ - HANDLE hFile; - int ret; - - hFile = pgwin32_open_handle(name, O_RDONLY, true); - if (hFile == INVALID_HANDLE_VALUE) - return -1; - - 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); - DWORD fileType = FILE_TYPE_UNKNOWN; - unsigned short st_mode; - - if (buf == NULL) - { - errno = EINVAL; - return -1; - } - - fileType = pgwin32_get_file_type(hFile); - if (errno != 0) - return -1; - - switch (fileType) - { - /* The specified file is a disk file */ - case FILE_TYPE_DISK: - return fileinfo_to_stat(hFile, buf); - - /* - * The specified file is a socket, a named pipe, or an anonymous - * pipe. - */ - case FILE_TYPE_PIPE: - st_mode = _S_IFIFO; - break; - /* The specified file is a character file */ - case FILE_TYPE_CHAR: - st_mode = _S_IFCHR; - break; - /* Unused flag and unknown file type */ - case FILE_TYPE_REMOTE: - case FILE_TYPE_UNKNOWN: - default: - errno = EINVAL; - return -1; - } - - memset(buf, 0, sizeof(*buf)); - buf->st_mode = st_mode; - buf->st_dev = fileno; - buf->st_rdev = fileno; - buf->st_nlink = 1; - return 0; -} - -#endif /* WIN32 */ |