diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 13:44:03 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 13:44:03 +0000 |
commit | 293913568e6a7a86fd1479e1cff8e2ecb58d6568 (patch) | |
tree | fc3b469a3ec5ab71b36ea97cc7aaddb838423a0c /src/interfaces/libpq | |
parent | Initial commit. (diff) | |
download | postgresql-16-293913568e6a7a86fd1479e1cff8e2ecb58d6568.tar.xz postgresql-16-293913568e6a7a86fd1479e1cff8e2ecb58d6568.zip |
Adding upstream version 16.2.upstream/16.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/interfaces/libpq')
64 files changed, 54944 insertions, 0 deletions
diff --git a/src/interfaces/libpq/.gitignore b/src/interfaces/libpq/.gitignore new file mode 100644 index 0000000..829d683 --- /dev/null +++ b/src/interfaces/libpq/.gitignore @@ -0,0 +1,3 @@ +/exports.list +/libpq-refs-stamp +/tmp_check/ diff --git a/src/interfaces/libpq/Makefile b/src/interfaces/libpq/Makefile new file mode 100644 index 0000000..0919d8f --- /dev/null +++ b/src/interfaces/libpq/Makefile @@ -0,0 +1,173 @@ +#------------------------------------------------------------------------- +# +# Makefile for src/interfaces/libpq library +# +# Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group +# Portions Copyright (c) 1994, Regents of the University of California +# +# src/interfaces/libpq/Makefile +# +#------------------------------------------------------------------------- + +subdir = src/interfaces/libpq +top_builddir = ../../.. +include $(top_builddir)/src/Makefile.global + +export with_ssl + +PGFILEDESC = "PostgreSQL Access Library" + +# shared library parameters +NAME= pq +SO_MAJOR_VERSION= 5 +SO_MINOR_VERSION= $(MAJORVERSION) + +override CPPFLAGS := -I$(srcdir) $(CPPFLAGS) -I$(top_builddir)/src/port -I$(top_srcdir)/src/port +ifneq ($(PORTNAME), win32) +override CFLAGS += $(PTHREAD_CFLAGS) +endif + +# The MSVC build system scrapes OBJS from this file. If you change any of +# the conditional additions of files to OBJS, update Mkvcbuild.pm to match. + +OBJS = \ + $(WIN32RES) \ + fe-auth-scram.o \ + fe-connect.o \ + fe-exec.o \ + fe-lobj.o \ + fe-misc.o \ + fe-print.o \ + fe-protocol3.o \ + fe-secure.o \ + fe-trace.o \ + legacy-pqsignal.o \ + libpq-events.o \ + pqexpbuffer.o \ + fe-auth.o + +# File shared across all SSL implementations supported. +ifneq ($(with_ssl),no) +OBJS += \ + fe-secure-common.o +endif + +ifeq ($(with_ssl),openssl) +OBJS += \ + fe-secure-openssl.o +endif + +ifeq ($(with_gssapi),yes) +OBJS += \ + fe-gssapi-common.o \ + fe-secure-gssapi.o +endif + +ifeq ($(PORTNAME), cygwin) +override shlib = cyg$(NAME)$(DLSUFFIX) +endif + +ifeq ($(PORTNAME), win32) +OBJS += \ + win32.o + +ifeq ($(enable_thread_safety), yes) +OBJS += pthread-win32.o +endif +endif + + +# Add libraries that libpq depends (or might depend) on into the +# shared library link. (The order in which you list them here doesn't +# matter.) Note that we filter out -lpgcommon and -lpgport from LIBS and +# instead link with -lpgcommon_shlib and -lpgport_shlib, to get object files +# that are built correctly for use in a shlib. +SHLIB_LINK_INTERNAL = -lpgcommon_shlib -lpgport_shlib +ifneq ($(PORTNAME), win32) +SHLIB_LINK += $(filter -lcrypt -ldes -lcom_err -lcrypto -lk5crypto -lkrb5 -lgssapi_krb5 -lgss -lgssapi -lssl -lsocket -lnsl -lresolv -lintl -lm, $(LIBS)) $(LDAP_LIBS_FE) $(PTHREAD_LIBS) +else +SHLIB_LINK += $(filter -lcrypt -ldes -lcom_err -lcrypto -lk5crypto -lkrb5 -lgssapi32 -lssl -lsocket -lnsl -lresolv -lintl -lm $(PTHREAD_LIBS), $(LIBS)) $(LDAP_LIBS_FE) +endif +ifeq ($(PORTNAME), win32) +SHLIB_LINK += -lshell32 -lws2_32 -lsecur32 $(filter -leay32 -lssleay32 -lcomerr32 -lkrb5_32, $(LIBS)) +endif +SHLIB_PREREQS = submake-libpgport + +SHLIB_EXPORTS = exports.txt + +ifeq ($(with_ssl),openssl) +PKG_CONFIG_REQUIRES_PRIVATE = libssl, libcrypto +endif + +all: all-lib libpq-refs-stamp + +# Shared library stuff +include $(top_srcdir)/src/Makefile.shlib +backend_src = $(top_srcdir)/src/backend + +# Check for functions that libpq must not call, currently just exit(). +# (Ideally we'd reject abort() too, but there are various scenarios where +# build toolchains insert abort() calls, e.g. to implement assert().) +# If nm doesn't exist or doesn't work on shlibs, this test will do nothing, +# which is fine. The exclusion of __cxa_atexit is necessary on OpenBSD, +# which seems to insert references to that even in pure C code. +# Skip the test when profiling, as gcc may insert exit() calls for that. +# Also skip the test on platforms where libpq infrastructure may be provided +# by statically-linked libraries, as we can't expect them to honor this +# coding rule. +libpq-refs-stamp: $(shlib) +ifneq ($(enable_coverage), yes) +ifeq (,$(filter aix solaris,$(PORTNAME))) + @if nm -A -u $< 2>/dev/null | grep -v __cxa_atexit | grep exit; then \ + echo 'libpq must not be calling any function which invokes exit'; exit 1; \ + fi +endif +endif + touch $@ + +# Make dependencies on pg_config_paths.h visible in all builds. +fe-connect.o: fe-connect.c $(top_builddir)/src/port/pg_config_paths.h +fe-misc.o: fe-misc.c $(top_builddir)/src/port/pg_config_paths.h + +$(top_builddir)/src/port/pg_config_paths.h: + $(MAKE) -C $(top_builddir)/src/port pg_config_paths.h + +install: all installdirs install-lib + $(INSTALL_DATA) $(srcdir)/libpq-fe.h '$(DESTDIR)$(includedir)' + $(INSTALL_DATA) $(srcdir)/libpq-events.h '$(DESTDIR)$(includedir)' + $(INSTALL_DATA) $(srcdir)/libpq-int.h '$(DESTDIR)$(includedir_internal)' + $(INSTALL_DATA) $(srcdir)/fe-auth-sasl.h '$(DESTDIR)$(includedir_internal)' + $(INSTALL_DATA) $(srcdir)/pqexpbuffer.h '$(DESTDIR)$(includedir_internal)' + $(INSTALL_DATA) $(srcdir)/pg_service.conf.sample '$(DESTDIR)$(datadir)/pg_service.conf.sample' + +test-build: + $(MAKE) -C test all + +check installcheck: export PATH := $(CURDIR)/test:$(PATH) + +check: test-build all + $(prove_check) + +installcheck: test-build all + $(prove_installcheck) + +installdirs: installdirs-lib + $(MKDIR_P) '$(DESTDIR)$(includedir)' '$(DESTDIR)$(includedir_internal)' '$(DESTDIR)$(datadir)' + +uninstall: uninstall-lib + rm -f '$(DESTDIR)$(includedir)/libpq-fe.h' + rm -f '$(DESTDIR)$(includedir)/libpq-events.h' + rm -f '$(DESTDIR)$(includedir_internal)/libpq-int.h' + rm -f '$(DESTDIR)$(includedir_internal)/fe-auth-sasl.h' + rm -f '$(DESTDIR)$(includedir_internal)/pqexpbuffer.h' + rm -f '$(DESTDIR)$(datadir)/pg_service.conf.sample' + +clean distclean: clean-lib + $(MAKE) -C test $@ + rm -rf tmp_check + rm -f $(OBJS) pthread.h libpq-refs-stamp +# Might be left over from a Win32 client-only build + rm -f pg_config_paths.h + +maintainer-clean: distclean + $(MAKE) -C test $@ diff --git a/src/interfaces/libpq/README b/src/interfaces/libpq/README new file mode 100644 index 0000000..0dcef75 --- /dev/null +++ b/src/interfaces/libpq/README @@ -0,0 +1,3 @@ +src/interfaces/libpq/README + +This directory contains the C version of Libpq, the POSTGRES frontend library. diff --git a/src/interfaces/libpq/exports.txt b/src/interfaces/libpq/exports.txt new file mode 100644 index 0000000..7ded77a --- /dev/null +++ b/src/interfaces/libpq/exports.txt @@ -0,0 +1,189 @@ +# src/interfaces/libpq/exports.txt +# Functions to be exported by libpq DLLs +PQconnectdb 1 +PQsetdbLogin 2 +PQconndefaults 3 +PQfinish 4 +PQreset 5 +PQrequestCancel 6 +PQdb 7 +PQuser 8 +PQpass 9 +PQhost 10 +PQport 11 +PQtty 12 +PQoptions 13 +PQstatus 14 +PQerrorMessage 15 +PQsocket 16 +PQbackendPID 17 +PQtrace 18 +PQuntrace 19 +PQsetNoticeProcessor 20 +PQexec 21 +PQnotifies 22 +PQsendQuery 23 +PQgetResult 24 +PQisBusy 25 +PQconsumeInput 26 +PQgetline 27 +PQputline 28 +PQgetlineAsync 29 +PQputnbytes 30 +PQendcopy 31 +PQfn 32 +PQresultStatus 33 +PQntuples 34 +PQnfields 35 +PQbinaryTuples 36 +PQfname 37 +PQfnumber 38 +PQftype 39 +PQfsize 40 +PQfmod 41 +PQcmdStatus 42 +PQoidStatus 43 +PQcmdTuples 44 +PQgetvalue 45 +PQgetlength 46 +PQgetisnull 47 +PQclear 48 +PQmakeEmptyPGresult 49 +PQprint 50 +PQdisplayTuples 51 +PQprintTuples 52 +lo_open 53 +lo_close 54 +lo_read 55 +lo_write 56 +lo_lseek 57 +lo_creat 58 +lo_tell 59 +lo_unlink 60 +lo_import 61 +lo_export 62 +pgresStatus 63 +PQmblen 64 +PQresultErrorMessage 65 +PQresStatus 66 +termPQExpBuffer 67 +appendPQExpBufferChar 68 +initPQExpBuffer 69 +resetPQExpBuffer 70 +PQoidValue 71 +PQclientEncoding 72 +PQenv2encoding 73 +appendBinaryPQExpBuffer 74 +appendPQExpBufferStr 75 +destroyPQExpBuffer 76 +createPQExpBuffer 77 +PQconninfoFree 78 +PQconnectPoll 79 +PQconnectStart 80 +PQflush 81 +PQisnonblocking 82 +PQresetPoll 83 +PQresetStart 84 +PQsetClientEncoding 85 +PQsetnonblocking 86 +PQfreeNotify 87 +PQescapeString 88 +PQescapeBytea 89 +printfPQExpBuffer 90 +appendPQExpBuffer 91 +pg_encoding_to_char 92 +pg_utf_mblen 93 +PQunescapeBytea 94 +PQfreemem 95 +PQtransactionStatus 96 +PQparameterStatus 97 +PQprotocolVersion 98 +PQsetErrorVerbosity 99 +PQsetNoticeReceiver 100 +PQexecParams 101 +PQsendQueryParams 102 +PQputCopyData 103 +PQputCopyEnd 104 +PQgetCopyData 105 +PQresultErrorField 106 +PQftable 107 +PQftablecol 108 +PQfformat 109 +PQexecPrepared 110 +PQsendQueryPrepared 111 +PQdsplen 112 +PQserverVersion 113 +PQgetssl 114 +pg_char_to_encoding 115 +pg_valid_server_encoding 116 +pqsignal 117 +PQprepare 118 +PQsendPrepare 119 +PQgetCancel 120 +PQfreeCancel 121 +PQcancel 122 +lo_create 123 +PQinitSSL 124 +PQregisterThreadLock 125 +PQescapeStringConn 126 +PQescapeByteaConn 127 +PQencryptPassword 128 +PQisthreadsafe 129 +enlargePQExpBuffer 130 +PQnparams 131 +PQparamtype 132 +PQdescribePrepared 133 +PQdescribePortal 134 +PQsendDescribePrepared 135 +PQsendDescribePortal 136 +lo_truncate 137 +PQconnectionUsedPassword 138 +pg_valid_server_encoding_id 139 +PQconnectionNeedsPassword 140 +lo_import_with_oid 141 +PQcopyResult 142 +PQsetResultAttrs 143 +PQsetvalue 144 +PQresultAlloc 145 +PQregisterEventProc 146 +PQinstanceData 147 +PQsetInstanceData 148 +PQresultInstanceData 149 +PQresultSetInstanceData 150 +PQfireResultCreateEvents 151 +PQconninfoParse 152 +PQinitOpenSSL 153 +PQescapeLiteral 154 +PQescapeIdentifier 155 +PQconnectdbParams 156 +PQconnectStartParams 157 +PQping 158 +PQpingParams 159 +PQlibVersion 160 +PQsetSingleRowMode 161 +lo_lseek64 162 +lo_tell64 163 +lo_truncate64 164 +PQconninfo 165 +PQsslInUse 166 +PQsslStruct 167 +PQsslAttributeNames 168 +PQsslAttribute 169 +PQsetErrorContextVisibility 170 +PQresultVerboseErrorMessage 171 +PQencryptPasswordConn 172 +PQresultMemorySize 173 +PQhostaddr 174 +PQgssEncInUse 175 +PQgetgssctx 176 +PQsetSSLKeyPassHook_OpenSSL 177 +PQgetSSLKeyPassHook_OpenSSL 178 +PQdefaultSSLKeyPassHook_OpenSSL 179 +PQenterPipelineMode 180 +PQexitPipelineMode 181 +PQpipelineSync 182 +PQpipelineStatus 183 +PQsetTraceFlags 184 +PQmblenBounded 185 +PQsendFlushRequest 186 +PQconnectionUsedGSSAPI 187 diff --git a/src/interfaces/libpq/fe-auth-sasl.h b/src/interfaces/libpq/fe-auth-sasl.h new file mode 100644 index 0000000..ddf6ea3 --- /dev/null +++ b/src/interfaces/libpq/fe-auth-sasl.h @@ -0,0 +1,131 @@ +/*------------------------------------------------------------------------- + * + * fe-auth-sasl.h + * Defines the SASL mechanism interface for libpq. + * + * Each SASL mechanism defines a frontend and a backend callback structure. + * This is not part of the public API for applications. + * + * See src/include/libpq/sasl.h for the backend counterpart. + * + * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/interfaces/libpq/fe-auth-sasl.h + * + *------------------------------------------------------------------------- + */ + +#ifndef FE_AUTH_SASL_H +#define FE_AUTH_SASL_H + +#include "libpq-fe.h" + +/* + * Frontend SASL mechanism callbacks. + * + * To implement a frontend mechanism, declare a pg_be_sasl_mech struct with + * appropriate callback implementations, then hook it into conn->sasl during + * pg_SASL_init()'s mechanism negotiation. + */ +typedef struct pg_fe_sasl_mech +{ + /*------- + * init() + * + * Initializes mechanism-specific state for a connection. This + * callback must return a pointer to its allocated state, which will + * be passed as-is as the first argument to the other callbacks. + * the free() callback is called to release any state resources. + * + * If state allocation fails, the implementation should return NULL to + * fail the authentication exchange. + * + * Input parameters: + * + * conn: The connection to the server + * + * password: The user's supplied password for the current connection + * + * mech: The mechanism name in use, for implementations that may + * advertise more than one name (such as *-PLUS variants). + *------- + */ + void *(*init) (PGconn *conn, const char *password, const char *mech); + + /*-------- + * exchange() + * + * Produces a client response to a server challenge. As a special case + * for client-first SASL mechanisms, exchange() is called with a NULL + * server response once at the start of the authentication exchange to + * generate an initial response. + * + * Input parameters: + * + * state: The opaque mechanism state returned by init() + * + * input: The challenge data sent by the server, or NULL when + * generating a client-first initial response (that is, when + * the server expects the client to send a message to start + * the exchange). This is guaranteed to be null-terminated + * for safety, but SASL allows embedded nulls in challenges, + * so mechanisms must be careful to check inputlen. + * + * inputlen: The length of the challenge data sent by the server, or -1 + * during client-first initial response generation. + * + * Output parameters, to be set by the callback function: + * + * output: A malloc'd buffer containing the client's response to + * the server (can be empty), or NULL if the exchange should + * be aborted. (*success should be set to false in the + * latter case.) + * + * outputlen: The length (0 or higher) of the client response buffer, + * ignored if output is NULL. + * + * done: Set to true if the SASL exchange should not continue, + * because the exchange is either complete or failed + * + * success: Set to true if the SASL exchange completed successfully. + * Ignored if *done is false. + *-------- + */ + void (*exchange) (void *state, char *input, int inputlen, + char **output, int *outputlen, + bool *done, bool *success); + + /*-------- + * channel_bound() + * + * Returns true if the connection has an established channel binding. A + * mechanism implementation must ensure that a SASL exchange has actually + * been completed, in addition to checking that channel binding is in use. + * + * Mechanisms that do not implement channel binding may simply return + * false. + * + * Input parameters: + * + * state: The opaque mechanism state returned by init() + *-------- + */ + bool (*channel_bound) (void *state); + + /*-------- + * free() + * + * Frees the state allocated by init(). This is called when the connection + * is dropped, not when the exchange is completed. + * + * Input parameters: + * + * state: The opaque mechanism state returned by init() + *-------- + */ + void (*free) (void *state); + +} pg_fe_sasl_mech; + +#endif /* FE_AUTH_SASL_H */ diff --git a/src/interfaces/libpq/fe-auth-scram.c b/src/interfaces/libpq/fe-auth-scram.c new file mode 100644 index 0000000..6b779ec --- /dev/null +++ b/src/interfaces/libpq/fe-auth-scram.c @@ -0,0 +1,936 @@ +/*------------------------------------------------------------------------- + * + * fe-auth-scram.c + * The front-end (client) implementation of SCRAM authentication. + * + * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/interfaces/libpq/fe-auth-scram.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres_fe.h" + +#include "common/base64.h" +#include "common/hmac.h" +#include "common/saslprep.h" +#include "common/scram-common.h" +#include "fe-auth.h" + + +/* The exported SCRAM callback mechanism. */ +static void *scram_init(PGconn *conn, const char *password, + const char *sasl_mechanism); +static void scram_exchange(void *opaq, char *input, int inputlen, + char **output, int *outputlen, + bool *done, bool *success); +static bool scram_channel_bound(void *opaq); +static void scram_free(void *opaq); + +const pg_fe_sasl_mech pg_scram_mech = { + scram_init, + scram_exchange, + scram_channel_bound, + scram_free +}; + +/* + * Status of exchange messages used for SCRAM authentication via the + * SASL protocol. + */ +typedef enum +{ + FE_SCRAM_INIT, + FE_SCRAM_NONCE_SENT, + FE_SCRAM_PROOF_SENT, + FE_SCRAM_FINISHED +} fe_scram_state_enum; + +typedef struct +{ + fe_scram_state_enum state; + + /* These are supplied by the user */ + PGconn *conn; + char *password; + char *sasl_mechanism; + + /* State data depending on the hash type */ + pg_cryptohash_type hash_type; + int key_length; + + /* We construct these */ + uint8 SaltedPassword[SCRAM_MAX_KEY_LEN]; + char *client_nonce; + char *client_first_message_bare; + char *client_final_message_without_proof; + + /* These come from the server-first message */ + char *server_first_message; + char *salt; + int saltlen; + int iterations; + char *nonce; + + /* These come from the server-final message */ + char *server_final_message; + char ServerSignature[SCRAM_MAX_KEY_LEN]; +} fe_scram_state; + +static bool read_server_first_message(fe_scram_state *state, char *input); +static bool read_server_final_message(fe_scram_state *state, char *input); +static char *build_client_first_message(fe_scram_state *state); +static char *build_client_final_message(fe_scram_state *state); +static bool verify_server_signature(fe_scram_state *state, bool *match, + const char **errstr); +static bool calculate_client_proof(fe_scram_state *state, + const char *client_final_message_without_proof, + uint8 *result, const char **errstr); + +/* + * Initialize SCRAM exchange status. + */ +static void * +scram_init(PGconn *conn, + const char *password, + const char *sasl_mechanism) +{ + fe_scram_state *state; + char *prep_password; + pg_saslprep_rc rc; + + Assert(sasl_mechanism != NULL); + + state = (fe_scram_state *) malloc(sizeof(fe_scram_state)); + if (!state) + return NULL; + memset(state, 0, sizeof(fe_scram_state)); + state->conn = conn; + state->state = FE_SCRAM_INIT; + state->key_length = SCRAM_SHA_256_KEY_LEN; + state->hash_type = PG_SHA256; + + state->sasl_mechanism = strdup(sasl_mechanism); + if (!state->sasl_mechanism) + { + free(state); + return NULL; + } + + /* Normalize the password with SASLprep, if possible */ + rc = pg_saslprep(password, &prep_password); + if (rc == SASLPREP_OOM) + { + free(state->sasl_mechanism); + free(state); + return NULL; + } + if (rc != SASLPREP_SUCCESS) + { + prep_password = strdup(password); + if (!prep_password) + { + free(state->sasl_mechanism); + free(state); + return NULL; + } + } + state->password = prep_password; + + return state; +} + +/* + * Return true if channel binding was employed and the SCRAM exchange + * completed. This should be used after a successful exchange to determine + * whether the server authenticated itself to the client. + * + * Note that the caller must also ensure that the exchange was actually + * successful. + */ +static bool +scram_channel_bound(void *opaq) +{ + fe_scram_state *state = (fe_scram_state *) opaq; + + /* no SCRAM exchange done */ + if (state == NULL) + return false; + + /* SCRAM exchange not completed */ + if (state->state != FE_SCRAM_FINISHED) + return false; + + /* channel binding mechanism not used */ + if (strcmp(state->sasl_mechanism, SCRAM_SHA_256_PLUS_NAME) != 0) + return false; + + /* all clear! */ + return true; +} + +/* + * Free SCRAM exchange status + */ +static void +scram_free(void *opaq) +{ + fe_scram_state *state = (fe_scram_state *) opaq; + + free(state->password); + free(state->sasl_mechanism); + + /* client messages */ + free(state->client_nonce); + free(state->client_first_message_bare); + free(state->client_final_message_without_proof); + + /* first message from server */ + free(state->server_first_message); + free(state->salt); + free(state->nonce); + + /* final message from server */ + free(state->server_final_message); + + free(state); +} + +/* + * Exchange a SCRAM message with backend. + */ +static void +scram_exchange(void *opaq, char *input, int inputlen, + char **output, int *outputlen, + bool *done, bool *success) +{ + fe_scram_state *state = (fe_scram_state *) opaq; + PGconn *conn = state->conn; + const char *errstr = NULL; + + *done = false; + *success = false; + *output = NULL; + *outputlen = 0; + + /* + * Check that the input length agrees with the string length of the input. + * We can ignore inputlen after this. + */ + if (state->state != FE_SCRAM_INIT) + { + if (inputlen == 0) + { + libpq_append_conn_error(conn, "malformed SCRAM message (empty message)"); + goto error; + } + if (inputlen != strlen(input)) + { + libpq_append_conn_error(conn, "malformed SCRAM message (length mismatch)"); + goto error; + } + } + + switch (state->state) + { + case FE_SCRAM_INIT: + /* Begin the SCRAM handshake, by sending client nonce */ + *output = build_client_first_message(state); + if (*output == NULL) + goto error; + + *outputlen = strlen(*output); + *done = false; + state->state = FE_SCRAM_NONCE_SENT; + break; + + case FE_SCRAM_NONCE_SENT: + /* Receive salt and server nonce, send response. */ + if (!read_server_first_message(state, input)) + goto error; + + *output = build_client_final_message(state); + if (*output == NULL) + goto error; + + *outputlen = strlen(*output); + *done = false; + state->state = FE_SCRAM_PROOF_SENT; + break; + + case FE_SCRAM_PROOF_SENT: + /* Receive server signature */ + if (!read_server_final_message(state, input)) + goto error; + + /* + * Verify server signature, to make sure we're talking to the + * genuine server. + */ + if (!verify_server_signature(state, success, &errstr)) + { + libpq_append_conn_error(conn, "could not verify server signature: %s", errstr); + goto error; + } + + if (!*success) + { + libpq_append_conn_error(conn, "incorrect server signature"); + } + *done = true; + state->state = FE_SCRAM_FINISHED; + state->conn->client_finished_auth = true; + break; + + default: + /* shouldn't happen */ + libpq_append_conn_error(conn, "invalid SCRAM exchange state"); + goto error; + } + return; + +error: + *done = true; + *success = false; +} + +/* + * Read value for an attribute part of a SCRAM message. + * + * The buffer at **input is destructively modified, and *input is + * advanced over the "attr=value" string and any following comma. + * + * On failure, append an error message to *errorMessage and return NULL. + */ +static char * +read_attr_value(char **input, char attr, PQExpBuffer errorMessage) +{ + char *begin = *input; + char *end; + + if (*begin != attr) + { + libpq_append_error(errorMessage, + "malformed SCRAM message (attribute \"%c\" expected)", + attr); + return NULL; + } + begin++; + + if (*begin != '=') + { + libpq_append_error(errorMessage, + "malformed SCRAM message (expected character \"=\" for attribute \"%c\")", + attr); + return NULL; + } + begin++; + + end = begin; + while (*end && *end != ',') + end++; + + if (*end) + { + *end = '\0'; + *input = end + 1; + } + else + *input = end; + + return begin; +} + +/* + * Build the first exchange message sent by the client. + */ +static char * +build_client_first_message(fe_scram_state *state) +{ + PGconn *conn = state->conn; + char raw_nonce[SCRAM_RAW_NONCE_LEN + 1]; + char *result; + int channel_info_len; + int encoded_len; + PQExpBufferData buf; + + /* + * Generate a "raw" nonce. This is converted to ASCII-printable form by + * base64-encoding it. + */ + if (!pg_strong_random(raw_nonce, SCRAM_RAW_NONCE_LEN)) + { + libpq_append_conn_error(conn, "could not generate nonce"); + return NULL; + } + + encoded_len = pg_b64_enc_len(SCRAM_RAW_NONCE_LEN); + /* don't forget the zero-terminator */ + state->client_nonce = malloc(encoded_len + 1); + if (state->client_nonce == NULL) + { + libpq_append_conn_error(conn, "out of memory"); + return NULL; + } + encoded_len = pg_b64_encode(raw_nonce, SCRAM_RAW_NONCE_LEN, + state->client_nonce, encoded_len); + if (encoded_len < 0) + { + libpq_append_conn_error(conn, "could not encode nonce"); + return NULL; + } + state->client_nonce[encoded_len] = '\0'; + + /* + * Generate message. The username is left empty as the backend uses the + * value provided by the startup packet. Also, as this username is not + * prepared with SASLprep, the message parsing would fail if it includes + * '=' or ',' characters. + */ + + initPQExpBuffer(&buf); + + /* + * First build the gs2-header with channel binding information. + */ + if (strcmp(state->sasl_mechanism, SCRAM_SHA_256_PLUS_NAME) == 0) + { + Assert(conn->ssl_in_use); + appendPQExpBufferStr(&buf, "p=tls-server-end-point"); + } +#ifdef HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH + else if (conn->channel_binding[0] != 'd' && /* disable */ + conn->ssl_in_use) + { + /* + * Client supports channel binding, but thinks the server does not. + */ + appendPQExpBufferChar(&buf, 'y'); + } +#endif + else + { + /* + * Client does not support channel binding, or has disabled it. + */ + appendPQExpBufferChar(&buf, 'n'); + } + + if (PQExpBufferDataBroken(buf)) + goto oom_error; + + channel_info_len = buf.len; + + appendPQExpBuffer(&buf, ",,n=,r=%s", state->client_nonce); + if (PQExpBufferDataBroken(buf)) + goto oom_error; + + /* + * The first message content needs to be saved without channel binding + * information. + */ + state->client_first_message_bare = strdup(buf.data + channel_info_len + 2); + if (!state->client_first_message_bare) + goto oom_error; + + result = strdup(buf.data); + if (result == NULL) + goto oom_error; + + termPQExpBuffer(&buf); + return result; + +oom_error: + termPQExpBuffer(&buf); + libpq_append_conn_error(conn, "out of memory"); + return NULL; +} + +/* + * Build the final exchange message sent from the client. + */ +static char * +build_client_final_message(fe_scram_state *state) +{ + PQExpBufferData buf; + PGconn *conn = state->conn; + uint8 client_proof[SCRAM_MAX_KEY_LEN]; + char *result; + int encoded_len; + const char *errstr = NULL; + + initPQExpBuffer(&buf); + + /* + * Construct client-final-message-without-proof. We need to remember it + * for verifying the server proof in the final step of authentication. + * + * The channel binding flag handling (p/y/n) must be consistent with + * build_client_first_message(), because the server will check that it's + * the same flag both times. + */ + if (strcmp(state->sasl_mechanism, SCRAM_SHA_256_PLUS_NAME) == 0) + { +#ifdef HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH + char *cbind_data = NULL; + size_t cbind_data_len = 0; + size_t cbind_header_len; + char *cbind_input; + size_t cbind_input_len; + int encoded_cbind_len; + + /* Fetch hash data of server's SSL certificate */ + cbind_data = + pgtls_get_peer_certificate_hash(state->conn, + &cbind_data_len); + if (cbind_data == NULL) + { + /* error message is already set on error */ + termPQExpBuffer(&buf); + return NULL; + } + + appendPQExpBufferStr(&buf, "c="); + + /* p=type,, */ + cbind_header_len = strlen("p=tls-server-end-point,,"); + cbind_input_len = cbind_header_len + cbind_data_len; + cbind_input = malloc(cbind_input_len); + if (!cbind_input) + { + free(cbind_data); + goto oom_error; + } + memcpy(cbind_input, "p=tls-server-end-point,,", cbind_header_len); + memcpy(cbind_input + cbind_header_len, cbind_data, cbind_data_len); + + encoded_cbind_len = pg_b64_enc_len(cbind_input_len); + if (!enlargePQExpBuffer(&buf, encoded_cbind_len)) + { + free(cbind_data); + free(cbind_input); + goto oom_error; + } + encoded_cbind_len = pg_b64_encode(cbind_input, cbind_input_len, + buf.data + buf.len, + encoded_cbind_len); + if (encoded_cbind_len < 0) + { + free(cbind_data); + free(cbind_input); + termPQExpBuffer(&buf); + appendPQExpBufferStr(&conn->errorMessage, + "could not encode cbind data for channel binding\n"); + return NULL; + } + buf.len += encoded_cbind_len; + buf.data[buf.len] = '\0'; + + free(cbind_data); + free(cbind_input); +#else + /* + * Chose channel binding, but the SSL library doesn't support it. + * Shouldn't happen. + */ + termPQExpBuffer(&buf); + appendPQExpBufferStr(&conn->errorMessage, + "channel binding not supported by this build\n"); + return NULL; +#endif /* HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH */ + } +#ifdef HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH + else if (conn->channel_binding[0] != 'd' && /* disable */ + conn->ssl_in_use) + appendPQExpBufferStr(&buf, "c=eSws"); /* base64 of "y,," */ +#endif + else + appendPQExpBufferStr(&buf, "c=biws"); /* base64 of "n,," */ + + if (PQExpBufferDataBroken(buf)) + goto oom_error; + + appendPQExpBuffer(&buf, ",r=%s", state->nonce); + if (PQExpBufferDataBroken(buf)) + goto oom_error; + + state->client_final_message_without_proof = strdup(buf.data); + if (state->client_final_message_without_proof == NULL) + goto oom_error; + + /* Append proof to it, to form client-final-message. */ + if (!calculate_client_proof(state, + state->client_final_message_without_proof, + client_proof, &errstr)) + { + termPQExpBuffer(&buf); + libpq_append_conn_error(conn, "could not calculate client proof: %s", errstr); + return NULL; + } + + appendPQExpBufferStr(&buf, ",p="); + encoded_len = pg_b64_enc_len(state->key_length); + if (!enlargePQExpBuffer(&buf, encoded_len)) + goto oom_error; + encoded_len = pg_b64_encode((char *) client_proof, + state->key_length, + buf.data + buf.len, + encoded_len); + if (encoded_len < 0) + { + termPQExpBuffer(&buf); + libpq_append_conn_error(conn, "could not encode client proof"); + return NULL; + } + buf.len += encoded_len; + buf.data[buf.len] = '\0'; + + result = strdup(buf.data); + if (result == NULL) + goto oom_error; + + termPQExpBuffer(&buf); + return result; + +oom_error: + termPQExpBuffer(&buf); + libpq_append_conn_error(conn, "out of memory"); + return NULL; +} + +/* + * Read the first exchange message coming from the server. + */ +static bool +read_server_first_message(fe_scram_state *state, char *input) +{ + PGconn *conn = state->conn; + char *iterations_str; + char *endptr; + char *encoded_salt; + char *nonce; + int decoded_salt_len; + + state->server_first_message = strdup(input); + if (state->server_first_message == NULL) + { + libpq_append_conn_error(conn, "out of memory"); + return false; + } + + /* parse the message */ + nonce = read_attr_value(&input, 'r', + &conn->errorMessage); + if (nonce == NULL) + { + /* read_attr_value() has appended an error string */ + return false; + } + + /* Verify immediately that the server used our part of the nonce */ + if (strlen(nonce) < strlen(state->client_nonce) || + memcmp(nonce, state->client_nonce, strlen(state->client_nonce)) != 0) + { + libpq_append_conn_error(conn, "invalid SCRAM response (nonce mismatch)"); + return false; + } + + state->nonce = strdup(nonce); + if (state->nonce == NULL) + { + libpq_append_conn_error(conn, "out of memory"); + return false; + } + + encoded_salt = read_attr_value(&input, 's', &conn->errorMessage); + if (encoded_salt == NULL) + { + /* read_attr_value() has appended an error string */ + return false; + } + decoded_salt_len = pg_b64_dec_len(strlen(encoded_salt)); + state->salt = malloc(decoded_salt_len); + if (state->salt == NULL) + { + libpq_append_conn_error(conn, "out of memory"); + return false; + } + state->saltlen = pg_b64_decode(encoded_salt, + strlen(encoded_salt), + state->salt, + decoded_salt_len); + if (state->saltlen < 0) + { + libpq_append_conn_error(conn, "malformed SCRAM message (invalid salt)"); + return false; + } + + iterations_str = read_attr_value(&input, 'i', &conn->errorMessage); + if (iterations_str == NULL) + { + /* read_attr_value() has appended an error string */ + return false; + } + state->iterations = strtol(iterations_str, &endptr, 10); + if (*endptr != '\0' || state->iterations < 1) + { + libpq_append_conn_error(conn, "malformed SCRAM message (invalid iteration count)"); + return false; + } + + if (*input != '\0') + libpq_append_conn_error(conn, "malformed SCRAM message (garbage at end of server-first-message)"); + + return true; +} + +/* + * Read the final exchange message coming from the server. + */ +static bool +read_server_final_message(fe_scram_state *state, char *input) +{ + PGconn *conn = state->conn; + char *encoded_server_signature; + char *decoded_server_signature; + int server_signature_len; + + state->server_final_message = strdup(input); + if (!state->server_final_message) + { + libpq_append_conn_error(conn, "out of memory"); + return false; + } + + /* Check for error result. */ + if (*input == 'e') + { + char *errmsg = read_attr_value(&input, 'e', + &conn->errorMessage); + + if (errmsg == NULL) + { + /* read_attr_value() has appended an error message */ + return false; + } + libpq_append_conn_error(conn, "error received from server in SCRAM exchange: %s", + errmsg); + return false; + } + + /* Parse the message. */ + encoded_server_signature = read_attr_value(&input, 'v', + &conn->errorMessage); + if (encoded_server_signature == NULL) + { + /* read_attr_value() has appended an error message */ + return false; + } + + if (*input != '\0') + libpq_append_conn_error(conn, "malformed SCRAM message (garbage at end of server-final-message)"); + + server_signature_len = pg_b64_dec_len(strlen(encoded_server_signature)); + decoded_server_signature = malloc(server_signature_len); + if (!decoded_server_signature) + { + libpq_append_conn_error(conn, "out of memory"); + return false; + } + + server_signature_len = pg_b64_decode(encoded_server_signature, + strlen(encoded_server_signature), + decoded_server_signature, + server_signature_len); + if (server_signature_len != state->key_length) + { + free(decoded_server_signature); + libpq_append_conn_error(conn, "malformed SCRAM message (invalid server signature)"); + return false; + } + memcpy(state->ServerSignature, decoded_server_signature, + state->key_length); + free(decoded_server_signature); + + return true; +} + +/* + * Calculate the client proof, part of the final exchange message sent + * by the client. Returns true on success, false on failure with *errstr + * pointing to a message about the error details. + */ +static bool +calculate_client_proof(fe_scram_state *state, + const char *client_final_message_without_proof, + uint8 *result, const char **errstr) +{ + uint8 StoredKey[SCRAM_MAX_KEY_LEN]; + uint8 ClientKey[SCRAM_MAX_KEY_LEN]; + uint8 ClientSignature[SCRAM_MAX_KEY_LEN]; + int i; + pg_hmac_ctx *ctx; + + ctx = pg_hmac_create(state->hash_type); + if (ctx == NULL) + { + *errstr = pg_hmac_error(NULL); /* returns OOM */ + return false; + } + + /* + * Calculate SaltedPassword, and store it in 'state' so that we can reuse + * it later in verify_server_signature. + */ + if (scram_SaltedPassword(state->password, state->hash_type, + state->key_length, state->salt, state->saltlen, + state->iterations, state->SaltedPassword, + errstr) < 0 || + scram_ClientKey(state->SaltedPassword, state->hash_type, + state->key_length, ClientKey, errstr) < 0 || + scram_H(ClientKey, state->hash_type, state->key_length, + StoredKey, errstr) < 0) + { + /* errstr is already filled here */ + pg_hmac_free(ctx); + return false; + } + + if (pg_hmac_init(ctx, StoredKey, state->key_length) < 0 || + pg_hmac_update(ctx, + (uint8 *) state->client_first_message_bare, + strlen(state->client_first_message_bare)) < 0 || + pg_hmac_update(ctx, (uint8 *) ",", 1) < 0 || + pg_hmac_update(ctx, + (uint8 *) state->server_first_message, + strlen(state->server_first_message)) < 0 || + pg_hmac_update(ctx, (uint8 *) ",", 1) < 0 || + pg_hmac_update(ctx, + (uint8 *) client_final_message_without_proof, + strlen(client_final_message_without_proof)) < 0 || + pg_hmac_final(ctx, ClientSignature, state->key_length) < 0) + { + *errstr = pg_hmac_error(ctx); + pg_hmac_free(ctx); + return false; + } + + for (i = 0; i < state->key_length; i++) + result[i] = ClientKey[i] ^ ClientSignature[i]; + + pg_hmac_free(ctx); + return true; +} + +/* + * Validate the server signature, received as part of the final exchange + * message received from the server. *match tracks if the server signature + * matched or not. Returns true if the server signature got verified, and + * false for a processing error with *errstr pointing to a message about the + * error details. + */ +static bool +verify_server_signature(fe_scram_state *state, bool *match, + const char **errstr) +{ + uint8 expected_ServerSignature[SCRAM_MAX_KEY_LEN]; + uint8 ServerKey[SCRAM_MAX_KEY_LEN]; + pg_hmac_ctx *ctx; + + ctx = pg_hmac_create(state->hash_type); + if (ctx == NULL) + { + *errstr = pg_hmac_error(NULL); /* returns OOM */ + return false; + } + + if (scram_ServerKey(state->SaltedPassword, state->hash_type, + state->key_length, ServerKey, errstr) < 0) + { + /* errstr is filled already */ + pg_hmac_free(ctx); + return false; + } + + /* calculate ServerSignature */ + if (pg_hmac_init(ctx, ServerKey, state->key_length) < 0 || + pg_hmac_update(ctx, + (uint8 *) state->client_first_message_bare, + strlen(state->client_first_message_bare)) < 0 || + pg_hmac_update(ctx, (uint8 *) ",", 1) < 0 || + pg_hmac_update(ctx, + (uint8 *) state->server_first_message, + strlen(state->server_first_message)) < 0 || + pg_hmac_update(ctx, (uint8 *) ",", 1) < 0 || + pg_hmac_update(ctx, + (uint8 *) state->client_final_message_without_proof, + strlen(state->client_final_message_without_proof)) < 0 || + pg_hmac_final(ctx, expected_ServerSignature, + state->key_length) < 0) + { + *errstr = pg_hmac_error(ctx); + pg_hmac_free(ctx); + return false; + } + + pg_hmac_free(ctx); + + /* signature processed, so now check after it */ + if (memcmp(expected_ServerSignature, state->ServerSignature, + state->key_length) != 0) + *match = false; + else + *match = true; + + return true; +} + +/* + * Build a new SCRAM secret. + * + * On error, returns NULL and sets *errstr to point to a message about the + * error details. + */ +char * +pg_fe_scram_build_secret(const char *password, int iterations, const char **errstr) +{ + char *prep_password; + pg_saslprep_rc rc; + char saltbuf[SCRAM_DEFAULT_SALT_LEN]; + char *result; + + /* + * Normalize the password with SASLprep. If that doesn't work, because + * the password isn't valid UTF-8 or contains prohibited characters, just + * proceed with the original password. (See comments at the top of + * auth-scram.c.) + */ + rc = pg_saslprep(password, &prep_password); + if (rc == SASLPREP_OOM) + { + *errstr = libpq_gettext("out of memory"); + return NULL; + } + if (rc == SASLPREP_SUCCESS) + password = (const char *) prep_password; + + /* Generate a random salt */ + if (!pg_strong_random(saltbuf, SCRAM_DEFAULT_SALT_LEN)) + { + *errstr = libpq_gettext("could not generate random salt"); + free(prep_password); + return NULL; + } + + result = scram_build_secret(PG_SHA256, SCRAM_SHA_256_KEY_LEN, saltbuf, + SCRAM_DEFAULT_SALT_LEN, + iterations, password, + errstr); + + free(prep_password); + + return result; +} diff --git a/src/interfaces/libpq/fe-auth.c b/src/interfaces/libpq/fe-auth.c new file mode 100644 index 0000000..12c6cd2 --- /dev/null +++ b/src/interfaces/libpq/fe-auth.c @@ -0,0 +1,1385 @@ +/*------------------------------------------------------------------------- + * + * fe-auth.c + * The front-end (client) authorization routines + * + * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/interfaces/libpq/fe-auth.c + * + *------------------------------------------------------------------------- + */ + +/* + * INTERFACE ROUTINES + * frontend (client) routines: + * pg_fe_sendauth send authentication information + * pg_fe_getauthname get user's name according to the client side + * of the authentication system + */ + +#include "postgres_fe.h" + +#ifdef WIN32 +#include "win32.h" +#else +#include <unistd.h> +#include <fcntl.h> +#include <limits.h> +#include <sys/param.h> /* for MAXHOSTNAMELEN on most */ +#include <sys/socket.h> +#ifdef HAVE_SYS_UCRED_H +#include <sys/ucred.h> +#endif +#ifndef MAXHOSTNAMELEN +#include <netdb.h> /* for MAXHOSTNAMELEN on some */ +#endif +#endif + +#include "common/md5.h" +#include "common/scram-common.h" +#include "fe-auth.h" +#include "fe-auth-sasl.h" +#include "libpq-fe.h" + +#ifdef ENABLE_GSS +/* + * GSSAPI authentication system. + */ + +#include "fe-gssapi-common.h" + +/* + * Continue GSS authentication with next token as needed. + */ +static int +pg_GSS_continue(PGconn *conn, int payloadlen) +{ + OM_uint32 maj_stat, + min_stat, + lmin_s, + gss_flags = GSS_C_MUTUAL_FLAG; + gss_buffer_desc ginbuf; + gss_buffer_desc goutbuf; + + /* + * On first call, there's no input token. On subsequent calls, read the + * input token into a GSS buffer. + */ + if (conn->gctx != GSS_C_NO_CONTEXT) + { + ginbuf.length = payloadlen; + ginbuf.value = malloc(payloadlen); + if (!ginbuf.value) + { + libpq_append_conn_error(conn, "out of memory allocating GSSAPI buffer (%d)", + payloadlen); + return STATUS_ERROR; + } + if (pqGetnchar(ginbuf.value, payloadlen, conn)) + { + /* + * Shouldn't happen, because the caller should've ensured that the + * whole message is already in the input buffer. + */ + free(ginbuf.value); + return STATUS_ERROR; + } + } + else + { + ginbuf.length = 0; + ginbuf.value = NULL; + } + + /* Only try to acquire credentials if GSS delegation isn't disabled. */ + if (!pg_GSS_have_cred_cache(&conn->gcred)) + conn->gcred = GSS_C_NO_CREDENTIAL; + + if (conn->gssdelegation && conn->gssdelegation[0] == '1') + gss_flags |= GSS_C_DELEG_FLAG; + + maj_stat = gss_init_sec_context(&min_stat, + conn->gcred, + &conn->gctx, + conn->gtarg_nam, + GSS_C_NO_OID, + gss_flags, + 0, + GSS_C_NO_CHANNEL_BINDINGS, + (ginbuf.value == NULL) ? GSS_C_NO_BUFFER : &ginbuf, + NULL, + &goutbuf, + NULL, + NULL); + + free(ginbuf.value); + + if (goutbuf.length != 0) + { + /* + * GSS generated data to send to the server. We don't care if it's the + * first or subsequent packet, just send the same kind of password + * packet. + */ + if (pqPacketSend(conn, 'p', + goutbuf.value, goutbuf.length) != STATUS_OK) + { + gss_release_buffer(&lmin_s, &goutbuf); + return STATUS_ERROR; + } + } + gss_release_buffer(&lmin_s, &goutbuf); + + if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED) + { + pg_GSS_error(libpq_gettext("GSSAPI continuation error"), + conn, + maj_stat, min_stat); + gss_release_name(&lmin_s, &conn->gtarg_nam); + if (conn->gctx) + gss_delete_sec_context(&lmin_s, &conn->gctx, GSS_C_NO_BUFFER); + return STATUS_ERROR; + } + + if (maj_stat == GSS_S_COMPLETE) + { + conn->client_finished_auth = true; + gss_release_name(&lmin_s, &conn->gtarg_nam); + conn->gssapi_used = true; + } + + return STATUS_OK; +} + +/* + * Send initial GSS authentication token + */ +static int +pg_GSS_startup(PGconn *conn, int payloadlen) +{ + int ret; + char *host = conn->connhost[conn->whichhost].host; + + if (!(host && host[0] != '\0')) + { + libpq_append_conn_error(conn, "host name must be specified"); + return STATUS_ERROR; + } + + if (conn->gctx) + { + libpq_append_conn_error(conn, "duplicate GSS authentication request"); + return STATUS_ERROR; + } + + ret = pg_GSS_load_servicename(conn); + if (ret != STATUS_OK) + return ret; + + /* + * Initial packet is the same as a continuation packet with no initial + * context. + */ + conn->gctx = GSS_C_NO_CONTEXT; + + return pg_GSS_continue(conn, payloadlen); +} +#endif /* ENABLE_GSS */ + + +#ifdef ENABLE_SSPI +/* + * SSPI authentication system (Windows only) + */ + +static void +pg_SSPI_error(PGconn *conn, const char *mprefix, SECURITY_STATUS r) +{ + char sysmsg[256]; + + if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, r, 0, + sysmsg, sizeof(sysmsg), NULL) == 0) + appendPQExpBuffer(&conn->errorMessage, "%s: SSPI error %x\n", + mprefix, (unsigned int) r); + else + appendPQExpBuffer(&conn->errorMessage, "%s: %s (%x)\n", + mprefix, sysmsg, (unsigned int) r); +} + +/* + * Continue SSPI authentication with next token as needed. + */ +static int +pg_SSPI_continue(PGconn *conn, int payloadlen) +{ + SECURITY_STATUS r; + CtxtHandle newContext; + ULONG contextAttr; + SecBufferDesc inbuf; + SecBufferDesc outbuf; + SecBuffer OutBuffers[1]; + SecBuffer InBuffers[1]; + char *inputbuf = NULL; + + if (conn->sspictx != NULL) + { + /* + * On runs other than the first we have some data to send. Put this + * data in a SecBuffer type structure. + */ + inputbuf = malloc(payloadlen); + if (!inputbuf) + { + libpq_append_conn_error(conn, "out of memory allocating SSPI buffer (%d)", + payloadlen); + return STATUS_ERROR; + } + if (pqGetnchar(inputbuf, payloadlen, conn)) + { + /* + * Shouldn't happen, because the caller should've ensured that the + * whole message is already in the input buffer. + */ + free(inputbuf); + return STATUS_ERROR; + } + + inbuf.ulVersion = SECBUFFER_VERSION; + inbuf.cBuffers = 1; + inbuf.pBuffers = InBuffers; + InBuffers[0].pvBuffer = inputbuf; + InBuffers[0].cbBuffer = payloadlen; + InBuffers[0].BufferType = SECBUFFER_TOKEN; + } + + OutBuffers[0].pvBuffer = NULL; + OutBuffers[0].BufferType = SECBUFFER_TOKEN; + OutBuffers[0].cbBuffer = 0; + outbuf.cBuffers = 1; + outbuf.pBuffers = OutBuffers; + outbuf.ulVersion = SECBUFFER_VERSION; + + r = InitializeSecurityContext(conn->sspicred, + conn->sspictx, + conn->sspitarget, + ISC_REQ_ALLOCATE_MEMORY, + 0, + SECURITY_NETWORK_DREP, + (conn->sspictx == NULL) ? NULL : &inbuf, + 0, + &newContext, + &outbuf, + &contextAttr, + NULL); + + /* we don't need the input anymore */ + free(inputbuf); + + if (r != SEC_E_OK && r != SEC_I_CONTINUE_NEEDED) + { + pg_SSPI_error(conn, libpq_gettext("SSPI continuation error"), r); + + return STATUS_ERROR; + } + + if (conn->sspictx == NULL) + { + /* On first run, transfer retrieved context handle */ + conn->sspictx = malloc(sizeof(CtxtHandle)); + if (conn->sspictx == NULL) + { + libpq_append_conn_error(conn, "out of memory"); + return STATUS_ERROR; + } + memcpy(conn->sspictx, &newContext, sizeof(CtxtHandle)); + } + + /* + * If SSPI returned any data to be sent to the server (as it normally + * would), send this data as a password packet. + */ + if (outbuf.cBuffers > 0) + { + if (outbuf.cBuffers != 1) + { + /* + * This should never happen, at least not for Kerberos + * authentication. Keep check in case it shows up with other + * authentication methods later. + */ + appendPQExpBufferStr(&conn->errorMessage, + "SSPI returned invalid number of output buffers\n"); + return STATUS_ERROR; + } + + /* + * If the negotiation is complete, there may be zero bytes to send. + * The server is at this point not expecting any more data, so don't + * send it. + */ + if (outbuf.pBuffers[0].cbBuffer > 0) + { + if (pqPacketSend(conn, 'p', + outbuf.pBuffers[0].pvBuffer, outbuf.pBuffers[0].cbBuffer)) + { + FreeContextBuffer(outbuf.pBuffers[0].pvBuffer); + return STATUS_ERROR; + } + } + FreeContextBuffer(outbuf.pBuffers[0].pvBuffer); + } + + if (r == SEC_E_OK) + conn->client_finished_auth = true; + + /* Cleanup is handled by the code in freePGconn() */ + return STATUS_OK; +} + +/* + * Send initial SSPI authentication token. + * If use_negotiate is 0, use kerberos authentication package which is + * compatible with Unix. If use_negotiate is 1, use the negotiate package + * which supports both kerberos and NTLM, but is not compatible with Unix. + */ +static int +pg_SSPI_startup(PGconn *conn, int use_negotiate, int payloadlen) +{ + SECURITY_STATUS r; + TimeStamp expire; + char *host = conn->connhost[conn->whichhost].host; + + if (conn->sspictx) + { + libpq_append_conn_error(conn, "duplicate SSPI authentication request"); + return STATUS_ERROR; + } + + /* + * Retrieve credentials handle + */ + conn->sspicred = malloc(sizeof(CredHandle)); + if (conn->sspicred == NULL) + { + libpq_append_conn_error(conn, "out of memory"); + return STATUS_ERROR; + } + + r = AcquireCredentialsHandle(NULL, + use_negotiate ? "negotiate" : "kerberos", + SECPKG_CRED_OUTBOUND, + NULL, + NULL, + NULL, + NULL, + conn->sspicred, + &expire); + if (r != SEC_E_OK) + { + pg_SSPI_error(conn, libpq_gettext("could not acquire SSPI credentials"), r); + free(conn->sspicred); + conn->sspicred = NULL; + return STATUS_ERROR; + } + + /* + * Compute target principal name. SSPI has a different format from GSSAPI, + * but not more complex. We can skip the @REALM part, because Windows will + * fill that in for us automatically. + */ + if (!(host && host[0] != '\0')) + { + libpq_append_conn_error(conn, "host name must be specified"); + return STATUS_ERROR; + } + conn->sspitarget = malloc(strlen(conn->krbsrvname) + strlen(host) + 2); + if (!conn->sspitarget) + { + libpq_append_conn_error(conn, "out of memory"); + return STATUS_ERROR; + } + sprintf(conn->sspitarget, "%s/%s", conn->krbsrvname, host); + + /* + * Indicate that we're in SSPI authentication mode to make sure that + * pg_SSPI_continue is called next time in the negotiation. + */ + conn->usesspi = 1; + + return pg_SSPI_continue(conn, payloadlen); +} +#endif /* ENABLE_SSPI */ + +/* + * Initialize SASL authentication exchange. + */ +static int +pg_SASL_init(PGconn *conn, int payloadlen) +{ + char *initialresponse = NULL; + int initialresponselen; + bool done; + bool success; + const char *selected_mechanism; + PQExpBufferData mechanism_buf; + char *password; + + initPQExpBuffer(&mechanism_buf); + + if (conn->channel_binding[0] == 'r' && /* require */ + !conn->ssl_in_use) + { + libpq_append_conn_error(conn, "channel binding required, but SSL not in use"); + goto error; + } + + if (conn->sasl_state) + { + libpq_append_conn_error(conn, "duplicate SASL authentication request"); + goto error; + } + + /* + * Parse the list of SASL authentication mechanisms in the + * AuthenticationSASL message, and select the best mechanism that we + * support. SCRAM-SHA-256-PLUS and SCRAM-SHA-256 are the only ones + * supported at the moment, listed by order of decreasing importance. + */ + selected_mechanism = NULL; + for (;;) + { + if (pqGets(&mechanism_buf, conn)) + { + appendPQExpBufferStr(&conn->errorMessage, + "fe_sendauth: invalid authentication request from server: invalid list of authentication mechanisms\n"); + goto error; + } + if (PQExpBufferDataBroken(mechanism_buf)) + goto oom_error; + + /* An empty string indicates end of list */ + if (mechanism_buf.data[0] == '\0') + break; + + /* + * Select the mechanism to use. Pick SCRAM-SHA-256-PLUS over anything + * else if a channel binding type is set and if the client supports it + * (and did not set channel_binding=disable). Pick SCRAM-SHA-256 if + * nothing else has already been picked. If we add more mechanisms, a + * more refined priority mechanism might become necessary. + */ + if (strcmp(mechanism_buf.data, SCRAM_SHA_256_PLUS_NAME) == 0) + { + if (conn->ssl_in_use) + { + /* The server has offered SCRAM-SHA-256-PLUS. */ + +#ifdef HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH + /* + * The client supports channel binding, which is chosen if + * channel_binding is not disabled. + */ + if (conn->channel_binding[0] != 'd') /* disable */ + { + selected_mechanism = SCRAM_SHA_256_PLUS_NAME; + conn->sasl = &pg_scram_mech; + } +#else + /* + * The client does not support channel binding. If it is + * required, complain immediately instead of the error below + * which would be confusing as the server is publishing + * SCRAM-SHA-256-PLUS. + */ + if (conn->channel_binding[0] == 'r') /* require */ + { + libpq_append_conn_error(conn, "channel binding is required, but client does not support it"); + goto error; + } +#endif + } + else + { + /* + * The server offered SCRAM-SHA-256-PLUS, but the connection + * is not SSL-encrypted. That's not sane. Perhaps SSL was + * stripped by a proxy? There's no point in continuing, + * because the server will reject the connection anyway if we + * try authenticate without channel binding even though both + * the client and server supported it. The SCRAM exchange + * checks for that, to prevent downgrade attacks. + */ + libpq_append_conn_error(conn, "server offered SCRAM-SHA-256-PLUS authentication over a non-SSL connection"); + goto error; + } + } + else if (strcmp(mechanism_buf.data, SCRAM_SHA_256_NAME) == 0 && + !selected_mechanism) + { + selected_mechanism = SCRAM_SHA_256_NAME; + conn->sasl = &pg_scram_mech; + } + } + + if (!selected_mechanism) + { + libpq_append_conn_error(conn, "none of the server's SASL authentication mechanisms are supported"); + goto error; + } + + if (conn->channel_binding[0] == 'r' && /* require */ + strcmp(selected_mechanism, SCRAM_SHA_256_PLUS_NAME) != 0) + { + libpq_append_conn_error(conn, "channel binding is required, but server did not offer an authentication method that supports channel binding"); + goto error; + } + + /* + * Now that the SASL mechanism has been chosen for the exchange, + * initialize its state information. + */ + + /* + * First, select the password to use for the exchange, complaining if + * there isn't one. Currently, all supported SASL mechanisms require a + * password, so we can just go ahead here without further distinction. + */ + conn->password_needed = true; + password = conn->connhost[conn->whichhost].password; + if (password == NULL) + password = conn->pgpass; + if (password == NULL || password[0] == '\0') + { + appendPQExpBufferStr(&conn->errorMessage, + PQnoPasswordSupplied); + goto error; + } + + Assert(conn->sasl); + + /* + * Initialize the SASL state information with all the information gathered + * during the initial exchange. + * + * Note: Only tls-unique is supported for the moment. + */ + conn->sasl_state = conn->sasl->init(conn, + password, + selected_mechanism); + if (!conn->sasl_state) + goto oom_error; + + /* Get the mechanism-specific Initial Client Response, if any */ + conn->sasl->exchange(conn->sasl_state, + NULL, -1, + &initialresponse, &initialresponselen, + &done, &success); + + if (done && !success) + goto error; + + /* + * Build a SASLInitialResponse message, and send it. + */ + if (pqPutMsgStart('p', conn)) + goto error; + if (pqPuts(selected_mechanism, conn)) + goto error; + if (initialresponse) + { + if (pqPutInt(initialresponselen, 4, conn)) + goto error; + if (pqPutnchar(initialresponse, initialresponselen, conn)) + goto error; + } + if (pqPutMsgEnd(conn)) + goto error; + if (pqFlush(conn)) + goto error; + + termPQExpBuffer(&mechanism_buf); + free(initialresponse); + + return STATUS_OK; + +error: + termPQExpBuffer(&mechanism_buf); + free(initialresponse); + return STATUS_ERROR; + +oom_error: + termPQExpBuffer(&mechanism_buf); + free(initialresponse); + libpq_append_conn_error(conn, "out of memory"); + return STATUS_ERROR; +} + +/* + * Exchange a message for SASL communication protocol with the backend. + * This should be used after calling pg_SASL_init to set up the status of + * the protocol. + */ +static int +pg_SASL_continue(PGconn *conn, int payloadlen, bool final) +{ + char *output; + int outputlen; + bool done; + bool success; + int res; + char *challenge; + + /* Read the SASL challenge from the AuthenticationSASLContinue message. */ + challenge = malloc(payloadlen + 1); + if (!challenge) + { + libpq_append_conn_error(conn, "out of memory allocating SASL buffer (%d)", + payloadlen); + return STATUS_ERROR; + } + + if (pqGetnchar(challenge, payloadlen, conn)) + { + free(challenge); + return STATUS_ERROR; + } + /* For safety and convenience, ensure the buffer is NULL-terminated. */ + challenge[payloadlen] = '\0'; + + conn->sasl->exchange(conn->sasl_state, + challenge, payloadlen, + &output, &outputlen, + &done, &success); + free(challenge); /* don't need the input anymore */ + + if (final && !done) + { + if (outputlen != 0) + free(output); + + libpq_append_conn_error(conn, "AuthenticationSASLFinal received from server, but SASL authentication was not completed"); + return STATUS_ERROR; + } + + /* + * If the exchange is not completed yet, we need to make sure that the + * SASL mechanism has generated a message to send back. + */ + if (output == NULL && !done) + { + libpq_append_conn_error(conn, "no client response found after SASL exchange success"); + return STATUS_ERROR; + } + + /* + * SASL allows zero-length responses, so this check uses "output" and not + * "outputlen" to allow the case of an empty message. + */ + if (output) + { + /* + * Send the SASL response to the server. + */ + res = pqPacketSend(conn, 'p', output, outputlen); + free(output); + + if (res != STATUS_OK) + return STATUS_ERROR; + } + + if (done && !success) + return STATUS_ERROR; + + return STATUS_OK; +} + +static int +pg_password_sendauth(PGconn *conn, const char *password, AuthRequest areq) +{ + int ret; + char *crypt_pwd = NULL; + const char *pwd_to_send; + char md5Salt[4]; + + /* Read the salt from the AuthenticationMD5Password message. */ + if (areq == AUTH_REQ_MD5) + { + if (pqGetnchar(md5Salt, 4, conn)) + return STATUS_ERROR; /* shouldn't happen */ + } + + /* Encrypt the password if needed. */ + + switch (areq) + { + case AUTH_REQ_MD5: + { + char *crypt_pwd2; + const char *errstr = NULL; + + /* Allocate enough space for two MD5 hashes */ + crypt_pwd = malloc(2 * (MD5_PASSWD_LEN + 1)); + if (!crypt_pwd) + { + libpq_append_conn_error(conn, "out of memory"); + return STATUS_ERROR; + } + + crypt_pwd2 = crypt_pwd + MD5_PASSWD_LEN + 1; + if (!pg_md5_encrypt(password, conn->pguser, + strlen(conn->pguser), crypt_pwd2, + &errstr)) + { + libpq_append_conn_error(conn, "could not encrypt password: %s", errstr); + free(crypt_pwd); + return STATUS_ERROR; + } + if (!pg_md5_encrypt(crypt_pwd2 + strlen("md5"), md5Salt, + 4, crypt_pwd, &errstr)) + { + libpq_append_conn_error(conn, "could not encrypt password: %s", errstr); + free(crypt_pwd); + return STATUS_ERROR; + } + + pwd_to_send = crypt_pwd; + break; + } + case AUTH_REQ_PASSWORD: + pwd_to_send = password; + break; + default: + return STATUS_ERROR; + } + ret = pqPacketSend(conn, 'p', pwd_to_send, strlen(pwd_to_send) + 1); + free(crypt_pwd); + return ret; +} + +/* + * Translate a disallowed AuthRequest code into an error message. + */ +static const char * +auth_method_description(AuthRequest areq) +{ + switch (areq) + { + case AUTH_REQ_PASSWORD: + return libpq_gettext("server requested a cleartext password"); + case AUTH_REQ_MD5: + return libpq_gettext("server requested a hashed password"); + case AUTH_REQ_GSS: + case AUTH_REQ_GSS_CONT: + return libpq_gettext("server requested GSSAPI authentication"); + case AUTH_REQ_SSPI: + return libpq_gettext("server requested SSPI authentication"); + case AUTH_REQ_SASL: + case AUTH_REQ_SASL_CONT: + case AUTH_REQ_SASL_FIN: + return libpq_gettext("server requested SASL authentication"); + } + + return libpq_gettext("server requested an unknown authentication type"); +} + +/* + * Convenience macro for checking the allowed_auth_methods bitmask. Caller + * must ensure that type is not greater than 31 (high bit of the bitmask). + */ +#define auth_method_allowed(conn, type) \ + (((conn)->allowed_auth_methods & (1 << (type))) != 0) + +/* + * Verify that the authentication request is expected, given the connection + * parameters. This is especially important when the client wishes to + * authenticate the server before any sensitive information is exchanged. + */ +static bool +check_expected_areq(AuthRequest areq, PGconn *conn) +{ + bool result = true; + const char *reason = NULL; + + StaticAssertDecl((sizeof(conn->allowed_auth_methods) * CHAR_BIT) > AUTH_REQ_MAX, + "AUTH_REQ_MAX overflows the allowed_auth_methods bitmask"); + + if (conn->sslcertmode[0] == 'r' /* require */ + && areq == AUTH_REQ_OK) + { + /* + * Trade off a little bit of complexity to try to get these error + * messages as precise as possible. + */ + if (!conn->ssl_cert_requested) + { + libpq_append_conn_error(conn, "server did not request an SSL certificate"); + return false; + } + else if (!conn->ssl_cert_sent) + { + libpq_append_conn_error(conn, "server accepted connection without a valid SSL certificate"); + return false; + } + } + + /* + * If the user required a specific auth method, or specified an allowed + * set, then reject all others here, and make sure the server actually + * completes an authentication exchange. + */ + if (conn->require_auth) + { + switch (areq) + { + case AUTH_REQ_OK: + + /* + * Check to make sure we've actually finished our exchange (or + * else that the user has allowed an authentication-less + * connection). + * + * If the user has allowed both SCRAM and unauthenticated + * (trust) connections, then this check will silently accept + * partial SCRAM exchanges, where a misbehaving server does + * not provide its verifier before sending an OK. This is + * consistent with historical behavior, but it may be a point + * to revisit in the future, since it could allow a server + * that doesn't know the user's password to silently harvest + * material for a brute force attack. + */ + if (!conn->auth_required || conn->client_finished_auth) + break; + + /* + * No explicit authentication request was made by the server + * -- or perhaps it was made and not completed, in the case of + * SCRAM -- but there is one special case to check. If the + * user allowed "gss", then a GSS-encrypted channel also + * satisfies the check. + */ +#ifdef ENABLE_GSS + if (auth_method_allowed(conn, AUTH_REQ_GSS) && conn->gssenc) + { + /* + * If implicit GSS auth has already been performed via GSS + * encryption, we don't need to have performed an + * AUTH_REQ_GSS exchange. This allows require_auth=gss to + * be combined with gssencmode, since there won't be an + * explicit authentication request in that case. + */ + } + else +#endif + { + reason = libpq_gettext("server did not complete authentication"); + result = false; + } + + break; + + case AUTH_REQ_PASSWORD: + case AUTH_REQ_MD5: + case AUTH_REQ_GSS: + case AUTH_REQ_GSS_CONT: + case AUTH_REQ_SSPI: + case AUTH_REQ_SASL: + case AUTH_REQ_SASL_CONT: + case AUTH_REQ_SASL_FIN: + + /* + * We don't handle these with the default case, to avoid + * bit-shifting past the end of the allowed_auth_methods mask + * if the server sends an unexpected AuthRequest. + */ + result = auth_method_allowed(conn, areq); + break; + + default: + result = false; + break; + } + } + + if (!result) + { + if (!reason) + reason = auth_method_description(areq); + + libpq_append_conn_error(conn, "authentication method requirement \"%s\" failed: %s", + conn->require_auth, reason); + return result; + } + + /* + * When channel_binding=require, we must protect against two cases: (1) we + * must not respond to non-SASL authentication requests, which might leak + * information such as the client's password; and (2) even if we receive + * AUTH_REQ_OK, we still must ensure that channel binding has happened in + * order to authenticate the server. + */ + if (conn->channel_binding[0] == 'r' /* require */ ) + { + switch (areq) + { + case AUTH_REQ_SASL: + case AUTH_REQ_SASL_CONT: + case AUTH_REQ_SASL_FIN: + break; + case AUTH_REQ_OK: + if (!conn->sasl || !conn->sasl->channel_bound(conn->sasl_state)) + { + libpq_append_conn_error(conn, "channel binding required, but server authenticated client without channel binding"); + result = false; + } + break; + default: + libpq_append_conn_error(conn, "channel binding required but not supported by server's authentication request"); + result = false; + break; + } + } + + return result; +} + +/* + * pg_fe_sendauth + * client demux routine for processing an authentication request + * + * The server has sent us an authentication challenge (or OK). Send an + * appropriate response. The caller has ensured that the whole message is + * now in the input buffer, and has already read the type and length of + * it. We are responsible for reading any remaining extra data, specific + * to the authentication method. 'payloadlen' is the remaining length in + * the message. + */ +int +pg_fe_sendauth(AuthRequest areq, int payloadlen, PGconn *conn) +{ + int oldmsglen; + + if (!check_expected_areq(areq, conn)) + return STATUS_ERROR; + + switch (areq) + { + case AUTH_REQ_OK: + break; + + case AUTH_REQ_KRB4: + libpq_append_conn_error(conn, "Kerberos 4 authentication not supported"); + return STATUS_ERROR; + + case AUTH_REQ_KRB5: + libpq_append_conn_error(conn, "Kerberos 5 authentication not supported"); + return STATUS_ERROR; + +#if defined(ENABLE_GSS) || defined(ENABLE_SSPI) + case AUTH_REQ_GSS: +#if !defined(ENABLE_SSPI) + /* no native SSPI, so use GSSAPI library for it */ + case AUTH_REQ_SSPI: +#endif + { + int r; + + pglock_thread(); + + /* + * If we have both GSS and SSPI support compiled in, use SSPI + * support by default. This is overridable by a connection + * string parameter. Note that when using SSPI we still leave + * the negotiate parameter off, since we want SSPI to use the + * GSSAPI kerberos protocol. For actual SSPI negotiate + * protocol, we use AUTH_REQ_SSPI. + */ +#if defined(ENABLE_GSS) && defined(ENABLE_SSPI) + if (conn->gsslib && (pg_strcasecmp(conn->gsslib, "gssapi") == 0)) + r = pg_GSS_startup(conn, payloadlen); + else + r = pg_SSPI_startup(conn, 0, payloadlen); +#elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI) + r = pg_GSS_startup(conn, payloadlen); +#elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI) + r = pg_SSPI_startup(conn, 0, payloadlen); +#endif + if (r != STATUS_OK) + { + /* Error message already filled in. */ + pgunlock_thread(); + return STATUS_ERROR; + } + pgunlock_thread(); + } + break; + + case AUTH_REQ_GSS_CONT: + { + int r; + + pglock_thread(); +#if defined(ENABLE_GSS) && defined(ENABLE_SSPI) + if (conn->usesspi) + r = pg_SSPI_continue(conn, payloadlen); + else + r = pg_GSS_continue(conn, payloadlen); +#elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI) + r = pg_GSS_continue(conn, payloadlen); +#elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI) + r = pg_SSPI_continue(conn, payloadlen); +#endif + if (r != STATUS_OK) + { + /* Error message already filled in. */ + pgunlock_thread(); + return STATUS_ERROR; + } + pgunlock_thread(); + } + break; +#else /* defined(ENABLE_GSS) || defined(ENABLE_SSPI) */ + /* No GSSAPI *or* SSPI support */ + case AUTH_REQ_GSS: + case AUTH_REQ_GSS_CONT: + libpq_append_conn_error(conn, "GSSAPI authentication not supported"); + return STATUS_ERROR; +#endif /* defined(ENABLE_GSS) || defined(ENABLE_SSPI) */ + +#ifdef ENABLE_SSPI + case AUTH_REQ_SSPI: + + /* + * SSPI has its own startup message so libpq can decide which + * method to use. Indicate to pg_SSPI_startup that we want SSPI + * negotiation instead of Kerberos. + */ + pglock_thread(); + if (pg_SSPI_startup(conn, 1, payloadlen) != STATUS_OK) + { + /* Error message already filled in. */ + pgunlock_thread(); + return STATUS_ERROR; + } + pgunlock_thread(); + break; +#else + + /* + * No SSPI support. However, if we have GSSAPI but not SSPI + * support, AUTH_REQ_SSPI will have been handled in the codepath + * for AUTH_REQ_GSS above, so don't duplicate the case label in + * that case. + */ +#if !defined(ENABLE_GSS) + case AUTH_REQ_SSPI: + libpq_append_conn_error(conn, "SSPI authentication not supported"); + return STATUS_ERROR; +#endif /* !define(ENABLE_GSS) */ +#endif /* ENABLE_SSPI */ + + + case AUTH_REQ_CRYPT: + libpq_append_conn_error(conn, "Crypt authentication not supported"); + return STATUS_ERROR; + + case AUTH_REQ_MD5: + case AUTH_REQ_PASSWORD: + { + char *password; + + conn->password_needed = true; + password = conn->connhost[conn->whichhost].password; + if (password == NULL) + password = conn->pgpass; + if (password == NULL || password[0] == '\0') + { + appendPQExpBufferStr(&conn->errorMessage, + PQnoPasswordSupplied); + return STATUS_ERROR; + } + if (pg_password_sendauth(conn, password, areq) != STATUS_OK) + { + appendPQExpBufferStr(&conn->errorMessage, + "fe_sendauth: error sending password authentication\n"); + return STATUS_ERROR; + } + + /* We expect no further authentication requests. */ + conn->client_finished_auth = true; + break; + } + + case AUTH_REQ_SASL: + + /* + * The request contains the name (as assigned by IANA) of the + * authentication mechanism. + */ + if (pg_SASL_init(conn, payloadlen) != STATUS_OK) + { + /* pg_SASL_init already set the error message */ + return STATUS_ERROR; + } + break; + + case AUTH_REQ_SASL_CONT: + case AUTH_REQ_SASL_FIN: + if (conn->sasl_state == NULL) + { + appendPQExpBufferStr(&conn->errorMessage, + "fe_sendauth: invalid authentication request from server: AUTH_REQ_SASL_CONT without AUTH_REQ_SASL\n"); + return STATUS_ERROR; + } + oldmsglen = conn->errorMessage.len; + if (pg_SASL_continue(conn, payloadlen, + (areq == AUTH_REQ_SASL_FIN)) != STATUS_OK) + { + /* Use this message if pg_SASL_continue didn't supply one */ + if (conn->errorMessage.len == oldmsglen) + appendPQExpBufferStr(&conn->errorMessage, + "fe_sendauth: error in SASL authentication\n"); + return STATUS_ERROR; + } + break; + + default: + libpq_append_conn_error(conn, "authentication method %u not supported", areq); + return STATUS_ERROR; + } + + return STATUS_OK; +} + + +/* + * pg_fe_getusername + * + * Returns a pointer to malloc'd space containing the name of the + * specified user_id. If there is an error, return NULL, and append + * a suitable error message to *errorMessage if that's not NULL. + * + * Caution: on Windows, the user_id argument is ignored, and we always + * fetch the current user's name. + */ +char * +pg_fe_getusername(uid_t user_id, PQExpBuffer errorMessage) +{ + char *result = NULL; + const char *name = NULL; + +#ifdef WIN32 + /* Microsoft recommends buffer size of UNLEN+1, where UNLEN = 256 */ + char username[256 + 1]; + DWORD namesize = sizeof(username); +#else + char pwdbuf[BUFSIZ]; +#endif + + /* + * Some users are using configure --enable-thread-safety-force, so we + * might as well do the locking within our library to protect getpwuid(). + * In fact, application developers can use getpwuid() in their application + * if they use the locking call we provide, or install their own locking + * function using PQregisterThreadLock(). + */ + pglock_thread(); + +#ifdef WIN32 + if (GetUserName(username, &namesize)) + name = username; + else if (errorMessage) + libpq_append_error(errorMessage, + "user name lookup failure: error code %lu", + GetLastError()); +#else + if (pg_get_user_name(user_id, pwdbuf, sizeof(pwdbuf))) + name = pwdbuf; + else if (errorMessage) + appendPQExpBuffer(errorMessage, "%s\n", pwdbuf); +#endif + + if (name) + { + result = strdup(name); + if (result == NULL && errorMessage) + libpq_append_error(errorMessage, "out of memory"); + } + + pgunlock_thread(); + + return result; +} + +/* + * pg_fe_getauthname + * + * Returns a pointer to malloc'd space containing whatever name the user + * has authenticated to the system. If there is an error, return NULL, + * and append a suitable error message to *errorMessage if that's not NULL. + */ +char * +pg_fe_getauthname(PQExpBuffer errorMessage) +{ +#ifdef WIN32 + return pg_fe_getusername(0, errorMessage); +#else + return pg_fe_getusername(geteuid(), errorMessage); +#endif +} + + +/* + * PQencryptPassword -- exported routine to encrypt a password with MD5 + * + * This function is equivalent to calling PQencryptPasswordConn with + * "md5" as the encryption method, except that this doesn't require + * a connection object. This function is deprecated, use + * PQencryptPasswordConn instead. + */ +char * +PQencryptPassword(const char *passwd, const char *user) +{ + char *crypt_pwd; + const char *errstr = NULL; + + crypt_pwd = malloc(MD5_PASSWD_LEN + 1); + if (!crypt_pwd) + return NULL; + + if (!pg_md5_encrypt(passwd, user, strlen(user), crypt_pwd, &errstr)) + { + free(crypt_pwd); + return NULL; + } + + return crypt_pwd; +} + +/* + * PQencryptPasswordConn -- exported routine to encrypt a password + * + * This is intended to be used by client applications that wish to send + * commands like ALTER USER joe PASSWORD 'pwd'. The password need not + * be sent in cleartext if it is encrypted on the client side. This is + * good because it ensures the cleartext password won't end up in logs, + * pg_stat displays, etc. We export the function so that clients won't + * be dependent on low-level details like whether the encryption is MD5 + * or something else. + * + * Arguments are a connection object, the cleartext password, the SQL + * name of the user it is for, and a string indicating the algorithm to + * use for encrypting the password. If algorithm is NULL, this queries + * the server for the current 'password_encryption' value. If you wish + * to avoid that, e.g. to avoid blocking, you can execute + * 'show password_encryption' yourself before calling this function, and + * pass it as the algorithm. + * + * Return value is a malloc'd string. The client may assume the string + * doesn't contain any special characters that would require escaping. + * On error, an error message is stored in the connection object, and + * returns NULL. + */ +char * +PQencryptPasswordConn(PGconn *conn, const char *passwd, const char *user, + const char *algorithm) +{ +#define MAX_ALGORITHM_NAME_LEN 50 + char algobuf[MAX_ALGORITHM_NAME_LEN + 1]; + char *crypt_pwd = NULL; + + if (!conn) + return NULL; + + pqClearConnErrorState(conn); + + /* If no algorithm was given, ask the server. */ + if (algorithm == NULL) + { + PGresult *res; + char *val; + + res = PQexec(conn, "show password_encryption"); + if (res == NULL) + { + /* PQexec() should've set conn->errorMessage already */ + return NULL; + } + if (PQresultStatus(res) != PGRES_TUPLES_OK) + { + /* PQexec() should've set conn->errorMessage already */ + PQclear(res); + return NULL; + } + if (PQntuples(res) != 1 || PQnfields(res) != 1) + { + PQclear(res); + libpq_append_conn_error(conn, "unexpected shape of result set returned for SHOW"); + return NULL; + } + val = PQgetvalue(res, 0, 0); + + if (strlen(val) > MAX_ALGORITHM_NAME_LEN) + { + PQclear(res); + libpq_append_conn_error(conn, "password_encryption value too long"); + return NULL; + } + strcpy(algobuf, val); + PQclear(res); + + algorithm = algobuf; + } + + /* + * Also accept "on" and "off" as aliases for "md5", because + * password_encryption was a boolean before PostgreSQL 10. We refuse to + * send the password in plaintext even if it was "off". + */ + if (strcmp(algorithm, "on") == 0 || + strcmp(algorithm, "off") == 0) + algorithm = "md5"; + + /* + * Ok, now we know what algorithm to use + */ + if (strcmp(algorithm, "scram-sha-256") == 0) + { + const char *errstr = NULL; + + crypt_pwd = pg_fe_scram_build_secret(passwd, + conn->scram_sha_256_iterations, + &errstr); + if (!crypt_pwd) + libpq_append_conn_error(conn, "could not encrypt password: %s", errstr); + } + else if (strcmp(algorithm, "md5") == 0) + { + crypt_pwd = malloc(MD5_PASSWD_LEN + 1); + if (crypt_pwd) + { + const char *errstr = NULL; + + if (!pg_md5_encrypt(passwd, user, strlen(user), crypt_pwd, &errstr)) + { + libpq_append_conn_error(conn, "could not encrypt password: %s", errstr); + free(crypt_pwd); + crypt_pwd = NULL; + } + } + else + libpq_append_conn_error(conn, "out of memory"); + } + else + { + libpq_append_conn_error(conn, "unrecognized password encryption algorithm \"%s\"", + algorithm); + return NULL; + } + + return crypt_pwd; +} diff --git a/src/interfaces/libpq/fe-auth.h b/src/interfaces/libpq/fe-auth.h new file mode 100644 index 0000000..124dd5d --- /dev/null +++ b/src/interfaces/libpq/fe-auth.h @@ -0,0 +1,32 @@ +/*------------------------------------------------------------------------- + * + * fe-auth.h + * + * Definitions for network authentication routines + * + * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/interfaces/libpq/fe-auth.h + * + *------------------------------------------------------------------------- + */ +#ifndef FE_AUTH_H +#define FE_AUTH_H + +#include "libpq-fe.h" +#include "libpq-int.h" + + +/* Prototypes for functions in fe-auth.c */ +extern int pg_fe_sendauth(AuthRequest areq, int payloadlen, PGconn *conn); +extern char *pg_fe_getusername(uid_t user_id, PQExpBuffer errorMessage); +extern char *pg_fe_getauthname(PQExpBuffer errorMessage); + +/* Mechanisms in fe-auth-scram.c */ +extern const pg_fe_sasl_mech pg_scram_mech; +extern char *pg_fe_scram_build_secret(const char *password, + int iterations, + const char **errstr); + +#endif /* FE_AUTH_H */ diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c new file mode 100644 index 0000000..a8584d2 --- /dev/null +++ b/src/interfaces/libpq/fe-connect.c @@ -0,0 +1,7830 @@ +/*------------------------------------------------------------------------- + * + * fe-connect.c + * functions related to setting up a connection to the backend + * + * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * src/interfaces/libpq/fe-connect.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres_fe.h" + +#include <sys/stat.h> +#include <fcntl.h> +#include <ctype.h> +#include <netdb.h> +#include <time.h> +#include <unistd.h> + +#include "common/ip.h" +#include "common/link-canary.h" +#include "common/scram-common.h" +#include "common/string.h" +#include "fe-auth.h" +#include "libpq-fe.h" +#include "libpq-int.h" +#include "mb/pg_wchar.h" +#include "pg_config_paths.h" +#include "port/pg_bswap.h" + +#ifdef WIN32 +#include "win32.h" +#ifdef _WIN32_IE +#undef _WIN32_IE +#endif +#define _WIN32_IE 0x0500 +#ifdef near +#undef near +#endif +#define near +#include <shlobj.h> +#include <mstcpip.h> +#else +#include <sys/socket.h> +#include <netdb.h> +#include <netinet/in.h> +#include <netinet/tcp.h> +#endif + +#ifdef ENABLE_THREAD_SAFETY +#ifdef WIN32 +#include "pthread-win32.h" +#else +#include <pthread.h> +#endif +#endif + +#ifdef USE_LDAP +#ifdef WIN32 +#include <winldap.h> +#else +/* OpenLDAP deprecates RFC 1823, but we want standard conformance */ +#define LDAP_DEPRECATED 1 +#include <ldap.h> +typedef struct timeval LDAP_TIMEVAL; +#endif +static int ldapServiceLookup(const char *purl, PQconninfoOption *options, + PQExpBuffer errorMessage); +#endif + +#ifndef WIN32 +#define PGPASSFILE ".pgpass" +#else +#define PGPASSFILE "pgpass.conf" +#endif + +/* + * Pre-9.0 servers will return this SQLSTATE if asked to set + * application_name in a startup packet. We hard-wire the value rather + * than looking into errcodes.h since it reflects historical behavior + * rather than that of the current code. + */ +#define ERRCODE_APPNAME_UNKNOWN "42704" + +/* This is part of the protocol so just define it */ +#define ERRCODE_INVALID_PASSWORD "28P01" +/* This too */ +#define ERRCODE_CANNOT_CONNECT_NOW "57P03" + +/* + * Cope with the various platform-specific ways to spell TCP keepalive socket + * options. This doesn't cover Windows, which as usual does its own thing. + */ +#if defined(TCP_KEEPIDLE) +/* TCP_KEEPIDLE is the name of this option on Linux and *BSD */ +#define PG_TCP_KEEPALIVE_IDLE TCP_KEEPIDLE +#define PG_TCP_KEEPALIVE_IDLE_STR "TCP_KEEPIDLE" +#elif defined(TCP_KEEPALIVE_THRESHOLD) +/* TCP_KEEPALIVE_THRESHOLD is the name of this option on Solaris >= 11 */ +#define PG_TCP_KEEPALIVE_IDLE TCP_KEEPALIVE_THRESHOLD +#define PG_TCP_KEEPALIVE_IDLE_STR "TCP_KEEPALIVE_THRESHOLD" +#elif defined(TCP_KEEPALIVE) && defined(__darwin__) +/* TCP_KEEPALIVE is the name of this option on macOS */ +/* Caution: Solaris has this symbol but it means something different */ +#define PG_TCP_KEEPALIVE_IDLE TCP_KEEPALIVE +#define PG_TCP_KEEPALIVE_IDLE_STR "TCP_KEEPALIVE" +#endif + +/* + * fall back options if they are not specified by arguments or defined + * by environment variables + */ +#define DefaultHost "localhost" +#define DefaultOption "" +#ifdef USE_SSL +#define DefaultChannelBinding "prefer" +#else +#define DefaultChannelBinding "disable" +#endif +#define DefaultTargetSessionAttrs "any" +#define DefaultLoadBalanceHosts "disable" +#ifdef USE_SSL +#define DefaultSSLMode "prefer" +#define DefaultSSLCertMode "allow" +#else +#define DefaultSSLMode "disable" +#define DefaultSSLCertMode "disable" +#endif +#ifdef ENABLE_GSS +#include "fe-gssapi-common.h" +#define DefaultGSSMode "prefer" +#else +#define DefaultGSSMode "disable" +#endif + +/* ---------- + * Definition of the conninfo parameters and their fallback resources. + * + * If Environment-Var and Compiled-in are specified as NULL, no + * fallback is available. If after all no value can be determined + * for an option, an error is returned. + * + * The value for the username is treated specially in conninfo_add_defaults. + * If the value is not obtained any other way, the username is determined + * by pg_fe_getauthname(). + * + * The Label and Disp-Char entries are provided for applications that + * want to use PQconndefaults() to create a generic database connection + * dialog. Disp-Char is defined as follows: + * "" Normal input field + * "*" Password field - hide value + * "D" Debug option - don't show by default + * + * PQconninfoOptions[] is a constant static array that we use to initialize + * a dynamically allocated working copy. All the "val" fields in + * PQconninfoOptions[] *must* be NULL. In a working copy, non-null "val" + * fields point to malloc'd strings that should be freed when the working + * array is freed (see PQconninfoFree). + * + * The first part of each struct is identical to the one in libpq-fe.h, + * which is required since we memcpy() data between the two! + * ---------- + */ +typedef struct _internalPQconninfoOption +{ + char *keyword; /* The keyword of the option */ + char *envvar; /* Fallback environment variable name */ + char *compiled; /* Fallback compiled in default value */ + char *val; /* Option's current value, or NULL */ + char *label; /* Label for field in connect dialog */ + char *dispchar; /* Indicates how to display this field in a + * connect dialog. Values are: "" Display + * entered value as is "*" Password field - + * hide value "D" Debug option - don't show + * by default */ + int dispsize; /* Field size in characters for dialog */ + /* --- + * Anything above this comment must be synchronized with + * PQconninfoOption in libpq-fe.h, since we memcpy() data + * between them! + * --- + */ + off_t connofs; /* Offset into PGconn struct, -1 if not there */ +} internalPQconninfoOption; + +static const internalPQconninfoOption PQconninfoOptions[] = { + {"service", "PGSERVICE", NULL, NULL, + "Database-Service", "", 20, -1}, + + {"user", "PGUSER", NULL, NULL, + "Database-User", "", 20, + offsetof(struct pg_conn, pguser)}, + + {"password", "PGPASSWORD", NULL, NULL, + "Database-Password", "*", 20, + offsetof(struct pg_conn, pgpass)}, + + {"passfile", "PGPASSFILE", NULL, NULL, + "Database-Password-File", "", 64, + offsetof(struct pg_conn, pgpassfile)}, + + {"channel_binding", "PGCHANNELBINDING", DefaultChannelBinding, NULL, + "Channel-Binding", "", 8, /* sizeof("require") == 8 */ + offsetof(struct pg_conn, channel_binding)}, + + {"connect_timeout", "PGCONNECT_TIMEOUT", NULL, NULL, + "Connect-timeout", "", 10, /* strlen(INT32_MAX) == 10 */ + offsetof(struct pg_conn, connect_timeout)}, + + {"dbname", "PGDATABASE", NULL, NULL, + "Database-Name", "", 20, + offsetof(struct pg_conn, dbName)}, + + {"host", "PGHOST", NULL, NULL, + "Database-Host", "", 40, + offsetof(struct pg_conn, pghost)}, + + {"hostaddr", "PGHOSTADDR", NULL, NULL, + "Database-Host-IP-Address", "", 45, + offsetof(struct pg_conn, pghostaddr)}, + + {"port", "PGPORT", DEF_PGPORT_STR, NULL, + "Database-Port", "", 6, + offsetof(struct pg_conn, pgport)}, + + {"client_encoding", "PGCLIENTENCODING", NULL, NULL, + "Client-Encoding", "", 10, + offsetof(struct pg_conn, client_encoding_initial)}, + + {"options", "PGOPTIONS", DefaultOption, NULL, + "Backend-Options", "", 40, + offsetof(struct pg_conn, pgoptions)}, + + {"application_name", "PGAPPNAME", NULL, NULL, + "Application-Name", "", 64, + offsetof(struct pg_conn, appname)}, + + {"fallback_application_name", NULL, NULL, NULL, + "Fallback-Application-Name", "", 64, + offsetof(struct pg_conn, fbappname)}, + + {"keepalives", NULL, NULL, NULL, + "TCP-Keepalives", "", 1, /* should be just '0' or '1' */ + offsetof(struct pg_conn, keepalives)}, + + {"keepalives_idle", NULL, NULL, NULL, + "TCP-Keepalives-Idle", "", 10, /* strlen(INT32_MAX) == 10 */ + offsetof(struct pg_conn, keepalives_idle)}, + + {"keepalives_interval", NULL, NULL, NULL, + "TCP-Keepalives-Interval", "", 10, /* strlen(INT32_MAX) == 10 */ + offsetof(struct pg_conn, keepalives_interval)}, + + {"keepalives_count", NULL, NULL, NULL, + "TCP-Keepalives-Count", "", 10, /* strlen(INT32_MAX) == 10 */ + offsetof(struct pg_conn, keepalives_count)}, + + {"tcp_user_timeout", NULL, NULL, NULL, + "TCP-User-Timeout", "", 10, /* strlen(INT32_MAX) == 10 */ + offsetof(struct pg_conn, pgtcp_user_timeout)}, + + /* + * ssl options are allowed even without client SSL support because the + * client can still handle SSL modes "disable" and "allow". Other + * parameters have no effect on non-SSL connections, so there is no reason + * to exclude them since none of them are mandatory. + */ + {"sslmode", "PGSSLMODE", DefaultSSLMode, NULL, + "SSL-Mode", "", 12, /* sizeof("verify-full") == 12 */ + offsetof(struct pg_conn, sslmode)}, + + {"sslcompression", "PGSSLCOMPRESSION", "0", NULL, + "SSL-Compression", "", 1, + offsetof(struct pg_conn, sslcompression)}, + + {"sslcert", "PGSSLCERT", NULL, NULL, + "SSL-Client-Cert", "", 64, + offsetof(struct pg_conn, sslcert)}, + + {"sslkey", "PGSSLKEY", NULL, NULL, + "SSL-Client-Key", "", 64, + offsetof(struct pg_conn, sslkey)}, + + {"sslcertmode", "PGSSLCERTMODE", NULL, NULL, + "SSL-Client-Cert-Mode", "", 8, /* sizeof("disable") == 8 */ + offsetof(struct pg_conn, sslcertmode)}, + + {"sslpassword", NULL, NULL, NULL, + "SSL-Client-Key-Password", "*", 20, + offsetof(struct pg_conn, sslpassword)}, + + {"sslrootcert", "PGSSLROOTCERT", NULL, NULL, + "SSL-Root-Certificate", "", 64, + offsetof(struct pg_conn, sslrootcert)}, + + {"sslcrl", "PGSSLCRL", NULL, NULL, + "SSL-Revocation-List", "", 64, + offsetof(struct pg_conn, sslcrl)}, + + {"sslcrldir", "PGSSLCRLDIR", NULL, NULL, + "SSL-Revocation-List-Dir", "", 64, + offsetof(struct pg_conn, sslcrldir)}, + + {"sslsni", "PGSSLSNI", "1", NULL, + "SSL-SNI", "", 1, + offsetof(struct pg_conn, sslsni)}, + + {"requirepeer", "PGREQUIREPEER", NULL, NULL, + "Require-Peer", "", 10, + offsetof(struct pg_conn, requirepeer)}, + + {"require_auth", "PGREQUIREAUTH", NULL, NULL, + "Require-Auth", "", 14, /* sizeof("scram-sha-256") == 14 */ + offsetof(struct pg_conn, require_auth)}, + + {"ssl_min_protocol_version", "PGSSLMINPROTOCOLVERSION", "TLSv1.2", NULL, + "SSL-Minimum-Protocol-Version", "", 8, /* sizeof("TLSv1.x") == 8 */ + offsetof(struct pg_conn, ssl_min_protocol_version)}, + + {"ssl_max_protocol_version", "PGSSLMAXPROTOCOLVERSION", NULL, NULL, + "SSL-Maximum-Protocol-Version", "", 8, /* sizeof("TLSv1.x") == 8 */ + offsetof(struct pg_conn, ssl_max_protocol_version)}, + + /* + * As with SSL, all GSS options are exposed even in builds that don't have + * support. + */ + {"gssencmode", "PGGSSENCMODE", DefaultGSSMode, NULL, + "GSSENC-Mode", "", 8, /* sizeof("disable") == 8 */ + offsetof(struct pg_conn, gssencmode)}, + + /* Kerberos and GSSAPI authentication support specifying the service name */ + {"krbsrvname", "PGKRBSRVNAME", PG_KRB_SRVNAM, NULL, + "Kerberos-service-name", "", 20, + offsetof(struct pg_conn, krbsrvname)}, + + {"gsslib", "PGGSSLIB", NULL, NULL, + "GSS-library", "", 7, /* sizeof("gssapi") == 7 */ + offsetof(struct pg_conn, gsslib)}, + + {"gssdelegation", "PGGSSDELEGATION", "0", NULL, + "GSS-delegation", "", 1, + offsetof(struct pg_conn, gssdelegation)}, + + {"replication", NULL, NULL, NULL, + "Replication", "D", 5, + offsetof(struct pg_conn, replication)}, + + {"target_session_attrs", "PGTARGETSESSIONATTRS", + DefaultTargetSessionAttrs, NULL, + "Target-Session-Attrs", "", 15, /* sizeof("prefer-standby") = 15 */ + offsetof(struct pg_conn, target_session_attrs)}, + + {"load_balance_hosts", "PGLOADBALANCEHOSTS", + DefaultLoadBalanceHosts, NULL, + "Load-Balance-Hosts", "", 8, /* sizeof("disable") = 8 */ + offsetof(struct pg_conn, load_balance_hosts)}, + + /* Terminating entry --- MUST BE LAST */ + {NULL, NULL, NULL, NULL, + NULL, NULL, 0} +}; + +static const PQEnvironmentOption EnvironmentOptions[] = +{ + /* common user-interface settings */ + { + "PGDATESTYLE", "datestyle" + }, + { + "PGTZ", "timezone" + }, + /* internal performance-related settings */ + { + "PGGEQO", "geqo" + }, + { + NULL, NULL + } +}; + +/* The connection URI must start with either of the following designators: */ +static const char uri_designator[] = "postgresql://"; +static const char short_uri_designator[] = "postgres://"; + +static bool connectOptions1(PGconn *conn, const char *conninfo); +static bool connectOptions2(PGconn *conn); +static int connectDBStart(PGconn *conn); +static int connectDBComplete(PGconn *conn); +static PGPing internal_ping(PGconn *conn); +static PGconn *makeEmptyPGconn(void); +static void pqFreeCommandQueue(PGcmdQueueEntry *queue); +static bool fillPGconn(PGconn *conn, PQconninfoOption *connOptions); +static void freePGconn(PGconn *conn); +static void closePGconn(PGconn *conn); +static void release_conn_addrinfo(PGconn *conn); +static int store_conn_addrinfo(PGconn *conn, struct addrinfo *addrlist); +static void sendTerminateConn(PGconn *conn); +static PQconninfoOption *conninfo_init(PQExpBuffer errorMessage); +static PQconninfoOption *parse_connection_string(const char *connstr, + PQExpBuffer errorMessage, bool use_defaults); +static int uri_prefix_length(const char *connstr); +static bool recognized_connection_string(const char *connstr); +static PQconninfoOption *conninfo_parse(const char *conninfo, + PQExpBuffer errorMessage, bool use_defaults); +static PQconninfoOption *conninfo_array_parse(const char *const *keywords, + const char *const *values, PQExpBuffer errorMessage, + bool use_defaults, int expand_dbname); +static bool conninfo_add_defaults(PQconninfoOption *options, + PQExpBuffer errorMessage); +static PQconninfoOption *conninfo_uri_parse(const char *uri, + PQExpBuffer errorMessage, bool use_defaults); +static bool conninfo_uri_parse_options(PQconninfoOption *options, + const char *uri, PQExpBuffer errorMessage); +static bool conninfo_uri_parse_params(char *params, + PQconninfoOption *connOptions, + PQExpBuffer errorMessage); +static char *conninfo_uri_decode(const char *str, PQExpBuffer errorMessage); +static bool get_hexdigit(char digit, int *value); +static const char *conninfo_getval(PQconninfoOption *connOptions, + const char *keyword); +static PQconninfoOption *conninfo_storeval(PQconninfoOption *connOptions, + const char *keyword, const char *value, + PQExpBuffer errorMessage, bool ignoreMissing, bool uri_decode); +static PQconninfoOption *conninfo_find(PQconninfoOption *connOptions, + const char *keyword); +static void defaultNoticeReceiver(void *arg, const PGresult *res); +static void defaultNoticeProcessor(void *arg, const char *message); +static int parseServiceInfo(PQconninfoOption *options, + PQExpBuffer errorMessage); +static int parseServiceFile(const char *serviceFile, + const char *service, + PQconninfoOption *options, + PQExpBuffer errorMessage, + bool *group_found); +static char *pwdfMatchesString(char *buf, const char *token); +static char *passwordFromFile(const char *hostname, const char *port, const char *dbname, + const char *username, const char *pgpassfile); +static void pgpassfileWarning(PGconn *conn); +static void default_threadlock(int acquire); +static bool sslVerifyProtocolVersion(const char *version); +static bool sslVerifyProtocolRange(const char *min, const char *max); +static bool parse_int_param(const char *value, int *result, PGconn *conn, + const char *context); + + +/* global variable because fe-auth.c needs to access it */ +pgthreadlock_t pg_g_threadlock = default_threadlock; + + +/* + * pqDropConnection + * + * Close any physical connection to the server, and reset associated + * state inside the connection object. We don't release state that + * would be needed to reconnect, though, nor local state that might still + * be useful later. + * + * We can always flush the output buffer, since there's no longer any hope + * of sending that data. However, unprocessed input data might still be + * valuable, so the caller must tell us whether to flush that or not. + */ +void +pqDropConnection(PGconn *conn, bool flushInput) +{ + /* Drop any SSL state */ + pqsecure_close(conn); + + /* Close the socket itself */ + if (conn->sock != PGINVALID_SOCKET) + closesocket(conn->sock); + conn->sock = PGINVALID_SOCKET; + + /* Optionally discard any unread data */ + if (flushInput) + conn->inStart = conn->inCursor = conn->inEnd = 0; + + /* Always discard any unsent data */ + conn->outCount = 0; + + /* Likewise, discard any pending pipelined commands */ + pqFreeCommandQueue(conn->cmd_queue_head); + conn->cmd_queue_head = conn->cmd_queue_tail = NULL; + pqFreeCommandQueue(conn->cmd_queue_recycle); + conn->cmd_queue_recycle = NULL; + + /* Free authentication/encryption state */ +#ifdef ENABLE_GSS + { + OM_uint32 min_s; + + if (conn->gcred != GSS_C_NO_CREDENTIAL) + { + gss_release_cred(&min_s, &conn->gcred); + conn->gcred = GSS_C_NO_CREDENTIAL; + } + if (conn->gctx) + gss_delete_sec_context(&min_s, &conn->gctx, GSS_C_NO_BUFFER); + if (conn->gtarg_nam) + gss_release_name(&min_s, &conn->gtarg_nam); + if (conn->gss_SendBuffer) + { + free(conn->gss_SendBuffer); + conn->gss_SendBuffer = NULL; + } + if (conn->gss_RecvBuffer) + { + free(conn->gss_RecvBuffer); + conn->gss_RecvBuffer = NULL; + } + if (conn->gss_ResultBuffer) + { + free(conn->gss_ResultBuffer); + conn->gss_ResultBuffer = NULL; + } + conn->gssenc = false; + } +#endif +#ifdef ENABLE_SSPI + if (conn->sspitarget) + { + free(conn->sspitarget); + conn->sspitarget = NULL; + } + if (conn->sspicred) + { + FreeCredentialsHandle(conn->sspicred); + free(conn->sspicred); + conn->sspicred = NULL; + } + if (conn->sspictx) + { + DeleteSecurityContext(conn->sspictx); + free(conn->sspictx); + conn->sspictx = NULL; + } + conn->usesspi = 0; +#endif + if (conn->sasl_state) + { + conn->sasl->free(conn->sasl_state); + conn->sasl_state = NULL; + } +} + +/* + * pqFreeCommandQueue + * Free all the entries of PGcmdQueueEntry queue passed. + */ +static void +pqFreeCommandQueue(PGcmdQueueEntry *queue) +{ + while (queue != NULL) + { + PGcmdQueueEntry *cur = queue; + + queue = cur->next; + free(cur->query); + free(cur); + } +} + +/* + * pqDropServerData + * + * Clear all connection state data that was received from (or deduced about) + * the server. This is essential to do between connection attempts to + * different servers, else we may incorrectly hold over some data from the + * old server. + * + * It would be better to merge this into pqDropConnection, perhaps, but + * right now we cannot because that function is called immediately on + * detection of connection loss (cf. pqReadData, for instance). This data + * should be kept until we are actually starting a new connection. + */ +static void +pqDropServerData(PGconn *conn) +{ + PGnotify *notify; + pgParameterStatus *pstatus; + + /* Forget pending notifies */ + notify = conn->notifyHead; + while (notify != NULL) + { + PGnotify *prev = notify; + + notify = notify->next; + free(prev); + } + conn->notifyHead = conn->notifyTail = NULL; + + /* Reset ParameterStatus data, as well as variables deduced from it */ + pstatus = conn->pstatus; + while (pstatus != NULL) + { + pgParameterStatus *prev = pstatus; + + pstatus = pstatus->next; + free(prev); + } + conn->pstatus = NULL; + conn->client_encoding = PG_SQL_ASCII; + conn->std_strings = false; + conn->default_transaction_read_only = PG_BOOL_UNKNOWN; + conn->in_hot_standby = PG_BOOL_UNKNOWN; + conn->scram_sha_256_iterations = SCRAM_SHA_256_DEFAULT_ITERATIONS; + conn->sversion = 0; + + /* Drop large-object lookup data */ + free(conn->lobjfuncs); + conn->lobjfuncs = NULL; + + /* Reset assorted other per-connection state */ + conn->last_sqlstate[0] = '\0'; + conn->auth_req_received = false; + conn->client_finished_auth = false; + conn->password_needed = false; + conn->gssapi_used = false; + conn->write_failed = false; + free(conn->write_err_msg); + conn->write_err_msg = NULL; + conn->be_pid = 0; + conn->be_key = 0; +} + + +/* + * Connecting to a Database + * + * There are now six different ways a user of this API can connect to the + * database. Two are not recommended for use in new code, because of their + * lack of extensibility with respect to the passing of options to the + * backend. These are PQsetdb and PQsetdbLogin (the former now being a macro + * to the latter). + * + * If it is desired to connect in a synchronous (blocking) manner, use the + * function PQconnectdb or PQconnectdbParams. The former accepts a string of + * option = value pairs (or a URI) which must be parsed; the latter takes two + * NULL terminated arrays instead. + * + * To connect in an asynchronous (non-blocking) manner, use the functions + * PQconnectStart or PQconnectStartParams (which differ in the same way as + * PQconnectdb and PQconnectdbParams) and PQconnectPoll. + * + * Internally, the static functions connectDBStart, connectDBComplete + * are part of the connection procedure. + */ + +/* + * PQconnectdbParams + * + * establishes a connection to a postgres backend through the postmaster + * using connection information in two arrays. + * + * The keywords array is defined as + * + * const char *params[] = {"option1", "option2", NULL} + * + * The values array is defined as + * + * const char *values[] = {"value1", "value2", NULL} + * + * Returns a PGconn* which is needed for all subsequent libpq calls, or NULL + * if a memory allocation failed. + * If the status field of the connection returned is CONNECTION_BAD, + * then some fields may be null'ed out instead of having valid values. + * + * You should call PQfinish (if conn is not NULL) regardless of whether this + * call succeeded. + */ +PGconn * +PQconnectdbParams(const char *const *keywords, + const char *const *values, + int expand_dbname) +{ + PGconn *conn = PQconnectStartParams(keywords, values, expand_dbname); + + if (conn && conn->status != CONNECTION_BAD) + (void) connectDBComplete(conn); + + return conn; +} + +/* + * PQpingParams + * + * check server status, accepting parameters identical to PQconnectdbParams + */ +PGPing +PQpingParams(const char *const *keywords, + const char *const *values, + int expand_dbname) +{ + PGconn *conn = PQconnectStartParams(keywords, values, expand_dbname); + PGPing ret; + + ret = internal_ping(conn); + PQfinish(conn); + + return ret; +} + +/* + * PQconnectdb + * + * establishes a connection to a postgres backend through the postmaster + * using connection information in a string. + * + * The conninfo string is either a whitespace-separated list of + * + * option = value + * + * definitions or a URI (refer to the documentation for details.) Value + * might be a single value containing no whitespaces or a single quoted + * string. If a single quote should appear anywhere in the value, it must be + * escaped with a backslash like \' + * + * Returns a PGconn* which is needed for all subsequent libpq calls, or NULL + * if a memory allocation failed. + * If the status field of the connection returned is CONNECTION_BAD, + * then some fields may be null'ed out instead of having valid values. + * + * You should call PQfinish (if conn is not NULL) regardless of whether this + * call succeeded. + */ +PGconn * +PQconnectdb(const char *conninfo) +{ + PGconn *conn = PQconnectStart(conninfo); + + if (conn && conn->status != CONNECTION_BAD) + (void) connectDBComplete(conn); + + return conn; +} + +/* + * PQping + * + * check server status, accepting parameters identical to PQconnectdb + */ +PGPing +PQping(const char *conninfo) +{ + PGconn *conn = PQconnectStart(conninfo); + PGPing ret; + + ret = internal_ping(conn); + PQfinish(conn); + + return ret; +} + +/* + * PQconnectStartParams + * + * Begins the establishment of a connection to a postgres backend through the + * postmaster using connection information in a struct. + * + * See comment for PQconnectdbParams for the definition of the string format. + * + * Returns a PGconn*. If NULL is returned, a malloc error has occurred, and + * you should not attempt to proceed with this connection. If the status + * field of the connection returned is CONNECTION_BAD, an error has + * occurred. In this case you should call PQfinish on the result, (perhaps + * inspecting the error message first). Other fields of the structure may not + * be valid if that occurs. If the status field is not CONNECTION_BAD, then + * this stage has succeeded - call PQconnectPoll, using select(2) to see when + * this is necessary. + * + * See PQconnectPoll for more info. + */ +PGconn * +PQconnectStartParams(const char *const *keywords, + const char *const *values, + int expand_dbname) +{ + PGconn *conn; + PQconninfoOption *connOptions; + + /* + * Allocate memory for the conn structure. Note that we also expect this + * to initialize conn->errorMessage to empty. All subsequent steps during + * connection initialization will only append to that buffer. + */ + conn = makeEmptyPGconn(); + if (conn == NULL) + return NULL; + + /* + * Parse the conninfo arrays + */ + connOptions = conninfo_array_parse(keywords, values, + &conn->errorMessage, + true, expand_dbname); + if (connOptions == NULL) + { + conn->status = CONNECTION_BAD; + /* errorMessage is already set */ + return conn; + } + + /* + * Move option values into conn structure + */ + if (!fillPGconn(conn, connOptions)) + { + PQconninfoFree(connOptions); + return conn; + } + + /* + * Free the option info - all is in conn now + */ + PQconninfoFree(connOptions); + + /* + * Compute derived options + */ + if (!connectOptions2(conn)) + return conn; + + /* + * Connect to the database + */ + if (!connectDBStart(conn)) + { + /* Just in case we failed to set it in connectDBStart */ + conn->status = CONNECTION_BAD; + } + + return conn; +} + +/* + * PQconnectStart + * + * Begins the establishment of a connection to a postgres backend through the + * postmaster using connection information in a string. + * + * See comment for PQconnectdb for the definition of the string format. + * + * Returns a PGconn*. If NULL is returned, a malloc error has occurred, and + * you should not attempt to proceed with this connection. If the status + * field of the connection returned is CONNECTION_BAD, an error has + * occurred. In this case you should call PQfinish on the result, (perhaps + * inspecting the error message first). Other fields of the structure may not + * be valid if that occurs. If the status field is not CONNECTION_BAD, then + * this stage has succeeded - call PQconnectPoll, using select(2) to see when + * this is necessary. + * + * See PQconnectPoll for more info. + */ +PGconn * +PQconnectStart(const char *conninfo) +{ + PGconn *conn; + + /* + * Allocate memory for the conn structure. Note that we also expect this + * to initialize conn->errorMessage to empty. All subsequent steps during + * connection initialization will only append to that buffer. + */ + conn = makeEmptyPGconn(); + if (conn == NULL) + return NULL; + + /* + * Parse the conninfo string + */ + if (!connectOptions1(conn, conninfo)) + return conn; + + /* + * Compute derived options + */ + if (!connectOptions2(conn)) + return conn; + + /* + * Connect to the database + */ + if (!connectDBStart(conn)) + { + /* Just in case we failed to set it in connectDBStart */ + conn->status = CONNECTION_BAD; + } + + return conn; +} + +/* + * Move option values into conn structure + * + * Don't put anything cute here --- intelligence should be in + * connectOptions2 ... + * + * Returns true on success. On failure, returns false and sets error message. + */ +static bool +fillPGconn(PGconn *conn, PQconninfoOption *connOptions) +{ + const internalPQconninfoOption *option; + + for (option = PQconninfoOptions; option->keyword; option++) + { + if (option->connofs >= 0) + { + const char *tmp = conninfo_getval(connOptions, option->keyword); + + if (tmp) + { + char **connmember = (char **) ((char *) conn + option->connofs); + + free(*connmember); + *connmember = strdup(tmp); + if (*connmember == NULL) + { + libpq_append_conn_error(conn, "out of memory"); + return false; + } + } + } + } + + return true; +} + +/* + * connectOptions1 + * + * Internal subroutine to set up connection parameters given an already- + * created PGconn and a conninfo string. Derived settings should be + * processed by calling connectOptions2 next. (We split them because + * PQsetdbLogin overrides defaults in between.) + * + * Returns true if OK, false if trouble (in which case errorMessage is set + * and so is conn->status). + */ +static bool +connectOptions1(PGconn *conn, const char *conninfo) +{ + PQconninfoOption *connOptions; + + /* + * Parse the conninfo string + */ + connOptions = parse_connection_string(conninfo, &conn->errorMessage, true); + if (connOptions == NULL) + { + conn->status = CONNECTION_BAD; + /* errorMessage is already set */ + return false; + } + + /* + * Move option values into conn structure + */ + if (!fillPGconn(conn, connOptions)) + { + conn->status = CONNECTION_BAD; + PQconninfoFree(connOptions); + return false; + } + + /* + * Free the option info - all is in conn now + */ + PQconninfoFree(connOptions); + + return true; +} + +/* + * Count the number of elements in a simple comma-separated list. + */ +static int +count_comma_separated_elems(const char *input) +{ + int n; + + n = 1; + for (; *input != '\0'; input++) + { + if (*input == ',') + n++; + } + + return n; +} + +/* + * Parse a simple comma-separated list. + * + * On each call, returns a malloc'd copy of the next element, and sets *more + * to indicate whether there are any more elements in the list after this, + * and updates *startptr to point to the next element, if any. + * + * On out of memory, returns NULL. + */ +static char * +parse_comma_separated_list(char **startptr, bool *more) +{ + char *p; + char *s = *startptr; + char *e; + int len; + + /* + * Search for the end of the current element; a comma or end-of-string + * acts as a terminator. + */ + e = s; + while (*e != '\0' && *e != ',') + ++e; + *more = (*e == ','); + + len = e - s; + p = (char *) malloc(sizeof(char) * (len + 1)); + if (p) + { + memcpy(p, s, len); + p[len] = '\0'; + } + *startptr = e + 1; + + return p; +} + +/* + * Initializes the prng_state field of the connection. We want something + * unpredictable, so if possible, use high-quality random bits for the + * seed. Otherwise, fall back to a seed based on the connection address, + * timestamp and PID. + */ +static void +libpq_prng_init(PGconn *conn) +{ + uint64 rseed; + struct timeval tval = {0}; + + if (pg_prng_strong_seed(&conn->prng_state)) + return; + + gettimeofday(&tval, NULL); + + rseed = ((uintptr_t) conn) ^ + ((uint64) getpid()) ^ + ((uint64) tval.tv_usec) ^ + ((uint64) tval.tv_sec); + + pg_prng_seed(&conn->prng_state, rseed); +} + +/* + * connectOptions2 + * + * Compute derived connection options after absorbing all user-supplied info. + * + * Returns true if OK, false if trouble (in which case errorMessage is set + * and so is conn->status). + */ +static bool +connectOptions2(PGconn *conn) +{ + int i; + + /* + * Allocate memory for details about each host to which we might possibly + * try to connect. For that, count the number of elements in the hostaddr + * or host options. If neither is given, assume one host. + */ + conn->whichhost = 0; + if (conn->pghostaddr && conn->pghostaddr[0] != '\0') + conn->nconnhost = count_comma_separated_elems(conn->pghostaddr); + else if (conn->pghost && conn->pghost[0] != '\0') + conn->nconnhost = count_comma_separated_elems(conn->pghost); + else + conn->nconnhost = 1; + conn->connhost = (pg_conn_host *) + calloc(conn->nconnhost, sizeof(pg_conn_host)); + if (conn->connhost == NULL) + goto oom_error; + + /* + * We now have one pg_conn_host structure per possible host. Fill in the + * host and hostaddr fields for each, by splitting the parameter strings. + */ + if (conn->pghostaddr != NULL && conn->pghostaddr[0] != '\0') + { + char *s = conn->pghostaddr; + bool more = true; + + for (i = 0; i < conn->nconnhost && more; i++) + { + conn->connhost[i].hostaddr = parse_comma_separated_list(&s, &more); + if (conn->connhost[i].hostaddr == NULL) + goto oom_error; + } + + /* + * If hostaddr was given, the array was allocated according to the + * number of elements in the hostaddr list, so it really should be the + * right size. + */ + Assert(!more); + Assert(i == conn->nconnhost); + } + + if (conn->pghost != NULL && conn->pghost[0] != '\0') + { + char *s = conn->pghost; + bool more = true; + + for (i = 0; i < conn->nconnhost && more; i++) + { + conn->connhost[i].host = parse_comma_separated_list(&s, &more); + if (conn->connhost[i].host == NULL) + goto oom_error; + } + + /* Check for wrong number of host items. */ + if (more || i != conn->nconnhost) + { + conn->status = CONNECTION_BAD; + libpq_append_conn_error(conn, "could not match %d host names to %d hostaddr values", + count_comma_separated_elems(conn->pghost), conn->nconnhost); + return false; + } + } + + /* + * Now, for each host slot, identify the type of address spec, and fill in + * the default address if nothing was given. + */ + for (i = 0; i < conn->nconnhost; i++) + { + pg_conn_host *ch = &conn->connhost[i]; + + if (ch->hostaddr != NULL && ch->hostaddr[0] != '\0') + ch->type = CHT_HOST_ADDRESS; + else if (ch->host != NULL && ch->host[0] != '\0') + { + ch->type = CHT_HOST_NAME; + if (is_unixsock_path(ch->host)) + ch->type = CHT_UNIX_SOCKET; + } + else + { + free(ch->host); + + /* + * This bit selects the default host location. If you change + * this, see also pg_regress. + */ + if (DEFAULT_PGSOCKET_DIR[0]) + { + ch->host = strdup(DEFAULT_PGSOCKET_DIR); + ch->type = CHT_UNIX_SOCKET; + } + else + { + ch->host = strdup(DefaultHost); + ch->type = CHT_HOST_NAME; + } + if (ch->host == NULL) + goto oom_error; + } + } + + /* + * Next, work out the port number corresponding to each host name. + * + * Note: unlike the above for host names, this could leave the port fields + * as null or empty strings. We will substitute DEF_PGPORT whenever we + * read such a port field. + */ + if (conn->pgport != NULL && conn->pgport[0] != '\0') + { + char *s = conn->pgport; + bool more = true; + + for (i = 0; i < conn->nconnhost && more; i++) + { + conn->connhost[i].port = parse_comma_separated_list(&s, &more); + if (conn->connhost[i].port == NULL) + goto oom_error; + } + + /* + * If exactly one port was given, use it for every host. Otherwise, + * there must be exactly as many ports as there were hosts. + */ + if (i == 1 && !more) + { + for (i = 1; i < conn->nconnhost; i++) + { + conn->connhost[i].port = strdup(conn->connhost[0].port); + if (conn->connhost[i].port == NULL) + goto oom_error; + } + } + else if (more || i != conn->nconnhost) + { + conn->status = CONNECTION_BAD; + libpq_append_conn_error(conn, "could not match %d port numbers to %d hosts", + count_comma_separated_elems(conn->pgport), conn->nconnhost); + return false; + } + } + + /* + * If user name was not given, fetch it. (Most likely, the fetch will + * fail, since the only way we get here is if pg_fe_getauthname() failed + * during conninfo_add_defaults(). But now we want an error message.) + */ + if (conn->pguser == NULL || conn->pguser[0] == '\0') + { + free(conn->pguser); + conn->pguser = pg_fe_getauthname(&conn->errorMessage); + if (!conn->pguser) + { + conn->status = CONNECTION_BAD; + return false; + } + } + + /* + * If database name was not given, default it to equal user name + */ + if (conn->dbName == NULL || conn->dbName[0] == '\0') + { + free(conn->dbName); + conn->dbName = strdup(conn->pguser); + if (!conn->dbName) + goto oom_error; + } + + /* + * If password was not given, try to look it up in password file. Note + * that the result might be different for each host/port pair. + */ + if (conn->pgpass == NULL || conn->pgpass[0] == '\0') + { + /* If password file wasn't specified, use ~/PGPASSFILE */ + if (conn->pgpassfile == NULL || conn->pgpassfile[0] == '\0') + { + char homedir[MAXPGPATH]; + + if (pqGetHomeDirectory(homedir, sizeof(homedir))) + { + free(conn->pgpassfile); + conn->pgpassfile = malloc(MAXPGPATH); + if (!conn->pgpassfile) + goto oom_error; + snprintf(conn->pgpassfile, MAXPGPATH, "%s/%s", + homedir, PGPASSFILE); + } + } + + if (conn->pgpassfile != NULL && conn->pgpassfile[0] != '\0') + { + for (i = 0; i < conn->nconnhost; i++) + { + /* + * Try to get a password for this host from file. We use host + * for the hostname search key if given, else hostaddr (at + * least one of them is guaranteed nonempty by now). + */ + const char *pwhost = conn->connhost[i].host; + + if (pwhost == NULL || pwhost[0] == '\0') + pwhost = conn->connhost[i].hostaddr; + + conn->connhost[i].password = + passwordFromFile(pwhost, + conn->connhost[i].port, + conn->dbName, + conn->pguser, + conn->pgpassfile); + } + } + } + + /* + * parse and validate require_auth option + */ + if (conn->require_auth && conn->require_auth[0]) + { + char *s = conn->require_auth; + bool first, + more; + bool negated = false; + + /* + * By default, start from an empty set of allowed options and add to + * it. + */ + conn->auth_required = true; + conn->allowed_auth_methods = 0; + + for (first = true, more = true; more; first = false) + { + char *method, + *part; + uint32 bits; + + part = parse_comma_separated_list(&s, &more); + if (part == NULL) + goto oom_error; + + /* + * Check for negation, e.g. '!password'. If one element is + * negated, they all have to be. + */ + method = part; + if (*method == '!') + { + if (first) + { + /* + * Switch to a permissive set of allowed options, and + * subtract from it. + */ + conn->auth_required = false; + conn->allowed_auth_methods = -1; + } + else if (!negated) + { + conn->status = CONNECTION_BAD; + libpq_append_conn_error(conn, "negative require_auth method \"%s\" cannot be mixed with non-negative methods", + method); + + free(part); + return false; + } + + negated = true; + method++; + } + else if (negated) + { + conn->status = CONNECTION_BAD; + libpq_append_conn_error(conn, "require_auth method \"%s\" cannot be mixed with negative methods", + method); + + free(part); + return false; + } + + if (strcmp(method, "password") == 0) + { + bits = (1 << AUTH_REQ_PASSWORD); + } + else if (strcmp(method, "md5") == 0) + { + bits = (1 << AUTH_REQ_MD5); + } + else if (strcmp(method, "gss") == 0) + { + bits = (1 << AUTH_REQ_GSS); + bits |= (1 << AUTH_REQ_GSS_CONT); + } + else if (strcmp(method, "sspi") == 0) + { + bits = (1 << AUTH_REQ_SSPI); + bits |= (1 << AUTH_REQ_GSS_CONT); + } + else if (strcmp(method, "scram-sha-256") == 0) + { + /* This currently assumes that SCRAM is the only SASL method. */ + bits = (1 << AUTH_REQ_SASL); + bits |= (1 << AUTH_REQ_SASL_CONT); + bits |= (1 << AUTH_REQ_SASL_FIN); + } + else if (strcmp(method, "none") == 0) + { + /* + * Special case: let the user explicitly allow (or disallow) + * connections where the server does not send an explicit + * authentication challenge, such as "trust" and "cert" auth. + */ + if (negated) /* "!none" */ + { + if (conn->auth_required) + goto duplicate; + + conn->auth_required = true; + } + else /* "none" */ + { + if (!conn->auth_required) + goto duplicate; + + conn->auth_required = false; + } + + free(part); + continue; /* avoid the bitmask manipulation below */ + } + else + { + conn->status = CONNECTION_BAD; + libpq_append_conn_error(conn, "invalid %s value: \"%s\"", + "require_auth", method); + + free(part); + return false; + } + + /* Update the bitmask. */ + if (negated) + { + if ((conn->allowed_auth_methods & bits) == 0) + goto duplicate; + + conn->allowed_auth_methods &= ~bits; + } + else + { + if ((conn->allowed_auth_methods & bits) == bits) + goto duplicate; + + conn->allowed_auth_methods |= bits; + } + + free(part); + continue; + + duplicate: + + /* + * A duplicated method probably indicates a typo in a setting + * where typos are extremely risky. + */ + conn->status = CONNECTION_BAD; + libpq_append_conn_error(conn, "require_auth method \"%s\" is specified more than once", + part); + + free(part); + return false; + } + } + + /* + * validate channel_binding option + */ + if (conn->channel_binding) + { + if (strcmp(conn->channel_binding, "disable") != 0 + && strcmp(conn->channel_binding, "prefer") != 0 + && strcmp(conn->channel_binding, "require") != 0) + { + conn->status = CONNECTION_BAD; + libpq_append_conn_error(conn, "invalid %s value: \"%s\"", + "channel_binding", conn->channel_binding); + return false; + } + } + else + { + conn->channel_binding = strdup(DefaultChannelBinding); + if (!conn->channel_binding) + goto oom_error; + } + +#ifndef USE_SSL + + /* + * sslrootcert=system is not supported. Since setting this changes the + * default sslmode, check this _before_ we validate sslmode, to avoid + * confusing the user with errors for an option they may not have set. + */ + if (conn->sslrootcert + && strcmp(conn->sslrootcert, "system") == 0) + { + conn->status = CONNECTION_BAD; + libpq_append_conn_error(conn, "%s value \"%s\" invalid when SSL support is not compiled in", + "sslrootcert", conn->sslrootcert); + return false; + } +#endif + + /* + * validate sslmode option + */ + if (conn->sslmode) + { + if (strcmp(conn->sslmode, "disable") != 0 + && strcmp(conn->sslmode, "allow") != 0 + && strcmp(conn->sslmode, "prefer") != 0 + && strcmp(conn->sslmode, "require") != 0 + && strcmp(conn->sslmode, "verify-ca") != 0 + && strcmp(conn->sslmode, "verify-full") != 0) + { + conn->status = CONNECTION_BAD; + libpq_append_conn_error(conn, "invalid %s value: \"%s\"", + "sslmode", conn->sslmode); + return false; + } + +#ifndef USE_SSL + switch (conn->sslmode[0]) + { + case 'a': /* "allow" */ + case 'p': /* "prefer" */ + + /* + * warn user that an SSL connection will never be negotiated + * since SSL was not compiled in? + */ + break; + + case 'r': /* "require" */ + case 'v': /* "verify-ca" or "verify-full" */ + conn->status = CONNECTION_BAD; + libpq_append_conn_error(conn, "%s value \"%s\" invalid when SSL support is not compiled in", + "sslmode", conn->sslmode); + return false; + } +#endif + } + else + { + conn->sslmode = strdup(DefaultSSLMode); + if (!conn->sslmode) + goto oom_error; + } + +#ifdef USE_SSL + + /* + * If sslrootcert=system, make sure our chosen sslmode is compatible. + */ + if (conn->sslrootcert + && strcmp(conn->sslrootcert, "system") == 0 + && strcmp(conn->sslmode, "verify-full") != 0) + { + conn->status = CONNECTION_BAD; + libpq_append_conn_error(conn, "weak sslmode \"%s\" may not be used with sslrootcert=system (use \"verify-full\")", + conn->sslmode); + return false; + } +#endif + + /* + * Validate TLS protocol versions for ssl_min_protocol_version and + * ssl_max_protocol_version. + */ + if (!sslVerifyProtocolVersion(conn->ssl_min_protocol_version)) + { + conn->status = CONNECTION_BAD; + libpq_append_conn_error(conn, "invalid %s value: \"%s\"", + "ssl_min_protocol_version", + conn->ssl_min_protocol_version); + return false; + } + if (!sslVerifyProtocolVersion(conn->ssl_max_protocol_version)) + { + conn->status = CONNECTION_BAD; + libpq_append_conn_error(conn, "invalid %s value: \"%s\"", + "ssl_max_protocol_version", + conn->ssl_max_protocol_version); + return false; + } + + /* + * Check if the range of SSL protocols defined is correct. This is done + * at this early step because this is independent of the SSL + * implementation used, and this avoids unnecessary cycles with an + * already-built SSL context when the connection is being established, as + * it would be doomed anyway. + */ + if (!sslVerifyProtocolRange(conn->ssl_min_protocol_version, + conn->ssl_max_protocol_version)) + { + conn->status = CONNECTION_BAD; + libpq_append_conn_error(conn, "invalid SSL protocol version range"); + return false; + } + + /* + * validate sslcertmode option + */ + if (conn->sslcertmode) + { + if (strcmp(conn->sslcertmode, "disable") != 0 && + strcmp(conn->sslcertmode, "allow") != 0 && + strcmp(conn->sslcertmode, "require") != 0) + { + conn->status = CONNECTION_BAD; + libpq_append_conn_error(conn, "invalid %s value: \"%s\"", + "sslcertmode", conn->sslcertmode); + return false; + } +#ifndef USE_SSL + if (strcmp(conn->sslcertmode, "require") == 0) + { + conn->status = CONNECTION_BAD; + libpq_append_conn_error(conn, "%s value \"%s\" invalid when SSL support is not compiled in", + "sslcertmode", conn->sslcertmode); + return false; + } +#endif +#ifndef HAVE_SSL_CTX_SET_CERT_CB + + /* + * Without a certificate callback, the current implementation can't + * figure out if a certificate was actually requested, so "require" is + * useless. + */ + if (strcmp(conn->sslcertmode, "require") == 0) + { + conn->status = CONNECTION_BAD; + libpq_append_conn_error(conn, "%s value \"%s\" is not supported (check OpenSSL version)", + "sslcertmode", conn->sslcertmode); + return false; + } +#endif + } + else + { + conn->sslcertmode = strdup(DefaultSSLCertMode); + if (!conn->sslcertmode) + goto oom_error; + } + + /* + * validate gssencmode option + */ + if (conn->gssencmode) + { + if (strcmp(conn->gssencmode, "disable") != 0 && + strcmp(conn->gssencmode, "prefer") != 0 && + strcmp(conn->gssencmode, "require") != 0) + { + conn->status = CONNECTION_BAD; + libpq_append_conn_error(conn, "invalid %s value: \"%s\"", "gssencmode", conn->gssencmode); + return false; + } +#ifndef ENABLE_GSS + if (strcmp(conn->gssencmode, "require") == 0) + { + conn->status = CONNECTION_BAD; + libpq_append_conn_error(conn, "gssencmode value \"%s\" invalid when GSSAPI support is not compiled in", + conn->gssencmode); + return false; + } +#endif + } + else + { + conn->gssencmode = strdup(DefaultGSSMode); + if (!conn->gssencmode) + goto oom_error; + } + + /* + * validate target_session_attrs option, and set target_server_type + */ + if (conn->target_session_attrs) + { + if (strcmp(conn->target_session_attrs, "any") == 0) + conn->target_server_type = SERVER_TYPE_ANY; + else if (strcmp(conn->target_session_attrs, "read-write") == 0) + conn->target_server_type = SERVER_TYPE_READ_WRITE; + else if (strcmp(conn->target_session_attrs, "read-only") == 0) + conn->target_server_type = SERVER_TYPE_READ_ONLY; + else if (strcmp(conn->target_session_attrs, "primary") == 0) + conn->target_server_type = SERVER_TYPE_PRIMARY; + else if (strcmp(conn->target_session_attrs, "standby") == 0) + conn->target_server_type = SERVER_TYPE_STANDBY; + else if (strcmp(conn->target_session_attrs, "prefer-standby") == 0) + conn->target_server_type = SERVER_TYPE_PREFER_STANDBY; + else + { + conn->status = CONNECTION_BAD; + libpq_append_conn_error(conn, "invalid %s value: \"%s\"", + "target_session_attrs", + conn->target_session_attrs); + return false; + } + } + else + conn->target_server_type = SERVER_TYPE_ANY; + + /* + * validate load_balance_hosts option, and set load_balance_type + */ + if (conn->load_balance_hosts) + { + if (strcmp(conn->load_balance_hosts, "disable") == 0) + conn->load_balance_type = LOAD_BALANCE_DISABLE; + else if (strcmp(conn->load_balance_hosts, "random") == 0) + conn->load_balance_type = LOAD_BALANCE_RANDOM; + else + { + conn->status = CONNECTION_BAD; + libpq_append_conn_error(conn, "invalid %s value: \"%s\"", + "load_balance_hosts", + conn->load_balance_hosts); + return false; + } + } + else + conn->load_balance_type = LOAD_BALANCE_DISABLE; + + if (conn->load_balance_type == LOAD_BALANCE_RANDOM) + { + libpq_prng_init(conn); + + /* + * This is the "inside-out" variant of the Fisher-Yates shuffle + * algorithm. Notionally, we append each new value to the array and + * then swap it with a randomly-chosen array element (possibly + * including itself, else we fail to generate permutations with the + * last integer last). The swap step can be optimized by combining it + * with the insertion. + */ + for (i = 1; i < conn->nconnhost; i++) + { + int j = pg_prng_uint64_range(&conn->prng_state, 0, i); + pg_conn_host temp = conn->connhost[j]; + + conn->connhost[j] = conn->connhost[i]; + conn->connhost[i] = temp; + } + } + + /* + * Resolve special "auto" client_encoding from the locale + */ + if (conn->client_encoding_initial && + strcmp(conn->client_encoding_initial, "auto") == 0) + { + free(conn->client_encoding_initial); + conn->client_encoding_initial = strdup(pg_encoding_to_char(pg_get_encoding_from_locale(NULL, true))); + if (!conn->client_encoding_initial) + goto oom_error; + } + + /* + * Only if we get this far is it appropriate to try to connect. (We need a + * state flag, rather than just the boolean result of this function, in + * case someone tries to PQreset() the PGconn.) + */ + conn->options_valid = true; + + return true; + +oom_error: + conn->status = CONNECTION_BAD; + libpq_append_conn_error(conn, "out of memory"); + return false; +} + +/* + * PQconndefaults + * + * Construct a default connection options array, which identifies all the + * available options and shows any default values that are available from the + * environment etc. On error (eg out of memory), NULL is returned. + * + * Using this function, an application may determine all possible options + * and their current default values. + * + * NOTE: as of PostgreSQL 7.0, the returned array is dynamically allocated + * and should be freed when no longer needed via PQconninfoFree(). (In prior + * versions, the returned array was static, but that's not thread-safe.) + * Pre-7.0 applications that use this function will see a small memory leak + * until they are updated to call PQconninfoFree. + */ +PQconninfoOption * +PQconndefaults(void) +{ + PQExpBufferData errorBuf; + PQconninfoOption *connOptions; + + /* We don't actually report any errors here, but callees want a buffer */ + initPQExpBuffer(&errorBuf); + if (PQExpBufferDataBroken(errorBuf)) + return NULL; /* out of memory already :-( */ + + connOptions = conninfo_init(&errorBuf); + if (connOptions != NULL) + { + /* pass NULL errorBuf to ignore errors */ + if (!conninfo_add_defaults(connOptions, NULL)) + { + PQconninfoFree(connOptions); + connOptions = NULL; + } + } + + termPQExpBuffer(&errorBuf); + return connOptions; +} + +/* ---------------- + * PQsetdbLogin + * + * establishes a connection to a postgres backend through the postmaster + * at the specified host and port. + * + * returns a PGconn* which is needed for all subsequent libpq calls + * + * if the status field of the connection returned is CONNECTION_BAD, + * then only the errorMessage is likely to be useful. + * ---------------- + */ +PGconn * +PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions, + const char *pgtty, const char *dbName, const char *login, + const char *pwd) +{ + PGconn *conn; + + /* + * Allocate memory for the conn structure. Note that we also expect this + * to initialize conn->errorMessage to empty. All subsequent steps during + * connection initialization will only append to that buffer. + */ + conn = makeEmptyPGconn(); + if (conn == NULL) + return NULL; + + /* + * If the dbName parameter contains what looks like a connection string, + * parse it into conn struct using connectOptions1. + */ + if (dbName && recognized_connection_string(dbName)) + { + if (!connectOptions1(conn, dbName)) + return conn; + } + else + { + /* + * Old-style path: first, parse an empty conninfo string in order to + * set up the same defaults that PQconnectdb() would use. + */ + if (!connectOptions1(conn, "")) + return conn; + + /* Insert dbName parameter value into struct */ + if (dbName && dbName[0] != '\0') + { + free(conn->dbName); + conn->dbName = strdup(dbName); + if (!conn->dbName) + goto oom_error; + } + } + + /* + * Insert remaining parameters into struct, overriding defaults (as well + * as any conflicting data from dbName taken as a conninfo). + */ + if (pghost && pghost[0] != '\0') + { + free(conn->pghost); + conn->pghost = strdup(pghost); + if (!conn->pghost) + goto oom_error; + } + + if (pgport && pgport[0] != '\0') + { + free(conn->pgport); + conn->pgport = strdup(pgport); + if (!conn->pgport) + goto oom_error; + } + + if (pgoptions && pgoptions[0] != '\0') + { + free(conn->pgoptions); + conn->pgoptions = strdup(pgoptions); + if (!conn->pgoptions) + goto oom_error; + } + + if (login && login[0] != '\0') + { + free(conn->pguser); + conn->pguser = strdup(login); + if (!conn->pguser) + goto oom_error; + } + + if (pwd && pwd[0] != '\0') + { + free(conn->pgpass); + conn->pgpass = strdup(pwd); + if (!conn->pgpass) + goto oom_error; + } + + /* + * Compute derived options + */ + if (!connectOptions2(conn)) + return conn; + + /* + * Connect to the database + */ + if (connectDBStart(conn)) + (void) connectDBComplete(conn); + + return conn; + +oom_error: + conn->status = CONNECTION_BAD; + libpq_append_conn_error(conn, "out of memory"); + return conn; +} + + +/* ---------- + * connectNoDelay - + * Sets the TCP_NODELAY socket option. + * Returns 1 if successful, 0 if not. + * ---------- + */ +static int +connectNoDelay(PGconn *conn) +{ +#ifdef TCP_NODELAY + int on = 1; + + if (setsockopt(conn->sock, IPPROTO_TCP, TCP_NODELAY, + (char *) &on, + sizeof(on)) < 0) + { + char sebuf[PG_STRERROR_R_BUFLEN]; + + libpq_append_conn_error(conn, "could not set socket to TCP no delay mode: %s", + SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf))); + return 0; + } +#endif + + return 1; +} + +/* ---------- + * Write currently connected IP address into host_addr (of len host_addr_len). + * If unable to, set it to the empty string. + * ---------- + */ +static void +getHostaddr(PGconn *conn, char *host_addr, int host_addr_len) +{ + struct sockaddr_storage *addr = &conn->raddr.addr; + + if (addr->ss_family == AF_INET) + { + if (pg_inet_net_ntop(AF_INET, + &((struct sockaddr_in *) addr)->sin_addr.s_addr, + 32, + host_addr, host_addr_len) == NULL) + host_addr[0] = '\0'; + } + else if (addr->ss_family == AF_INET6) + { + if (pg_inet_net_ntop(AF_INET6, + &((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr, + 128, + host_addr, host_addr_len) == NULL) + host_addr[0] = '\0'; + } + else + host_addr[0] = '\0'; +} + +/* + * emitHostIdentityInfo - + * Speculatively append "connection to server so-and-so failed: " to + * conn->errorMessage once we've identified the current connection target + * address. This ensures that any subsequent error message will be properly + * attributed to the server we couldn't connect to. conn->raddr must be + * valid, and the result of getHostaddr() must be supplied. + */ +static void +emitHostIdentityInfo(PGconn *conn, const char *host_addr) +{ + if (conn->raddr.addr.ss_family == AF_UNIX) + { + char service[NI_MAXHOST]; + + pg_getnameinfo_all(&conn->raddr.addr, conn->raddr.salen, + NULL, 0, + service, sizeof(service), + NI_NUMERICSERV); + appendPQExpBuffer(&conn->errorMessage, + libpq_gettext("connection to server on socket \"%s\" failed: "), + service); + } + else + { + const char *displayed_host; + const char *displayed_port; + + /* To which host and port were we actually connecting? */ + if (conn->connhost[conn->whichhost].type == CHT_HOST_ADDRESS) + displayed_host = conn->connhost[conn->whichhost].hostaddr; + else + displayed_host = conn->connhost[conn->whichhost].host; + displayed_port = conn->connhost[conn->whichhost].port; + if (displayed_port == NULL || displayed_port[0] == '\0') + displayed_port = DEF_PGPORT_STR; + + /* + * If the user did not supply an IP address using 'hostaddr', and + * 'host' was missing or does not match our lookup, display the + * looked-up IP address. + */ + if (conn->connhost[conn->whichhost].type != CHT_HOST_ADDRESS && + host_addr[0] && + strcmp(displayed_host, host_addr) != 0) + appendPQExpBuffer(&conn->errorMessage, + libpq_gettext("connection to server at \"%s\" (%s), port %s failed: "), + displayed_host, host_addr, + displayed_port); + else + appendPQExpBuffer(&conn->errorMessage, + libpq_gettext("connection to server at \"%s\", port %s failed: "), + displayed_host, + displayed_port); + } +} + +/* ---------- + * connectFailureMessage - + * create a friendly error message on connection failure, + * using the given errno value. Use this for error cases that + * imply that there's no server there. + * ---------- + */ +static void +connectFailureMessage(PGconn *conn, int errorno) +{ + char sebuf[PG_STRERROR_R_BUFLEN]; + + appendPQExpBuffer(&conn->errorMessage, + "%s\n", + SOCK_STRERROR(errorno, sebuf, sizeof(sebuf))); + + if (conn->raddr.addr.ss_family == AF_UNIX) + libpq_append_conn_error(conn, "\tIs the server running locally and accepting connections on that socket?"); + else + libpq_append_conn_error(conn, "\tIs the server running on that host and accepting TCP/IP connections?"); +} + +/* + * Should we use keepalives? Returns 1 if yes, 0 if no, and -1 if + * conn->keepalives is set to a value which is not parseable as an + * integer. + */ +static int +useKeepalives(PGconn *conn) +{ + char *ep; + int val; + + if (conn->keepalives == NULL) + return 1; + val = strtol(conn->keepalives, &ep, 10); + if (*ep) + return -1; + return val != 0 ? 1 : 0; +} + +/* + * Parse and try to interpret "value" as an integer value, and if successful, + * store it in *result, complaining if there is any trailing garbage or an + * overflow. This allows any number of leading and trailing whitespaces. + */ +static bool +parse_int_param(const char *value, int *result, PGconn *conn, + const char *context) +{ + char *end; + long numval; + + Assert(value != NULL); + + *result = 0; + + /* strtol(3) skips leading whitespaces */ + errno = 0; + numval = strtol(value, &end, 10); + + /* + * If no progress was done during the parsing or an error happened, fail. + * This tests properly for overflows of the result. + */ + if (value == end || errno != 0 || numval != (int) numval) + goto error; + + /* + * Skip any trailing whitespace; if anything but whitespace remains before + * the terminating character, fail + */ + while (*end != '\0' && isspace((unsigned char) *end)) + end++; + + if (*end != '\0') + goto error; + + *result = numval; + return true; + +error: + libpq_append_conn_error(conn, "invalid integer value \"%s\" for connection option \"%s\"", + value, context); + return false; +} + +#ifndef WIN32 +/* + * Set the keepalive idle timer. + */ +static int +setKeepalivesIdle(PGconn *conn) +{ + int idle; + + if (conn->keepalives_idle == NULL) + return 1; + + if (!parse_int_param(conn->keepalives_idle, &idle, conn, + "keepalives_idle")) + return 0; + if (idle < 0) + idle = 0; + +#ifdef PG_TCP_KEEPALIVE_IDLE + if (setsockopt(conn->sock, IPPROTO_TCP, PG_TCP_KEEPALIVE_IDLE, + (char *) &idle, sizeof(idle)) < 0) + { + char sebuf[PG_STRERROR_R_BUFLEN]; + + libpq_append_conn_error(conn, "%s(%s) failed: %s", + "setsockopt", + PG_TCP_KEEPALIVE_IDLE_STR, + SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf))); + return 0; + } +#endif + + return 1; +} + +/* + * Set the keepalive interval. + */ +static int +setKeepalivesInterval(PGconn *conn) +{ + int interval; + + if (conn->keepalives_interval == NULL) + return 1; + + if (!parse_int_param(conn->keepalives_interval, &interval, conn, + "keepalives_interval")) + return 0; + if (interval < 0) + interval = 0; + +#ifdef TCP_KEEPINTVL + if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPINTVL, + (char *) &interval, sizeof(interval)) < 0) + { + char sebuf[PG_STRERROR_R_BUFLEN]; + + libpq_append_conn_error(conn, "%s(%s) failed: %s", + "setsockopt", + "TCP_KEEPINTVL", + SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf))); + return 0; + } +#endif + + return 1; +} + +/* + * Set the count of lost keepalive packets that will trigger a connection + * break. + */ +static int +setKeepalivesCount(PGconn *conn) +{ + int count; + + if (conn->keepalives_count == NULL) + return 1; + + if (!parse_int_param(conn->keepalives_count, &count, conn, + "keepalives_count")) + return 0; + if (count < 0) + count = 0; + +#ifdef TCP_KEEPCNT + if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPCNT, + (char *) &count, sizeof(count)) < 0) + { + char sebuf[PG_STRERROR_R_BUFLEN]; + + libpq_append_conn_error(conn, "%s(%s) failed: %s", + "setsockopt", + "TCP_KEEPCNT", + SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf))); + return 0; + } +#endif + + return 1; +} +#else /* WIN32 */ +#ifdef SIO_KEEPALIVE_VALS +/* + * Enable keepalives and set the keepalive values on Win32, + * where they are always set in one batch. + * + * CAUTION: This needs to be signal safe, since it's used by PQcancel. + */ +static int +setKeepalivesWin32(pgsocket sock, int idle, int interval) +{ + struct tcp_keepalive ka; + DWORD retsize; + + if (idle <= 0) + idle = 2 * 60 * 60; /* 2 hours = default */ + if (interval <= 0) + interval = 1; /* 1 second = default */ + + ka.onoff = 1; + ka.keepalivetime = idle * 1000; + ka.keepaliveinterval = interval * 1000; + + if (WSAIoctl(sock, + SIO_KEEPALIVE_VALS, + (LPVOID) &ka, + sizeof(ka), + NULL, + 0, + &retsize, + NULL, + NULL) + != 0) + return 0; + return 1; +} + +static int +prepKeepalivesWin32(PGconn *conn) +{ + int idle = -1; + int interval = -1; + + if (conn->keepalives_idle && + !parse_int_param(conn->keepalives_idle, &idle, conn, + "keepalives_idle")) + return 0; + if (conn->keepalives_interval && + !parse_int_param(conn->keepalives_interval, &interval, conn, + "keepalives_interval")) + return 0; + + if (!setKeepalivesWin32(conn->sock, idle, interval)) + { + libpq_append_conn_error(conn, "%s(%s) failed: error code %d", + "WSAIoctl", "SIO_KEEPALIVE_VALS", + WSAGetLastError()); + return 0; + } + return 1; +} +#endif /* SIO_KEEPALIVE_VALS */ +#endif /* WIN32 */ + +/* + * Set the TCP user timeout. + */ +static int +setTCPUserTimeout(PGconn *conn) +{ + int timeout; + + if (conn->pgtcp_user_timeout == NULL) + return 1; + + if (!parse_int_param(conn->pgtcp_user_timeout, &timeout, conn, + "tcp_user_timeout")) + return 0; + + if (timeout < 0) + timeout = 0; + +#ifdef TCP_USER_TIMEOUT + if (setsockopt(conn->sock, IPPROTO_TCP, TCP_USER_TIMEOUT, + (char *) &timeout, sizeof(timeout)) < 0) + { + char sebuf[256]; + + libpq_append_conn_error(conn, "%s(%s) failed: %s", + "setsockopt", + "TCP_USER_TIMEOUT", + SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf))); + return 0; + } +#endif + + return 1; +} + +/* ---------- + * connectDBStart - + * Begin the process of making a connection to the backend. + * + * Returns 1 if successful, 0 if not. + * ---------- + */ +static int +connectDBStart(PGconn *conn) +{ + if (!conn) + return 0; + + if (!conn->options_valid) + goto connect_errReturn; + + /* + * Check for bad linking to backend-internal versions of src/common + * functions (see comments in link-canary.c for the reason we need this). + * Nobody but developers should see this message, so we don't bother + * translating it. + */ + if (!pg_link_canary_is_frontend()) + { + appendPQExpBufferStr(&conn->errorMessage, + "libpq is incorrectly linked to backend functions\n"); + goto connect_errReturn; + } + + /* Ensure our buffers are empty */ + conn->inStart = conn->inCursor = conn->inEnd = 0; + conn->outCount = 0; + + /* + * Set up to try to connect to the first host. (Setting whichhost = -1 is + * a bit of a cheat, but PQconnectPoll will advance it to 0 before + * anything else looks at it.) + */ + conn->whichhost = -1; + conn->try_next_addr = false; + conn->try_next_host = true; + conn->status = CONNECTION_NEEDED; + + /* Also reset the target_server_type state if needed */ + if (conn->target_server_type == SERVER_TYPE_PREFER_STANDBY_PASS2) + conn->target_server_type = SERVER_TYPE_PREFER_STANDBY; + + /* + * The code for processing CONNECTION_NEEDED state is in PQconnectPoll(), + * so that it can easily be re-executed if needed again during the + * asynchronous startup process. However, we must run it once here, + * because callers expect a success return from this routine to mean that + * we are in PGRES_POLLING_WRITING connection state. + */ + if (PQconnectPoll(conn) == PGRES_POLLING_WRITING) + return 1; + +connect_errReturn: + + /* + * If we managed to open a socket, close it immediately rather than + * waiting till PQfinish. (The application cannot have gotten the socket + * from PQsocket yet, so this doesn't risk breaking anything.) + */ + pqDropConnection(conn, true); + conn->status = CONNECTION_BAD; + return 0; +} + + +/* + * connectDBComplete + * + * Block and complete a connection. + * + * Returns 1 on success, 0 on failure. + */ +static int +connectDBComplete(PGconn *conn) +{ + PostgresPollingStatusType flag = PGRES_POLLING_WRITING; + time_t finish_time = ((time_t) -1); + int timeout = 0; + int last_whichhost = -2; /* certainly different from whichhost */ + int last_whichaddr = -2; /* certainly different from whichaddr */ + + if (conn == NULL || conn->status == CONNECTION_BAD) + return 0; + + /* + * Set up a time limit, if connect_timeout isn't zero. + */ + if (conn->connect_timeout != NULL) + { + if (!parse_int_param(conn->connect_timeout, &timeout, conn, + "connect_timeout")) + { + /* mark the connection as bad to report the parsing failure */ + conn->status = CONNECTION_BAD; + return 0; + } + + if (timeout > 0) + { + /* + * Rounding could cause connection to fail unexpectedly quickly; + * to prevent possibly waiting hardly-at-all, insist on at least + * two seconds. + */ + if (timeout < 2) + timeout = 2; + } + else /* negative means 0 */ + timeout = 0; + } + + for (;;) + { + int ret = 0; + + /* + * (Re)start the connect_timeout timer if it's active and we are + * considering a different host than we were last time through. If + * we've already succeeded, though, needn't recalculate. + */ + if (flag != PGRES_POLLING_OK && + timeout > 0 && + (conn->whichhost != last_whichhost || + conn->whichaddr != last_whichaddr)) + { + finish_time = time(NULL) + timeout; + last_whichhost = conn->whichhost; + last_whichaddr = conn->whichaddr; + } + + /* + * Wait, if necessary. Note that the initial state (just after + * PQconnectStart) is to wait for the socket to select for writing. + */ + switch (flag) + { + case PGRES_POLLING_OK: + return 1; /* success! */ + + case PGRES_POLLING_READING: + ret = pqWaitTimed(1, 0, conn, finish_time); + if (ret == -1) + { + /* hard failure, eg select() problem, aborts everything */ + conn->status = CONNECTION_BAD; + return 0; + } + break; + + case PGRES_POLLING_WRITING: + ret = pqWaitTimed(0, 1, conn, finish_time); + if (ret == -1) + { + /* hard failure, eg select() problem, aborts everything */ + conn->status = CONNECTION_BAD; + return 0; + } + break; + + default: + /* Just in case we failed to set it in PQconnectPoll */ + conn->status = CONNECTION_BAD; + return 0; + } + + if (ret == 1) /* connect_timeout elapsed */ + { + /* + * Give up on current server/address, try the next one. + */ + conn->try_next_addr = true; + conn->status = CONNECTION_NEEDED; + } + + /* + * Now try to advance the state machine. + */ + flag = PQconnectPoll(conn); + } +} + +/* ---------------- + * PQconnectPoll + * + * Poll an asynchronous connection. + * + * Returns a PostgresPollingStatusType. + * Before calling this function, use select(2) to determine when data + * has arrived.. + * + * You must call PQfinish whether or not this fails. + * + * This function and PQconnectStart are intended to allow connections to be + * made without blocking the execution of your program on remote I/O. However, + * there are a number of caveats: + * + * o If you call PQtrace, ensure that the stream object into which you trace + * will not block. + * o If you do not supply an IP address for the remote host (i.e. you + * supply a host name instead) then PQconnectStart will block on + * getaddrinfo. You will be fine if using Unix sockets (i.e. by + * supplying neither a host name nor a host address). + * o If your backend wants to use Kerberos authentication then you must + * supply both a host name and a host address, otherwise this function + * may block on gethostname. + * + * ---------------- + */ +PostgresPollingStatusType +PQconnectPoll(PGconn *conn) +{ + bool reset_connection_state_machine = false; + bool need_new_connection = false; + PGresult *res; + char sebuf[PG_STRERROR_R_BUFLEN]; + int optval; + + if (conn == NULL) + return PGRES_POLLING_FAILED; + + /* Get the new data */ + switch (conn->status) + { + /* + * We really shouldn't have been polled in these two cases, but we + * can handle it. + */ + case CONNECTION_BAD: + return PGRES_POLLING_FAILED; + case CONNECTION_OK: + return PGRES_POLLING_OK; + + /* These are reading states */ + case CONNECTION_AWAITING_RESPONSE: + case CONNECTION_AUTH_OK: + case CONNECTION_CHECK_WRITABLE: + case CONNECTION_CONSUME: + case CONNECTION_CHECK_STANDBY: + { + /* Load waiting data */ + int n = pqReadData(conn); + + if (n < 0) + goto error_return; + if (n == 0) + return PGRES_POLLING_READING; + + break; + } + + /* These are writing states, so we just proceed. */ + case CONNECTION_STARTED: + case CONNECTION_MADE: + break; + + /* Special cases: proceed without waiting. */ + case CONNECTION_SSL_STARTUP: + case CONNECTION_NEEDED: + case CONNECTION_GSS_STARTUP: + case CONNECTION_CHECK_TARGET: + break; + + default: + libpq_append_conn_error(conn, "invalid connection state, probably indicative of memory corruption"); + goto error_return; + } + + +keep_going: /* We will come back to here until there is + * nothing left to do. */ + + /* Time to advance to next address, or next host if no more addresses? */ + if (conn->try_next_addr) + { + if (conn->whichaddr < conn->naddr) + { + conn->whichaddr++; + reset_connection_state_machine = true; + } + else + conn->try_next_host = true; + conn->try_next_addr = false; + } + + /* Time to advance to next connhost[] entry? */ + if (conn->try_next_host) + { + pg_conn_host *ch; + struct addrinfo hint; + struct addrinfo *addrlist; + int thisport; + int ret; + char portstr[MAXPGPATH]; + + if (conn->whichhost + 1 < conn->nconnhost) + conn->whichhost++; + else + { + /* + * Oops, no more hosts. + * + * If we are trying to connect in "prefer-standby" mode, then drop + * the standby requirement and start over. + * + * Otherwise, an appropriate error message is already set up, so + * we just need to set the right status. + */ + if (conn->target_server_type == SERVER_TYPE_PREFER_STANDBY && + conn->nconnhost > 0) + { + conn->target_server_type = SERVER_TYPE_PREFER_STANDBY_PASS2; + conn->whichhost = 0; + } + else + goto error_return; + } + + /* Drop any address info for previous host */ + release_conn_addrinfo(conn); + + /* + * Look up info for the new host. On failure, log the problem in + * conn->errorMessage, then loop around to try the next host. (Note + * we don't clear try_next_host until we've succeeded.) + */ + ch = &conn->connhost[conn->whichhost]; + + /* Initialize hint structure */ + MemSet(&hint, 0, sizeof(hint)); + hint.ai_socktype = SOCK_STREAM; + hint.ai_family = AF_UNSPEC; + + /* Figure out the port number we're going to use. */ + if (ch->port == NULL || ch->port[0] == '\0') + thisport = DEF_PGPORT; + else + { + if (!parse_int_param(ch->port, &thisport, conn, "port")) + goto error_return; + + if (thisport < 1 || thisport > 65535) + { + libpq_append_conn_error(conn, "invalid port number: \"%s\"", ch->port); + goto keep_going; + } + } + snprintf(portstr, sizeof(portstr), "%d", thisport); + + /* Use pg_getaddrinfo_all() to resolve the address */ + switch (ch->type) + { + case CHT_HOST_NAME: + ret = pg_getaddrinfo_all(ch->host, portstr, &hint, + &addrlist); + if (ret || !addrlist) + { + libpq_append_conn_error(conn, "could not translate host name \"%s\" to address: %s", + ch->host, gai_strerror(ret)); + goto keep_going; + } + break; + + case CHT_HOST_ADDRESS: + hint.ai_flags = AI_NUMERICHOST; + ret = pg_getaddrinfo_all(ch->hostaddr, portstr, &hint, + &addrlist); + if (ret || !addrlist) + { + libpq_append_conn_error(conn, "could not parse network address \"%s\": %s", + ch->hostaddr, gai_strerror(ret)); + goto keep_going; + } + break; + + case CHT_UNIX_SOCKET: + hint.ai_family = AF_UNIX; + UNIXSOCK_PATH(portstr, thisport, ch->host); + if (strlen(portstr) >= UNIXSOCK_PATH_BUFLEN) + { + libpq_append_conn_error(conn, "Unix-domain socket path \"%s\" is too long (maximum %d bytes)", + portstr, + (int) (UNIXSOCK_PATH_BUFLEN - 1)); + goto keep_going; + } + + /* + * NULL hostname tells pg_getaddrinfo_all to parse the service + * name as a Unix-domain socket path. + */ + ret = pg_getaddrinfo_all(NULL, portstr, &hint, + &addrlist); + if (ret || !addrlist) + { + libpq_append_conn_error(conn, "could not translate Unix-domain socket path \"%s\" to address: %s", + portstr, gai_strerror(ret)); + goto keep_going; + } + break; + } + + /* + * Store a copy of the addrlist in private memory so we can perform + * randomization for load balancing. + */ + ret = store_conn_addrinfo(conn, addrlist); + pg_freeaddrinfo_all(hint.ai_family, addrlist); + if (ret) + goto error_return; /* message already logged */ + + /* + * If random load balancing is enabled we shuffle the addresses. + */ + if (conn->load_balance_type == LOAD_BALANCE_RANDOM) + { + /* + * This is the "inside-out" variant of the Fisher-Yates shuffle + * algorithm. Notionally, we append each new value to the array + * and then swap it with a randomly-chosen array element (possibly + * including itself, else we fail to generate permutations with + * the last integer last). The swap step can be optimized by + * combining it with the insertion. + * + * We don't need to initialize conn->prng_state here, because that + * already happened in connectOptions2. + */ + for (int i = 1; i < conn->naddr; i++) + { + int j = pg_prng_uint64_range(&conn->prng_state, 0, i); + AddrInfo temp = conn->addr[j]; + + conn->addr[j] = conn->addr[i]; + conn->addr[i] = temp; + } + } + + reset_connection_state_machine = true; + conn->try_next_host = false; + } + + /* Reset connection state machine? */ + if (reset_connection_state_machine) + { + /* + * (Re) initialize our connection control variables for a set of + * connection attempts to a single server address. These variables + * must persist across individual connection attempts, but we must + * reset them when we start to consider a new server. + */ + conn->pversion = PG_PROTOCOL(3, 0); + conn->send_appname = true; +#ifdef USE_SSL + /* initialize these values based on SSL mode */ + conn->allow_ssl_try = (conn->sslmode[0] != 'd'); /* "disable" */ + conn->wait_ssl_try = (conn->sslmode[0] == 'a'); /* "allow" */ +#endif +#ifdef ENABLE_GSS + conn->try_gss = (conn->gssencmode[0] != 'd'); /* "disable" */ +#endif + + reset_connection_state_machine = false; + need_new_connection = true; + } + + /* Force a new connection (perhaps to the same server as before)? */ + if (need_new_connection) + { + /* Drop any existing connection */ + pqDropConnection(conn, true); + + /* Reset all state obtained from old server */ + pqDropServerData(conn); + + /* Drop any PGresult we might have, too */ + conn->asyncStatus = PGASYNC_IDLE; + conn->xactStatus = PQTRANS_IDLE; + conn->pipelineStatus = PQ_PIPELINE_OFF; + pqClearAsyncResult(conn); + + /* Reset conn->status to put the state machine in the right state */ + conn->status = CONNECTION_NEEDED; + + need_new_connection = false; + } + + /* Now try to advance the state machine for this connection */ + switch (conn->status) + { + case CONNECTION_NEEDED: + { + /* + * Try to initiate a connection to one of the addresses + * returned by pg_getaddrinfo_all(). conn->whichaddr is the + * next one to try. + * + * The extra level of braces here is historical. It's not + * worth reindenting this whole switch case to remove 'em. + */ + { + char host_addr[NI_MAXHOST]; + int sock_type; + AddrInfo *addr_cur; + + /* + * Advance to next possible host, if we've tried all of + * the addresses for the current host. + */ + if (conn->whichaddr == conn->naddr) + { + conn->try_next_host = true; + goto keep_going; + } + addr_cur = &conn->addr[conn->whichaddr]; + + /* Remember current address for possible use later */ + memcpy(&conn->raddr, &addr_cur->addr, sizeof(SockAddr)); + + /* + * Set connip, too. Note we purposely ignore strdup + * failure; not a big problem if it fails. + */ + if (conn->connip != NULL) + { + free(conn->connip); + conn->connip = NULL; + } + getHostaddr(conn, host_addr, NI_MAXHOST); + if (host_addr[0]) + conn->connip = strdup(host_addr); + + /* Try to create the socket */ + sock_type = SOCK_STREAM; +#ifdef SOCK_CLOEXEC + + /* + * Atomically mark close-on-exec, if possible on this + * platform, so that there isn't a window where a + * subprogram executed by another thread inherits the + * socket. See fallback code below. + */ + sock_type |= SOCK_CLOEXEC; +#endif +#ifdef SOCK_NONBLOCK + + /* + * We might as well skip a system call for nonblocking + * mode too, if we can. + */ + sock_type |= SOCK_NONBLOCK; +#endif + conn->sock = socket(addr_cur->family, sock_type, 0); + if (conn->sock == PGINVALID_SOCKET) + { + int errorno = SOCK_ERRNO; + + /* + * Silently ignore socket() failure if we have more + * addresses to try; this reduces useless chatter in + * cases where the address list includes both IPv4 and + * IPv6 but kernel only accepts one family. + */ + if (conn->whichaddr < conn->naddr || + conn->whichhost + 1 < conn->nconnhost) + { + conn->try_next_addr = true; + goto keep_going; + } + emitHostIdentityInfo(conn, host_addr); + libpq_append_conn_error(conn, "could not create socket: %s", + SOCK_STRERROR(errorno, sebuf, sizeof(sebuf))); + goto error_return; + } + + /* + * Once we've identified a target address, all errors + * except the preceding socket()-failure case should be + * prefixed with host-identity information. (If the + * connection succeeds, the contents of conn->errorMessage + * won't matter, so this is harmless.) + */ + emitHostIdentityInfo(conn, host_addr); + + /* + * Select socket options: no delay of outgoing data for + * TCP sockets, nonblock mode, close-on-exec. Try the + * next address if any of this fails. + */ + if (addr_cur->family != AF_UNIX) + { + if (!connectNoDelay(conn)) + { + /* error message already created */ + conn->try_next_addr = true; + goto keep_going; + } + } +#ifndef SOCK_NONBLOCK + if (!pg_set_noblock(conn->sock)) + { + libpq_append_conn_error(conn, "could not set socket to nonblocking mode: %s", + SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf))); + conn->try_next_addr = true; + goto keep_going; + } +#endif + +#ifndef SOCK_CLOEXEC +#ifdef F_SETFD + if (fcntl(conn->sock, F_SETFD, FD_CLOEXEC) == -1) + { + libpq_append_conn_error(conn, "could not set socket to close-on-exec mode: %s", + SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf))); + conn->try_next_addr = true; + goto keep_going; + } +#endif /* F_SETFD */ +#endif + + if (addr_cur->family != AF_UNIX) + { +#ifndef WIN32 + int on = 1; +#endif + int usekeepalives = useKeepalives(conn); + int err = 0; + + if (usekeepalives < 0) + { + libpq_append_conn_error(conn, "keepalives parameter must be an integer"); + err = 1; + } + else if (usekeepalives == 0) + { + /* Do nothing */ + } +#ifndef WIN32 + else if (setsockopt(conn->sock, + SOL_SOCKET, SO_KEEPALIVE, + (char *) &on, sizeof(on)) < 0) + { + libpq_append_conn_error(conn, "%s(%s) failed: %s", + "setsockopt", + "SO_KEEPALIVE", + SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf))); + err = 1; + } + else if (!setKeepalivesIdle(conn) + || !setKeepalivesInterval(conn) + || !setKeepalivesCount(conn)) + err = 1; +#else /* WIN32 */ +#ifdef SIO_KEEPALIVE_VALS + else if (!prepKeepalivesWin32(conn)) + err = 1; +#endif /* SIO_KEEPALIVE_VALS */ +#endif /* WIN32 */ + else if (!setTCPUserTimeout(conn)) + err = 1; + + if (err) + { + conn->try_next_addr = true; + goto keep_going; + } + } + + /*---------- + * We have three methods of blocking SIGPIPE during + * send() calls to this socket: + * + * - setsockopt(sock, SO_NOSIGPIPE) + * - send(sock, ..., MSG_NOSIGNAL) + * - setting the signal mask to SIG_IGN during send() + * + * The third method requires three syscalls per send, + * so we prefer either of the first two, but they are + * less portable. The state is tracked in the following + * members of PGconn: + * + * conn->sigpipe_so - we have set up SO_NOSIGPIPE + * conn->sigpipe_flag - we're specifying MSG_NOSIGNAL + * + * If we can use SO_NOSIGPIPE, then set sigpipe_so here + * and we're done. Otherwise, set sigpipe_flag so that + * we will try MSG_NOSIGNAL on sends. If we get an error + * with MSG_NOSIGNAL, we'll clear that flag and revert to + * signal masking. + *---------- + */ + conn->sigpipe_so = false; +#ifdef MSG_NOSIGNAL + conn->sigpipe_flag = true; +#else + conn->sigpipe_flag = false; +#endif /* MSG_NOSIGNAL */ + +#ifdef SO_NOSIGPIPE + optval = 1; + if (setsockopt(conn->sock, SOL_SOCKET, SO_NOSIGPIPE, + (char *) &optval, sizeof(optval)) == 0) + { + conn->sigpipe_so = true; + conn->sigpipe_flag = false; + } +#endif /* SO_NOSIGPIPE */ + + /* + * Start/make connection. This should not block, since we + * are in nonblock mode. If it does, well, too bad. + */ + if (connect(conn->sock, (struct sockaddr *) &addr_cur->addr.addr, + addr_cur->addr.salen) < 0) + { + if (SOCK_ERRNO == EINPROGRESS || +#ifdef WIN32 + SOCK_ERRNO == EWOULDBLOCK || +#endif + SOCK_ERRNO == EINTR) + { + /* + * This is fine - we're in non-blocking mode, and + * the connection is in progress. Tell caller to + * wait for write-ready on socket. + */ + conn->status = CONNECTION_STARTED; + return PGRES_POLLING_WRITING; + } + /* otherwise, trouble */ + } + else + { + /* + * Hm, we're connected already --- seems the "nonblock + * connection" wasn't. Advance the state machine and + * go do the next stuff. + */ + conn->status = CONNECTION_STARTED; + goto keep_going; + } + + /* + * This connection failed. Add the error report to + * conn->errorMessage, then try the next address if any. + */ + connectFailureMessage(conn, SOCK_ERRNO); + conn->try_next_addr = true; + goto keep_going; + } + } + + case CONNECTION_STARTED: + { + socklen_t optlen = sizeof(optval); + + /* + * Write ready, since we've made it here, so the connection + * has been made ... or has failed. + */ + + /* + * Now check (using getsockopt) that there is not an error + * state waiting for us on the socket. + */ + + if (getsockopt(conn->sock, SOL_SOCKET, SO_ERROR, + (char *) &optval, &optlen) == -1) + { + libpq_append_conn_error(conn, "could not get socket error status: %s", + SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf))); + goto error_return; + } + else if (optval != 0) + { + /* + * When using a nonblocking connect, we will typically see + * connect failures at this point, so provide a friendly + * error message. + */ + connectFailureMessage(conn, optval); + + /* + * Try the next address if any, just as in the case where + * connect() returned failure immediately. + */ + conn->try_next_addr = true; + goto keep_going; + } + + /* Fill in the client address */ + conn->laddr.salen = sizeof(conn->laddr.addr); + if (getsockname(conn->sock, + (struct sockaddr *) &conn->laddr.addr, + &conn->laddr.salen) < 0) + { + libpq_append_conn_error(conn, "could not get client address from socket: %s", + SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf))); + goto error_return; + } + + /* + * Make sure we can write before advancing to next step. + */ + conn->status = CONNECTION_MADE; + return PGRES_POLLING_WRITING; + } + + case CONNECTION_MADE: + { + char *startpacket; + int packetlen; + + /* + * Implement requirepeer check, if requested and it's a + * Unix-domain socket. + */ + if (conn->requirepeer && conn->requirepeer[0] && + conn->raddr.addr.ss_family == AF_UNIX) + { +#ifndef WIN32 + char *remote_username; +#endif + uid_t uid; + gid_t gid; + + errno = 0; + if (getpeereid(conn->sock, &uid, &gid) != 0) + { + /* + * Provide special error message if getpeereid is a + * stub + */ + if (errno == ENOSYS) + libpq_append_conn_error(conn, "requirepeer parameter is not supported on this platform"); + else + libpq_append_conn_error(conn, "could not get peer credentials: %s", + strerror_r(errno, sebuf, sizeof(sebuf))); + goto error_return; + } + +#ifndef WIN32 + remote_username = pg_fe_getusername(uid, + &conn->errorMessage); + if (remote_username == NULL) + goto error_return; /* message already logged */ + + if (strcmp(remote_username, conn->requirepeer) != 0) + { + libpq_append_conn_error(conn, "requirepeer specifies \"%s\", but actual peer user name is \"%s\"", + conn->requirepeer, remote_username); + free(remote_username); + goto error_return; + } + free(remote_username); +#else /* WIN32 */ + /* should have failed with ENOSYS above */ + Assert(false); +#endif /* WIN32 */ + } + + if (conn->raddr.addr.ss_family == AF_UNIX) + { + /* Don't request SSL or GSSAPI over Unix sockets */ +#ifdef USE_SSL + conn->allow_ssl_try = false; +#endif +#ifdef ENABLE_GSS + conn->try_gss = false; +#endif + } + +#ifdef ENABLE_GSS + + /* + * If GSSAPI encryption is enabled, then call + * pg_GSS_have_cred_cache() which will return true if we can + * acquire credentials (and give us a handle to use in + * conn->gcred), and then send a packet to the server asking + * for GSSAPI Encryption (and skip past SSL negotiation and + * regular startup below). + */ + if (conn->try_gss && !conn->gctx) + conn->try_gss = pg_GSS_have_cred_cache(&conn->gcred); + if (conn->try_gss && !conn->gctx) + { + ProtocolVersion pv = pg_hton32(NEGOTIATE_GSS_CODE); + + if (pqPacketSend(conn, 0, &pv, sizeof(pv)) != STATUS_OK) + { + libpq_append_conn_error(conn, "could not send GSSAPI negotiation packet: %s", + SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf))); + goto error_return; + } + + /* Ok, wait for response */ + conn->status = CONNECTION_GSS_STARTUP; + return PGRES_POLLING_READING; + } + else if (!conn->gctx && conn->gssencmode[0] == 'r') + { + libpq_append_conn_error(conn, + "GSSAPI encryption required but was impossible (possibly no credential cache, no server support, or using a local socket)"); + goto error_return; + } +#endif + +#ifdef USE_SSL + + /* + * Enable the libcrypto callbacks before checking if SSL needs + * to be done. This is done before sending the startup packet + * as depending on the type of authentication done, like MD5 + * or SCRAM that use cryptohashes, the callbacks would be + * required even without a SSL connection + */ + if (pqsecure_initialize(conn, false, true) < 0) + goto error_return; + + /* + * If SSL is enabled and we haven't already got encryption of + * some sort running, request SSL instead of sending the + * startup message. + */ + if (conn->allow_ssl_try && !conn->wait_ssl_try && + !conn->ssl_in_use +#ifdef ENABLE_GSS + && !conn->gssenc +#endif + ) + { + ProtocolVersion pv; + + /* + * Send the SSL request packet. + * + * Theoretically, this could block, but it really + * shouldn't since we only got here if the socket is + * write-ready. + */ + pv = pg_hton32(NEGOTIATE_SSL_CODE); + if (pqPacketSend(conn, 0, &pv, sizeof(pv)) != STATUS_OK) + { + libpq_append_conn_error(conn, "could not send SSL negotiation packet: %s", + SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf))); + goto error_return; + } + /* Ok, wait for response */ + conn->status = CONNECTION_SSL_STARTUP; + return PGRES_POLLING_READING; + } +#endif /* USE_SSL */ + + /* + * Build the startup packet. + */ + startpacket = pqBuildStartupPacket3(conn, &packetlen, + EnvironmentOptions); + if (!startpacket) + { + libpq_append_conn_error(conn, "out of memory"); + goto error_return; + } + + /* + * Send the startup packet. + * + * Theoretically, this could block, but it really shouldn't + * since we only got here if the socket is write-ready. + */ + if (pqPacketSend(conn, 0, startpacket, packetlen) != STATUS_OK) + { + libpq_append_conn_error(conn, "could not send startup packet: %s", + SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf))); + free(startpacket); + goto error_return; + } + + free(startpacket); + + conn->status = CONNECTION_AWAITING_RESPONSE; + return PGRES_POLLING_READING; + } + + /* + * Handle SSL negotiation: wait for postmaster messages and + * respond as necessary. + */ + case CONNECTION_SSL_STARTUP: + { +#ifdef USE_SSL + PostgresPollingStatusType pollres; + + /* + * On first time through, get the postmaster's response to our + * SSL negotiation packet. + */ + if (!conn->ssl_in_use) + { + /* + * We use pqReadData here since it has the logic to + * distinguish no-data-yet from connection closure. Since + * conn->ssl isn't set, a plain recv() will occur. + */ + char SSLok; + int rdresult; + + rdresult = pqReadData(conn); + if (rdresult < 0) + { + /* errorMessage is already filled in */ + goto error_return; + } + if (rdresult == 0) + { + /* caller failed to wait for data */ + return PGRES_POLLING_READING; + } + if (pqGetc(&SSLok, conn) < 0) + { + /* should not happen really */ + return PGRES_POLLING_READING; + } + if (SSLok == 'S') + { + /* mark byte consumed */ + conn->inStart = conn->inCursor; + + /* + * Set up global SSL state if required. The crypto + * state has already been set if libpq took care of + * doing that, so there is no need to make that happen + * again. + */ + if (pqsecure_initialize(conn, true, false) != 0) + goto error_return; + } + else if (SSLok == 'N') + { + /* mark byte consumed */ + conn->inStart = conn->inCursor; + /* OK to do without SSL? */ + if (conn->sslmode[0] == 'r' || /* "require" */ + conn->sslmode[0] == 'v') /* "verify-ca" or + * "verify-full" */ + { + /* Require SSL, but server does not want it */ + libpq_append_conn_error(conn, "server does not support SSL, but SSL was required"); + goto error_return; + } + /* Otherwise, proceed with normal startup */ + conn->allow_ssl_try = false; + /* We can proceed using this connection */ + conn->status = CONNECTION_MADE; + return PGRES_POLLING_WRITING; + } + else if (SSLok == 'E') + { + /* + * Server failure of some sort, such as failure to + * fork a backend process. We need to process and + * report the error message, which might be formatted + * according to either protocol 2 or protocol 3. + * Rather than duplicate the code for that, we flip + * into AWAITING_RESPONSE state and let the code there + * deal with it. Note we have *not* consumed the "E" + * byte here. + */ + conn->status = CONNECTION_AWAITING_RESPONSE; + goto keep_going; + } + else + { + libpq_append_conn_error(conn, "received invalid response to SSL negotiation: %c", + SSLok); + goto error_return; + } + } + + /* + * Begin or continue the SSL negotiation process. + */ + pollres = pqsecure_open_client(conn); + if (pollres == PGRES_POLLING_OK) + { + /* + * At this point we should have no data already buffered. + * If we do, it was received before we performed the SSL + * handshake, so it wasn't encrypted and indeed may have + * been injected by a man-in-the-middle. + */ + if (conn->inCursor != conn->inEnd) + { + libpq_append_conn_error(conn, "received unencrypted data after SSL response"); + goto error_return; + } + + /* SSL handshake done, ready to send startup packet */ + conn->status = CONNECTION_MADE; + return PGRES_POLLING_WRITING; + } + if (pollres == PGRES_POLLING_FAILED) + { + /* + * Failed ... if sslmode is "prefer" then do a non-SSL + * retry + */ + if (conn->sslmode[0] == 'p' /* "prefer" */ + && conn->allow_ssl_try /* redundant? */ + && !conn->wait_ssl_try) /* redundant? */ + { + /* only retry once */ + conn->allow_ssl_try = false; + need_new_connection = true; + goto keep_going; + } + /* Else it's a hard failure */ + goto error_return; + } + /* Else, return POLLING_READING or POLLING_WRITING status */ + return pollres; +#else /* !USE_SSL */ + /* can't get here */ + goto error_return; +#endif /* USE_SSL */ + } + + case CONNECTION_GSS_STARTUP: + { +#ifdef ENABLE_GSS + PostgresPollingStatusType pollres; + + /* + * If we haven't yet, get the postmaster's response to our + * negotiation packet + */ + if (conn->try_gss && !conn->gctx) + { + char gss_ok; + int rdresult = pqReadData(conn); + + if (rdresult < 0) + /* pqReadData fills in error message */ + goto error_return; + else if (rdresult == 0) + /* caller failed to wait for data */ + return PGRES_POLLING_READING; + if (pqGetc(&gss_ok, conn) < 0) + /* shouldn't happen... */ + return PGRES_POLLING_READING; + + if (gss_ok == 'E') + { + /* + * Server failure of some sort. Assume it's a + * protocol version support failure, and let's see if + * we can't recover (if it's not, we'll get a better + * error message on retry). Server gets fussy if we + * don't hang up the socket, though. + */ + conn->try_gss = false; + need_new_connection = true; + goto keep_going; + } + + /* mark byte consumed */ + conn->inStart = conn->inCursor; + + if (gss_ok == 'N') + { + /* Server doesn't want GSSAPI; fall back if we can */ + if (conn->gssencmode[0] == 'r') + { + libpq_append_conn_error(conn, "server doesn't support GSSAPI encryption, but it was required"); + goto error_return; + } + + conn->try_gss = false; + /* We can proceed using this connection */ + conn->status = CONNECTION_MADE; + return PGRES_POLLING_WRITING; + } + else if (gss_ok != 'G') + { + libpq_append_conn_error(conn, "received invalid response to GSSAPI negotiation: %c", + gss_ok); + goto error_return; + } + } + + /* Begin or continue GSSAPI negotiation */ + pollres = pqsecure_open_gss(conn); + if (pollres == PGRES_POLLING_OK) + { + /* + * At this point we should have no data already buffered. + * If we do, it was received before we performed the GSS + * handshake, so it wasn't encrypted and indeed may have + * been injected by a man-in-the-middle. + */ + if (conn->inCursor != conn->inEnd) + { + libpq_append_conn_error(conn, "received unencrypted data after GSSAPI encryption response"); + goto error_return; + } + + /* All set for startup packet */ + conn->status = CONNECTION_MADE; + return PGRES_POLLING_WRITING; + } + else if (pollres == PGRES_POLLING_FAILED) + { + if (conn->gssencmode[0] == 'p') + { + /* + * We failed, but we can retry on "prefer". Have to + * drop the current connection to do so, though. + */ + conn->try_gss = false; + need_new_connection = true; + goto keep_going; + } + /* Else it's a hard failure */ + goto error_return; + } + /* Else, return POLLING_READING or POLLING_WRITING status */ + return pollres; +#else /* !ENABLE_GSS */ + /* unreachable */ + goto error_return; +#endif /* ENABLE_GSS */ + } + + /* + * Handle authentication exchange: wait for postmaster messages + * and respond as necessary. + */ + case CONNECTION_AWAITING_RESPONSE: + { + char beresp; + int msgLength; + int avail; + AuthRequest areq; + int res; + + /* + * Scan the message from current point (note that if we find + * the message is incomplete, we will return without advancing + * inStart, and resume here next time). + */ + conn->inCursor = conn->inStart; + + /* Read type byte */ + if (pqGetc(&beresp, conn)) + { + /* We'll come back when there is more data */ + return PGRES_POLLING_READING; + } + + /* + * Validate message type: we expect only an authentication + * request, NegotiateProtocolVersion, or an error here. + * Anything else probably means it's not Postgres on the other + * end at all. + */ + if (!(beresp == 'R' || beresp == 'v' || beresp == 'E')) + { + libpq_append_conn_error(conn, "expected authentication request from server, but received %c", + beresp); + goto error_return; + } + + /* Read message length word */ + if (pqGetInt(&msgLength, 4, conn)) + { + /* We'll come back when there is more data */ + return PGRES_POLLING_READING; + } + + /* + * Try to validate message length before using it. + * + * Authentication requests can't be very large, although GSS + * auth requests may not be that small. Same for + * NegotiateProtocolVersion. + * + * Errors can be a little larger, but not huge. If we see a + * large apparent length in an error, it means we're really + * talking to a pre-3.0-protocol server; cope. (Before + * version 14, the server also used the old protocol for + * errors that happened before processing the startup packet.) + */ + if (beresp == 'R' && (msgLength < 8 || msgLength > 2000)) + { + libpq_append_conn_error(conn, "received invalid authentication request"); + goto error_return; + } + if (beresp == 'v' && (msgLength < 8 || msgLength > 2000)) + { + libpq_append_conn_error(conn, "received invalid protocol negotiation message"); + goto error_return; + } + +#define MAX_ERRLEN 30000 + if (beresp == 'E' && (msgLength < 8 || msgLength > MAX_ERRLEN)) + { + /* Handle error from a pre-3.0 server */ + conn->inCursor = conn->inStart + 1; /* reread data */ + if (pqGets_append(&conn->errorMessage, conn)) + { + /* + * We may not have authenticated the server yet, so + * don't let the buffer grow forever. + */ + avail = conn->inEnd - conn->inCursor; + if (avail > MAX_ERRLEN) + { + libpq_append_conn_error(conn, "received invalid error message"); + goto error_return; + } + + /* We'll come back when there is more data */ + return PGRES_POLLING_READING; + } + /* OK, we read the message; mark data consumed */ + conn->inStart = conn->inCursor; + + /* + * Before 7.2, the postmaster didn't always end its + * messages with a newline, so add one if needed to + * conform to libpq conventions. + */ + if (conn->errorMessage.len == 0 || + conn->errorMessage.data[conn->errorMessage.len - 1] != '\n') + { + appendPQExpBufferChar(&conn->errorMessage, '\n'); + } + + goto error_return; + } +#undef MAX_ERRLEN + + /* + * Can't process if message body isn't all here yet. + * + * After this check passes, any further EOF during parsing + * implies that the server sent a bad/truncated message. + * Reading more bytes won't help in that case, so don't return + * PGRES_POLLING_READING after this point. + */ + msgLength -= 4; + avail = conn->inEnd - conn->inCursor; + if (avail < msgLength) + { + /* + * Before returning, try to enlarge the input buffer if + * needed to hold the whole message; see notes in + * pqParseInput3. + */ + if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength, + conn)) + goto error_return; + /* We'll come back when there is more data */ + return PGRES_POLLING_READING; + } + + /* Handle errors. */ + if (beresp == 'E') + { + if (pqGetErrorNotice3(conn, true)) + { + libpq_append_conn_error(conn, "received invalid error message"); + goto error_return; + } + /* OK, we read the message; mark data consumed */ + conn->inStart = conn->inCursor; + + /* + * If error is "cannot connect now", try the next host if + * any (but we don't want to consider additional addresses + * for this host, nor is there much point in changing SSL + * or GSS mode). This is helpful when dealing with + * standby servers that might not be in hot-standby state. + */ + if (strcmp(conn->last_sqlstate, + ERRCODE_CANNOT_CONNECT_NOW) == 0) + { + conn->try_next_host = true; + goto keep_going; + } + + /* Check to see if we should mention pgpassfile */ + pgpassfileWarning(conn); + +#ifdef ENABLE_GSS + + /* + * If gssencmode is "prefer" and we're using GSSAPI, retry + * without it. + */ + if (conn->gssenc && conn->gssencmode[0] == 'p') + { + /* only retry once */ + conn->try_gss = false; + need_new_connection = true; + goto keep_going; + } +#endif + +#ifdef USE_SSL + + /* + * if sslmode is "allow" and we haven't tried an SSL + * connection already, then retry with an SSL connection + */ + if (conn->sslmode[0] == 'a' /* "allow" */ + && !conn->ssl_in_use + && conn->allow_ssl_try + && conn->wait_ssl_try) + { + /* only retry once */ + conn->wait_ssl_try = false; + need_new_connection = true; + goto keep_going; + } + + /* + * if sslmode is "prefer" and we're in an SSL connection, + * then do a non-SSL retry + */ + if (conn->sslmode[0] == 'p' /* "prefer" */ + && conn->ssl_in_use + && conn->allow_ssl_try /* redundant? */ + && !conn->wait_ssl_try) /* redundant? */ + { + /* only retry once */ + conn->allow_ssl_try = false; + need_new_connection = true; + goto keep_going; + } +#endif + + goto error_return; + } + else if (beresp == 'v') + { + if (pqGetNegotiateProtocolVersion3(conn)) + { + libpq_append_conn_error(conn, "received invalid protocol negotiation message"); + goto error_return; + } + /* OK, we read the message; mark data consumed */ + conn->inStart = conn->inCursor; + goto error_return; + } + + /* It is an authentication request. */ + conn->auth_req_received = true; + + /* Get the type of request. */ + if (pqGetInt((int *) &areq, 4, conn)) + { + /* can't happen because we checked the length already */ + libpq_append_conn_error(conn, "received invalid authentication request"); + goto error_return; + } + msgLength -= 4; + + /* + * Process the rest of the authentication request message, and + * respond to it if necessary. + * + * Note that conn->pghost must be non-NULL if we are going to + * avoid the Kerberos code doing a hostname look-up. + */ + res = pg_fe_sendauth(areq, msgLength, conn); + + /* OK, we have processed the message; mark data consumed */ + conn->inStart = conn->inCursor; + + if (res != STATUS_OK) + goto error_return; + + /* + * Just make sure that any data sent by pg_fe_sendauth is + * flushed out. Although this theoretically could block, it + * really shouldn't since we don't send large auth responses. + */ + if (pqFlush(conn)) + goto error_return; + + if (areq == AUTH_REQ_OK) + { + /* We are done with authentication exchange */ + conn->status = CONNECTION_AUTH_OK; + + /* + * Set asyncStatus so that PQgetResult will think that + * what comes back next is the result of a query. See + * below. + */ + conn->asyncStatus = PGASYNC_BUSY; + } + + /* Look to see if we have more data yet. */ + goto keep_going; + } + + case CONNECTION_AUTH_OK: + { + /* + * Now we expect to hear from the backend. A ReadyForQuery + * message indicates that startup is successful, but we might + * also get an Error message indicating failure. (Notice + * messages indicating nonfatal warnings are also allowed by + * the protocol, as are ParameterStatus and BackendKeyData + * messages.) Easiest way to handle this is to let + * PQgetResult() read the messages. We just have to fake it + * out about the state of the connection, by setting + * asyncStatus = PGASYNC_BUSY (done above). + */ + + if (PQisBusy(conn)) + return PGRES_POLLING_READING; + + res = PQgetResult(conn); + + /* + * NULL return indicating we have gone to IDLE state is + * expected + */ + if (res) + { + if (res->resultStatus != PGRES_FATAL_ERROR) + libpq_append_conn_error(conn, "unexpected message from server during startup"); + else if (conn->send_appname && + (conn->appname || conn->fbappname)) + { + /* + * If we tried to send application_name, check to see + * if the error is about that --- pre-9.0 servers will + * reject it at this stage of the process. If so, + * close the connection and retry without sending + * application_name. We could possibly get a false + * SQLSTATE match here and retry uselessly, but there + * seems no great harm in that; we'll just get the + * same error again if it's unrelated. + */ + const char *sqlstate; + + sqlstate = PQresultErrorField(res, PG_DIAG_SQLSTATE); + if (sqlstate && + strcmp(sqlstate, ERRCODE_APPNAME_UNKNOWN) == 0) + { + PQclear(res); + conn->send_appname = false; + need_new_connection = true; + goto keep_going; + } + } + + /* + * if the resultStatus is FATAL, then conn->errorMessage + * already has a copy of the error; needn't copy it back. + * But add a newline if it's not there already, since + * postmaster error messages may not have one. + */ + if (conn->errorMessage.len <= 0 || + conn->errorMessage.data[conn->errorMessage.len - 1] != '\n') + appendPQExpBufferChar(&conn->errorMessage, '\n'); + PQclear(res); + goto error_return; + } + + /* Almost there now ... */ + conn->status = CONNECTION_CHECK_TARGET; + goto keep_going; + } + + case CONNECTION_CHECK_TARGET: + { + /* + * If a read-write, read-only, primary, or standby connection + * is required, see if we have one. + */ + if (conn->target_server_type == SERVER_TYPE_READ_WRITE || + conn->target_server_type == SERVER_TYPE_READ_ONLY) + { + bool read_only_server; + + /* + * If the server didn't report + * "default_transaction_read_only" or "in_hot_standby" at + * startup, we must determine its state by sending the + * query "SHOW transaction_read_only". This GUC exists in + * all server versions that support 3.0 protocol. + */ + if (conn->default_transaction_read_only == PG_BOOL_UNKNOWN || + conn->in_hot_standby == PG_BOOL_UNKNOWN) + { + /* + * We use PQsendQueryContinue so that + * conn->errorMessage does not get cleared. We need + * to preserve any error messages related to previous + * hosts we have tried and failed to connect to. + */ + conn->status = CONNECTION_OK; + if (!PQsendQueryContinue(conn, + "SHOW transaction_read_only")) + goto error_return; + /* We'll return to this state when we have the answer */ + conn->status = CONNECTION_CHECK_WRITABLE; + return PGRES_POLLING_READING; + } + + /* OK, we can make the test */ + read_only_server = + (conn->default_transaction_read_only == PG_BOOL_YES || + conn->in_hot_standby == PG_BOOL_YES); + + if ((conn->target_server_type == SERVER_TYPE_READ_WRITE) ? + read_only_server : !read_only_server) + { + /* Wrong server state, reject and try the next host */ + if (conn->target_server_type == SERVER_TYPE_READ_WRITE) + libpq_append_conn_error(conn, "session is read-only"); + else + libpq_append_conn_error(conn, "session is not read-only"); + + /* Close connection politely. */ + conn->status = CONNECTION_OK; + sendTerminateConn(conn); + + /* + * Try next host if any, but we don't want to consider + * additional addresses for this host. + */ + conn->try_next_host = true; + goto keep_going; + } + } + else if (conn->target_server_type == SERVER_TYPE_PRIMARY || + conn->target_server_type == SERVER_TYPE_STANDBY || + conn->target_server_type == SERVER_TYPE_PREFER_STANDBY) + { + /* + * If the server didn't report "in_hot_standby" at + * startup, we must determine its state by sending the + * query "SELECT pg_catalog.pg_is_in_recovery()". Servers + * before 9.0 don't have that function, but by the same + * token they don't have any standby mode, so we may just + * assume the result. + */ + if (conn->sversion < 90000) + conn->in_hot_standby = PG_BOOL_NO; + + if (conn->in_hot_standby == PG_BOOL_UNKNOWN) + { + /* + * We use PQsendQueryContinue so that + * conn->errorMessage does not get cleared. We need + * to preserve any error messages related to previous + * hosts we have tried and failed to connect to. + */ + conn->status = CONNECTION_OK; + if (!PQsendQueryContinue(conn, + "SELECT pg_catalog.pg_is_in_recovery()")) + goto error_return; + /* We'll return to this state when we have the answer */ + conn->status = CONNECTION_CHECK_STANDBY; + return PGRES_POLLING_READING; + } + + /* OK, we can make the test */ + if ((conn->target_server_type == SERVER_TYPE_PRIMARY) ? + (conn->in_hot_standby == PG_BOOL_YES) : + (conn->in_hot_standby == PG_BOOL_NO)) + { + /* Wrong server state, reject and try the next host */ + if (conn->target_server_type == SERVER_TYPE_PRIMARY) + libpq_append_conn_error(conn, "server is in hot standby mode"); + else + libpq_append_conn_error(conn, "server is not in hot standby mode"); + + /* Close connection politely. */ + conn->status = CONNECTION_OK; + sendTerminateConn(conn); + + /* + * Try next host if any, but we don't want to consider + * additional addresses for this host. + */ + conn->try_next_host = true; + goto keep_going; + } + } + + /* We can release the address list now. */ + release_conn_addrinfo(conn); + + /* + * Contents of conn->errorMessage are no longer interesting + * (and it seems some clients expect it to be empty after a + * successful connection). + */ + pqClearConnErrorState(conn); + + /* We are open for business! */ + conn->status = CONNECTION_OK; + return PGRES_POLLING_OK; + } + + case CONNECTION_CONSUME: + { + /* + * This state just makes sure the connection is idle after + * we've obtained the result of a SHOW or SELECT query. Once + * we're clear, return to CONNECTION_CHECK_TARGET state to + * decide what to do next. We must transiently set status = + * CONNECTION_OK in order to use the result-consuming + * subroutines. + */ + conn->status = CONNECTION_OK; + if (!PQconsumeInput(conn)) + goto error_return; + + if (PQisBusy(conn)) + { + conn->status = CONNECTION_CONSUME; + return PGRES_POLLING_READING; + } + + /* Call PQgetResult() again until we get a NULL result */ + res = PQgetResult(conn); + if (res != NULL) + { + PQclear(res); + conn->status = CONNECTION_CONSUME; + return PGRES_POLLING_READING; + } + + conn->status = CONNECTION_CHECK_TARGET; + goto keep_going; + } + + case CONNECTION_CHECK_WRITABLE: + { + /* + * Waiting for result of "SHOW transaction_read_only". We + * must transiently set status = CONNECTION_OK in order to use + * the result-consuming subroutines. + */ + conn->status = CONNECTION_OK; + if (!PQconsumeInput(conn)) + goto error_return; + + if (PQisBusy(conn)) + { + conn->status = CONNECTION_CHECK_WRITABLE; + return PGRES_POLLING_READING; + } + + res = PQgetResult(conn); + if (res && PQresultStatus(res) == PGRES_TUPLES_OK && + PQntuples(res) == 1) + { + char *val = PQgetvalue(res, 0, 0); + + /* + * "transaction_read_only = on" proves that at least one + * of default_transaction_read_only and in_hot_standby is + * on, but we don't actually know which. We don't care + * though for the purpose of identifying a read-only + * session, so satisfy the CONNECTION_CHECK_TARGET code by + * claiming they are both on. On the other hand, if it's + * a read-write session, they are certainly both off. + */ + if (strncmp(val, "on", 2) == 0) + { + conn->default_transaction_read_only = PG_BOOL_YES; + conn->in_hot_standby = PG_BOOL_YES; + } + else + { + conn->default_transaction_read_only = PG_BOOL_NO; + conn->in_hot_standby = PG_BOOL_NO; + } + PQclear(res); + + /* Finish reading messages before continuing */ + conn->status = CONNECTION_CONSUME; + goto keep_going; + } + + /* Something went wrong with "SHOW transaction_read_only". */ + PQclear(res); + + /* Append error report to conn->errorMessage. */ + libpq_append_conn_error(conn, "\"%s\" failed", + "SHOW transaction_read_only"); + + /* Close connection politely. */ + conn->status = CONNECTION_OK; + sendTerminateConn(conn); + + /* Try next host. */ + conn->try_next_host = true; + goto keep_going; + } + + case CONNECTION_CHECK_STANDBY: + { + /* + * Waiting for result of "SELECT pg_is_in_recovery()". We + * must transiently set status = CONNECTION_OK in order to use + * the result-consuming subroutines. + */ + conn->status = CONNECTION_OK; + if (!PQconsumeInput(conn)) + goto error_return; + + if (PQisBusy(conn)) + { + conn->status = CONNECTION_CHECK_STANDBY; + return PGRES_POLLING_READING; + } + + res = PQgetResult(conn); + if (res && PQresultStatus(res) == PGRES_TUPLES_OK && + PQntuples(res) == 1) + { + char *val = PQgetvalue(res, 0, 0); + + if (strncmp(val, "t", 1) == 0) + conn->in_hot_standby = PG_BOOL_YES; + else + conn->in_hot_standby = PG_BOOL_NO; + PQclear(res); + + /* Finish reading messages before continuing */ + conn->status = CONNECTION_CONSUME; + goto keep_going; + } + + /* Something went wrong with "SELECT pg_is_in_recovery()". */ + PQclear(res); + + /* Append error report to conn->errorMessage. */ + libpq_append_conn_error(conn, "\"%s\" failed", + "SELECT pg_is_in_recovery()"); + + /* Close connection politely. */ + conn->status = CONNECTION_OK; + sendTerminateConn(conn); + + /* Try next host. */ + conn->try_next_host = true; + goto keep_going; + } + + default: + libpq_append_conn_error(conn, + "invalid connection state %d, probably indicative of memory corruption", + conn->status); + goto error_return; + } + + /* Unreachable */ + +error_return: + + /* + * We used to close the socket at this point, but that makes it awkward + * for those above us if they wish to remove this socket from their own + * records (an fd_set for example). We'll just have this socket closed + * when PQfinish is called (which is compulsory even after an error, since + * the connection structure must be freed). + */ + conn->status = CONNECTION_BAD; + return PGRES_POLLING_FAILED; +} + + +/* + * internal_ping + * Determine if a server is running and if we can connect to it. + * + * The argument is a connection that's been started, but not completed. + */ +static PGPing +internal_ping(PGconn *conn) +{ + /* Say "no attempt" if we never got to PQconnectPoll */ + if (!conn || !conn->options_valid) + return PQPING_NO_ATTEMPT; + + /* Attempt to complete the connection */ + if (conn->status != CONNECTION_BAD) + (void) connectDBComplete(conn); + + /* Definitely OK if we succeeded */ + if (conn->status != CONNECTION_BAD) + return PQPING_OK; + + /* + * Here begins the interesting part of "ping": determine the cause of the + * failure in sufficient detail to decide what to return. We do not want + * to report that the server is not up just because we didn't have a valid + * password, for example. In fact, any sort of authentication request + * implies the server is up. (We need this check since the libpq side of + * things might have pulled the plug on the connection before getting an + * error as such from the postmaster.) + */ + if (conn->auth_req_received) + return PQPING_OK; + + /* + * If we failed to get any ERROR response from the postmaster, report + * PQPING_NO_RESPONSE. This result could be somewhat misleading for a + * pre-7.4 server, since it won't send back a SQLSTATE, but those are long + * out of support. Another corner case where the server could return a + * failure without a SQLSTATE is fork failure, but PQPING_NO_RESPONSE + * isn't totally unreasonable for that anyway. We expect that every other + * failure case in a modern server will produce a report with a SQLSTATE. + * + * NOTE: whenever we get around to making libpq generate SQLSTATEs for + * client-side errors, we should either not store those into + * last_sqlstate, or add an extra flag so we can tell client-side errors + * apart from server-side ones. + */ + if (strlen(conn->last_sqlstate) != 5) + return PQPING_NO_RESPONSE; + + /* + * Report PQPING_REJECT if server says it's not accepting connections. + */ + if (strcmp(conn->last_sqlstate, ERRCODE_CANNOT_CONNECT_NOW) == 0) + return PQPING_REJECT; + + /* + * Any other SQLSTATE can be taken to indicate that the server is up. + * Presumably it didn't like our username, password, or database name; or + * perhaps it had some transient failure, but that should not be taken as + * meaning "it's down". + */ + return PQPING_OK; +} + + +/* + * makeEmptyPGconn + * - create a PGconn data structure with (as yet) no interesting data + */ +static PGconn * +makeEmptyPGconn(void) +{ + PGconn *conn; + +#ifdef WIN32 + + /* + * Make sure socket support is up and running in this process. + * + * Note: the Windows documentation says that we should eventually do a + * matching WSACleanup() call, but experience suggests that that is at + * least as likely to cause problems as fix them. So we don't. + */ + static bool wsastartup_done = false; + + if (!wsastartup_done) + { + WSADATA wsaData; + + if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) + return NULL; + wsastartup_done = true; + } + + /* Forget any earlier error */ + WSASetLastError(0); +#endif /* WIN32 */ + + conn = (PGconn *) malloc(sizeof(PGconn)); + if (conn == NULL) + return conn; + + /* Zero all pointers and booleans */ + MemSet(conn, 0, sizeof(PGconn)); + + /* install default notice hooks */ + conn->noticeHooks.noticeRec = defaultNoticeReceiver; + conn->noticeHooks.noticeProc = defaultNoticeProcessor; + + conn->status = CONNECTION_BAD; + conn->asyncStatus = PGASYNC_IDLE; + conn->pipelineStatus = PQ_PIPELINE_OFF; + conn->xactStatus = PQTRANS_IDLE; + conn->options_valid = false; + conn->nonblocking = false; + conn->client_encoding = PG_SQL_ASCII; + conn->std_strings = false; /* unless server says differently */ + conn->default_transaction_read_only = PG_BOOL_UNKNOWN; + conn->in_hot_standby = PG_BOOL_UNKNOWN; + conn->scram_sha_256_iterations = SCRAM_SHA_256_DEFAULT_ITERATIONS; + conn->verbosity = PQERRORS_DEFAULT; + conn->show_context = PQSHOW_CONTEXT_ERRORS; + conn->sock = PGINVALID_SOCKET; + conn->Pfdebug = NULL; + + /* + * We try to send at least 8K at a time, which is the usual size of pipe + * buffers on Unix systems. That way, when we are sending a large amount + * of data, we avoid incurring extra kernel context swaps for partial + * bufferloads. The output buffer is initially made 16K in size, and we + * try to dump it after accumulating 8K. + * + * With the same goal of minimizing context swaps, the input buffer will + * be enlarged anytime it has less than 8K free, so we initially allocate + * twice that. + */ + conn->inBufSize = 16 * 1024; + conn->inBuffer = (char *) malloc(conn->inBufSize); + conn->outBufSize = 16 * 1024; + conn->outBuffer = (char *) malloc(conn->outBufSize); + conn->rowBufLen = 32; + conn->rowBuf = (PGdataValue *) malloc(conn->rowBufLen * sizeof(PGdataValue)); + initPQExpBuffer(&conn->errorMessage); + initPQExpBuffer(&conn->workBuffer); + + if (conn->inBuffer == NULL || + conn->outBuffer == NULL || + conn->rowBuf == NULL || + PQExpBufferBroken(&conn->errorMessage) || + PQExpBufferBroken(&conn->workBuffer)) + { + /* out of memory already :-( */ + freePGconn(conn); + conn = NULL; + } + + return conn; +} + +/* + * freePGconn + * - free an idle (closed) PGconn data structure + * + * NOTE: this should not overlap any functionality with closePGconn(). + * Clearing/resetting of transient state belongs there; what we do here is + * release data that is to be held for the life of the PGconn structure. + * If a value ought to be cleared/freed during PQreset(), do it there not here. + */ +static void +freePGconn(PGconn *conn) +{ + /* let any event procs clean up their state data */ + for (int i = 0; i < conn->nEvents; i++) + { + PGEventConnDestroy evt; + + evt.conn = conn; + (void) conn->events[i].proc(PGEVT_CONNDESTROY, &evt, + conn->events[i].passThrough); + free(conn->events[i].name); + } + + /* clean up pg_conn_host structures */ + for (int i = 0; i < conn->nconnhost; ++i) + { + free(conn->connhost[i].host); + free(conn->connhost[i].hostaddr); + free(conn->connhost[i].port); + if (conn->connhost[i].password != NULL) + { + explicit_bzero(conn->connhost[i].password, strlen(conn->connhost[i].password)); + free(conn->connhost[i].password); + } + } + free(conn->connhost); + + free(conn->client_encoding_initial); + free(conn->events); + free(conn->pghost); + free(conn->pghostaddr); + free(conn->pgport); + free(conn->connect_timeout); + free(conn->pgtcp_user_timeout); + free(conn->pgoptions); + free(conn->appname); + free(conn->fbappname); + free(conn->dbName); + free(conn->replication); + free(conn->pguser); + if (conn->pgpass) + { + explicit_bzero(conn->pgpass, strlen(conn->pgpass)); + free(conn->pgpass); + } + free(conn->pgpassfile); + free(conn->channel_binding); + free(conn->keepalives); + free(conn->keepalives_idle); + free(conn->keepalives_interval); + free(conn->keepalives_count); + free(conn->sslmode); + free(conn->sslcert); + free(conn->sslkey); + if (conn->sslpassword) + { + explicit_bzero(conn->sslpassword, strlen(conn->sslpassword)); + free(conn->sslpassword); + } + free(conn->sslcertmode); + free(conn->sslrootcert); + free(conn->sslcrl); + free(conn->sslcrldir); + free(conn->sslcompression); + free(conn->sslsni); + free(conn->requirepeer); + free(conn->require_auth); + free(conn->ssl_min_protocol_version); + free(conn->ssl_max_protocol_version); + free(conn->gssencmode); + free(conn->krbsrvname); + free(conn->gsslib); + free(conn->gssdelegation); + free(conn->connip); + /* Note that conn->Pfdebug is not ours to close or free */ + free(conn->write_err_msg); + free(conn->inBuffer); + free(conn->outBuffer); + free(conn->rowBuf); + free(conn->target_session_attrs); + free(conn->load_balance_hosts); + termPQExpBuffer(&conn->errorMessage); + termPQExpBuffer(&conn->workBuffer); + + free(conn); +} + +/* + * store_conn_addrinfo + * - copy addrinfo to PGconn object + * + * Copies the addrinfos from addrlist to the PGconn object such that the + * addrinfos can be manipulated by libpq. Returns a positive integer on + * failure, otherwise zero. + */ +static int +store_conn_addrinfo(PGconn *conn, struct addrinfo *addrlist) +{ + struct addrinfo *ai = addrlist; + + conn->whichaddr = 0; + + conn->naddr = 0; + while (ai) + { + ai = ai->ai_next; + conn->naddr++; + } + + conn->addr = calloc(conn->naddr, sizeof(AddrInfo)); + if (conn->addr == NULL) + { + libpq_append_conn_error(conn, "out of memory"); + return 1; + } + + ai = addrlist; + for (int i = 0; i < conn->naddr; i++) + { + conn->addr[i].family = ai->ai_family; + + memcpy(&conn->addr[i].addr.addr, ai->ai_addr, + ai->ai_addrlen); + conn->addr[i].addr.salen = ai->ai_addrlen; + ai = ai->ai_next; + } + + return 0; +} + +/* + * release_conn_addrinfo + * - Free any addrinfo list in the PGconn. + */ +static void +release_conn_addrinfo(PGconn *conn) +{ + if (conn->addr) + { + free(conn->addr); + conn->addr = NULL; + } +} + +/* + * sendTerminateConn + * - Send a terminate message to backend. + */ +static void +sendTerminateConn(PGconn *conn) +{ + /* + * Note that the protocol doesn't allow us to send Terminate messages + * during the startup phase. + */ + if (conn->sock != PGINVALID_SOCKET && conn->status == CONNECTION_OK) + { + /* + * Try to send "close connection" message to backend. Ignore any + * error. + */ + pqPutMsgStart('X', conn); + pqPutMsgEnd(conn); + (void) pqFlush(conn); + } +} + +/* + * closePGconn + * - properly close a connection to the backend + * + * This should reset or release all transient state, but NOT the connection + * parameters. On exit, the PGconn should be in condition to start a fresh + * connection with the same parameters (see PQreset()). + */ +static void +closePGconn(PGconn *conn) +{ + /* + * If possible, send Terminate message to close the connection politely. + */ + sendTerminateConn(conn); + + /* + * Must reset the blocking status so a possible reconnect will work. + * + * Don't call PQsetnonblocking() because it will fail if it's unable to + * flush the connection. + */ + conn->nonblocking = false; + + /* + * Close the connection, reset all transient state, flush I/O buffers. + * Note that this includes clearing conn's error state; we're no longer + * interested in any failures associated with the old connection, and we + * want a clean slate for any new connection attempt. + */ + pqDropConnection(conn, true); + conn->status = CONNECTION_BAD; /* Well, not really _bad_ - just absent */ + conn->asyncStatus = PGASYNC_IDLE; + conn->xactStatus = PQTRANS_IDLE; + conn->pipelineStatus = PQ_PIPELINE_OFF; + pqClearAsyncResult(conn); /* deallocate result */ + pqClearConnErrorState(conn); + release_conn_addrinfo(conn); + + /* Reset all state obtained from server, too */ + pqDropServerData(conn); +} + +/* + * PQfinish: properly close a connection to the backend. Also frees + * the PGconn data structure so it shouldn't be re-used after this. + */ +void +PQfinish(PGconn *conn) +{ + if (conn) + { + closePGconn(conn); + freePGconn(conn); + } +} + +/* + * PQreset: resets the connection to the backend by closing the + * existing connection and creating a new one. + */ +void +PQreset(PGconn *conn) +{ + if (conn) + { + closePGconn(conn); + + if (connectDBStart(conn) && connectDBComplete(conn)) + { + /* + * Notify event procs of successful reset. + */ + int i; + + for (i = 0; i < conn->nEvents; i++) + { + PGEventConnReset evt; + + evt.conn = conn; + (void) conn->events[i].proc(PGEVT_CONNRESET, &evt, + conn->events[i].passThrough); + } + } + } +} + + +/* + * PQresetStart: + * resets the connection to the backend + * closes the existing connection and makes a new one + * Returns 1 on success, 0 on failure. + */ +int +PQresetStart(PGconn *conn) +{ + if (conn) + { + closePGconn(conn); + + return connectDBStart(conn); + } + + return 0; +} + + +/* + * PQresetPoll: + * resets the connection to the backend + * closes the existing connection and makes a new one + */ +PostgresPollingStatusType +PQresetPoll(PGconn *conn) +{ + if (conn) + { + PostgresPollingStatusType status = PQconnectPoll(conn); + + if (status == PGRES_POLLING_OK) + { + /* + * Notify event procs of successful reset. + */ + int i; + + for (i = 0; i < conn->nEvents; i++) + { + PGEventConnReset evt; + + evt.conn = conn; + (void) conn->events[i].proc(PGEVT_CONNRESET, &evt, + conn->events[i].passThrough); + } + } + + return status; + } + + return PGRES_POLLING_FAILED; +} + +/* + * PQgetCancel: get a PGcancel structure corresponding to a connection. + * + * A copy is needed to be able to cancel a running query from a different + * thread. If the same structure is used all structure members would have + * to be individually locked (if the entire structure was locked, it would + * be impossible to cancel a synchronous query because the structure would + * have to stay locked for the duration of the query). + */ +PGcancel * +PQgetCancel(PGconn *conn) +{ + PGcancel *cancel; + + if (!conn) + return NULL; + + if (conn->sock == PGINVALID_SOCKET) + return NULL; + + cancel = malloc(sizeof(PGcancel)); + if (cancel == NULL) + return NULL; + + memcpy(&cancel->raddr, &conn->raddr, sizeof(SockAddr)); + cancel->be_pid = conn->be_pid; + cancel->be_key = conn->be_key; + /* We use -1 to indicate an unset connection option */ + cancel->pgtcp_user_timeout = -1; + cancel->keepalives = -1; + cancel->keepalives_idle = -1; + cancel->keepalives_interval = -1; + cancel->keepalives_count = -1; + if (conn->pgtcp_user_timeout != NULL) + { + if (!parse_int_param(conn->pgtcp_user_timeout, + &cancel->pgtcp_user_timeout, + conn, "tcp_user_timeout")) + goto fail; + } + if (conn->keepalives != NULL) + { + if (!parse_int_param(conn->keepalives, + &cancel->keepalives, + conn, "keepalives")) + goto fail; + } + if (conn->keepalives_idle != NULL) + { + if (!parse_int_param(conn->keepalives_idle, + &cancel->keepalives_idle, + conn, "keepalives_idle")) + goto fail; + } + if (conn->keepalives_interval != NULL) + { + if (!parse_int_param(conn->keepalives_interval, + &cancel->keepalives_interval, + conn, "keepalives_interval")) + goto fail; + } + if (conn->keepalives_count != NULL) + { + if (!parse_int_param(conn->keepalives_count, + &cancel->keepalives_count, + conn, "keepalives_count")) + goto fail; + } + + return cancel; + +fail: + free(cancel); + return NULL; +} + +/* PQfreeCancel: free a cancel structure */ +void +PQfreeCancel(PGcancel *cancel) +{ + free(cancel); +} + + +/* + * Sets an integer socket option on a TCP socket, if the provided value is + * not negative. Returns false if setsockopt fails for some reason. + * + * CAUTION: This needs to be signal safe, since it's used by PQcancel. + */ +#if defined(TCP_USER_TIMEOUT) || !defined(WIN32) +static bool +optional_setsockopt(int fd, int protoid, int optid, int value) +{ + if (value < 0) + return true; + if (setsockopt(fd, protoid, optid, (char *) &value, sizeof(value)) < 0) + return false; + return true; +} +#endif + + +/* + * PQcancel: request query cancel + * + * The return value is true if the cancel request was successfully + * dispatched, false if not (in which case an error message is available). + * Note: successful dispatch is no guarantee that there will be any effect at + * the backend. The application must read the operation result as usual. + * + * On failure, an error message is stored in *errbuf, which must be of size + * errbufsize (recommended size is 256 bytes). *errbuf is not changed on + * success return. + * + * CAUTION: we want this routine to be safely callable from a signal handler + * (for example, an application might want to call it in a SIGINT handler). + * This means we cannot use any C library routine that might be non-reentrant. + * malloc/free are often non-reentrant, and anything that might call them is + * just as dangerous. We avoid sprintf here for that reason. Building up + * error messages with strcpy/strcat is tedious but should be quite safe. + * We also save/restore errno in case the signal handler support doesn't. + */ +int +PQcancel(PGcancel *cancel, char *errbuf, int errbufsize) +{ + int save_errno = SOCK_ERRNO; + pgsocket tmpsock = PGINVALID_SOCKET; + int maxlen; + struct + { + uint32 packetlen; + CancelRequestPacket cp; + } crp; + + if (!cancel) + { + strlcpy(errbuf, "PQcancel() -- no cancel object supplied", errbufsize); + /* strlcpy probably doesn't change errno, but be paranoid */ + SOCK_ERRNO_SET(save_errno); + return false; + } + + /* + * We need to open a temporary connection to the postmaster. Do this with + * only kernel calls. + */ + if ((tmpsock = socket(cancel->raddr.addr.ss_family, SOCK_STREAM, 0)) == PGINVALID_SOCKET) + { + strlcpy(errbuf, "PQcancel() -- socket() failed: ", errbufsize); + goto cancel_errReturn; + } + + /* + * Since this connection will only be used to send a single packet of + * data, we don't need NODELAY. We also don't set the socket to + * nonblocking mode, because the API definition of PQcancel requires the + * cancel to be sent in a blocking way. + * + * We do set socket options related to keepalives and other TCP timeouts. + * This ensures that this function does not block indefinitely when + * reasonable keepalive and timeout settings have been provided. + */ + if (cancel->raddr.addr.ss_family != AF_UNIX && + cancel->keepalives != 0) + { +#ifndef WIN32 + if (!optional_setsockopt(tmpsock, SOL_SOCKET, SO_KEEPALIVE, 1)) + { + strlcpy(errbuf, "PQcancel() -- setsockopt(SO_KEEPALIVE) failed: ", errbufsize); + goto cancel_errReturn; + } + +#ifdef PG_TCP_KEEPALIVE_IDLE + if (!optional_setsockopt(tmpsock, IPPROTO_TCP, PG_TCP_KEEPALIVE_IDLE, + cancel->keepalives_idle)) + { + strlcpy(errbuf, "PQcancel() -- setsockopt(" PG_TCP_KEEPALIVE_IDLE_STR ") failed: ", errbufsize); + goto cancel_errReturn; + } +#endif + +#ifdef TCP_KEEPINTVL + if (!optional_setsockopt(tmpsock, IPPROTO_TCP, TCP_KEEPINTVL, + cancel->keepalives_interval)) + { + strlcpy(errbuf, "PQcancel() -- setsockopt(TCP_KEEPINTVL) failed: ", errbufsize); + goto cancel_errReturn; + } +#endif + +#ifdef TCP_KEEPCNT + if (!optional_setsockopt(tmpsock, IPPROTO_TCP, TCP_KEEPCNT, + cancel->keepalives_count)) + { + strlcpy(errbuf, "PQcancel() -- setsockopt(TCP_KEEPCNT) failed: ", errbufsize); + goto cancel_errReturn; + } +#endif + +#else /* WIN32 */ + +#ifdef SIO_KEEPALIVE_VALS + if (!setKeepalivesWin32(tmpsock, + cancel->keepalives_idle, + cancel->keepalives_interval)) + { + strlcpy(errbuf, "PQcancel() -- WSAIoctl(SIO_KEEPALIVE_VALS) failed: ", errbufsize); + goto cancel_errReturn; + } +#endif /* SIO_KEEPALIVE_VALS */ +#endif /* WIN32 */ + + /* TCP_USER_TIMEOUT works the same way on Unix and Windows */ +#ifdef TCP_USER_TIMEOUT + if (!optional_setsockopt(tmpsock, IPPROTO_TCP, TCP_USER_TIMEOUT, + cancel->pgtcp_user_timeout)) + { + strlcpy(errbuf, "PQcancel() -- setsockopt(TCP_USER_TIMEOUT) failed: ", errbufsize); + goto cancel_errReturn; + } +#endif + } + +retry3: + if (connect(tmpsock, (struct sockaddr *) &cancel->raddr.addr, + cancel->raddr.salen) < 0) + { + if (SOCK_ERRNO == EINTR) + /* Interrupted system call - we'll just try again */ + goto retry3; + strlcpy(errbuf, "PQcancel() -- connect() failed: ", errbufsize); + goto cancel_errReturn; + } + + /* Create and send the cancel request packet. */ + + crp.packetlen = pg_hton32((uint32) sizeof(crp)); + crp.cp.cancelRequestCode = (MsgType) pg_hton32(CANCEL_REQUEST_CODE); + crp.cp.backendPID = pg_hton32(cancel->be_pid); + crp.cp.cancelAuthCode = pg_hton32(cancel->be_key); + +retry4: + if (send(tmpsock, (char *) &crp, sizeof(crp), 0) != (int) sizeof(crp)) + { + if (SOCK_ERRNO == EINTR) + /* Interrupted system call - we'll just try again */ + goto retry4; + strlcpy(errbuf, "PQcancel() -- send() failed: ", errbufsize); + goto cancel_errReturn; + } + + /* + * Wait for the postmaster to close the connection, which indicates that + * it's processed the request. Without this delay, we might issue another + * command only to find that our cancel zaps that command instead of the + * one we thought we were canceling. Note we don't actually expect this + * read to obtain any data, we are just waiting for EOF to be signaled. + */ +retry5: + if (recv(tmpsock, (char *) &crp, 1, 0) < 0) + { + if (SOCK_ERRNO == EINTR) + /* Interrupted system call - we'll just try again */ + goto retry5; + /* we ignore other error conditions */ + } + + /* All done */ + closesocket(tmpsock); + SOCK_ERRNO_SET(save_errno); + return true; + +cancel_errReturn: + + /* + * Make sure we don't overflow the error buffer. Leave space for the \n at + * the end, and for the terminating zero. + */ + maxlen = errbufsize - strlen(errbuf) - 2; + if (maxlen >= 0) + { + /* + * We can't invoke strerror here, since it's not signal-safe. Settle + * for printing the decimal value of errno. Even that has to be done + * the hard way. + */ + int val = SOCK_ERRNO; + char buf[32]; + char *bufp; + + bufp = buf + sizeof(buf) - 1; + *bufp = '\0'; + do + { + *(--bufp) = (val % 10) + '0'; + val /= 10; + } while (val > 0); + bufp -= 6; + memcpy(bufp, "error ", 6); + strncat(errbuf, bufp, maxlen); + strcat(errbuf, "\n"); + } + if (tmpsock != PGINVALID_SOCKET) + closesocket(tmpsock); + SOCK_ERRNO_SET(save_errno); + return false; +} + + +/* + * PQrequestCancel: old, not thread-safe function for requesting query cancel + * + * Returns true if able to send the cancel request, false if not. + * + * On failure, the error message is saved in conn->errorMessage; this means + * that this can't be used when there might be other active operations on + * the connection object. + * + * NOTE: error messages will be cut off at the current size of the + * error message buffer, since we dare not try to expand conn->errorMessage! + */ +int +PQrequestCancel(PGconn *conn) +{ + int r; + PGcancel *cancel; + + /* Check we have an open connection */ + if (!conn) + return false; + + if (conn->sock == PGINVALID_SOCKET) + { + strlcpy(conn->errorMessage.data, + "PQrequestCancel() -- connection is not open\n", + conn->errorMessage.maxlen); + conn->errorMessage.len = strlen(conn->errorMessage.data); + conn->errorReported = 0; + + return false; + } + + cancel = PQgetCancel(conn); + if (cancel) + { + r = PQcancel(cancel, conn->errorMessage.data, + conn->errorMessage.maxlen); + PQfreeCancel(cancel); + } + else + { + strlcpy(conn->errorMessage.data, "out of memory", + conn->errorMessage.maxlen); + r = false; + } + + if (!r) + { + conn->errorMessage.len = strlen(conn->errorMessage.data); + conn->errorReported = 0; + } + + return r; +} + + +/* + * pqPacketSend() -- convenience routine to send a message to server. + * + * pack_type: the single-byte message type code. (Pass zero for startup + * packets, which have no message type code.) + * + * buf, buf_len: contents of message. The given length includes only what + * is in buf; the message type and message length fields are added here. + * + * RETURNS: STATUS_ERROR if the write fails, STATUS_OK otherwise. + * SIDE_EFFECTS: may block. + */ +int +pqPacketSend(PGconn *conn, char pack_type, + const void *buf, size_t buf_len) +{ + /* Start the message. */ + if (pqPutMsgStart(pack_type, conn)) + return STATUS_ERROR; + + /* Send the message body. */ + if (pqPutnchar(buf, buf_len, conn)) + return STATUS_ERROR; + + /* Finish the message. */ + if (pqPutMsgEnd(conn)) + return STATUS_ERROR; + + /* Flush to ensure backend gets it. */ + if (pqFlush(conn)) + return STATUS_ERROR; + + return STATUS_OK; +} + +#ifdef USE_LDAP + +#define LDAP_URL "ldap://" +#define LDAP_DEF_PORT 389 +#define PGLDAP_TIMEOUT 2 + +#define ld_is_sp_tab(x) ((x) == ' ' || (x) == '\t') +#define ld_is_nl_cr(x) ((x) == '\r' || (x) == '\n') + + +/* + * ldapServiceLookup + * + * Search the LDAP URL passed as first argument, treat the result as a + * string of connection options that are parsed and added to the array of + * options passed as second argument. + * + * LDAP URLs must conform to RFC 1959 without escape sequences. + * ldap://host:port/dn?attributes?scope?filter?extensions + * + * Returns + * 0 if the lookup was successful, + * 1 if the connection to the LDAP server could be established but + * the search was unsuccessful, + * 2 if a connection could not be established, and + * 3 if a fatal error occurred. + * + * An error message is appended to *errorMessage for return codes 1 and 3. + */ +static int +ldapServiceLookup(const char *purl, PQconninfoOption *options, + PQExpBuffer errorMessage) +{ + int port = LDAP_DEF_PORT, + scope, + rc, + size, + state, + oldstate, + i; +#ifndef WIN32 + int msgid; +#endif + bool found_keyword; + char *url, + *hostname, + *portstr, + *endptr, + *dn, + *scopestr, + *filter, + *result, + *p, + *p1 = NULL, + *optname = NULL, + *optval = NULL; + char *attrs[2] = {NULL, NULL}; + LDAP *ld = NULL; + LDAPMessage *res, + *entry; + struct berval **values; + LDAP_TIMEVAL time = {PGLDAP_TIMEOUT, 0}; + + if ((url = strdup(purl)) == NULL) + { + libpq_append_error(errorMessage, "out of memory"); + return 3; + } + + /* + * Parse URL components, check for correctness. Basically, url has '\0' + * placed at component boundaries and variables are pointed at each + * component. + */ + + if (pg_strncasecmp(url, LDAP_URL, strlen(LDAP_URL)) != 0) + { + libpq_append_error(errorMessage, + "invalid LDAP URL \"%s\": scheme must be ldap://", purl); + free(url); + return 3; + } + + /* hostname */ + hostname = url + strlen(LDAP_URL); + if (*hostname == '/') /* no hostname? */ + hostname = DefaultHost; /* the default */ + + /* dn, "distinguished name" */ + p = strchr(url + strlen(LDAP_URL), '/'); + if (p == NULL || *(p + 1) == '\0' || *(p + 1) == '?') + { + libpq_append_error(errorMessage, + "invalid LDAP URL \"%s\": missing distinguished name", + purl); + free(url); + return 3; + } + *p = '\0'; /* terminate hostname */ + dn = p + 1; + + /* attribute */ + if ((p = strchr(dn, '?')) == NULL || *(p + 1) == '\0' || *(p + 1) == '?') + { + libpq_append_error(errorMessage, + "invalid LDAP URL \"%s\": must have exactly one attribute", + purl); + free(url); + return 3; + } + *p = '\0'; + attrs[0] = p + 1; + + /* scope */ + if ((p = strchr(attrs[0], '?')) == NULL || *(p + 1) == '\0' || *(p + 1) == '?') + { + libpq_append_error(errorMessage, + "invalid LDAP URL \"%s\": must have search scope (base/one/sub)", + purl); + free(url); + return 3; + } + *p = '\0'; + scopestr = p + 1; + + /* filter */ + if ((p = strchr(scopestr, '?')) == NULL || *(p + 1) == '\0' || *(p + 1) == '?') + { + libpq_append_error(errorMessage, + "invalid LDAP URL \"%s\": no filter", + purl); + free(url); + return 3; + } + *p = '\0'; + filter = p + 1; + if ((p = strchr(filter, '?')) != NULL) + *p = '\0'; + + /* port number? */ + if ((p1 = strchr(hostname, ':')) != NULL) + { + long lport; + + *p1 = '\0'; + portstr = p1 + 1; + errno = 0; + lport = strtol(portstr, &endptr, 10); + if (*portstr == '\0' || *endptr != '\0' || errno || lport < 0 || lport > 65535) + { + libpq_append_error(errorMessage, + "invalid LDAP URL \"%s\": invalid port number", + purl); + free(url); + return 3; + } + port = (int) lport; + } + + /* Allow only one attribute */ + if (strchr(attrs[0], ',') != NULL) + { + libpq_append_error(errorMessage, + "invalid LDAP URL \"%s\": must have exactly one attribute", + purl); + free(url); + return 3; + } + + /* set scope */ + if (pg_strcasecmp(scopestr, "base") == 0) + scope = LDAP_SCOPE_BASE; + else if (pg_strcasecmp(scopestr, "one") == 0) + scope = LDAP_SCOPE_ONELEVEL; + else if (pg_strcasecmp(scopestr, "sub") == 0) + scope = LDAP_SCOPE_SUBTREE; + else + { + libpq_append_error(errorMessage, + "invalid LDAP URL \"%s\": must have search scope (base/one/sub)", + purl); + free(url); + return 3; + } + + /* initialize LDAP structure */ + if ((ld = ldap_init(hostname, port)) == NULL) + { + libpq_append_error(errorMessage, "could not create LDAP structure"); + free(url); + return 3; + } + + /* + * Perform an explicit anonymous bind. + * + * LDAP does not require that an anonymous bind is performed explicitly, + * but we want to distinguish between the case where LDAP bind does not + * succeed within PGLDAP_TIMEOUT seconds (return 2 to continue parsing the + * service control file) and the case where querying the LDAP server fails + * (return 1 to end parsing). + * + * Unfortunately there is no way of setting a timeout that works for both + * Windows and OpenLDAP. + */ +#ifdef WIN32 + /* the nonstandard ldap_connect function performs an anonymous bind */ + if (ldap_connect(ld, &time) != LDAP_SUCCESS) + { + /* error or timeout in ldap_connect */ + free(url); + ldap_unbind(ld); + return 2; + } +#else /* !WIN32 */ + /* in OpenLDAP, use the LDAP_OPT_NETWORK_TIMEOUT option */ + if (ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, &time) != LDAP_SUCCESS) + { + free(url); + ldap_unbind(ld); + return 3; + } + + /* anonymous bind */ + if ((msgid = ldap_simple_bind(ld, NULL, NULL)) == -1) + { + /* error or network timeout */ + free(url); + ldap_unbind(ld); + return 2; + } + + /* wait some time for the connection to succeed */ + res = NULL; + if ((rc = ldap_result(ld, msgid, LDAP_MSG_ALL, &time, &res)) == -1 || + res == NULL) + { + /* error or timeout */ + if (res != NULL) + ldap_msgfree(res); + free(url); + ldap_unbind(ld); + return 2; + } + ldap_msgfree(res); + + /* reset timeout */ + time.tv_sec = -1; + if (ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, &time) != LDAP_SUCCESS) + { + free(url); + ldap_unbind(ld); + return 3; + } +#endif /* WIN32 */ + + /* search */ + res = NULL; + if ((rc = ldap_search_st(ld, dn, scope, filter, attrs, 0, &time, &res)) + != LDAP_SUCCESS) + { + if (res != NULL) + ldap_msgfree(res); + libpq_append_error(errorMessage, "lookup on LDAP server failed: %s", ldap_err2string(rc)); + ldap_unbind(ld); + free(url); + return 1; + } + + /* complain if there was not exactly one result */ + if ((rc = ldap_count_entries(ld, res)) != 1) + { + if (rc > 1) + libpq_append_error(errorMessage, "more than one entry found on LDAP lookup"); + else + libpq_append_error(errorMessage, "no entry found on LDAP lookup"); + ldap_msgfree(res); + ldap_unbind(ld); + free(url); + return 1; + } + + /* get entry */ + if ((entry = ldap_first_entry(ld, res)) == NULL) + { + /* should never happen */ + libpq_append_error(errorMessage, "no entry found on LDAP lookup"); + ldap_msgfree(res); + ldap_unbind(ld); + free(url); + return 1; + } + + /* get values */ + if ((values = ldap_get_values_len(ld, entry, attrs[0])) == NULL) + { + libpq_append_error(errorMessage, "attribute has no values on LDAP lookup"); + ldap_msgfree(res); + ldap_unbind(ld); + free(url); + return 1; + } + + ldap_msgfree(res); + free(url); + + if (values[0] == NULL) + { + libpq_append_error(errorMessage, "attribute has no values on LDAP lookup"); + ldap_value_free_len(values); + ldap_unbind(ld); + return 1; + } + + /* concatenate values into a single string with newline terminators */ + size = 1; /* for the trailing null */ + for (i = 0; values[i] != NULL; i++) + size += values[i]->bv_len + 1; + if ((result = malloc(size)) == NULL) + { + libpq_append_error(errorMessage, "out of memory"); + ldap_value_free_len(values); + ldap_unbind(ld); + return 3; + } + p = result; + for (i = 0; values[i] != NULL; i++) + { + memcpy(p, values[i]->bv_val, values[i]->bv_len); + p += values[i]->bv_len; + *(p++) = '\n'; + } + *p = '\0'; + + ldap_value_free_len(values); + ldap_unbind(ld); + + /* parse result string */ + oldstate = state = 0; + for (p = result; *p != '\0'; ++p) + { + switch (state) + { + case 0: /* between entries */ + if (!ld_is_sp_tab(*p) && !ld_is_nl_cr(*p)) + { + optname = p; + state = 1; + } + break; + case 1: /* in option name */ + if (ld_is_sp_tab(*p)) + { + *p = '\0'; + state = 2; + } + else if (ld_is_nl_cr(*p)) + { + libpq_append_error(errorMessage, + "missing \"=\" after \"%s\" in connection info string", + optname); + free(result); + return 3; + } + else if (*p == '=') + { + *p = '\0'; + state = 3; + } + break; + case 2: /* after option name */ + if (*p == '=') + { + state = 3; + } + else if (!ld_is_sp_tab(*p)) + { + libpq_append_error(errorMessage, + "missing \"=\" after \"%s\" in connection info string", + optname); + free(result); + return 3; + } + break; + case 3: /* before option value */ + if (*p == '\'') + { + optval = p + 1; + p1 = p + 1; + state = 5; + } + else if (ld_is_nl_cr(*p)) + { + optval = optname + strlen(optname); /* empty */ + state = 0; + } + else if (!ld_is_sp_tab(*p)) + { + optval = p; + state = 4; + } + break; + case 4: /* in unquoted option value */ + if (ld_is_sp_tab(*p) || ld_is_nl_cr(*p)) + { + *p = '\0'; + state = 0; + } + break; + case 5: /* in quoted option value */ + if (*p == '\'') + { + *p1 = '\0'; + state = 0; + } + else if (*p == '\\') + state = 6; + else + *(p1++) = *p; + break; + case 6: /* in quoted option value after escape */ + *(p1++) = *p; + state = 5; + break; + } + + if (state == 0 && oldstate != 0) + { + found_keyword = false; + for (i = 0; options[i].keyword; i++) + { + if (strcmp(options[i].keyword, optname) == 0) + { + if (options[i].val == NULL) + { + options[i].val = strdup(optval); + if (!options[i].val) + { + libpq_append_error(errorMessage, "out of memory"); + free(result); + return 3; + } + } + found_keyword = true; + break; + } + } + if (!found_keyword) + { + libpq_append_error(errorMessage, "invalid connection option \"%s\"", optname); + free(result); + return 1; + } + optname = NULL; + optval = NULL; + } + oldstate = state; + } + + free(result); + + if (state == 5 || state == 6) + { + libpq_append_error(errorMessage, + "unterminated quoted string in connection info string"); + return 3; + } + + return 0; +} + +#endif /* USE_LDAP */ + +/* + * parseServiceInfo: if a service name has been given, look it up and absorb + * connection options from it into *options. + * + * Returns 0 on success, nonzero on failure. On failure, if errorMessage + * isn't null, also store an error message there. (Note: the only reason + * this function and related ones don't dump core on errorMessage == NULL + * is the undocumented fact that appendPQExpBuffer does nothing when passed + * a null PQExpBuffer pointer.) + */ +static int +parseServiceInfo(PQconninfoOption *options, PQExpBuffer errorMessage) +{ + const char *service = conninfo_getval(options, "service"); + char serviceFile[MAXPGPATH]; + char *env; + bool group_found = false; + int status; + struct stat stat_buf; + + /* + * We have to special-case the environment variable PGSERVICE here, since + * this is and should be called before inserting environment defaults for + * other connection options. + */ + if (service == NULL) + service = getenv("PGSERVICE"); + + /* If no service name given, nothing to do */ + if (service == NULL) + return 0; + + /* + * Try PGSERVICEFILE if specified, else try ~/.pg_service.conf (if that + * exists). + */ + if ((env = getenv("PGSERVICEFILE")) != NULL) + strlcpy(serviceFile, env, sizeof(serviceFile)); + else + { + char homedir[MAXPGPATH]; + + if (!pqGetHomeDirectory(homedir, sizeof(homedir))) + goto next_file; + snprintf(serviceFile, MAXPGPATH, "%s/%s", homedir, ".pg_service.conf"); + if (stat(serviceFile, &stat_buf) != 0) + goto next_file; + } + + status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found); + if (group_found || status != 0) + return status; + +next_file: + + /* + * This could be used by any application so we can't use the binary + * location to find our config files. + */ + snprintf(serviceFile, MAXPGPATH, "%s/pg_service.conf", + getenv("PGSYSCONFDIR") ? getenv("PGSYSCONFDIR") : SYSCONFDIR); + if (stat(serviceFile, &stat_buf) != 0) + goto last_file; + + status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found); + if (status != 0) + return status; + +last_file: + if (!group_found) + { + libpq_append_error(errorMessage, "definition of service \"%s\" not found", service); + return 3; + } + + return 0; +} + +static int +parseServiceFile(const char *serviceFile, + const char *service, + PQconninfoOption *options, + PQExpBuffer errorMessage, + bool *group_found) +{ + int result = 0, + linenr = 0, + i; + FILE *f; + char *line; + char buf[1024]; + + *group_found = false; + + f = fopen(serviceFile, "r"); + if (f == NULL) + { + libpq_append_error(errorMessage, "service file \"%s\" not found", serviceFile); + return 1; + } + + while ((line = fgets(buf, sizeof(buf), f)) != NULL) + { + int len; + + linenr++; + + if (strlen(line) >= sizeof(buf) - 1) + { + libpq_append_error(errorMessage, + "line %d too long in service file \"%s\"", + linenr, + serviceFile); + result = 2; + goto exit; + } + + /* ignore whitespace at end of line, especially the newline */ + len = strlen(line); + while (len > 0 && isspace((unsigned char) line[len - 1])) + line[--len] = '\0'; + + /* ignore leading whitespace too */ + while (*line && isspace((unsigned char) line[0])) + line++; + + /* ignore comments and empty lines */ + if (line[0] == '\0' || line[0] == '#') + continue; + + /* Check for right groupname */ + if (line[0] == '[') + { + if (*group_found) + { + /* end of desired group reached; return success */ + goto exit; + } + + if (strncmp(line + 1, service, strlen(service)) == 0 && + line[strlen(service) + 1] == ']') + *group_found = true; + else + *group_found = false; + } + else + { + if (*group_found) + { + /* + * Finally, we are in the right group and can parse the line + */ + char *key, + *val; + bool found_keyword; + +#ifdef USE_LDAP + if (strncmp(line, "ldap", 4) == 0) + { + int rc = ldapServiceLookup(line, options, errorMessage); + + /* if rc = 2, go on reading for fallback */ + switch (rc) + { + case 0: + goto exit; + case 1: + case 3: + result = 3; + goto exit; + case 2: + continue; + } + } +#endif + + key = line; + val = strchr(line, '='); + if (val == NULL) + { + libpq_append_error(errorMessage, + "syntax error in service file \"%s\", line %d", + serviceFile, + linenr); + result = 3; + goto exit; + } + *val++ = '\0'; + + if (strcmp(key, "service") == 0) + { + libpq_append_error(errorMessage, + "nested service specifications not supported in service file \"%s\", line %d", + serviceFile, + linenr); + result = 3; + goto exit; + } + + /* + * Set the parameter --- but don't override any previous + * explicit setting. + */ + found_keyword = false; + for (i = 0; options[i].keyword; i++) + { + if (strcmp(options[i].keyword, key) == 0) + { + if (options[i].val == NULL) + options[i].val = strdup(val); + if (!options[i].val) + { + libpq_append_error(errorMessage, "out of memory"); + result = 3; + goto exit; + } + found_keyword = true; + break; + } + } + + if (!found_keyword) + { + libpq_append_error(errorMessage, + "syntax error in service file \"%s\", line %d", + serviceFile, + linenr); + result = 3; + goto exit; + } + } + } + } + +exit: + fclose(f); + + return result; +} + + +/* + * PQconninfoParse + * + * Parse a string like PQconnectdb() would do and return the + * resulting connection options array. NULL is returned on failure. + * The result contains only options specified directly in the string, + * not any possible default values. + * + * If errmsg isn't NULL, *errmsg is set to NULL on success, or a malloc'd + * string on failure (use PQfreemem to free it). In out-of-memory conditions + * both *errmsg and the result could be NULL. + * + * NOTE: the returned array is dynamically allocated and should + * be freed when no longer needed via PQconninfoFree(). + */ +PQconninfoOption * +PQconninfoParse(const char *conninfo, char **errmsg) +{ + PQExpBufferData errorBuf; + PQconninfoOption *connOptions; + + if (errmsg) + *errmsg = NULL; /* default */ + initPQExpBuffer(&errorBuf); + if (PQExpBufferDataBroken(errorBuf)) + return NULL; /* out of memory already :-( */ + connOptions = parse_connection_string(conninfo, &errorBuf, false); + if (connOptions == NULL && errmsg) + *errmsg = errorBuf.data; + else + termPQExpBuffer(&errorBuf); + return connOptions; +} + +/* + * Build a working copy of the constant PQconninfoOptions array. + */ +static PQconninfoOption * +conninfo_init(PQExpBuffer errorMessage) +{ + PQconninfoOption *options; + PQconninfoOption *opt_dest; + const internalPQconninfoOption *cur_opt; + + /* + * Get enough memory for all options in PQconninfoOptions, even if some + * end up being filtered out. + */ + options = (PQconninfoOption *) malloc(sizeof(PQconninfoOption) * sizeof(PQconninfoOptions) / sizeof(PQconninfoOptions[0])); + if (options == NULL) + { + libpq_append_error(errorMessage, "out of memory"); + return NULL; + } + opt_dest = options; + + for (cur_opt = PQconninfoOptions; cur_opt->keyword; cur_opt++) + { + /* Only copy the public part of the struct, not the full internal */ + memcpy(opt_dest, cur_opt, sizeof(PQconninfoOption)); + opt_dest++; + } + MemSet(opt_dest, 0, sizeof(PQconninfoOption)); + + return options; +} + +/* + * Connection string parser + * + * Returns a malloc'd PQconninfoOption array, if parsing is successful. + * Otherwise, NULL is returned and an error message is added to errorMessage. + * + * If use_defaults is true, default values are filled in (from a service file, + * environment variables, etc). + */ +static PQconninfoOption * +parse_connection_string(const char *connstr, PQExpBuffer errorMessage, + bool use_defaults) +{ + /* Parse as URI if connection string matches URI prefix */ + if (uri_prefix_length(connstr) != 0) + return conninfo_uri_parse(connstr, errorMessage, use_defaults); + + /* Parse as default otherwise */ + return conninfo_parse(connstr, errorMessage, use_defaults); +} + +/* + * Checks if connection string starts with either of the valid URI prefix + * designators. + * + * Returns the URI prefix length, 0 if the string doesn't contain a URI prefix. + * + * XXX this is duplicated in psql/common.c. + */ +static int +uri_prefix_length(const char *connstr) +{ + if (strncmp(connstr, uri_designator, + sizeof(uri_designator) - 1) == 0) + return sizeof(uri_designator) - 1; + + if (strncmp(connstr, short_uri_designator, + sizeof(short_uri_designator) - 1) == 0) + return sizeof(short_uri_designator) - 1; + + return 0; +} + +/* + * Recognized connection string either starts with a valid URI prefix or + * contains a "=" in it. + * + * Must be consistent with parse_connection_string: anything for which this + * returns true should at least look like it's parseable by that routine. + * + * XXX this is duplicated in psql/common.c + */ +static bool +recognized_connection_string(const char *connstr) +{ + return uri_prefix_length(connstr) != 0 || strchr(connstr, '=') != NULL; +} + +/* + * Subroutine for parse_connection_string + * + * Deal with a string containing key=value pairs. + */ +static PQconninfoOption * +conninfo_parse(const char *conninfo, PQExpBuffer errorMessage, + bool use_defaults) +{ + char *pname; + char *pval; + char *buf; + char *cp; + char *cp2; + PQconninfoOption *options; + + /* Make a working copy of PQconninfoOptions */ + options = conninfo_init(errorMessage); + if (options == NULL) + return NULL; + + /* Need a modifiable copy of the input string */ + if ((buf = strdup(conninfo)) == NULL) + { + libpq_append_error(errorMessage, "out of memory"); + PQconninfoFree(options); + return NULL; + } + cp = buf; + + while (*cp) + { + /* Skip blanks before the parameter name */ + if (isspace((unsigned char) *cp)) + { + cp++; + continue; + } + + /* Get the parameter name */ + pname = cp; + while (*cp) + { + if (*cp == '=') + break; + if (isspace((unsigned char) *cp)) + { + *cp++ = '\0'; + while (*cp) + { + if (!isspace((unsigned char) *cp)) + break; + cp++; + } + break; + } + cp++; + } + + /* Check that there is a following '=' */ + if (*cp != '=') + { + libpq_append_error(errorMessage, + "missing \"=\" after \"%s\" in connection info string", + pname); + PQconninfoFree(options); + free(buf); + return NULL; + } + *cp++ = '\0'; + + /* Skip blanks after the '=' */ + while (*cp) + { + if (!isspace((unsigned char) *cp)) + break; + cp++; + } + + /* Get the parameter value */ + pval = cp; + + if (*cp != '\'') + { + cp2 = pval; + while (*cp) + { + if (isspace((unsigned char) *cp)) + { + *cp++ = '\0'; + break; + } + if (*cp == '\\') + { + cp++; + if (*cp != '\0') + *cp2++ = *cp++; + } + else + *cp2++ = *cp++; + } + *cp2 = '\0'; + } + else + { + cp2 = pval; + cp++; + for (;;) + { + if (*cp == '\0') + { + libpq_append_error(errorMessage, "unterminated quoted string in connection info string"); + PQconninfoFree(options); + free(buf); + return NULL; + } + if (*cp == '\\') + { + cp++; + if (*cp != '\0') + *cp2++ = *cp++; + continue; + } + if (*cp == '\'') + { + *cp2 = '\0'; + cp++; + break; + } + *cp2++ = *cp++; + } + } + + /* + * Now that we have the name and the value, store the record. + */ + if (!conninfo_storeval(options, pname, pval, errorMessage, false, false)) + { + PQconninfoFree(options); + free(buf); + return NULL; + } + } + + /* Done with the modifiable input string */ + free(buf); + + /* + * Add in defaults if the caller wants that. + */ + if (use_defaults) + { + if (!conninfo_add_defaults(options, errorMessage)) + { + PQconninfoFree(options); + return NULL; + } + } + + return options; +} + +/* + * Conninfo array parser routine + * + * If successful, a malloc'd PQconninfoOption array is returned. + * If not successful, NULL is returned and an error message is + * appended to errorMessage. + * Defaults are supplied (from a service file, environment variables, etc) + * for unspecified options, but only if use_defaults is true. + * + * If expand_dbname is non-zero, and the value passed for the first occurrence + * of "dbname" keyword is a connection string (as indicated by + * recognized_connection_string) then parse and process it, overriding any + * previously processed conflicting keywords. Subsequent keywords will take + * precedence, however. In-tree programs generally specify expand_dbname=true, + * so command-line arguments naming a database can use a connection string. + * Some code acquires arbitrary database names from known-literal sources like + * PQdb(), PQconninfoParse() and pg_database.datname. When connecting to such + * a database, in-tree code first wraps the name in a connection string. + */ +static PQconninfoOption * +conninfo_array_parse(const char *const *keywords, const char *const *values, + PQExpBuffer errorMessage, bool use_defaults, + int expand_dbname) +{ + PQconninfoOption *options; + PQconninfoOption *dbname_options = NULL; + PQconninfoOption *option; + int i = 0; + + /* + * If expand_dbname is non-zero, check keyword "dbname" to see if val is + * actually a recognized connection string. + */ + while (expand_dbname && keywords[i]) + { + const char *pname = keywords[i]; + const char *pvalue = values[i]; + + /* first find "dbname" if any */ + if (strcmp(pname, "dbname") == 0 && pvalue) + { + /* + * If value is a connection string, parse it, but do not use + * defaults here -- those get picked up later. We only want to + * override for those parameters actually passed. + */ + if (recognized_connection_string(pvalue)) + { + dbname_options = parse_connection_string(pvalue, errorMessage, false); + if (dbname_options == NULL) + return NULL; + } + break; + } + ++i; + } + + /* Make a working copy of PQconninfoOptions */ + options = conninfo_init(errorMessage); + if (options == NULL) + { + PQconninfoFree(dbname_options); + return NULL; + } + + /* Parse the keywords/values arrays */ + i = 0; + while (keywords[i]) + { + const char *pname = keywords[i]; + const char *pvalue = values[i]; + + if (pvalue != NULL && pvalue[0] != '\0') + { + /* Search for the param record */ + for (option = options; option->keyword != NULL; option++) + { + if (strcmp(option->keyword, pname) == 0) + break; + } + + /* Check for invalid connection option */ + if (option->keyword == NULL) + { + libpq_append_error(errorMessage, "invalid connection option \"%s\"", pname); + PQconninfoFree(options); + PQconninfoFree(dbname_options); + return NULL; + } + + /* + * If we are on the first dbname parameter, and we have a parsed + * connection string, copy those parameters across, overriding any + * existing previous settings. + */ + if (strcmp(pname, "dbname") == 0 && dbname_options) + { + PQconninfoOption *str_option; + + for (str_option = dbname_options; str_option->keyword != NULL; str_option++) + { + if (str_option->val != NULL) + { + int k; + + for (k = 0; options[k].keyword; k++) + { + if (strcmp(options[k].keyword, str_option->keyword) == 0) + { + free(options[k].val); + options[k].val = strdup(str_option->val); + if (!options[k].val) + { + libpq_append_error(errorMessage, "out of memory"); + PQconninfoFree(options); + PQconninfoFree(dbname_options); + return NULL; + } + break; + } + } + } + } + + /* + * Forget the parsed connection string, so that any subsequent + * dbname parameters will not be expanded. + */ + PQconninfoFree(dbname_options); + dbname_options = NULL; + } + else + { + /* + * Store the value, overriding previous settings + */ + free(option->val); + option->val = strdup(pvalue); + if (!option->val) + { + libpq_append_error(errorMessage, "out of memory"); + PQconninfoFree(options); + PQconninfoFree(dbname_options); + return NULL; + } + } + } + ++i; + } + PQconninfoFree(dbname_options); + + /* + * Add in defaults if the caller wants that. + */ + if (use_defaults) + { + if (!conninfo_add_defaults(options, errorMessage)) + { + PQconninfoFree(options); + return NULL; + } + } + + return options; +} + +/* + * Add the default values for any unspecified options to the connection + * options array. + * + * Defaults are obtained from a service file, environment variables, etc. + * + * Returns true if successful, otherwise false; errorMessage, if supplied, + * is filled in upon failure. Note that failure to locate a default value + * is not an error condition here --- we just leave the option's value as + * NULL. + */ +static bool +conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage) +{ + PQconninfoOption *option; + PQconninfoOption *sslmode_default = NULL, + *sslrootcert = NULL; + char *tmp; + + /* + * If there's a service spec, use it to obtain any not-explicitly-given + * parameters. Ignore error if no error message buffer is passed because + * there is no way to pass back the failure message. + */ + if (parseServiceInfo(options, errorMessage) != 0 && errorMessage) + return false; + + /* + * Get the fallback resources for parameters not specified in the conninfo + * string nor the service. + */ + for (option = options; option->keyword != NULL; option++) + { + if (strcmp(option->keyword, "sslrootcert") == 0) + sslrootcert = option; /* save for later */ + + if (option->val != NULL) + continue; /* Value was in conninfo or service */ + + /* + * Try to get the environment variable fallback + */ + if (option->envvar != NULL) + { + if ((tmp = getenv(option->envvar)) != NULL) + { + option->val = strdup(tmp); + if (!option->val) + { + if (errorMessage) + libpq_append_error(errorMessage, "out of memory"); + return false; + } + continue; + } + } + + /* + * Interpret the deprecated PGREQUIRESSL environment variable. Per + * tradition, translate values starting with "1" to sslmode=require, + * and ignore other values. Given both PGREQUIRESSL=1 and PGSSLMODE, + * PGSSLMODE takes precedence; the opposite was true before v9.3. + */ + if (strcmp(option->keyword, "sslmode") == 0) + { + const char *requiresslenv = getenv("PGREQUIRESSL"); + + if (requiresslenv != NULL && requiresslenv[0] == '1') + { + option->val = strdup("require"); + if (!option->val) + { + if (errorMessage) + libpq_append_error(errorMessage, "out of memory"); + return false; + } + continue; + } + + /* + * sslmode is not specified. Let it be filled in with the compiled + * default for now, but if sslrootcert=system, we'll override the + * default later before returning. + */ + sslmode_default = option; + } + + /* + * No environment variable specified or the variable isn't set - try + * compiled-in default + */ + if (option->compiled != NULL) + { + option->val = strdup(option->compiled); + if (!option->val) + { + if (errorMessage) + libpq_append_error(errorMessage, "out of memory"); + return false; + } + continue; + } + + /* + * Special handling for "user" option. Note that if pg_fe_getauthname + * fails, we just leave the value as NULL; there's no need for this to + * be an error condition if the caller provides a user name. The only + * reason we do this now at all is so that callers of PQconndefaults + * will see a correct default (barring error, of course). + */ + if (strcmp(option->keyword, "user") == 0) + { + option->val = pg_fe_getauthname(NULL); + continue; + } + } + + /* + * Special handling for sslrootcert=system with no sslmode explicitly + * defined. In this case we want to strengthen the default sslmode to + * verify-full. + */ + if (sslmode_default && sslrootcert) + { + if (sslrootcert->val && strcmp(sslrootcert->val, "system") == 0) + { + free(sslmode_default->val); + + sslmode_default->val = strdup("verify-full"); + if (!sslmode_default->val) + { + if (errorMessage) + libpq_append_error(errorMessage, "out of memory"); + return false; + } + } + } + + return true; +} + +/* + * Subroutine for parse_connection_string + * + * Deal with a URI connection string. + */ +static PQconninfoOption * +conninfo_uri_parse(const char *uri, PQExpBuffer errorMessage, + bool use_defaults) +{ + PQconninfoOption *options; + + /* Make a working copy of PQconninfoOptions */ + options = conninfo_init(errorMessage); + if (options == NULL) + return NULL; + + if (!conninfo_uri_parse_options(options, uri, errorMessage)) + { + PQconninfoFree(options); + return NULL; + } + + /* + * Add in defaults if the caller wants that. + */ + if (use_defaults) + { + if (!conninfo_add_defaults(options, errorMessage)) + { + PQconninfoFree(options); + return NULL; + } + } + + return options; +} + +/* + * conninfo_uri_parse_options + * Actual URI parser. + * + * If successful, returns true while the options array is filled with parsed + * options from the URI. + * If not successful, returns false and fills errorMessage accordingly. + * + * Parses the connection URI string in 'uri' according to the URI syntax (RFC + * 3986): + * + * postgresql://[user[:password]@][netloc][:port][/dbname][?param1=value1&...] + * + * where "netloc" is a hostname, an IPv4 address, or an IPv6 address surrounded + * by literal square brackets. As an extension, we also allow multiple + * netloc[:port] specifications, separated by commas: + * + * postgresql://[user[:password]@][netloc][:port][,...][/dbname][?param1=value1&...] + * + * Any of the URI parts might use percent-encoding (%xy). + */ +static bool +conninfo_uri_parse_options(PQconninfoOption *options, const char *uri, + PQExpBuffer errorMessage) +{ + int prefix_len; + char *p; + char *buf = NULL; + char *start; + char prevchar = '\0'; + char *user = NULL; + char *host = NULL; + bool retval = false; + PQExpBufferData hostbuf; + PQExpBufferData portbuf; + + initPQExpBuffer(&hostbuf); + initPQExpBuffer(&portbuf); + if (PQExpBufferDataBroken(hostbuf) || PQExpBufferDataBroken(portbuf)) + { + libpq_append_error(errorMessage, "out of memory"); + goto cleanup; + } + + /* need a modifiable copy of the input URI */ + buf = strdup(uri); + if (buf == NULL) + { + libpq_append_error(errorMessage, "out of memory"); + goto cleanup; + } + start = buf; + + /* Skip the URI prefix */ + prefix_len = uri_prefix_length(uri); + if (prefix_len == 0) + { + /* Should never happen */ + libpq_append_error(errorMessage, + "invalid URI propagated to internal parser routine: \"%s\"", + uri); + goto cleanup; + } + start += prefix_len; + p = start; + + /* Look ahead for possible user credentials designator */ + while (*p && *p != '@' && *p != '/') + ++p; + if (*p == '@') + { + /* + * Found username/password designator, so URI should be of the form + * "scheme://user[:password]@[netloc]". + */ + user = start; + + p = user; + while (*p != ':' && *p != '@') + ++p; + + /* Save last char and cut off at end of user name */ + prevchar = *p; + *p = '\0'; + + if (*user && + !conninfo_storeval(options, "user", user, + errorMessage, false, true)) + goto cleanup; + + if (prevchar == ':') + { + const char *password = p + 1; + + while (*p != '@') + ++p; + *p = '\0'; + + if (*password && + !conninfo_storeval(options, "password", password, + errorMessage, false, true)) + goto cleanup; + } + + /* Advance past end of parsed user name or password token */ + ++p; + } + else + { + /* + * No username/password designator found. Reset to start of URI. + */ + p = start; + } + + /* + * There may be multiple netloc[:port] pairs, each separated from the next + * by a comma. When we initially enter this loop, "p" has been + * incremented past optional URI credential information at this point and + * now points at the "netloc" part of the URI. On subsequent loop + * iterations, "p" has been incremented past the comma separator and now + * points at the start of the next "netloc". + */ + for (;;) + { + /* + * Look for IPv6 address. + */ + if (*p == '[') + { + host = ++p; + while (*p && *p != ']') + ++p; + if (!*p) + { + libpq_append_error(errorMessage, + "end of string reached when looking for matching \"]\" in IPv6 host address in URI: \"%s\"", + uri); + goto cleanup; + } + if (p == host) + { + libpq_append_error(errorMessage, + "IPv6 host address may not be empty in URI: \"%s\"", + uri); + goto cleanup; + } + + /* Cut off the bracket and advance */ + *(p++) = '\0'; + + /* + * The address may be followed by a port specifier or a slash or a + * query or a separator comma. + */ + if (*p && *p != ':' && *p != '/' && *p != '?' && *p != ',') + { + libpq_append_error(errorMessage, + "unexpected character \"%c\" at position %d in URI (expected \":\" or \"/\"): \"%s\"", + *p, (int) (p - buf + 1), uri); + goto cleanup; + } + } + else + { + /* not an IPv6 address: DNS-named or IPv4 netloc */ + host = p; + + /* + * Look for port specifier (colon) or end of host specifier + * (slash) or query (question mark) or host separator (comma). + */ + while (*p && *p != ':' && *p != '/' && *p != '?' && *p != ',') + ++p; + } + + /* Save the hostname terminator before we null it */ + prevchar = *p; + *p = '\0'; + + appendPQExpBufferStr(&hostbuf, host); + + if (prevchar == ':') + { + const char *port = ++p; /* advance past host terminator */ + + while (*p && *p != '/' && *p != '?' && *p != ',') + ++p; + + prevchar = *p; + *p = '\0'; + + appendPQExpBufferStr(&portbuf, port); + } + + if (prevchar != ',') + break; + ++p; /* advance past comma separator */ + appendPQExpBufferChar(&hostbuf, ','); + appendPQExpBufferChar(&portbuf, ','); + } + + /* Save final values for host and port. */ + if (PQExpBufferDataBroken(hostbuf) || PQExpBufferDataBroken(portbuf)) + goto cleanup; + if (hostbuf.data[0] && + !conninfo_storeval(options, "host", hostbuf.data, + errorMessage, false, true)) + goto cleanup; + if (portbuf.data[0] && + !conninfo_storeval(options, "port", portbuf.data, + errorMessage, false, true)) + goto cleanup; + + if (prevchar && prevchar != '?') + { + const char *dbname = ++p; /* advance past host terminator */ + + /* Look for query parameters */ + while (*p && *p != '?') + ++p; + + prevchar = *p; + *p = '\0'; + + /* + * Avoid setting dbname to an empty string, as it forces the default + * value (username) and ignores $PGDATABASE, as opposed to not setting + * it at all. + */ + if (*dbname && + !conninfo_storeval(options, "dbname", dbname, + errorMessage, false, true)) + goto cleanup; + } + + if (prevchar) + { + ++p; /* advance past terminator */ + + if (!conninfo_uri_parse_params(p, options, errorMessage)) + goto cleanup; + } + + /* everything parsed okay */ + retval = true; + +cleanup: + termPQExpBuffer(&hostbuf); + termPQExpBuffer(&portbuf); + free(buf); + return retval; +} + +/* + * Connection URI parameters parser routine + * + * If successful, returns true while connOptions is filled with parsed + * parameters. Otherwise, returns false and fills errorMessage appropriately. + * + * Destructively modifies 'params' buffer. + */ +static bool +conninfo_uri_parse_params(char *params, + PQconninfoOption *connOptions, + PQExpBuffer errorMessage) +{ + while (*params) + { + char *keyword = params; + char *value = NULL; + char *p = params; + bool malloced = false; + int oldmsglen; + + /* + * Scan the params string for '=' and '&', marking the end of keyword + * and value respectively. + */ + for (;;) + { + if (*p == '=') + { + /* Was there '=' already? */ + if (value != NULL) + { + libpq_append_error(errorMessage, + "extra key/value separator \"=\" in URI query parameter: \"%s\"", + keyword); + return false; + } + /* Cut off keyword, advance to value */ + *p++ = '\0'; + value = p; + } + else if (*p == '&' || *p == '\0') + { + /* + * If not at the end, cut off value and advance; leave p + * pointing to start of the next parameter, if any. + */ + if (*p != '\0') + *p++ = '\0'; + /* Was there '=' at all? */ + if (value == NULL) + { + libpq_append_error(errorMessage, + "missing key/value separator \"=\" in URI query parameter: \"%s\"", + keyword); + return false; + } + /* Got keyword and value, go process them. */ + break; + } + else + ++p; /* Advance over all other bytes. */ + } + + keyword = conninfo_uri_decode(keyword, errorMessage); + if (keyword == NULL) + { + /* conninfo_uri_decode already set an error message */ + return false; + } + value = conninfo_uri_decode(value, errorMessage); + if (value == NULL) + { + /* conninfo_uri_decode already set an error message */ + free(keyword); + return false; + } + malloced = true; + + /* + * Special keyword handling for improved JDBC compatibility. + */ + if (strcmp(keyword, "ssl") == 0 && + strcmp(value, "true") == 0) + { + free(keyword); + free(value); + malloced = false; + + keyword = "sslmode"; + value = "require"; + } + + /* + * Store the value if the corresponding option exists; ignore + * otherwise. At this point both keyword and value are not + * URI-encoded. + */ + oldmsglen = errorMessage->len; + if (!conninfo_storeval(connOptions, keyword, value, + errorMessage, true, false)) + { + /* Insert generic message if conninfo_storeval didn't give one. */ + if (errorMessage->len == oldmsglen) + libpq_append_error(errorMessage, + "invalid URI query parameter: \"%s\"", + keyword); + /* And fail. */ + if (malloced) + { + free(keyword); + free(value); + } + return false; + } + + if (malloced) + { + free(keyword); + free(value); + } + + /* Proceed to next key=value pair, if any */ + params = p; + } + + return true; +} + +/* + * Connection URI decoder routine + * + * If successful, returns the malloc'd decoded string. + * If not successful, returns NULL and fills errorMessage accordingly. + * + * The string is decoded by replacing any percent-encoded tokens with + * corresponding characters, while preserving any non-encoded characters. A + * percent-encoded token is a character triplet: a percent sign, followed by a + * pair of hexadecimal digits (0-9A-F), where lower- and upper-case letters are + * treated identically. + */ +static char * +conninfo_uri_decode(const char *str, PQExpBuffer errorMessage) +{ + char *buf; + char *p; + const char *q = str; + + buf = malloc(strlen(str) + 1); + if (buf == NULL) + { + libpq_append_error(errorMessage, "out of memory"); + return NULL; + } + p = buf; + + for (;;) + { + if (*q != '%') + { + /* copy and check for NUL terminator */ + if (!(*(p++) = *(q++))) + break; + } + else + { + int hi; + int lo; + int c; + + ++q; /* skip the percent sign itself */ + + /* + * Possible EOL will be caught by the first call to + * get_hexdigit(), so we never dereference an invalid q pointer. + */ + if (!(get_hexdigit(*q++, &hi) && get_hexdigit(*q++, &lo))) + { + libpq_append_error(errorMessage, + "invalid percent-encoded token: \"%s\"", + str); + free(buf); + return NULL; + } + + c = (hi << 4) | lo; + if (c == 0) + { + libpq_append_error(errorMessage, + "forbidden value %%00 in percent-encoded value: \"%s\"", + str); + free(buf); + return NULL; + } + *(p++) = c; + } + } + + return buf; +} + +/* + * Convert hexadecimal digit character to its integer value. + * + * If successful, returns true and value is filled with digit's base 16 value. + * If not successful, returns false. + * + * Lower- and upper-case letters in the range A-F are treated identically. + */ +static bool +get_hexdigit(char digit, int *value) +{ + if ('0' <= digit && digit <= '9') + *value = digit - '0'; + else if ('A' <= digit && digit <= 'F') + *value = digit - 'A' + 10; + else if ('a' <= digit && digit <= 'f') + *value = digit - 'a' + 10; + else + return false; + + return true; +} + +/* + * Find an option value corresponding to the keyword in the connOptions array. + * + * If successful, returns a pointer to the corresponding option's value. + * If not successful, returns NULL. + */ +static const char * +conninfo_getval(PQconninfoOption *connOptions, + const char *keyword) +{ + PQconninfoOption *option; + + option = conninfo_find(connOptions, keyword); + + return option ? option->val : NULL; +} + +/* + * Store a (new) value for an option corresponding to the keyword in + * connOptions array. + * + * If uri_decode is true, the value is URI-decoded. The keyword is always + * assumed to be non URI-encoded. + * + * If successful, returns a pointer to the corresponding PQconninfoOption, + * which value is replaced with a strdup'd copy of the passed value string. + * The existing value for the option is free'd before replacing, if any. + * + * If not successful, returns NULL and fills errorMessage accordingly. + * However, if the reason of failure is an invalid keyword being passed and + * ignoreMissing is true, errorMessage will be left untouched. + */ +static PQconninfoOption * +conninfo_storeval(PQconninfoOption *connOptions, + const char *keyword, const char *value, + PQExpBuffer errorMessage, bool ignoreMissing, + bool uri_decode) +{ + PQconninfoOption *option; + char *value_copy; + + /* + * For backwards compatibility, requiressl=1 gets translated to + * sslmode=require, and requiressl=0 gets translated to sslmode=prefer + * (which is the default for sslmode). + */ + if (strcmp(keyword, "requiressl") == 0) + { + keyword = "sslmode"; + if (value[0] == '1') + value = "require"; + else + value = "prefer"; + } + + option = conninfo_find(connOptions, keyword); + if (option == NULL) + { + if (!ignoreMissing) + libpq_append_error(errorMessage, + "invalid connection option \"%s\"", + keyword); + return NULL; + } + + if (uri_decode) + { + value_copy = conninfo_uri_decode(value, errorMessage); + if (value_copy == NULL) + /* conninfo_uri_decode already set an error message */ + return NULL; + } + else + { + value_copy = strdup(value); + if (value_copy == NULL) + { + libpq_append_error(errorMessage, "out of memory"); + return NULL; + } + } + + free(option->val); + option->val = value_copy; + + return option; +} + +/* + * Find a PQconninfoOption option corresponding to the keyword in the + * connOptions array. + * + * If successful, returns a pointer to the corresponding PQconninfoOption + * structure. + * If not successful, returns NULL. + */ +static PQconninfoOption * +conninfo_find(PQconninfoOption *connOptions, const char *keyword) +{ + PQconninfoOption *option; + + for (option = connOptions; option->keyword != NULL; option++) + { + if (strcmp(option->keyword, keyword) == 0) + return option; + } + + return NULL; +} + + +/* + * Return the connection options used for the connection + */ +PQconninfoOption * +PQconninfo(PGconn *conn) +{ + PQExpBufferData errorBuf; + PQconninfoOption *connOptions; + + if (conn == NULL) + return NULL; + + /* + * We don't actually report any errors here, but callees want a buffer, + * and we prefer not to trash the conn's errorMessage. + */ + initPQExpBuffer(&errorBuf); + if (PQExpBufferDataBroken(errorBuf)) + return NULL; /* out of memory already :-( */ + + connOptions = conninfo_init(&errorBuf); + + if (connOptions != NULL) + { + const internalPQconninfoOption *option; + + for (option = PQconninfoOptions; option->keyword; option++) + { + char **connmember; + + if (option->connofs < 0) + continue; + + connmember = (char **) ((char *) conn + option->connofs); + + if (*connmember) + conninfo_storeval(connOptions, option->keyword, *connmember, + &errorBuf, true, false); + } + } + + termPQExpBuffer(&errorBuf); + + return connOptions; +} + + +void +PQconninfoFree(PQconninfoOption *connOptions) +{ + if (connOptions == NULL) + return; + + for (PQconninfoOption *option = connOptions; option->keyword != NULL; option++) + free(option->val); + free(connOptions); +} + + +/* =========== accessor functions for PGconn ========= */ +char * +PQdb(const PGconn *conn) +{ + if (!conn) + return NULL; + return conn->dbName; +} + +char * +PQuser(const PGconn *conn) +{ + if (!conn) + return NULL; + return conn->pguser; +} + +char * +PQpass(const PGconn *conn) +{ + char *password = NULL; + + if (!conn) + return NULL; + if (conn->connhost != NULL) + password = conn->connhost[conn->whichhost].password; + if (password == NULL) + password = conn->pgpass; + /* Historically we've returned "" not NULL for no password specified */ + if (password == NULL) + password = ""; + return password; +} + +char * +PQhost(const PGconn *conn) +{ + if (!conn) + return NULL; + + if (conn->connhost != NULL) + { + /* + * Return the verbatim host value provided by user, or hostaddr in its + * lack. + */ + if (conn->connhost[conn->whichhost].host != NULL && + conn->connhost[conn->whichhost].host[0] != '\0') + return conn->connhost[conn->whichhost].host; + else if (conn->connhost[conn->whichhost].hostaddr != NULL && + conn->connhost[conn->whichhost].hostaddr[0] != '\0') + return conn->connhost[conn->whichhost].hostaddr; + } + + return ""; +} + +char * +PQhostaddr(const PGconn *conn) +{ + if (!conn) + return NULL; + + /* Return the parsed IP address */ + if (conn->connhost != NULL && conn->connip != NULL) + return conn->connip; + + return ""; +} + +char * +PQport(const PGconn *conn) +{ + if (!conn) + return NULL; + + if (conn->connhost != NULL) + return conn->connhost[conn->whichhost].port; + + return ""; +} + +/* + * No longer does anything, but the function remains for API backwards + * compatibility. + */ +char * +PQtty(const PGconn *conn) +{ + if (!conn) + return NULL; + return ""; +} + +char * +PQoptions(const PGconn *conn) +{ + if (!conn) + return NULL; + return conn->pgoptions; +} + +ConnStatusType +PQstatus(const PGconn *conn) +{ + if (!conn) + return CONNECTION_BAD; + return conn->status; +} + +PGTransactionStatusType +PQtransactionStatus(const PGconn *conn) +{ + if (!conn || conn->status != CONNECTION_OK) + return PQTRANS_UNKNOWN; + if (conn->asyncStatus != PGASYNC_IDLE) + return PQTRANS_ACTIVE; + return conn->xactStatus; +} + +const char * +PQparameterStatus(const PGconn *conn, const char *paramName) +{ + const pgParameterStatus *pstatus; + + if (!conn || !paramName) + return NULL; + for (pstatus = conn->pstatus; pstatus != NULL; pstatus = pstatus->next) + { + if (strcmp(pstatus->name, paramName) == 0) + return pstatus->value; + } + return NULL; +} + +int +PQprotocolVersion(const PGconn *conn) +{ + if (!conn) + return 0; + if (conn->status == CONNECTION_BAD) + return 0; + return PG_PROTOCOL_MAJOR(conn->pversion); +} + +int +PQserverVersion(const PGconn *conn) +{ + if (!conn) + return 0; + if (conn->status == CONNECTION_BAD) + return 0; + return conn->sversion; +} + +char * +PQerrorMessage(const PGconn *conn) +{ + if (!conn) + return libpq_gettext("connection pointer is NULL\n"); + + /* + * The errorMessage buffer might be marked "broken" due to having + * previously failed to allocate enough memory for the message. In that + * case, tell the application we ran out of memory. + */ + if (PQExpBufferBroken(&conn->errorMessage)) + return libpq_gettext("out of memory\n"); + + return conn->errorMessage.data; +} + +/* + * In Windows, socket values are unsigned, and an invalid socket value + * (INVALID_SOCKET) is ~0, which equals -1 in comparisons (with no compiler + * warning). Ideally we would return an unsigned value for PQsocket() on + * Windows, but that would cause the function's return value to differ from + * Unix, so we just return -1 for invalid sockets. + * http://msdn.microsoft.com/en-us/library/windows/desktop/cc507522%28v=vs.85%29.aspx + * http://stackoverflow.com/questions/10817252/why-is-invalid-socket-defined-as-0-in-winsock2-h-c + */ +int +PQsocket(const PGconn *conn) +{ + if (!conn) + return -1; + return (conn->sock != PGINVALID_SOCKET) ? conn->sock : -1; +} + +int +PQbackendPID(const PGconn *conn) +{ + if (!conn || conn->status != CONNECTION_OK) + return 0; + return conn->be_pid; +} + +PGpipelineStatus +PQpipelineStatus(const PGconn *conn) +{ + if (!conn) + return PQ_PIPELINE_OFF; + + return conn->pipelineStatus; +} + +int +PQconnectionNeedsPassword(const PGconn *conn) +{ + char *password; + + if (!conn) + return false; + password = PQpass(conn); + if (conn->password_needed && + (password == NULL || password[0] == '\0')) + return true; + else + return false; +} + +int +PQconnectionUsedPassword(const PGconn *conn) +{ + if (!conn) + return false; + if (conn->password_needed) + return true; + else + return false; +} + +int +PQconnectionUsedGSSAPI(const PGconn *conn) +{ + if (!conn) + return false; + if (conn->gssapi_used) + return true; + else + return false; +} + +int +PQclientEncoding(const PGconn *conn) +{ + if (!conn || conn->status != CONNECTION_OK) + return -1; + return conn->client_encoding; +} + +int +PQsetClientEncoding(PGconn *conn, const char *encoding) +{ + char qbuf[128]; + static const char query[] = "set client_encoding to '%s'"; + PGresult *res; + int status; + + if (!conn || conn->status != CONNECTION_OK) + return -1; + + if (!encoding) + return -1; + + /* Resolve special "auto" value from the locale */ + if (strcmp(encoding, "auto") == 0) + encoding = pg_encoding_to_char(pg_get_encoding_from_locale(NULL, true)); + + /* check query buffer overflow */ + if (sizeof(qbuf) < (sizeof(query) + strlen(encoding))) + return -1; + + /* ok, now send a query */ + sprintf(qbuf, query, encoding); + res = PQexec(conn, qbuf); + + if (res == NULL) + return -1; + if (res->resultStatus != PGRES_COMMAND_OK) + status = -1; + else + { + /* + * We rely on the backend to report the parameter value, and we'll + * change state at that time. + */ + status = 0; /* everything is ok */ + } + PQclear(res); + return status; +} + +PGVerbosity +PQsetErrorVerbosity(PGconn *conn, PGVerbosity verbosity) +{ + PGVerbosity old; + + if (!conn) + return PQERRORS_DEFAULT; + old = conn->verbosity; + conn->verbosity = verbosity; + return old; +} + +PGContextVisibility +PQsetErrorContextVisibility(PGconn *conn, PGContextVisibility show_context) +{ + PGContextVisibility old; + + if (!conn) + return PQSHOW_CONTEXT_ERRORS; + old = conn->show_context; + conn->show_context = show_context; + return old; +} + +PQnoticeReceiver +PQsetNoticeReceiver(PGconn *conn, PQnoticeReceiver proc, void *arg) +{ + PQnoticeReceiver old; + + if (conn == NULL) + return NULL; + + old = conn->noticeHooks.noticeRec; + if (proc) + { + conn->noticeHooks.noticeRec = proc; + conn->noticeHooks.noticeRecArg = arg; + } + return old; +} + +PQnoticeProcessor +PQsetNoticeProcessor(PGconn *conn, PQnoticeProcessor proc, void *arg) +{ + PQnoticeProcessor old; + + if (conn == NULL) + return NULL; + + old = conn->noticeHooks.noticeProc; + if (proc) + { + conn->noticeHooks.noticeProc = proc; + conn->noticeHooks.noticeProcArg = arg; + } + return old; +} + +/* + * The default notice message receiver just gets the standard notice text + * and sends it to the notice processor. This two-level setup exists + * mostly for backwards compatibility; perhaps we should deprecate use of + * PQsetNoticeProcessor? + */ +static void +defaultNoticeReceiver(void *arg, const PGresult *res) +{ + (void) arg; /* not used */ + if (res->noticeHooks.noticeProc != NULL) + res->noticeHooks.noticeProc(res->noticeHooks.noticeProcArg, + PQresultErrorMessage(res)); +} + +/* + * The default notice message processor just prints the + * message on stderr. Applications can override this if they + * want the messages to go elsewhere (a window, for example). + * Note that simply discarding notices is probably a bad idea. + */ +static void +defaultNoticeProcessor(void *arg, const char *message) +{ + (void) arg; /* not used */ + /* Note: we expect the supplied string to end with a newline already. */ + fprintf(stderr, "%s", message); +} + +/* + * returns a pointer to the next token or NULL if the current + * token doesn't match + */ +static char * +pwdfMatchesString(char *buf, const char *token) +{ + char *tbuf; + const char *ttok; + bool bslash = false; + + if (buf == NULL || token == NULL) + return NULL; + tbuf = buf; + ttok = token; + if (tbuf[0] == '*' && tbuf[1] == ':') + return tbuf + 2; + while (*tbuf != 0) + { + if (*tbuf == '\\' && !bslash) + { + tbuf++; + bslash = true; + } + if (*tbuf == ':' && *ttok == 0 && !bslash) + return tbuf + 1; + bslash = false; + if (*ttok == 0) + return NULL; + if (*tbuf == *ttok) + { + tbuf++; + ttok++; + } + else + return NULL; + } + return NULL; +} + +/* Get a password from the password file. Return value is malloc'd. */ +static char * +passwordFromFile(const char *hostname, const char *port, const char *dbname, + const char *username, const char *pgpassfile) +{ + FILE *fp; + struct stat stat_buf; + PQExpBufferData buf; + + if (dbname == NULL || dbname[0] == '\0') + return NULL; + + if (username == NULL || username[0] == '\0') + return NULL; + + /* 'localhost' matches pghost of '' or the default socket directory */ + if (hostname == NULL || hostname[0] == '\0') + hostname = DefaultHost; + else if (is_unixsock_path(hostname)) + + /* + * We should probably use canonicalize_path(), but then we have to + * bring path.c into libpq, and it doesn't seem worth it. + */ + if (strcmp(hostname, DEFAULT_PGSOCKET_DIR) == 0) + hostname = DefaultHost; + + if (port == NULL || port[0] == '\0') + port = DEF_PGPORT_STR; + + /* If password file cannot be opened, ignore it. */ + if (stat(pgpassfile, &stat_buf) != 0) + return NULL; + +#ifndef WIN32 + if (!S_ISREG(stat_buf.st_mode)) + { + fprintf(stderr, + libpq_gettext("WARNING: password file \"%s\" is not a plain file\n"), + pgpassfile); + return NULL; + } + + /* If password file is insecure, alert the user and ignore it. */ + if (stat_buf.st_mode & (S_IRWXG | S_IRWXO)) + { + fprintf(stderr, + libpq_gettext("WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n"), + pgpassfile); + return NULL; + } +#else + + /* + * On Win32, the directory is protected, so we don't have to check the + * file. + */ +#endif + + fp = fopen(pgpassfile, "r"); + if (fp == NULL) + return NULL; + + /* Use an expansible buffer to accommodate any reasonable line length */ + initPQExpBuffer(&buf); + + while (!feof(fp) && !ferror(fp)) + { + /* Make sure there's a reasonable amount of room in the buffer */ + if (!enlargePQExpBuffer(&buf, 128)) + break; + + /* Read some data, appending it to what we already have */ + if (fgets(buf.data + buf.len, buf.maxlen - buf.len, fp) == NULL) + break; + buf.len += strlen(buf.data + buf.len); + + /* If we don't yet have a whole line, loop around to read more */ + if (!(buf.len > 0 && buf.data[buf.len - 1] == '\n') && !feof(fp)) + continue; + + /* ignore comments */ + if (buf.data[0] != '#') + { + char *t = buf.data; + int len; + + /* strip trailing newline and carriage return */ + len = pg_strip_crlf(t); + + if (len > 0 && + (t = pwdfMatchesString(t, hostname)) != NULL && + (t = pwdfMatchesString(t, port)) != NULL && + (t = pwdfMatchesString(t, dbname)) != NULL && + (t = pwdfMatchesString(t, username)) != NULL) + { + /* Found a match. */ + char *ret, + *p1, + *p2; + + ret = strdup(t); + + fclose(fp); + explicit_bzero(buf.data, buf.maxlen); + termPQExpBuffer(&buf); + + if (!ret) + { + /* Out of memory. XXX: an error message would be nice. */ + return NULL; + } + + /* De-escape password. */ + for (p1 = p2 = ret; *p1 != ':' && *p1 != '\0'; ++p1, ++p2) + { + if (*p1 == '\\' && p1[1] != '\0') + ++p1; + *p2 = *p1; + } + *p2 = '\0'; + + return ret; + } + } + + /* No match, reset buffer to prepare for next line. */ + buf.len = 0; + } + + fclose(fp); + explicit_bzero(buf.data, buf.maxlen); + termPQExpBuffer(&buf); + return NULL; +} + + +/* + * If the connection failed due to bad password, we should mention + * if we got the password from the pgpassfile. + */ +static void +pgpassfileWarning(PGconn *conn) +{ + /* If it was 'invalid authorization', add pgpassfile mention */ + /* only works with >= 9.0 servers */ + if (conn->password_needed && + conn->connhost[conn->whichhost].password != NULL && + conn->result) + { + const char *sqlstate = PQresultErrorField(conn->result, + PG_DIAG_SQLSTATE); + + if (sqlstate && strcmp(sqlstate, ERRCODE_INVALID_PASSWORD) == 0) + libpq_append_conn_error(conn, "password retrieved from file \"%s\"", + conn->pgpassfile); + } +} + +/* + * Check if the SSL protocol value given in input is valid or not. + * This is used as a sanity check routine for the connection parameters + * ssl_min_protocol_version and ssl_max_protocol_version. + */ +static bool +sslVerifyProtocolVersion(const char *version) +{ + /* + * An empty string and a NULL value are considered valid as it is + * equivalent to ignoring the parameter. + */ + if (!version || strlen(version) == 0) + return true; + + if (pg_strcasecmp(version, "TLSv1") == 0 || + pg_strcasecmp(version, "TLSv1.1") == 0 || + pg_strcasecmp(version, "TLSv1.2") == 0 || + pg_strcasecmp(version, "TLSv1.3") == 0) + return true; + + /* anything else is wrong */ + return false; +} + + +/* + * Ensure that the SSL protocol range given in input is correct. The check + * is performed on the input string to keep it TLS backend agnostic. Input + * to this function is expected verified with sslVerifyProtocolVersion(). + */ +static bool +sslVerifyProtocolRange(const char *min, const char *max) +{ + Assert(sslVerifyProtocolVersion(min) && + sslVerifyProtocolVersion(max)); + + /* If at least one of the bounds is not set, the range is valid */ + if (min == NULL || max == NULL || strlen(min) == 0 || strlen(max) == 0) + return true; + + /* + * If the minimum version is the lowest one we accept, then all options + * for the maximum are valid. + */ + if (pg_strcasecmp(min, "TLSv1") == 0) + return true; + + /* + * The minimum bound is valid, and cannot be TLSv1, so using TLSv1 for the + * maximum is incorrect. + */ + if (pg_strcasecmp(max, "TLSv1") == 0) + return false; + + /* + * At this point we know that we have a mix of TLSv1.1 through 1.3 + * versions. + */ + if (pg_strcasecmp(min, max) > 0) + return false; + + return true; +} + + +/* + * Obtain user's home directory, return in given buffer + * + * On Unix, this actually returns the user's home directory. On Windows + * it returns the PostgreSQL-specific application data folder. + * + * This is essentially the same as get_home_path(), but we don't use that + * because we don't want to pull path.c into libpq (it pollutes application + * namespace). + * + * Returns true on success, false on failure to obtain the directory name. + * + * CAUTION: although in most situations failure is unexpected, there are users + * who like to run applications in a home-directory-less environment. On + * failure, you almost certainly DO NOT want to report an error. Just act as + * though whatever file you were hoping to find in the home directory isn't + * there (which it isn't). + */ +bool +pqGetHomeDirectory(char *buf, int bufsize) +{ +#ifndef WIN32 + const char *home; + + home = getenv("HOME"); + if (home == NULL || home[0] == '\0') + return pg_get_user_home_dir(geteuid(), buf, bufsize); + strlcpy(buf, home, bufsize); + return true; +#else + char tmppath[MAX_PATH]; + + ZeroMemory(tmppath, sizeof(tmppath)); + if (SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, tmppath) != S_OK) + return false; + snprintf(buf, bufsize, "%s/postgresql", tmppath); + return true; +#endif +} + +/* + * To keep the API consistent, the locking stubs are always provided, even + * if they are not required. + * + * Since we neglected to provide any error-return convention in the + * pgthreadlock_t API, we can't do much except Assert upon failure of any + * mutex primitive. Fortunately, such failures appear to be nonexistent in + * the field. + */ + +static void +default_threadlock(int acquire) +{ +#ifdef ENABLE_THREAD_SAFETY +#ifndef WIN32 + static pthread_mutex_t singlethread_lock = PTHREAD_MUTEX_INITIALIZER; +#else + static pthread_mutex_t singlethread_lock = NULL; + static long mutex_initlock = 0; + + if (singlethread_lock == NULL) + { + while (InterlockedExchange(&mutex_initlock, 1) == 1) + /* loop, another thread own the lock */ ; + if (singlethread_lock == NULL) + { + if (pthread_mutex_init(&singlethread_lock, NULL)) + Assert(false); + } + InterlockedExchange(&mutex_initlock, 0); + } +#endif + if (acquire) + { + if (pthread_mutex_lock(&singlethread_lock)) + Assert(false); + } + else + { + if (pthread_mutex_unlock(&singlethread_lock)) + Assert(false); + } +#endif +} + +pgthreadlock_t +PQregisterThreadLock(pgthreadlock_t newhandler) +{ + pgthreadlock_t prev = pg_g_threadlock; + + if (newhandler) + pg_g_threadlock = newhandler; + else + pg_g_threadlock = default_threadlock; + + return prev; +} diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c new file mode 100644 index 0000000..fa9d6aa --- /dev/null +++ b/src/interfaces/libpq/fe-exec.c @@ -0,0 +1,4469 @@ +/*------------------------------------------------------------------------- + * + * fe-exec.c + * functions related to sending a query down to the backend + * + * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * src/interfaces/libpq/fe-exec.c + * + *------------------------------------------------------------------------- + */ +#include "postgres_fe.h" + +#include <ctype.h> +#include <fcntl.h> +#include <limits.h> + +#ifdef WIN32 +#include "win32.h" +#else +#include <unistd.h> +#endif + +#include "libpq-fe.h" +#include "libpq-int.h" +#include "mb/pg_wchar.h" + +/* keep this in same order as ExecStatusType in libpq-fe.h */ +char *const pgresStatus[] = { + "PGRES_EMPTY_QUERY", + "PGRES_COMMAND_OK", + "PGRES_TUPLES_OK", + "PGRES_COPY_OUT", + "PGRES_COPY_IN", + "PGRES_BAD_RESPONSE", + "PGRES_NONFATAL_ERROR", + "PGRES_FATAL_ERROR", + "PGRES_COPY_BOTH", + "PGRES_SINGLE_TUPLE", + "PGRES_PIPELINE_SYNC", + "PGRES_PIPELINE_ABORTED" +}; + +/* We return this if we're unable to make a PGresult at all */ +static const PGresult OOM_result = { + .resultStatus = PGRES_FATAL_ERROR, + .client_encoding = PG_SQL_ASCII, + .errMsg = "out of memory\n", +}; + +/* + * static state needed by PQescapeString and PQescapeBytea; initialize to + * values that result in backward-compatible behavior + */ +static int static_client_encoding = PG_SQL_ASCII; +static bool static_std_strings = false; + + +static PGEvent *dupEvents(PGEvent *events, int count, size_t *memSize); +static bool pqAddTuple(PGresult *res, PGresAttValue *tup, + const char **errmsgp); +static int PQsendQueryInternal(PGconn *conn, const char *query, bool newQuery); +static bool PQsendQueryStart(PGconn *conn, bool newQuery); +static int PQsendQueryGuts(PGconn *conn, + const char *command, + const char *stmtName, + int nParams, + const Oid *paramTypes, + const char *const *paramValues, + const int *paramLengths, + const int *paramFormats, + int resultFormat); +static void parseInput(PGconn *conn); +static PGresult *getCopyResult(PGconn *conn, ExecStatusType copytype); +static bool PQexecStart(PGconn *conn); +static PGresult *PQexecFinish(PGconn *conn); +static int PQsendDescribe(PGconn *conn, char desc_type, + const char *desc_target); +static int check_field_number(const PGresult *res, int field_num); +static void pqPipelineProcessQueue(PGconn *conn); +static int pqPipelineFlush(PGconn *conn); + + +/* ---------------- + * Space management for PGresult. + * + * Formerly, libpq did a separate malloc() for each field of each tuple + * returned by a query. This was remarkably expensive --- malloc/free + * consumed a sizable part of the application's runtime. And there is + * no real need to keep track of the fields separately, since they will + * all be freed together when the PGresult is released. So now, we grab + * large blocks of storage from malloc and allocate space for query data + * within these blocks, using a trivially simple allocator. This reduces + * the number of malloc/free calls dramatically, and it also avoids + * fragmentation of the malloc storage arena. + * The PGresult structure itself is still malloc'd separately. We could + * combine it with the first allocation block, but that would waste space + * for the common case that no extra storage is actually needed (that is, + * the SQL command did not return tuples). + * + * We also malloc the top-level array of tuple pointers separately, because + * we need to be able to enlarge it via realloc, and our trivial space + * allocator doesn't handle that effectively. (Too bad the FE/BE protocol + * doesn't tell us up front how many tuples will be returned.) + * All other subsidiary storage for a PGresult is kept in PGresult_data blocks + * of size PGRESULT_DATA_BLOCKSIZE. The overhead at the start of each block + * is just a link to the next one, if any. Free-space management info is + * kept in the owning PGresult. + * A query returning a small amount of data will thus require three malloc + * calls: one for the PGresult, one for the tuples pointer array, and one + * PGresult_data block. + * + * Only the most recently allocated PGresult_data block is a candidate to + * have more stuff added to it --- any extra space left over in older blocks + * is wasted. We could be smarter and search the whole chain, but the point + * here is to be simple and fast. Typical applications do not keep a PGresult + * around very long anyway, so some wasted space within one is not a problem. + * + * Tuning constants for the space allocator are: + * PGRESULT_DATA_BLOCKSIZE: size of a standard allocation block, in bytes + * PGRESULT_ALIGN_BOUNDARY: assumed alignment requirement for binary data + * PGRESULT_SEP_ALLOC_THRESHOLD: objects bigger than this are given separate + * blocks, instead of being crammed into a regular allocation block. + * Requirements for correct function are: + * PGRESULT_ALIGN_BOUNDARY must be a multiple of the alignment requirements + * of all machine data types. (Currently this is set from configure + * tests, so it should be OK automatically.) + * PGRESULT_SEP_ALLOC_THRESHOLD + PGRESULT_BLOCK_OVERHEAD <= + * PGRESULT_DATA_BLOCKSIZE + * pqResultAlloc assumes an object smaller than the threshold will fit + * in a new block. + * The amount of space wasted at the end of a block could be as much as + * PGRESULT_SEP_ALLOC_THRESHOLD, so it doesn't pay to make that too large. + * ---------------- + */ + +#define PGRESULT_DATA_BLOCKSIZE 2048 +#define PGRESULT_ALIGN_BOUNDARY MAXIMUM_ALIGNOF /* from configure */ +#define PGRESULT_BLOCK_OVERHEAD Max(sizeof(PGresult_data), PGRESULT_ALIGN_BOUNDARY) +#define PGRESULT_SEP_ALLOC_THRESHOLD (PGRESULT_DATA_BLOCKSIZE / 2) + + +/* + * PQmakeEmptyPGresult + * returns a newly allocated, initialized PGresult with given status. + * If conn is not NULL and status indicates an error, the conn's + * errorMessage is copied. Also, any PGEvents are copied from the conn. + * + * Note: the logic to copy the conn's errorMessage is now vestigial; + * no internal caller uses it. However, that behavior is documented for + * outside callers, so we'd better keep it. + */ +PGresult * +PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status) +{ + PGresult *result; + + result = (PGresult *) malloc(sizeof(PGresult)); + if (!result) + return NULL; + + result->ntups = 0; + result->numAttributes = 0; + result->attDescs = NULL; + result->tuples = NULL; + result->tupArrSize = 0; + result->numParameters = 0; + result->paramDescs = NULL; + result->resultStatus = status; + result->cmdStatus[0] = '\0'; + result->binary = 0; + result->events = NULL; + result->nEvents = 0; + result->errMsg = NULL; + result->errFields = NULL; + result->errQuery = NULL; + result->null_field[0] = '\0'; + result->curBlock = NULL; + result->curOffset = 0; + result->spaceLeft = 0; + result->memorySize = sizeof(PGresult); + + if (conn) + { + /* copy connection data we might need for operations on PGresult */ + result->noticeHooks = conn->noticeHooks; + result->client_encoding = conn->client_encoding; + + /* consider copying conn's errorMessage */ + switch (status) + { + case PGRES_EMPTY_QUERY: + case PGRES_COMMAND_OK: + case PGRES_TUPLES_OK: + case PGRES_COPY_OUT: + case PGRES_COPY_IN: + case PGRES_COPY_BOTH: + case PGRES_SINGLE_TUPLE: + /* non-error cases */ + break; + default: + /* we intentionally do not use or modify errorReported here */ + pqSetResultError(result, &conn->errorMessage, 0); + break; + } + + /* copy events last; result must be valid if we need to PQclear */ + if (conn->nEvents > 0) + { + result->events = dupEvents(conn->events, conn->nEvents, + &result->memorySize); + if (!result->events) + { + PQclear(result); + return NULL; + } + result->nEvents = conn->nEvents; + } + } + else + { + /* defaults... */ + result->noticeHooks.noticeRec = NULL; + result->noticeHooks.noticeRecArg = NULL; + result->noticeHooks.noticeProc = NULL; + result->noticeHooks.noticeProcArg = NULL; + result->client_encoding = PG_SQL_ASCII; + } + + return result; +} + +/* + * PQsetResultAttrs + * + * Set the attributes for a given result. This function fails if there are + * already attributes contained in the provided result. The call is + * ignored if numAttributes is zero or attDescs is NULL. If the + * function fails, it returns zero. If the function succeeds, it + * returns a non-zero value. + */ +int +PQsetResultAttrs(PGresult *res, int numAttributes, PGresAttDesc *attDescs) +{ + int i; + + /* Fail if argument is NULL or OOM_result */ + if (!res || (const PGresult *) res == &OOM_result) + return false; + + /* If attrs already exist, they cannot be overwritten. */ + if (res->numAttributes > 0) + return false; + + /* ignore no-op request */ + if (numAttributes <= 0 || !attDescs) + return true; + + res->attDescs = (PGresAttDesc *) + PQresultAlloc(res, numAttributes * sizeof(PGresAttDesc)); + + if (!res->attDescs) + return false; + + res->numAttributes = numAttributes; + memcpy(res->attDescs, attDescs, numAttributes * sizeof(PGresAttDesc)); + + /* deep-copy the attribute names, and determine format */ + res->binary = 1; + for (i = 0; i < res->numAttributes; i++) + { + if (res->attDescs[i].name) + res->attDescs[i].name = pqResultStrdup(res, res->attDescs[i].name); + else + res->attDescs[i].name = res->null_field; + + if (!res->attDescs[i].name) + return false; + + if (res->attDescs[i].format == 0) + res->binary = 0; + } + + return true; +} + +/* + * PQcopyResult + * + * Returns a deep copy of the provided 'src' PGresult, which cannot be NULL. + * The 'flags' argument controls which portions of the result will or will + * NOT be copied. The created result is always put into the + * PGRES_TUPLES_OK status. The source result error message is not copied, + * although cmdStatus is. + * + * To set custom attributes, use PQsetResultAttrs. That function requires + * that there are no attrs contained in the result, so to use that + * function you cannot use the PG_COPYRES_ATTRS or PG_COPYRES_TUPLES + * options with this function. + * + * Options: + * PG_COPYRES_ATTRS - Copy the source result's attributes + * + * PG_COPYRES_TUPLES - Copy the source result's tuples. This implies + * copying the attrs, seeing how the attrs are needed by the tuples. + * + * PG_COPYRES_EVENTS - Copy the source result's events. + * + * PG_COPYRES_NOTICEHOOKS - Copy the source result's notice hooks. + */ +PGresult * +PQcopyResult(const PGresult *src, int flags) +{ + PGresult *dest; + int i; + + if (!src) + return NULL; + + dest = PQmakeEmptyPGresult(NULL, PGRES_TUPLES_OK); + if (!dest) + return NULL; + + /* Always copy these over. Is cmdStatus really useful here? */ + dest->client_encoding = src->client_encoding; + strcpy(dest->cmdStatus, src->cmdStatus); + + /* Wants attrs? */ + if (flags & (PG_COPYRES_ATTRS | PG_COPYRES_TUPLES)) + { + if (!PQsetResultAttrs(dest, src->numAttributes, src->attDescs)) + { + PQclear(dest); + return NULL; + } + } + + /* Wants to copy tuples? */ + if (flags & PG_COPYRES_TUPLES) + { + int tup, + field; + + for (tup = 0; tup < src->ntups; tup++) + { + for (field = 0; field < src->numAttributes; field++) + { + if (!PQsetvalue(dest, tup, field, + src->tuples[tup][field].value, + src->tuples[tup][field].len)) + { + PQclear(dest); + return NULL; + } + } + } + } + + /* Wants to copy notice hooks? */ + if (flags & PG_COPYRES_NOTICEHOOKS) + dest->noticeHooks = src->noticeHooks; + + /* Wants to copy PGEvents? */ + if ((flags & PG_COPYRES_EVENTS) && src->nEvents > 0) + { + dest->events = dupEvents(src->events, src->nEvents, + &dest->memorySize); + if (!dest->events) + { + PQclear(dest); + return NULL; + } + dest->nEvents = src->nEvents; + } + + /* Okay, trigger PGEVT_RESULTCOPY event */ + for (i = 0; i < dest->nEvents; i++) + { + /* We don't fire events that had some previous failure */ + if (src->events[i].resultInitialized) + { + PGEventResultCopy evt; + + evt.src = src; + evt.dest = dest; + if (dest->events[i].proc(PGEVT_RESULTCOPY, &evt, + dest->events[i].passThrough)) + dest->events[i].resultInitialized = true; + } + } + + return dest; +} + +/* + * Copy an array of PGEvents (with no extra space for more). + * Does not duplicate the event instance data, sets this to NULL. + * Also, the resultInitialized flags are all cleared. + * The total space allocated is added to *memSize. + */ +static PGEvent * +dupEvents(PGEvent *events, int count, size_t *memSize) +{ + PGEvent *newEvents; + size_t msize; + int i; + + if (!events || count <= 0) + return NULL; + + msize = count * sizeof(PGEvent); + newEvents = (PGEvent *) malloc(msize); + if (!newEvents) + return NULL; + + for (i = 0; i < count; i++) + { + newEvents[i].proc = events[i].proc; + newEvents[i].passThrough = events[i].passThrough; + newEvents[i].data = NULL; + newEvents[i].resultInitialized = false; + newEvents[i].name = strdup(events[i].name); + if (!newEvents[i].name) + { + while (--i >= 0) + free(newEvents[i].name); + free(newEvents); + return NULL; + } + msize += strlen(events[i].name) + 1; + } + + *memSize += msize; + return newEvents; +} + + +/* + * Sets the value for a tuple field. The tup_num must be less than or + * equal to PQntuples(res). If it is equal, a new tuple is created and + * added to the result. + * Returns a non-zero value for success and zero for failure. + * (On failure, we report the specific problem via pqInternalNotice.) + */ +int +PQsetvalue(PGresult *res, int tup_num, int field_num, char *value, int len) +{ + PGresAttValue *attval; + const char *errmsg = NULL; + + /* Fail if argument is NULL or OOM_result */ + if (!res || (const PGresult *) res == &OOM_result) + return false; + + /* Invalid field_num? */ + if (!check_field_number(res, field_num)) + return false; + + /* Invalid tup_num, must be <= ntups */ + if (tup_num < 0 || tup_num > res->ntups) + { + pqInternalNotice(&res->noticeHooks, + "row number %d is out of range 0..%d", + tup_num, res->ntups); + return false; + } + + /* need to allocate a new tuple? */ + if (tup_num == res->ntups) + { + PGresAttValue *tup; + int i; + + tup = (PGresAttValue *) + pqResultAlloc(res, res->numAttributes * sizeof(PGresAttValue), + true); + + if (!tup) + goto fail; + + /* initialize each column to NULL */ + for (i = 0; i < res->numAttributes; i++) + { + tup[i].len = NULL_LEN; + tup[i].value = res->null_field; + } + + /* add it to the array */ + if (!pqAddTuple(res, tup, &errmsg)) + goto fail; + } + + attval = &res->tuples[tup_num][field_num]; + + /* treat either NULL_LEN or NULL value pointer as a NULL field */ + if (len == NULL_LEN || value == NULL) + { + attval->len = NULL_LEN; + attval->value = res->null_field; + } + else if (len <= 0) + { + attval->len = 0; + attval->value = res->null_field; + } + else + { + attval->value = (char *) pqResultAlloc(res, len + 1, true); + if (!attval->value) + goto fail; + attval->len = len; + memcpy(attval->value, value, len); + attval->value[len] = '\0'; + } + + return true; + + /* + * Report failure via pqInternalNotice. If preceding code didn't provide + * an error message, assume "out of memory" was meant. + */ +fail: + if (!errmsg) + errmsg = libpq_gettext("out of memory"); + pqInternalNotice(&res->noticeHooks, "%s", errmsg); + + return false; +} + +/* + * pqResultAlloc - exported routine to allocate local storage in a PGresult. + * + * We force all such allocations to be maxaligned, since we don't know + * whether the value might be binary. + */ +void * +PQresultAlloc(PGresult *res, size_t nBytes) +{ + /* Fail if argument is NULL or OOM_result */ + if (!res || (const PGresult *) res == &OOM_result) + return NULL; + + return pqResultAlloc(res, nBytes, true); +} + +/* + * pqResultAlloc - + * Allocate subsidiary storage for a PGresult. + * + * nBytes is the amount of space needed for the object. + * If isBinary is true, we assume that we need to align the object on + * a machine allocation boundary. + * If isBinary is false, we assume the object is a char string and can + * be allocated on any byte boundary. + */ +void * +pqResultAlloc(PGresult *res, size_t nBytes, bool isBinary) +{ + char *space; + PGresult_data *block; + + if (!res) + return NULL; + + if (nBytes <= 0) + return res->null_field; + + /* + * If alignment is needed, round up the current position to an alignment + * boundary. + */ + if (isBinary) + { + int offset = res->curOffset % PGRESULT_ALIGN_BOUNDARY; + + if (offset) + { + res->curOffset += PGRESULT_ALIGN_BOUNDARY - offset; + res->spaceLeft -= PGRESULT_ALIGN_BOUNDARY - offset; + } + } + + /* If there's enough space in the current block, no problem. */ + if (nBytes <= (size_t) res->spaceLeft) + { + space = res->curBlock->space + res->curOffset; + res->curOffset += nBytes; + res->spaceLeft -= nBytes; + return space; + } + + /* + * If the requested object is very large, give it its own block; this + * avoids wasting what might be most of the current block to start a new + * block. (We'd have to special-case requests bigger than the block size + * anyway.) The object is always given binary alignment in this case. + */ + if (nBytes >= PGRESULT_SEP_ALLOC_THRESHOLD) + { + size_t alloc_size = nBytes + PGRESULT_BLOCK_OVERHEAD; + + block = (PGresult_data *) malloc(alloc_size); + if (!block) + return NULL; + res->memorySize += alloc_size; + space = block->space + PGRESULT_BLOCK_OVERHEAD; + if (res->curBlock) + { + /* + * Tuck special block below the active block, so that we don't + * have to waste the free space in the active block. + */ + block->next = res->curBlock->next; + res->curBlock->next = block; + } + else + { + /* Must set up the new block as the first active block. */ + block->next = NULL; + res->curBlock = block; + res->spaceLeft = 0; /* be sure it's marked full */ + } + return space; + } + + /* Otherwise, start a new block. */ + block = (PGresult_data *) malloc(PGRESULT_DATA_BLOCKSIZE); + if (!block) + return NULL; + res->memorySize += PGRESULT_DATA_BLOCKSIZE; + block->next = res->curBlock; + res->curBlock = block; + if (isBinary) + { + /* object needs full alignment */ + res->curOffset = PGRESULT_BLOCK_OVERHEAD; + res->spaceLeft = PGRESULT_DATA_BLOCKSIZE - PGRESULT_BLOCK_OVERHEAD; + } + else + { + /* we can cram it right after the overhead pointer */ + res->curOffset = sizeof(PGresult_data); + res->spaceLeft = PGRESULT_DATA_BLOCKSIZE - sizeof(PGresult_data); + } + + space = block->space + res->curOffset; + res->curOffset += nBytes; + res->spaceLeft -= nBytes; + return space; +} + +/* + * PQresultMemorySize - + * Returns total space allocated for the PGresult. + */ +size_t +PQresultMemorySize(const PGresult *res) +{ + if (!res) + return 0; + return res->memorySize; +} + +/* + * pqResultStrdup - + * Like strdup, but the space is subsidiary PGresult space. + */ +char * +pqResultStrdup(PGresult *res, const char *str) +{ + char *space = (char *) pqResultAlloc(res, strlen(str) + 1, false); + + if (space) + strcpy(space, str); + return space; +} + +/* + * pqSetResultError - + * assign a new error message to a PGresult + * + * Copy text from errorMessage buffer beginning at given offset + * (it's caller's responsibility that offset is valid) + */ +void +pqSetResultError(PGresult *res, PQExpBuffer errorMessage, int offset) +{ + char *msg; + + if (!res) + return; + + /* + * We handle two OOM scenarios here. The errorMessage buffer might be + * marked "broken" due to having previously failed to allocate enough + * memory for the message, or it might be fine but pqResultStrdup fails + * and returns NULL. In either case, just make res->errMsg point directly + * at a constant "out of memory" string. + */ + if (!PQExpBufferBroken(errorMessage)) + msg = pqResultStrdup(res, errorMessage->data + offset); + else + msg = NULL; + if (msg) + res->errMsg = msg; + else + res->errMsg = libpq_gettext("out of memory\n"); +} + +/* + * PQclear - + * free's the memory associated with a PGresult + */ +void +PQclear(PGresult *res) +{ + PGresult_data *block; + int i; + + /* As a convenience, do nothing for a NULL pointer */ + if (!res) + return; + /* Also, do nothing if the argument is OOM_result */ + if ((const PGresult *) res == &OOM_result) + return; + + /* Close down any events we may have */ + for (i = 0; i < res->nEvents; i++) + { + /* only send DESTROY to successfully-initialized event procs */ + if (res->events[i].resultInitialized) + { + PGEventResultDestroy evt; + + evt.result = res; + (void) res->events[i].proc(PGEVT_RESULTDESTROY, &evt, + res->events[i].passThrough); + } + free(res->events[i].name); + } + + free(res->events); + + /* Free all the subsidiary blocks */ + while ((block = res->curBlock) != NULL) + { + res->curBlock = block->next; + free(block); + } + + /* Free the top-level tuple pointer array */ + free(res->tuples); + + /* zero out the pointer fields to catch programming errors */ + res->attDescs = NULL; + res->tuples = NULL; + res->paramDescs = NULL; + res->errFields = NULL; + res->events = NULL; + res->nEvents = 0; + /* res->curBlock was zeroed out earlier */ + + /* Free the PGresult structure itself */ + free(res); +} + +/* + * Handy subroutine to deallocate any partially constructed async result. + * + * Any "next" result gets cleared too. + */ +void +pqClearAsyncResult(PGconn *conn) +{ + PQclear(conn->result); + conn->result = NULL; + conn->error_result = false; + PQclear(conn->next_result); + conn->next_result = NULL; +} + +/* + * pqSaveErrorResult - + * remember that we have an error condition + * + * In much of libpq, reporting an error just requires appending text to + * conn->errorMessage and returning a failure code to one's caller. + * Where returning a failure code is impractical, instead call this + * function to remember that an error needs to be reported. + * + * (It might seem that appending text to conn->errorMessage should be + * sufficient, but we can't rely on that working under out-of-memory + * conditions. The OOM hazard is also why we don't try to make a new + * PGresult right here.) + */ +void +pqSaveErrorResult(PGconn *conn) +{ + /* Drop any pending result ... */ + pqClearAsyncResult(conn); + /* ... and set flag to remember to make an error result later */ + conn->error_result = true; +} + +/* + * pqSaveWriteError - + * report a write failure + * + * As above, after appending conn->write_err_msg to whatever other error we + * have. This is used when we've detected a write failure and have exhausted + * our chances of reporting something else instead. + */ +static void +pqSaveWriteError(PGconn *conn) +{ + /* + * If write_err_msg is null because of previous strdup failure, do what we + * can. (It's likely our machinations here will get OOM failures as well, + * but might as well try.) + */ + if (conn->write_err_msg) + { + appendPQExpBufferStr(&conn->errorMessage, conn->write_err_msg); + /* Avoid possibly appending the same message twice */ + conn->write_err_msg[0] = '\0'; + } + else + libpq_append_conn_error(conn, "write to server failed"); + + pqSaveErrorResult(conn); +} + +/* + * pqPrepareAsyncResult - + * prepare the current async result object for return to the caller + * + * If there is not already an async result object, build an error object + * using whatever is in conn->errorMessage. In any case, clear the async + * result storage, and update our notion of how much error text has been + * returned to the application. + * + * Note that in no case (not even OOM) do we return NULL. + */ +PGresult * +pqPrepareAsyncResult(PGconn *conn) +{ + PGresult *res; + + res = conn->result; + if (res) + { + /* + * If the pre-existing result is an ERROR (presumably something + * received from the server), assume that it represents whatever is in + * conn->errorMessage, and advance errorReported. + */ + if (res->resultStatus == PGRES_FATAL_ERROR) + conn->errorReported = conn->errorMessage.len; + } + else + { + /* + * We get here after internal-to-libpq errors. We should probably + * always have error_result = true, but if we don't, gin up some error + * text. + */ + if (!conn->error_result) + libpq_append_conn_error(conn, "no error text available"); + + /* Paranoia: be sure errorReported offset is sane */ + if (conn->errorReported < 0 || + conn->errorReported >= conn->errorMessage.len) + conn->errorReported = 0; + + /* + * Make a PGresult struct for the error. We temporarily lie about the + * result status, so that PQmakeEmptyPGresult doesn't uselessly copy + * all of conn->errorMessage. + */ + res = PQmakeEmptyPGresult(conn, PGRES_EMPTY_QUERY); + if (res) + { + /* + * Report whatever new error text we have, and advance + * errorReported. + */ + res->resultStatus = PGRES_FATAL_ERROR; + pqSetResultError(res, &conn->errorMessage, conn->errorReported); + conn->errorReported = conn->errorMessage.len; + } + else + { + /* + * Ouch, not enough memory for a PGresult. Fortunately, we have a + * card up our sleeve: we can use the static OOM_result. Casting + * away const here is a bit ugly, but it seems best to declare + * OOM_result as const, in hopes it will be allocated in read-only + * storage. + */ + res = unconstify(PGresult *, &OOM_result); + + /* + * Don't advance errorReported. Perhaps we'll be able to report + * the text later. + */ + } + } + + /* + * Replace conn->result with next_result, if any. In the normal case + * there isn't a next result and we're just dropping ownership of the + * current result. In single-row mode this restores the situation to what + * it was before we created the current single-row result. + */ + conn->result = conn->next_result; + conn->error_result = false; /* next_result is never an error */ + conn->next_result = NULL; + + return res; +} + +/* + * pqInternalNotice - produce an internally-generated notice message + * + * A format string and optional arguments can be passed. Note that we do + * libpq_gettext() here, so callers need not. + * + * The supplied text is taken as primary message (ie., it should not include + * a trailing newline, and should not be more than one line). + */ +void +pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt,...) +{ + char msgBuf[1024]; + va_list args; + PGresult *res; + + if (hooks->noticeRec == NULL) + return; /* nobody home to receive notice? */ + + /* Format the message */ + va_start(args, fmt); + vsnprintf(msgBuf, sizeof(msgBuf), libpq_gettext(fmt), args); + va_end(args); + msgBuf[sizeof(msgBuf) - 1] = '\0'; /* make real sure it's terminated */ + + /* Make a PGresult to pass to the notice receiver */ + res = PQmakeEmptyPGresult(NULL, PGRES_NONFATAL_ERROR); + if (!res) + return; + res->noticeHooks = *hooks; + + /* + * Set up fields of notice. + */ + pqSaveMessageField(res, PG_DIAG_MESSAGE_PRIMARY, msgBuf); + pqSaveMessageField(res, PG_DIAG_SEVERITY, libpq_gettext("NOTICE")); + pqSaveMessageField(res, PG_DIAG_SEVERITY_NONLOCALIZED, "NOTICE"); + /* XXX should provide a SQLSTATE too? */ + + /* + * Result text is always just the primary message + newline. If we can't + * allocate it, substitute "out of memory", as in pqSetResultError. + */ + res->errMsg = (char *) pqResultAlloc(res, strlen(msgBuf) + 2, false); + if (res->errMsg) + sprintf(res->errMsg, "%s\n", msgBuf); + else + res->errMsg = libpq_gettext("out of memory\n"); + + /* + * Pass to receiver, then free it. + */ + res->noticeHooks.noticeRec(res->noticeHooks.noticeRecArg, res); + PQclear(res); +} + +/* + * pqAddTuple + * add a row pointer to the PGresult structure, growing it if necessary + * Returns true if OK, false if an error prevented adding the row + * + * On error, *errmsgp can be set to an error string to be returned. + * If it is left NULL, the error is presumed to be "out of memory". + */ +static bool +pqAddTuple(PGresult *res, PGresAttValue *tup, const char **errmsgp) +{ + if (res->ntups >= res->tupArrSize) + { + /* + * Try to grow the array. + * + * We can use realloc because shallow copying of the structure is + * okay. Note that the first time through, res->tuples is NULL. While + * ANSI says that realloc() should act like malloc() in that case, + * some old C libraries (like SunOS 4.1.x) coredump instead. On + * failure realloc is supposed to return NULL without damaging the + * existing allocation. Note that the positions beyond res->ntups are + * garbage, not necessarily NULL. + */ + int newSize; + PGresAttValue **newTuples; + + /* + * Since we use integers for row numbers, we can't support more than + * INT_MAX rows. Make sure we allow that many, though. + */ + if (res->tupArrSize <= INT_MAX / 2) + newSize = (res->tupArrSize > 0) ? res->tupArrSize * 2 : 128; + else if (res->tupArrSize < INT_MAX) + newSize = INT_MAX; + else + { + *errmsgp = libpq_gettext("PGresult cannot support more than INT_MAX tuples"); + return false; + } + + /* + * Also, on 32-bit platforms we could, in theory, overflow size_t even + * before newSize gets to INT_MAX. (In practice we'd doubtless hit + * OOM long before that, but let's check.) + */ +#if INT_MAX >= (SIZE_MAX / 2) + if (newSize > SIZE_MAX / sizeof(PGresAttValue *)) + { + *errmsgp = libpq_gettext("size_t overflow"); + return false; + } +#endif + + if (res->tuples == NULL) + newTuples = (PGresAttValue **) + malloc(newSize * sizeof(PGresAttValue *)); + else + newTuples = (PGresAttValue **) + realloc(res->tuples, newSize * sizeof(PGresAttValue *)); + if (!newTuples) + return false; /* malloc or realloc failed */ + res->memorySize += + (newSize - res->tupArrSize) * sizeof(PGresAttValue *); + res->tupArrSize = newSize; + res->tuples = newTuples; + } + res->tuples[res->ntups] = tup; + res->ntups++; + return true; +} + +/* + * pqSaveMessageField - save one field of an error or notice message + */ +void +pqSaveMessageField(PGresult *res, char code, const char *value) +{ + PGMessageField *pfield; + + pfield = (PGMessageField *) + pqResultAlloc(res, + offsetof(PGMessageField, contents) + + strlen(value) + 1, + true); + if (!pfield) + return; /* out of memory? */ + pfield->code = code; + strcpy(pfield->contents, value); + pfield->next = res->errFields; + res->errFields = pfield; +} + +/* + * pqSaveParameterStatus - remember parameter status sent by backend + */ +void +pqSaveParameterStatus(PGconn *conn, const char *name, const char *value) +{ + pgParameterStatus *pstatus; + pgParameterStatus *prev; + + /* + * Forget any old information about the parameter + */ + for (pstatus = conn->pstatus, prev = NULL; + pstatus != NULL; + prev = pstatus, pstatus = pstatus->next) + { + if (strcmp(pstatus->name, name) == 0) + { + if (prev) + prev->next = pstatus->next; + else + conn->pstatus = pstatus->next; + free(pstatus); /* frees name and value strings too */ + break; + } + } + + /* + * Store new info as a single malloc block + */ + pstatus = (pgParameterStatus *) malloc(sizeof(pgParameterStatus) + + strlen(name) + strlen(value) + 2); + if (pstatus) + { + char *ptr; + + ptr = ((char *) pstatus) + sizeof(pgParameterStatus); + pstatus->name = ptr; + strcpy(ptr, name); + ptr += strlen(name) + 1; + pstatus->value = ptr; + strcpy(ptr, value); + pstatus->next = conn->pstatus; + conn->pstatus = pstatus; + } + + /* + * Save values of settings that are of interest to libpq in fields of the + * PGconn object. We keep client_encoding and standard_conforming_strings + * in static variables as well, so that PQescapeString and PQescapeBytea + * can behave somewhat sanely (at least in single-connection-using + * programs). + */ + if (strcmp(name, "client_encoding") == 0) + { + conn->client_encoding = pg_char_to_encoding(value); + /* if we don't recognize the encoding name, fall back to SQL_ASCII */ + if (conn->client_encoding < 0) + conn->client_encoding = PG_SQL_ASCII; + static_client_encoding = conn->client_encoding; + } + else if (strcmp(name, "standard_conforming_strings") == 0) + { + conn->std_strings = (strcmp(value, "on") == 0); + static_std_strings = conn->std_strings; + } + else if (strcmp(name, "server_version") == 0) + { + /* We convert the server version to numeric form. */ + int cnt; + int vmaj, + vmin, + vrev; + + cnt = sscanf(value, "%d.%d.%d", &vmaj, &vmin, &vrev); + + if (cnt == 3) + { + /* old style, e.g. 9.6.1 */ + conn->sversion = (100 * vmaj + vmin) * 100 + vrev; + } + else if (cnt == 2) + { + if (vmaj >= 10) + { + /* new style, e.g. 10.1 */ + conn->sversion = 100 * 100 * vmaj + vmin; + } + else + { + /* old style without minor version, e.g. 9.6devel */ + conn->sversion = (100 * vmaj + vmin) * 100; + } + } + else if (cnt == 1) + { + /* new style without minor version, e.g. 10devel */ + conn->sversion = 100 * 100 * vmaj; + } + else + conn->sversion = 0; /* unknown */ + } + else if (strcmp(name, "default_transaction_read_only") == 0) + { + conn->default_transaction_read_only = + (strcmp(value, "on") == 0) ? PG_BOOL_YES : PG_BOOL_NO; + } + else if (strcmp(name, "in_hot_standby") == 0) + { + conn->in_hot_standby = + (strcmp(value, "on") == 0) ? PG_BOOL_YES : PG_BOOL_NO; + } + else if (strcmp(name, "scram_iterations") == 0) + { + conn->scram_sha_256_iterations = atoi(value); + } +} + + +/* + * pqRowProcessor + * Add the received row to the current async result (conn->result). + * Returns 1 if OK, 0 if error occurred. + * + * On error, *errmsgp can be set to an error string to be returned. + * (Such a string should already be translated via libpq_gettext().) + * If it is left NULL, the error is presumed to be "out of memory". + * + * In single-row mode, we create a new result holding just the current row, + * stashing the previous result in conn->next_result so that it becomes + * active again after pqPrepareAsyncResult(). This allows the result metadata + * (column descriptions) to be carried forward to each result row. + */ +int +pqRowProcessor(PGconn *conn, const char **errmsgp) +{ + PGresult *res = conn->result; + int nfields = res->numAttributes; + const PGdataValue *columns = conn->rowBuf; + PGresAttValue *tup; + int i; + + /* + * In single-row mode, make a new PGresult that will hold just this one + * row; the original conn->result is left unchanged so that it can be used + * again as the template for future rows. + */ + if (conn->singleRowMode) + { + /* Copy everything that should be in the result at this point */ + res = PQcopyResult(res, + PG_COPYRES_ATTRS | PG_COPYRES_EVENTS | + PG_COPYRES_NOTICEHOOKS); + if (!res) + return 0; + } + + /* + * Basically we just allocate space in the PGresult for each field and + * copy the data over. + * + * Note: on malloc failure, we return 0 leaving *errmsgp still NULL, which + * caller will take to mean "out of memory". This is preferable to trying + * to set up such a message here, because evidently there's not enough + * memory for gettext() to do anything. + */ + tup = (PGresAttValue *) + pqResultAlloc(res, nfields * sizeof(PGresAttValue), true); + if (tup == NULL) + goto fail; + + for (i = 0; i < nfields; i++) + { + int clen = columns[i].len; + + if (clen < 0) + { + /* null field */ + tup[i].len = NULL_LEN; + tup[i].value = res->null_field; + } + else + { + bool isbinary = (res->attDescs[i].format != 0); + char *val; + + val = (char *) pqResultAlloc(res, clen + 1, isbinary); + if (val == NULL) + goto fail; + + /* copy and zero-terminate the data (even if it's binary) */ + memcpy(val, columns[i].value, clen); + val[clen] = '\0'; + + tup[i].len = clen; + tup[i].value = val; + } + } + + /* And add the tuple to the PGresult's tuple array */ + if (!pqAddTuple(res, tup, errmsgp)) + goto fail; + + /* + * Success. In single-row mode, make the result available to the client + * immediately. + */ + if (conn->singleRowMode) + { + /* Change result status to special single-row value */ + res->resultStatus = PGRES_SINGLE_TUPLE; + /* Stash old result for re-use later */ + conn->next_result = conn->result; + conn->result = res; + /* And mark the result ready to return */ + conn->asyncStatus = PGASYNC_READY_MORE; + } + + return 1; + +fail: + /* release locally allocated PGresult, if we made one */ + if (res != conn->result) + PQclear(res); + return 0; +} + + +/* + * pqAllocCmdQueueEntry + * Get a command queue entry for caller to fill. + * + * If the recycle queue has a free element, that is returned; if not, a + * fresh one is allocated. Caller is responsible for adding it to the + * command queue (pqAppendCmdQueueEntry) once the struct is filled in, or + * releasing the memory (pqRecycleCmdQueueEntry) if an error occurs. + * + * If allocation fails, sets the error message and returns NULL. + */ +static PGcmdQueueEntry * +pqAllocCmdQueueEntry(PGconn *conn) +{ + PGcmdQueueEntry *entry; + + if (conn->cmd_queue_recycle == NULL) + { + entry = (PGcmdQueueEntry *) malloc(sizeof(PGcmdQueueEntry)); + if (entry == NULL) + { + libpq_append_conn_error(conn, "out of memory"); + return NULL; + } + } + else + { + entry = conn->cmd_queue_recycle; + conn->cmd_queue_recycle = entry->next; + } + entry->next = NULL; + entry->query = NULL; + + return entry; +} + +/* + * pqAppendCmdQueueEntry + * Append a caller-allocated entry to the command queue, and update + * conn->asyncStatus to account for it. + * + * The query itself must already have been put in the output buffer by the + * caller. + */ +static void +pqAppendCmdQueueEntry(PGconn *conn, PGcmdQueueEntry *entry) +{ + Assert(entry->next == NULL); + + if (conn->cmd_queue_head == NULL) + conn->cmd_queue_head = entry; + else + conn->cmd_queue_tail->next = entry; + + conn->cmd_queue_tail = entry; + + switch (conn->pipelineStatus) + { + case PQ_PIPELINE_OFF: + case PQ_PIPELINE_ON: + + /* + * When not in pipeline aborted state, if there's a result ready + * to be consumed, let it be so (that is, don't change away from + * READY or READY_MORE); otherwise set us busy to wait for + * something to arrive from the server. + */ + if (conn->asyncStatus == PGASYNC_IDLE) + conn->asyncStatus = PGASYNC_BUSY; + break; + + case PQ_PIPELINE_ABORTED: + + /* + * In aborted pipeline state, we don't expect anything from the + * server (since we don't send any queries that are queued). + * Therefore, if IDLE then do what PQgetResult would do to let + * itself consume commands from the queue; if we're in any other + * state, we don't have to do anything. + */ + if (conn->asyncStatus == PGASYNC_IDLE || + conn->asyncStatus == PGASYNC_PIPELINE_IDLE) + pqPipelineProcessQueue(conn); + break; + } +} + +/* + * pqRecycleCmdQueueEntry + * Push a command queue entry onto the freelist. + */ +static void +pqRecycleCmdQueueEntry(PGconn *conn, PGcmdQueueEntry *entry) +{ + if (entry == NULL) + return; + + /* recyclable entries should not have a follow-on command */ + Assert(entry->next == NULL); + + if (entry->query) + { + free(entry->query); + entry->query = NULL; + } + + entry->next = conn->cmd_queue_recycle; + conn->cmd_queue_recycle = entry; +} + + +/* + * PQsendQuery + * Submit a query, but don't wait for it to finish + * + * Returns: 1 if successfully submitted + * 0 if error (conn->errorMessage is set) + * + * PQsendQueryContinue is a non-exported version that behaves identically + * except that it doesn't reset conn->errorMessage. + */ +int +PQsendQuery(PGconn *conn, const char *query) +{ + return PQsendQueryInternal(conn, query, true); +} + +int +PQsendQueryContinue(PGconn *conn, const char *query) +{ + return PQsendQueryInternal(conn, query, false); +} + +static int +PQsendQueryInternal(PGconn *conn, const char *query, bool newQuery) +{ + PGcmdQueueEntry *entry = NULL; + + if (!PQsendQueryStart(conn, newQuery)) + return 0; + + /* check the argument */ + if (!query) + { + libpq_append_conn_error(conn, "command string is a null pointer"); + return 0; + } + + if (conn->pipelineStatus != PQ_PIPELINE_OFF) + { + libpq_append_conn_error(conn, "%s not allowed in pipeline mode", + "PQsendQuery"); + return 0; + } + + entry = pqAllocCmdQueueEntry(conn); + if (entry == NULL) + return 0; /* error msg already set */ + + /* Send the query message(s) */ + /* construct the outgoing Query message */ + if (pqPutMsgStart('Q', conn) < 0 || + pqPuts(query, conn) < 0 || + pqPutMsgEnd(conn) < 0) + { + /* error message should be set up already */ + pqRecycleCmdQueueEntry(conn, entry); + return 0; + } + + /* remember we are using simple query protocol */ + entry->queryclass = PGQUERY_SIMPLE; + /* and remember the query text too, if possible */ + entry->query = strdup(query); + + /* + * Give the data a push. In nonblock mode, don't complain if we're unable + * to send it all; PQgetResult() will do any additional flushing needed. + */ + if (pqFlush(conn) < 0) + goto sendFailed; + + /* OK, it's launched! */ + pqAppendCmdQueueEntry(conn, entry); + + return 1; + +sendFailed: + pqRecycleCmdQueueEntry(conn, entry); + /* error message should be set up already */ + return 0; +} + +/* + * PQsendQueryParams + * Like PQsendQuery, but use extended query protocol so we can pass parameters + */ +int +PQsendQueryParams(PGconn *conn, + const char *command, + int nParams, + const Oid *paramTypes, + const char *const *paramValues, + const int *paramLengths, + const int *paramFormats, + int resultFormat) +{ + if (!PQsendQueryStart(conn, true)) + return 0; + + /* check the arguments */ + if (!command) + { + libpq_append_conn_error(conn, "command string is a null pointer"); + return 0; + } + if (nParams < 0 || nParams > PQ_QUERY_PARAM_MAX_LIMIT) + { + libpq_append_conn_error(conn, "number of parameters must be between 0 and %d", + PQ_QUERY_PARAM_MAX_LIMIT); + return 0; + } + + return PQsendQueryGuts(conn, + command, + "", /* use unnamed statement */ + nParams, + paramTypes, + paramValues, + paramLengths, + paramFormats, + resultFormat); +} + +/* + * PQsendPrepare + * Submit a Parse message, but don't wait for it to finish + * + * Returns: 1 if successfully submitted + * 0 if error (conn->errorMessage is set) + */ +int +PQsendPrepare(PGconn *conn, + const char *stmtName, const char *query, + int nParams, const Oid *paramTypes) +{ + PGcmdQueueEntry *entry = NULL; + + if (!PQsendQueryStart(conn, true)) + return 0; + + /* check the arguments */ + if (!stmtName) + { + libpq_append_conn_error(conn, "statement name is a null pointer"); + return 0; + } + if (!query) + { + libpq_append_conn_error(conn, "command string is a null pointer"); + return 0; + } + if (nParams < 0 || nParams > PQ_QUERY_PARAM_MAX_LIMIT) + { + libpq_append_conn_error(conn, "number of parameters must be between 0 and %d", + PQ_QUERY_PARAM_MAX_LIMIT); + return 0; + } + + entry = pqAllocCmdQueueEntry(conn); + if (entry == NULL) + return 0; /* error msg already set */ + + /* construct the Parse message */ + if (pqPutMsgStart('P', conn) < 0 || + pqPuts(stmtName, conn) < 0 || + pqPuts(query, conn) < 0) + goto sendFailed; + + if (nParams > 0 && paramTypes) + { + int i; + + if (pqPutInt(nParams, 2, conn) < 0) + goto sendFailed; + for (i = 0; i < nParams; i++) + { + if (pqPutInt(paramTypes[i], 4, conn) < 0) + goto sendFailed; + } + } + else + { + if (pqPutInt(0, 2, conn) < 0) + goto sendFailed; + } + if (pqPutMsgEnd(conn) < 0) + goto sendFailed; + + /* Add a Sync, unless in pipeline mode. */ + if (conn->pipelineStatus == PQ_PIPELINE_OFF) + { + if (pqPutMsgStart('S', conn) < 0 || + pqPutMsgEnd(conn) < 0) + goto sendFailed; + } + + /* remember we are doing just a Parse */ + entry->queryclass = PGQUERY_PREPARE; + + /* and remember the query text too, if possible */ + /* if insufficient memory, query just winds up NULL */ + entry->query = strdup(query); + + /* + * Give the data a push (in pipeline mode, only if we're past the size + * threshold). In nonblock mode, don't complain if we're unable to send + * it all; PQgetResult() will do any additional flushing needed. + */ + if (pqPipelineFlush(conn) < 0) + goto sendFailed; + + /* OK, it's launched! */ + pqAppendCmdQueueEntry(conn, entry); + + return 1; + +sendFailed: + pqRecycleCmdQueueEntry(conn, entry); + /* error message should be set up already */ + return 0; +} + +/* + * PQsendQueryPrepared + * Like PQsendQuery, but execute a previously prepared statement, + * using extended query protocol so we can pass parameters + */ +int +PQsendQueryPrepared(PGconn *conn, + const char *stmtName, + int nParams, + const char *const *paramValues, + const int *paramLengths, + const int *paramFormats, + int resultFormat) +{ + if (!PQsendQueryStart(conn, true)) + return 0; + + /* check the arguments */ + if (!stmtName) + { + libpq_append_conn_error(conn, "statement name is a null pointer"); + return 0; + } + if (nParams < 0 || nParams > PQ_QUERY_PARAM_MAX_LIMIT) + { + libpq_append_conn_error(conn, "number of parameters must be between 0 and %d", + PQ_QUERY_PARAM_MAX_LIMIT); + return 0; + } + + return PQsendQueryGuts(conn, + NULL, /* no command to parse */ + stmtName, + nParams, + NULL, /* no param types */ + paramValues, + paramLengths, + paramFormats, + resultFormat); +} + +/* + * PQsendQueryStart + * Common startup code for PQsendQuery and sibling routines + */ +static bool +PQsendQueryStart(PGconn *conn, bool newQuery) +{ + if (!conn) + return false; + + /* + * If this is the beginning of a query cycle, reset the error state. + * However, in pipeline mode with something already queued, the error + * buffer belongs to that command and we shouldn't clear it. + */ + if (newQuery && conn->cmd_queue_head == NULL) + pqClearConnErrorState(conn); + + /* Don't try to send if we know there's no live connection. */ + if (conn->status != CONNECTION_OK) + { + libpq_append_conn_error(conn, "no connection to the server"); + return false; + } + + /* Can't send while already busy, either, unless enqueuing for later */ + if (conn->asyncStatus != PGASYNC_IDLE && + conn->pipelineStatus == PQ_PIPELINE_OFF) + { + libpq_append_conn_error(conn, "another command is already in progress"); + return false; + } + + if (conn->pipelineStatus != PQ_PIPELINE_OFF) + { + /* + * When enqueuing commands we don't change much of the connection + * state since it's already in use for the current command. The + * connection state will get updated when pqPipelineProcessQueue() + * advances to start processing the queued message. + * + * Just make sure we can safely enqueue given the current connection + * state. We can enqueue behind another queue item, or behind a + * non-queue command (one that sends its own sync), but we can't + * enqueue if the connection is in a copy state. + */ + switch (conn->asyncStatus) + { + case PGASYNC_IDLE: + case PGASYNC_PIPELINE_IDLE: + case PGASYNC_READY: + case PGASYNC_READY_MORE: + case PGASYNC_BUSY: + /* ok to queue */ + break; + + case PGASYNC_COPY_IN: + case PGASYNC_COPY_OUT: + case PGASYNC_COPY_BOTH: + libpq_append_conn_error(conn, "cannot queue commands during COPY"); + return false; + } + } + else + { + /* + * This command's results will come in immediately. Initialize async + * result-accumulation state + */ + pqClearAsyncResult(conn); + + /* reset single-row processing mode */ + conn->singleRowMode = false; + } + + /* ready to send command message */ + return true; +} + +/* + * PQsendQueryGuts + * Common code for sending a query with extended query protocol + * PQsendQueryStart should be done already + * + * command may be NULL to indicate we use an already-prepared statement + */ +static int +PQsendQueryGuts(PGconn *conn, + const char *command, + const char *stmtName, + int nParams, + const Oid *paramTypes, + const char *const *paramValues, + const int *paramLengths, + const int *paramFormats, + int resultFormat) +{ + int i; + PGcmdQueueEntry *entry; + + entry = pqAllocCmdQueueEntry(conn); + if (entry == NULL) + return 0; /* error msg already set */ + + /* + * We will send Parse (if needed), Bind, Describe Portal, Execute, Sync + * (if not in pipeline mode), using specified statement name and the + * unnamed portal. + */ + + if (command) + { + /* construct the Parse message */ + if (pqPutMsgStart('P', conn) < 0 || + pqPuts(stmtName, conn) < 0 || + pqPuts(command, conn) < 0) + goto sendFailed; + if (nParams > 0 && paramTypes) + { + if (pqPutInt(nParams, 2, conn) < 0) + goto sendFailed; + for (i = 0; i < nParams; i++) + { + if (pqPutInt(paramTypes[i], 4, conn) < 0) + goto sendFailed; + } + } + else + { + if (pqPutInt(0, 2, conn) < 0) + goto sendFailed; + } + if (pqPutMsgEnd(conn) < 0) + goto sendFailed; + } + + /* Construct the Bind message */ + if (pqPutMsgStart('B', conn) < 0 || + pqPuts("", conn) < 0 || + pqPuts(stmtName, conn) < 0) + goto sendFailed; + + /* Send parameter formats */ + if (nParams > 0 && paramFormats) + { + if (pqPutInt(nParams, 2, conn) < 0) + goto sendFailed; + for (i = 0; i < nParams; i++) + { + if (pqPutInt(paramFormats[i], 2, conn) < 0) + goto sendFailed; + } + } + else + { + if (pqPutInt(0, 2, conn) < 0) + goto sendFailed; + } + + if (pqPutInt(nParams, 2, conn) < 0) + goto sendFailed; + + /* Send parameters */ + for (i = 0; i < nParams; i++) + { + if (paramValues && paramValues[i]) + { + int nbytes; + + if (paramFormats && paramFormats[i] != 0) + { + /* binary parameter */ + if (paramLengths) + nbytes = paramLengths[i]; + else + { + libpq_append_conn_error(conn, "length must be given for binary parameter"); + goto sendFailed; + } + } + else + { + /* text parameter, do not use paramLengths */ + nbytes = strlen(paramValues[i]); + } + if (pqPutInt(nbytes, 4, conn) < 0 || + pqPutnchar(paramValues[i], nbytes, conn) < 0) + goto sendFailed; + } + else + { + /* take the param as NULL */ + if (pqPutInt(-1, 4, conn) < 0) + goto sendFailed; + } + } + if (pqPutInt(1, 2, conn) < 0 || + pqPutInt(resultFormat, 2, conn)) + goto sendFailed; + if (pqPutMsgEnd(conn) < 0) + goto sendFailed; + + /* construct the Describe Portal message */ + if (pqPutMsgStart('D', conn) < 0 || + pqPutc('P', conn) < 0 || + pqPuts("", conn) < 0 || + pqPutMsgEnd(conn) < 0) + goto sendFailed; + + /* construct the Execute message */ + if (pqPutMsgStart('E', conn) < 0 || + pqPuts("", conn) < 0 || + pqPutInt(0, 4, conn) < 0 || + pqPutMsgEnd(conn) < 0) + goto sendFailed; + + /* construct the Sync message if not in pipeline mode */ + if (conn->pipelineStatus == PQ_PIPELINE_OFF) + { + if (pqPutMsgStart('S', conn) < 0 || + pqPutMsgEnd(conn) < 0) + goto sendFailed; + } + + /* remember we are using extended query protocol */ + entry->queryclass = PGQUERY_EXTENDED; + + /* and remember the query text too, if possible */ + /* if insufficient memory, query just winds up NULL */ + if (command) + entry->query = strdup(command); + + /* + * Give the data a push (in pipeline mode, only if we're past the size + * threshold). In nonblock mode, don't complain if we're unable to send + * it all; PQgetResult() will do any additional flushing needed. + */ + if (pqPipelineFlush(conn) < 0) + goto sendFailed; + + /* OK, it's launched! */ + pqAppendCmdQueueEntry(conn, entry); + + return 1; + +sendFailed: + pqRecycleCmdQueueEntry(conn, entry); + /* error message should be set up already */ + return 0; +} + +/* + * Select row-by-row processing mode + */ +int +PQsetSingleRowMode(PGconn *conn) +{ + /* + * Only allow setting the flag when we have launched a query and not yet + * received any results. + */ + if (!conn) + return 0; + if (conn->asyncStatus != PGASYNC_BUSY) + return 0; + if (!conn->cmd_queue_head || + (conn->cmd_queue_head->queryclass != PGQUERY_SIMPLE && + conn->cmd_queue_head->queryclass != PGQUERY_EXTENDED)) + return 0; + if (pgHavePendingResult(conn)) + return 0; + + /* OK, set flag */ + conn->singleRowMode = true; + return 1; +} + +/* + * Consume any available input from the backend + * 0 return: some kind of trouble + * 1 return: no problem + */ +int +PQconsumeInput(PGconn *conn) +{ + if (!conn) + return 0; + + /* + * for non-blocking connections try to flush the send-queue, otherwise we + * may never get a response for something that may not have already been + * sent because it's in our write buffer! + */ + if (pqIsnonblocking(conn)) + { + if (pqFlush(conn) < 0) + return 0; + } + + /* + * Load more data, if available. We do this no matter what state we are + * in, since we are probably getting called because the application wants + * to get rid of a read-select condition. Note that we will NOT block + * waiting for more input. + */ + if (pqReadData(conn) < 0) + return 0; + + /* Parsing of the data waits till later. */ + return 1; +} + + +/* + * parseInput: if appropriate, parse input data from backend + * until input is exhausted or a stopping state is reached. + * Note that this function will NOT attempt to read more data from the backend. + */ +static void +parseInput(PGconn *conn) +{ + pqParseInput3(conn); +} + +/* + * PQisBusy + * Return true if PQgetResult would block waiting for input. + */ + +int +PQisBusy(PGconn *conn) +{ + if (!conn) + return false; + + /* Parse any available data, if our state permits. */ + parseInput(conn); + + /* + * PQgetResult will return immediately in all states except BUSY. Also, + * if we've detected read EOF and dropped the connection, we can expect + * that PQgetResult will fail immediately. Note that we do *not* check + * conn->write_failed here --- once that's become set, we know we have + * trouble, but we need to keep trying to read until we have a complete + * server message or detect read EOF. + */ + return conn->asyncStatus == PGASYNC_BUSY && conn->status != CONNECTION_BAD; +} + +/* + * PQgetResult + * Get the next PGresult produced by a query. Returns NULL if no + * query work remains or an error has occurred (e.g. out of + * memory). + * + * In pipeline mode, once all the result of a query have been returned, + * PQgetResult returns NULL to let the user know that the next + * query is being processed. At the end of the pipeline, returns a + * result with PQresultStatus(result) == PGRES_PIPELINE_SYNC. + */ +PGresult * +PQgetResult(PGconn *conn) +{ + PGresult *res; + + if (!conn) + return NULL; + + /* Parse any available data, if our state permits. */ + parseInput(conn); + + /* If not ready to return something, block until we are. */ + while (conn->asyncStatus == PGASYNC_BUSY) + { + int flushResult; + + /* + * If data remains unsent, send it. Else we might be waiting for the + * result of a command the backend hasn't even got yet. + */ + while ((flushResult = pqFlush(conn)) > 0) + { + if (pqWait(false, true, conn)) + { + flushResult = -1; + break; + } + } + + /* + * Wait for some more data, and load it. (Note: if the connection has + * been lost, pqWait should return immediately because the socket + * should be read-ready, either with the last server data or with an + * EOF indication. We expect therefore that this won't result in any + * undue delay in reporting a previous write failure.) + */ + if (flushResult || + pqWait(true, false, conn) || + pqReadData(conn) < 0) + { + /* Report the error saved by pqWait or pqReadData */ + pqSaveErrorResult(conn); + conn->asyncStatus = PGASYNC_IDLE; + return pqPrepareAsyncResult(conn); + } + + /* Parse it. */ + parseInput(conn); + + /* + * If we had a write error, but nothing above obtained a query result + * or detected a read error, report the write error. + */ + if (conn->write_failed && conn->asyncStatus == PGASYNC_BUSY) + { + pqSaveWriteError(conn); + conn->asyncStatus = PGASYNC_IDLE; + return pqPrepareAsyncResult(conn); + } + } + + /* Return the appropriate thing. */ + switch (conn->asyncStatus) + { + case PGASYNC_IDLE: + res = NULL; /* query is complete */ + break; + case PGASYNC_PIPELINE_IDLE: + Assert(conn->pipelineStatus != PQ_PIPELINE_OFF); + + /* + * We're about to return the NULL that terminates the round of + * results from the current query; prepare to send the results of + * the next query, if any, when we're called next. If there's no + * next element in the command queue, this gets us in IDLE state. + */ + pqPipelineProcessQueue(conn); + res = NULL; /* query is complete */ + break; + + case PGASYNC_READY: + res = pqPrepareAsyncResult(conn); + + /* Advance the queue as appropriate */ + pqCommandQueueAdvance(conn, false, + res->resultStatus == PGRES_PIPELINE_SYNC); + + if (conn->pipelineStatus != PQ_PIPELINE_OFF) + { + /* + * We're about to send the results of the current query. Set + * us idle now, and ... + */ + conn->asyncStatus = PGASYNC_PIPELINE_IDLE; + + /* + * ... in cases when we're sending a pipeline-sync result, + * move queue processing forwards immediately, so that next + * time we're called, we're prepared to return the next result + * received from the server. In all other cases, leave the + * queue state change for next time, so that a terminating + * NULL result is sent. + * + * (In other words: we don't return a NULL after a pipeline + * sync.) + */ + if (res->resultStatus == PGRES_PIPELINE_SYNC) + pqPipelineProcessQueue(conn); + } + else + { + /* Set the state back to BUSY, allowing parsing to proceed. */ + conn->asyncStatus = PGASYNC_BUSY; + } + break; + case PGASYNC_READY_MORE: + res = pqPrepareAsyncResult(conn); + /* Set the state back to BUSY, allowing parsing to proceed. */ + conn->asyncStatus = PGASYNC_BUSY; + break; + case PGASYNC_COPY_IN: + res = getCopyResult(conn, PGRES_COPY_IN); + break; + case PGASYNC_COPY_OUT: + res = getCopyResult(conn, PGRES_COPY_OUT); + break; + case PGASYNC_COPY_BOTH: + res = getCopyResult(conn, PGRES_COPY_BOTH); + break; + default: + libpq_append_conn_error(conn, "unexpected asyncStatus: %d", (int) conn->asyncStatus); + pqSaveErrorResult(conn); + conn->asyncStatus = PGASYNC_IDLE; /* try to restore valid state */ + res = pqPrepareAsyncResult(conn); + break; + } + + /* Time to fire PGEVT_RESULTCREATE events, if there are any */ + if (res && res->nEvents > 0) + (void) PQfireResultCreateEvents(conn, res); + + return res; +} + +/* + * getCopyResult + * Helper for PQgetResult: generate result for COPY-in-progress cases + */ +static PGresult * +getCopyResult(PGconn *conn, ExecStatusType copytype) +{ + /* + * If the server connection has been lost, don't pretend everything is + * hunky-dory; instead return a PGRES_FATAL_ERROR result, and reset the + * asyncStatus to idle (corresponding to what we'd do if we'd detected I/O + * error in the earlier steps in PQgetResult). The text returned in the + * result is whatever is in conn->errorMessage; we hope that was filled + * with something relevant when the lost connection was detected. + */ + if (conn->status != CONNECTION_OK) + { + pqSaveErrorResult(conn); + conn->asyncStatus = PGASYNC_IDLE; + return pqPrepareAsyncResult(conn); + } + + /* If we have an async result for the COPY, return that */ + if (conn->result && conn->result->resultStatus == copytype) + return pqPrepareAsyncResult(conn); + + /* Otherwise, invent a suitable PGresult */ + return PQmakeEmptyPGresult(conn, copytype); +} + + +/* + * PQexec + * send a query to the backend and package up the result in a PGresult + * + * If the query was not even sent, return NULL; conn->errorMessage is set to + * a relevant message. + * If the query was sent, a new PGresult is returned (which could indicate + * either success or failure). + * The user is responsible for freeing the PGresult via PQclear() + * when done with it. + */ +PGresult * +PQexec(PGconn *conn, const char *query) +{ + if (!PQexecStart(conn)) + return NULL; + if (!PQsendQuery(conn, query)) + return NULL; + return PQexecFinish(conn); +} + +/* + * PQexecParams + * Like PQexec, but use extended query protocol so we can pass parameters + */ +PGresult * +PQexecParams(PGconn *conn, + const char *command, + int nParams, + const Oid *paramTypes, + const char *const *paramValues, + const int *paramLengths, + const int *paramFormats, + int resultFormat) +{ + if (!PQexecStart(conn)) + return NULL; + if (!PQsendQueryParams(conn, command, + nParams, paramTypes, paramValues, paramLengths, + paramFormats, resultFormat)) + return NULL; + return PQexecFinish(conn); +} + +/* + * PQprepare + * Creates a prepared statement by issuing a Parse message. + * + * If the query was not even sent, return NULL; conn->errorMessage is set to + * a relevant message. + * If the query was sent, a new PGresult is returned (which could indicate + * either success or failure). + * The user is responsible for freeing the PGresult via PQclear() + * when done with it. + */ +PGresult * +PQprepare(PGconn *conn, + const char *stmtName, const char *query, + int nParams, const Oid *paramTypes) +{ + if (!PQexecStart(conn)) + return NULL; + if (!PQsendPrepare(conn, stmtName, query, nParams, paramTypes)) + return NULL; + return PQexecFinish(conn); +} + +/* + * PQexecPrepared + * Like PQexec, but execute a previously prepared statement, + * using extended query protocol so we can pass parameters + */ +PGresult * +PQexecPrepared(PGconn *conn, + const char *stmtName, + int nParams, + const char *const *paramValues, + const int *paramLengths, + const int *paramFormats, + int resultFormat) +{ + if (!PQexecStart(conn)) + return NULL; + if (!PQsendQueryPrepared(conn, stmtName, + nParams, paramValues, paramLengths, + paramFormats, resultFormat)) + return NULL; + return PQexecFinish(conn); +} + +/* + * Common code for PQexec and sibling routines: prepare to send command + */ +static bool +PQexecStart(PGconn *conn) +{ + PGresult *result; + + if (!conn) + return false; + + /* + * Since this is the beginning of a query cycle, reset the error state. + * However, in pipeline mode with something already queued, the error + * buffer belongs to that command and we shouldn't clear it. + */ + if (conn->cmd_queue_head == NULL) + pqClearConnErrorState(conn); + + if (conn->pipelineStatus != PQ_PIPELINE_OFF) + { + libpq_append_conn_error(conn, "synchronous command execution functions are not allowed in pipeline mode"); + return false; + } + + /* + * Silently discard any prior query result that application didn't eat. + * This is probably poor design, but it's here for backward compatibility. + */ + while ((result = PQgetResult(conn)) != NULL) + { + ExecStatusType resultStatus = result->resultStatus; + + PQclear(result); /* only need its status */ + if (resultStatus == PGRES_COPY_IN) + { + /* get out of a COPY IN state */ + if (PQputCopyEnd(conn, + libpq_gettext("COPY terminated by new PQexec")) < 0) + return false; + /* keep waiting to swallow the copy's failure message */ + } + else if (resultStatus == PGRES_COPY_OUT) + { + /* + * Get out of a COPY OUT state: we just switch back to BUSY and + * allow the remaining COPY data to be dropped on the floor. + */ + conn->asyncStatus = PGASYNC_BUSY; + /* keep waiting to swallow the copy's completion message */ + } + else if (resultStatus == PGRES_COPY_BOTH) + { + /* We don't allow PQexec during COPY BOTH */ + libpq_append_conn_error(conn, "PQexec not allowed during COPY BOTH"); + return false; + } + /* check for loss of connection, too */ + if (conn->status == CONNECTION_BAD) + return false; + } + + /* OK to send a command */ + return true; +} + +/* + * Common code for PQexec and sibling routines: wait for command result + */ +static PGresult * +PQexecFinish(PGconn *conn) +{ + PGresult *result; + PGresult *lastResult; + + /* + * For backwards compatibility, return the last result if there are more + * than one. (We used to have logic here to concatenate successive error + * messages, but now that happens automatically, since conn->errorMessage + * will continue to accumulate errors throughout this loop.) + * + * We have to stop if we see copy in/out/both, however. We will resume + * parsing after application performs the data transfer. + * + * Also stop if the connection is lost (else we'll loop infinitely). + */ + lastResult = NULL; + while ((result = PQgetResult(conn)) != NULL) + { + PQclear(lastResult); + lastResult = result; + if (result->resultStatus == PGRES_COPY_IN || + result->resultStatus == PGRES_COPY_OUT || + result->resultStatus == PGRES_COPY_BOTH || + conn->status == CONNECTION_BAD) + break; + } + + return lastResult; +} + +/* + * PQdescribePrepared + * Obtain information about a previously prepared statement + * + * If the query was not even sent, return NULL; conn->errorMessage is set to + * a relevant message. + * If the query was sent, a new PGresult is returned (which could indicate + * either success or failure). On success, the PGresult contains status + * PGRES_COMMAND_OK, and its parameter and column-heading fields describe + * the statement's inputs and outputs respectively. + * The user is responsible for freeing the PGresult via PQclear() + * when done with it. + */ +PGresult * +PQdescribePrepared(PGconn *conn, const char *stmt) +{ + if (!PQexecStart(conn)) + return NULL; + if (!PQsendDescribe(conn, 'S', stmt)) + return NULL; + return PQexecFinish(conn); +} + +/* + * PQdescribePortal + * Obtain information about a previously created portal + * + * This is much like PQdescribePrepared, except that no parameter info is + * returned. Note that at the moment, libpq doesn't really expose portals + * to the client; but this can be used with a portal created by a SQL + * DECLARE CURSOR command. + */ +PGresult * +PQdescribePortal(PGconn *conn, const char *portal) +{ + if (!PQexecStart(conn)) + return NULL; + if (!PQsendDescribe(conn, 'P', portal)) + return NULL; + return PQexecFinish(conn); +} + +/* + * PQsendDescribePrepared + * Submit a Describe Statement command, but don't wait for it to finish + * + * Returns: 1 if successfully submitted + * 0 if error (conn->errorMessage is set) + */ +int +PQsendDescribePrepared(PGconn *conn, const char *stmt) +{ + return PQsendDescribe(conn, 'S', stmt); +} + +/* + * PQsendDescribePortal + * Submit a Describe Portal command, but don't wait for it to finish + * + * Returns: 1 if successfully submitted + * 0 if error (conn->errorMessage is set) + */ +int +PQsendDescribePortal(PGconn *conn, const char *portal) +{ + return PQsendDescribe(conn, 'P', portal); +} + +/* + * PQsendDescribe + * Common code to send a Describe command + * + * Available options for desc_type are + * 'S' to describe a prepared statement; or + * 'P' to describe a portal. + * Returns 1 on success and 0 on failure. + */ +static int +PQsendDescribe(PGconn *conn, char desc_type, const char *desc_target) +{ + PGcmdQueueEntry *entry = NULL; + + /* Treat null desc_target as empty string */ + if (!desc_target) + desc_target = ""; + + if (!PQsendQueryStart(conn, true)) + return 0; + + entry = pqAllocCmdQueueEntry(conn); + if (entry == NULL) + return 0; /* error msg already set */ + + /* construct the Describe message */ + if (pqPutMsgStart('D', conn) < 0 || + pqPutc(desc_type, conn) < 0 || + pqPuts(desc_target, conn) < 0 || + pqPutMsgEnd(conn) < 0) + goto sendFailed; + + /* construct the Sync message */ + if (conn->pipelineStatus == PQ_PIPELINE_OFF) + { + if (pqPutMsgStart('S', conn) < 0 || + pqPutMsgEnd(conn) < 0) + goto sendFailed; + } + + /* remember we are doing a Describe */ + entry->queryclass = PGQUERY_DESCRIBE; + + /* + * Give the data a push (in pipeline mode, only if we're past the size + * threshold). In nonblock mode, don't complain if we're unable to send + * it all; PQgetResult() will do any additional flushing needed. + */ + if (pqPipelineFlush(conn) < 0) + goto sendFailed; + + /* OK, it's launched! */ + pqAppendCmdQueueEntry(conn, entry); + + return 1; + +sendFailed: + pqRecycleCmdQueueEntry(conn, entry); + /* error message should be set up already */ + return 0; +} + +/* + * PQnotifies + * returns a PGnotify* structure of the latest async notification + * that has not yet been handled + * + * returns NULL, if there is currently + * no unhandled async notification from the backend + * + * the CALLER is responsible for FREE'ing the structure returned + * + * Note that this function does not read any new data from the socket; + * so usually, caller should call PQconsumeInput() first. + */ +PGnotify * +PQnotifies(PGconn *conn) +{ + PGnotify *event; + + if (!conn) + return NULL; + + /* Parse any available data to see if we can extract NOTIFY messages. */ + parseInput(conn); + + event = conn->notifyHead; + if (event) + { + conn->notifyHead = event->next; + if (!conn->notifyHead) + conn->notifyTail = NULL; + event->next = NULL; /* don't let app see the internal state */ + } + return event; +} + +/* + * PQputCopyData - send some data to the backend during COPY IN or COPY BOTH + * + * Returns 1 if successful, 0 if data could not be sent (only possible + * in nonblock mode), or -1 if an error occurs. + */ +int +PQputCopyData(PGconn *conn, const char *buffer, int nbytes) +{ + if (!conn) + return -1; + if (conn->asyncStatus != PGASYNC_COPY_IN && + conn->asyncStatus != PGASYNC_COPY_BOTH) + { + libpq_append_conn_error(conn, "no COPY in progress"); + return -1; + } + + /* + * Process any NOTICE or NOTIFY messages that might be pending in the + * input buffer. Since the server might generate many notices during the + * COPY, we want to clean those out reasonably promptly to prevent + * indefinite expansion of the input buffer. (Note: the actual read of + * input data into the input buffer happens down inside pqSendSome, but + * it's not authorized to get rid of the data again.) + */ + parseInput(conn); + + if (nbytes > 0) + { + /* + * Try to flush any previously sent data in preference to growing the + * output buffer. If we can't enlarge the buffer enough to hold the + * data, return 0 in the nonblock case, else hard error. (For + * simplicity, always assume 5 bytes of overhead.) + */ + if ((conn->outBufSize - conn->outCount - 5) < nbytes) + { + if (pqFlush(conn) < 0) + return -1; + if (pqCheckOutBufferSpace(conn->outCount + 5 + (size_t) nbytes, + conn)) + return pqIsnonblocking(conn) ? 0 : -1; + } + /* Send the data (too simple to delegate to fe-protocol files) */ + if (pqPutMsgStart('d', conn) < 0 || + pqPutnchar(buffer, nbytes, conn) < 0 || + pqPutMsgEnd(conn) < 0) + return -1; + } + return 1; +} + +/* + * PQputCopyEnd - send EOF indication to the backend during COPY IN + * + * After calling this, use PQgetResult() to check command completion status. + * + * Returns 1 if successful, 0 if data could not be sent (only possible + * in nonblock mode), or -1 if an error occurs. + */ +int +PQputCopyEnd(PGconn *conn, const char *errormsg) +{ + if (!conn) + return -1; + if (conn->asyncStatus != PGASYNC_COPY_IN && + conn->asyncStatus != PGASYNC_COPY_BOTH) + { + libpq_append_conn_error(conn, "no COPY in progress"); + return -1; + } + + /* + * Send the COPY END indicator. This is simple enough that we don't + * bother delegating it to the fe-protocol files. + */ + if (errormsg) + { + /* Send COPY FAIL */ + if (pqPutMsgStart('f', conn) < 0 || + pqPuts(errormsg, conn) < 0 || + pqPutMsgEnd(conn) < 0) + return -1; + } + else + { + /* Send COPY DONE */ + if (pqPutMsgStart('c', conn) < 0 || + pqPutMsgEnd(conn) < 0) + return -1; + } + + /* + * If we sent the COPY command in extended-query mode, we must issue a + * Sync as well. + */ + if (conn->cmd_queue_head && + conn->cmd_queue_head->queryclass != PGQUERY_SIMPLE) + { + if (pqPutMsgStart('S', conn) < 0 || + pqPutMsgEnd(conn) < 0) + return -1; + } + + /* Return to active duty */ + if (conn->asyncStatus == PGASYNC_COPY_BOTH) + conn->asyncStatus = PGASYNC_COPY_OUT; + else + conn->asyncStatus = PGASYNC_BUSY; + + /* Try to flush data */ + if (pqFlush(conn) < 0) + return -1; + + return 1; +} + +/* + * PQgetCopyData - read a row of data from the backend during COPY OUT + * or COPY BOTH + * + * If successful, sets *buffer to point to a malloc'd row of data, and + * returns row length (always > 0) as result. + * Returns 0 if no row available yet (only possible if async is true), + * -1 if end of copy (consult PQgetResult), or -2 if error (consult + * PQerrorMessage). + */ +int +PQgetCopyData(PGconn *conn, char **buffer, int async) +{ + *buffer = NULL; /* for all failure cases */ + if (!conn) + return -2; + if (conn->asyncStatus != PGASYNC_COPY_OUT && + conn->asyncStatus != PGASYNC_COPY_BOTH) + { + libpq_append_conn_error(conn, "no COPY in progress"); + return -2; + } + return pqGetCopyData3(conn, buffer, async); +} + +/* + * PQgetline - gets a newline-terminated string from the backend. + * + * Chiefly here so that applications can use "COPY <rel> to stdout" + * and read the output string. Returns a null-terminated string in `buffer`. + * + * XXX this routine is now deprecated, because it can't handle binary data. + * If called during a COPY BINARY we return EOF. + * + * PQgetline reads up to `length`-1 characters (like fgets(3)) but strips + * the terminating \n (like gets(3)). + * + * CAUTION: the caller is responsible for detecting the end-of-copy signal + * (a line containing just "\.") when using this routine. + * + * RETURNS: + * EOF if error (eg, invalid arguments are given) + * 0 if EOL is reached (i.e., \n has been read) + * (this is required for backward-compatibility -- this + * routine used to always return EOF or 0, assuming that + * the line ended within `length` bytes.) + * 1 in other cases (i.e., the buffer was filled before \n is reached) + */ +int +PQgetline(PGconn *conn, char *buffer, int length) +{ + if (!buffer || length <= 0) + return EOF; + *buffer = '\0'; + /* length must be at least 3 to hold the \. terminator! */ + if (length < 3) + return EOF; + + if (!conn) + return EOF; + + return pqGetline3(conn, buffer, length); +} + +/* + * PQgetlineAsync - gets a COPY data row without blocking. + * + * This routine is for applications that want to do "COPY <rel> to stdout" + * asynchronously, that is without blocking. Having issued the COPY command + * and gotten a PGRES_COPY_OUT response, the app should call PQconsumeInput + * and this routine until the end-of-data signal is detected. Unlike + * PQgetline, this routine takes responsibility for detecting end-of-data. + * + * On each call, PQgetlineAsync will return data if a complete data row + * is available in libpq's input buffer. Otherwise, no data is returned + * until the rest of the row arrives. + * + * If -1 is returned, the end-of-data signal has been recognized (and removed + * from libpq's input buffer). The caller *must* next call PQendcopy and + * then return to normal processing. + * + * RETURNS: + * -1 if the end-of-copy-data marker has been recognized + * 0 if no data is available + * >0 the number of bytes returned. + * + * The data returned will not extend beyond a data-row boundary. If possible + * a whole row will be returned at one time. But if the buffer offered by + * the caller is too small to hold a row sent by the backend, then a partial + * data row will be returned. In text mode this can be detected by testing + * whether the last returned byte is '\n' or not. + * + * The returned data is *not* null-terminated. + */ + +int +PQgetlineAsync(PGconn *conn, char *buffer, int bufsize) +{ + if (!conn) + return -1; + + return pqGetlineAsync3(conn, buffer, bufsize); +} + +/* + * PQputline -- sends a string to the backend during COPY IN. + * Returns 0 if OK, EOF if not. + * + * This is deprecated primarily because the return convention doesn't allow + * caller to tell the difference between a hard error and a nonblock-mode + * send failure. + */ +int +PQputline(PGconn *conn, const char *string) +{ + return PQputnbytes(conn, string, strlen(string)); +} + +/* + * PQputnbytes -- like PQputline, but buffer need not be null-terminated. + * Returns 0 if OK, EOF if not. + */ +int +PQputnbytes(PGconn *conn, const char *buffer, int nbytes) +{ + if (PQputCopyData(conn, buffer, nbytes) > 0) + return 0; + else + return EOF; +} + +/* + * PQendcopy + * After completing the data transfer portion of a copy in/out, + * the application must call this routine to finish the command protocol. + * + * This is deprecated; it's cleaner to use PQgetResult to get the transfer + * status. + * + * RETURNS: + * 0 on success + * 1 on failure + */ +int +PQendcopy(PGconn *conn) +{ + if (!conn) + return 0; + + return pqEndcopy3(conn); +} + + +/* ---------------- + * PQfn - Send a function call to the POSTGRES backend. + * + * conn : backend connection + * fnid : OID of function to be called + * result_buf : pointer to result buffer + * result_len : actual length of result is returned here + * result_is_int : If the result is an integer, this must be 1, + * otherwise this should be 0 + * args : pointer to an array of function arguments + * (each has length, if integer, and value/pointer) + * nargs : # of arguments in args array. + * + * RETURNS + * PGresult with status = PGRES_COMMAND_OK if successful. + * *result_len is > 0 if there is a return value, 0 if not. + * PGresult with status = PGRES_FATAL_ERROR if backend returns an error. + * NULL on communications failure. conn->errorMessage will be set. + * ---------------- + */ + +PGresult * +PQfn(PGconn *conn, + int fnid, + int *result_buf, + int *result_len, + int result_is_int, + const PQArgBlock *args, + int nargs) +{ + *result_len = 0; + + if (!conn) + return NULL; + + /* + * Since this is the beginning of a query cycle, reset the error state. + * However, in pipeline mode with something already queued, the error + * buffer belongs to that command and we shouldn't clear it. + */ + if (conn->cmd_queue_head == NULL) + pqClearConnErrorState(conn); + + if (conn->pipelineStatus != PQ_PIPELINE_OFF) + { + libpq_append_conn_error(conn, "%s not allowed in pipeline mode", "PQfn"); + return NULL; + } + + if (conn->sock == PGINVALID_SOCKET || conn->asyncStatus != PGASYNC_IDLE || + pgHavePendingResult(conn)) + { + libpq_append_conn_error(conn, "connection in wrong state"); + return NULL; + } + + return pqFunctionCall3(conn, fnid, + result_buf, result_len, + result_is_int, + args, nargs); +} + +/* ====== Pipeline mode support ======== */ + +/* + * PQenterPipelineMode + * Put an idle connection in pipeline mode. + * + * Returns 1 on success. On failure, errorMessage is set and 0 is returned. + * + * Commands submitted after this can be pipelined on the connection; + * there's no requirement to wait for one to finish before the next is + * dispatched. + * + * Queuing of a new query or syncing during COPY is not allowed. + * + * A set of commands is terminated by a PQpipelineSync. Multiple sync + * points can be established while in pipeline mode. Pipeline mode can + * be exited by calling PQexitPipelineMode() once all results are processed. + * + * This doesn't actually send anything on the wire, it just puts libpq + * into a state where it can pipeline work. + */ +int +PQenterPipelineMode(PGconn *conn) +{ + if (!conn) + return 0; + + /* succeed with no action if already in pipeline mode */ + if (conn->pipelineStatus != PQ_PIPELINE_OFF) + return 1; + + if (conn->asyncStatus != PGASYNC_IDLE) + { + libpq_append_conn_error(conn, "cannot enter pipeline mode, connection not idle"); + return 0; + } + + conn->pipelineStatus = PQ_PIPELINE_ON; + + return 1; +} + +/* + * PQexitPipelineMode + * End pipeline mode and return to normal command mode. + * + * Returns 1 in success (pipeline mode successfully ended, or not in pipeline + * mode). + * + * Returns 0 if in pipeline mode and cannot be ended yet. Error message will + * be set. + */ +int +PQexitPipelineMode(PGconn *conn) +{ + if (!conn) + return 0; + + if (conn->pipelineStatus == PQ_PIPELINE_OFF && + (conn->asyncStatus == PGASYNC_IDLE || + conn->asyncStatus == PGASYNC_PIPELINE_IDLE) && + conn->cmd_queue_head == NULL) + return 1; + + switch (conn->asyncStatus) + { + case PGASYNC_READY: + case PGASYNC_READY_MORE: + /* there are some uncollected results */ + libpq_append_conn_error(conn, "cannot exit pipeline mode with uncollected results"); + return 0; + + case PGASYNC_BUSY: + libpq_append_conn_error(conn, "cannot exit pipeline mode while busy"); + return 0; + + case PGASYNC_IDLE: + case PGASYNC_PIPELINE_IDLE: + /* OK */ + break; + + case PGASYNC_COPY_IN: + case PGASYNC_COPY_OUT: + case PGASYNC_COPY_BOTH: + libpq_append_conn_error(conn, "cannot exit pipeline mode while in COPY"); + } + + /* still work to process */ + if (conn->cmd_queue_head != NULL) + { + libpq_append_conn_error(conn, "cannot exit pipeline mode with uncollected results"); + return 0; + } + + conn->pipelineStatus = PQ_PIPELINE_OFF; + conn->asyncStatus = PGASYNC_IDLE; + + /* Flush any pending data in out buffer */ + if (pqFlush(conn) < 0) + return 0; /* error message is setup already */ + return 1; +} + +/* + * pqCommandQueueAdvance + * Remove one query from the command queue, if appropriate. + * + * If we have received all results corresponding to the head element + * in the command queue, remove it. + * + * In simple query protocol we must not advance the command queue until the + * ReadyForQuery message has been received. This is because in simple mode a + * command can have multiple queries, and we must process result for all of + * them before moving on to the next command. + * + * Another consideration is synchronization during error processing in + * extended query protocol: we refuse to advance the queue past a SYNC queue + * element, unless the result we've received is also a SYNC. In particular + * this protects us from advancing when an error is received at an + * inappropriate moment. + */ +void +pqCommandQueueAdvance(PGconn *conn, bool isReadyForQuery, bool gotSync) +{ + PGcmdQueueEntry *prevquery; + + if (conn->cmd_queue_head == NULL) + return; + + /* + * If processing a query of simple query protocol, we only advance the + * queue when we receive the ReadyForQuery message for it. + */ + if (conn->cmd_queue_head->queryclass == PGQUERY_SIMPLE && !isReadyForQuery) + return; + + /* + * If we're waiting for a SYNC, don't advance the queue until we get one. + */ + if (conn->cmd_queue_head->queryclass == PGQUERY_SYNC && !gotSync) + return; + + /* delink element from queue */ + prevquery = conn->cmd_queue_head; + conn->cmd_queue_head = conn->cmd_queue_head->next; + + /* If the queue is now empty, reset the tail too */ + if (conn->cmd_queue_head == NULL) + conn->cmd_queue_tail = NULL; + + /* and make the queue element recyclable */ + prevquery->next = NULL; + pqRecycleCmdQueueEntry(conn, prevquery); +} + +/* + * pqPipelineProcessQueue: subroutine for PQgetResult + * In pipeline mode, start processing the results of the next query in the queue. + */ +static void +pqPipelineProcessQueue(PGconn *conn) +{ + switch (conn->asyncStatus) + { + case PGASYNC_COPY_IN: + case PGASYNC_COPY_OUT: + case PGASYNC_COPY_BOTH: + case PGASYNC_READY: + case PGASYNC_READY_MORE: + case PGASYNC_BUSY: + /* client still has to process current query or results */ + return; + + case PGASYNC_IDLE: + + /* + * If we're in IDLE mode and there's some command in the queue, + * get us into PIPELINE_IDLE mode and process normally. Otherwise + * there's nothing for us to do. + */ + if (conn->cmd_queue_head != NULL) + { + conn->asyncStatus = PGASYNC_PIPELINE_IDLE; + break; + } + return; + + case PGASYNC_PIPELINE_IDLE: + Assert(conn->pipelineStatus != PQ_PIPELINE_OFF); + /* next query please */ + break; + } + + /* + * Reset single-row processing mode. (Client has to set it up for each + * query, if desired.) + */ + conn->singleRowMode = false; + + /* + * If there are no further commands to process in the queue, get us in + * "real idle" mode now. + */ + if (conn->cmd_queue_head == NULL) + { + conn->asyncStatus = PGASYNC_IDLE; + return; + } + + /* + * Reset the error state. This and the next couple of steps correspond to + * what PQsendQueryStart didn't do for this query. + */ + pqClearConnErrorState(conn); + + /* Initialize async result-accumulation state */ + pqClearAsyncResult(conn); + + if (conn->pipelineStatus == PQ_PIPELINE_ABORTED && + conn->cmd_queue_head->queryclass != PGQUERY_SYNC) + { + /* + * In an aborted pipeline we don't get anything from the server for + * each result; we're just discarding commands from the queue until we + * get to the next sync from the server. + * + * The PGRES_PIPELINE_ABORTED results tell the client that its queries + * got aborted. + */ + conn->result = PQmakeEmptyPGresult(conn, PGRES_PIPELINE_ABORTED); + if (!conn->result) + { + libpq_append_conn_error(conn, "out of memory"); + pqSaveErrorResult(conn); + return; + } + conn->asyncStatus = PGASYNC_READY; + } + else + { + /* allow parsing to continue */ + conn->asyncStatus = PGASYNC_BUSY; + } +} + +/* + * PQpipelineSync + * Send a Sync message as part of a pipeline, and flush to server + * + * It's legal to start submitting more commands in the pipeline immediately, + * without waiting for the results of the current pipeline. There's no need to + * end pipeline mode and start it again. + * + * If a command in a pipeline fails, every subsequent command up to and including + * the result to the Sync message sent by PQpipelineSync gets set to + * PGRES_PIPELINE_ABORTED state. If the whole pipeline is processed without + * error, a PGresult with PGRES_PIPELINE_SYNC is produced. + * + * Queries can already have been sent before PQpipelineSync is called, but + * PQpipelineSync need to be called before retrieving command results. + * + * The connection will remain in pipeline mode and unavailable for new + * synchronous command execution functions until all results from the pipeline + * are processed by the client. + */ +int +PQpipelineSync(PGconn *conn) +{ + PGcmdQueueEntry *entry; + + if (!conn) + return 0; + + if (conn->pipelineStatus == PQ_PIPELINE_OFF) + { + libpq_append_conn_error(conn, "cannot send pipeline when not in pipeline mode"); + return 0; + } + + switch (conn->asyncStatus) + { + case PGASYNC_COPY_IN: + case PGASYNC_COPY_OUT: + case PGASYNC_COPY_BOTH: + /* should be unreachable */ + appendPQExpBufferStr(&conn->errorMessage, + "internal error: cannot send pipeline while in COPY\n"); + return 0; + case PGASYNC_READY: + case PGASYNC_READY_MORE: + case PGASYNC_BUSY: + case PGASYNC_IDLE: + case PGASYNC_PIPELINE_IDLE: + /* OK to send sync */ + break; + } + + entry = pqAllocCmdQueueEntry(conn); + if (entry == NULL) + return 0; /* error msg already set */ + + entry->queryclass = PGQUERY_SYNC; + entry->query = NULL; + + /* construct the Sync message */ + if (pqPutMsgStart('S', conn) < 0 || + pqPutMsgEnd(conn) < 0) + goto sendFailed; + + /* + * Give the data a push. In nonblock mode, don't complain if we're unable + * to send it all; PQgetResult() will do any additional flushing needed. + */ + if (PQflush(conn) < 0) + goto sendFailed; + + /* OK, it's launched! */ + pqAppendCmdQueueEntry(conn, entry); + + return 1; + +sendFailed: + pqRecycleCmdQueueEntry(conn, entry); + /* error message should be set up already */ + return 0; +} + +/* + * PQsendFlushRequest + * Send request for server to flush its buffer. Useful in pipeline + * mode when a sync point is not desired. + */ +int +PQsendFlushRequest(PGconn *conn) +{ + if (!conn) + return 0; + + /* Don't try to send if we know there's no live connection. */ + if (conn->status != CONNECTION_OK) + { + libpq_append_conn_error(conn, "no connection to the server"); + return 0; + } + + /* Can't send while already busy, either, unless enqueuing for later */ + if (conn->asyncStatus != PGASYNC_IDLE && + conn->pipelineStatus == PQ_PIPELINE_OFF) + { + libpq_append_conn_error(conn, "another command is already in progress"); + return 0; + } + + if (pqPutMsgStart('H', conn) < 0 || + pqPutMsgEnd(conn) < 0) + { + return 0; + } + + /* + * Give the data a push (in pipeline mode, only if we're past the size + * threshold). In nonblock mode, don't complain if we're unable to send + * it all; PQgetResult() will do any additional flushing needed. + */ + if (pqPipelineFlush(conn) < 0) + return 0; + + return 1; +} + +/* ====== accessor funcs for PGresult ======== */ + +ExecStatusType +PQresultStatus(const PGresult *res) +{ + if (!res) + return PGRES_FATAL_ERROR; + return res->resultStatus; +} + +char * +PQresStatus(ExecStatusType status) +{ + if ((unsigned int) status >= lengthof(pgresStatus)) + return libpq_gettext("invalid ExecStatusType code"); + return pgresStatus[status]; +} + +char * +PQresultErrorMessage(const PGresult *res) +{ + if (!res || !res->errMsg) + return ""; + return res->errMsg; +} + +char * +PQresultVerboseErrorMessage(const PGresult *res, + PGVerbosity verbosity, + PGContextVisibility show_context) +{ + PQExpBufferData workBuf; + + /* + * Because the caller is expected to free the result string, we must + * strdup any constant result. We use plain strdup and document that + * callers should expect NULL if out-of-memory. + */ + if (!res || + (res->resultStatus != PGRES_FATAL_ERROR && + res->resultStatus != PGRES_NONFATAL_ERROR)) + return strdup(libpq_gettext("PGresult is not an error result\n")); + + initPQExpBuffer(&workBuf); + + pqBuildErrorMessage3(&workBuf, res, verbosity, show_context); + + /* If insufficient memory to format the message, fail cleanly */ + if (PQExpBufferDataBroken(workBuf)) + { + termPQExpBuffer(&workBuf); + return strdup(libpq_gettext("out of memory\n")); + } + + return workBuf.data; +} + +char * +PQresultErrorField(const PGresult *res, int fieldcode) +{ + PGMessageField *pfield; + + if (!res) + return NULL; + for (pfield = res->errFields; pfield != NULL; pfield = pfield->next) + { + if (pfield->code == fieldcode) + return pfield->contents; + } + return NULL; +} + +int +PQntuples(const PGresult *res) +{ + if (!res) + return 0; + return res->ntups; +} + +int +PQnfields(const PGresult *res) +{ + if (!res) + return 0; + return res->numAttributes; +} + +int +PQbinaryTuples(const PGresult *res) +{ + if (!res) + return 0; + return res->binary; +} + +/* + * Helper routines to range-check field numbers and tuple numbers. + * Return true if OK, false if not + */ + +static int +check_field_number(const PGresult *res, int field_num) +{ + if (!res) + return false; /* no way to display error message... */ + if (field_num < 0 || field_num >= res->numAttributes) + { + pqInternalNotice(&res->noticeHooks, + "column number %d is out of range 0..%d", + field_num, res->numAttributes - 1); + return false; + } + return true; +} + +static int +check_tuple_field_number(const PGresult *res, + int tup_num, int field_num) +{ + if (!res) + return false; /* no way to display error message... */ + if (tup_num < 0 || tup_num >= res->ntups) + { + pqInternalNotice(&res->noticeHooks, + "row number %d is out of range 0..%d", + tup_num, res->ntups - 1); + return false; + } + if (field_num < 0 || field_num >= res->numAttributes) + { + pqInternalNotice(&res->noticeHooks, + "column number %d is out of range 0..%d", + field_num, res->numAttributes - 1); + return false; + } + return true; +} + +static int +check_param_number(const PGresult *res, int param_num) +{ + if (!res) + return false; /* no way to display error message... */ + if (param_num < 0 || param_num >= res->numParameters) + { + pqInternalNotice(&res->noticeHooks, + "parameter number %d is out of range 0..%d", + param_num, res->numParameters - 1); + return false; + } + + return true; +} + +/* + * returns NULL if the field_num is invalid + */ +char * +PQfname(const PGresult *res, int field_num) +{ + if (!check_field_number(res, field_num)) + return NULL; + if (res->attDescs) + return res->attDescs[field_num].name; + else + return NULL; +} + +/* + * PQfnumber: find column number given column name + * + * The column name is parsed as if it were in a SQL statement, including + * case-folding and double-quote processing. But note a possible gotcha: + * downcasing in the frontend might follow different locale rules than + * downcasing in the backend... + * + * Returns -1 if no match. In the present backend it is also possible + * to have multiple matches, in which case the first one is found. + */ +int +PQfnumber(const PGresult *res, const char *field_name) +{ + char *field_case; + bool in_quotes; + bool all_lower = true; + const char *iptr; + char *optr; + int i; + + if (!res) + return -1; + + /* + * Note: it is correct to reject a zero-length input string; the proper + * input to match a zero-length field name would be "". + */ + if (field_name == NULL || + field_name[0] == '\0' || + res->attDescs == NULL) + return -1; + + /* + * Check if we can avoid the strdup() and related work because the + * passed-in string wouldn't be changed before we do the check anyway. + */ + for (iptr = field_name; *iptr; iptr++) + { + char c = *iptr; + + if (c == '"' || c != pg_tolower((unsigned char) c)) + { + all_lower = false; + break; + } + } + + if (all_lower) + for (i = 0; i < res->numAttributes; i++) + if (strcmp(field_name, res->attDescs[i].name) == 0) + return i; + + /* Fall through to the normal check if that didn't work out. */ + + /* + * Note: this code will not reject partially quoted strings, eg + * foo"BAR"foo will become fooBARfoo when it probably ought to be an error + * condition. + */ + field_case = strdup(field_name); + if (field_case == NULL) + return -1; /* grotty */ + + in_quotes = false; + optr = field_case; + for (iptr = field_case; *iptr; iptr++) + { + char c = *iptr; + + if (in_quotes) + { + if (c == '"') + { + if (iptr[1] == '"') + { + /* doubled quotes become a single quote */ + *optr++ = '"'; + iptr++; + } + else + in_quotes = false; + } + else + *optr++ = c; + } + else if (c == '"') + in_quotes = true; + else + { + c = pg_tolower((unsigned char) c); + *optr++ = c; + } + } + *optr = '\0'; + + for (i = 0; i < res->numAttributes; i++) + { + if (strcmp(field_case, res->attDescs[i].name) == 0) + { + free(field_case); + return i; + } + } + free(field_case); + return -1; +} + +Oid +PQftable(const PGresult *res, int field_num) +{ + if (!check_field_number(res, field_num)) + return InvalidOid; + if (res->attDescs) + return res->attDescs[field_num].tableid; + else + return InvalidOid; +} + +int +PQftablecol(const PGresult *res, int field_num) +{ + if (!check_field_number(res, field_num)) + return 0; + if (res->attDescs) + return res->attDescs[field_num].columnid; + else + return 0; +} + +int +PQfformat(const PGresult *res, int field_num) +{ + if (!check_field_number(res, field_num)) + return 0; + if (res->attDescs) + return res->attDescs[field_num].format; + else + return 0; +} + +Oid +PQftype(const PGresult *res, int field_num) +{ + if (!check_field_number(res, field_num)) + return InvalidOid; + if (res->attDescs) + return res->attDescs[field_num].typid; + else + return InvalidOid; +} + +int +PQfsize(const PGresult *res, int field_num) +{ + if (!check_field_number(res, field_num)) + return 0; + if (res->attDescs) + return res->attDescs[field_num].typlen; + else + return 0; +} + +int +PQfmod(const PGresult *res, int field_num) +{ + if (!check_field_number(res, field_num)) + return 0; + if (res->attDescs) + return res->attDescs[field_num].atttypmod; + else + return 0; +} + +char * +PQcmdStatus(PGresult *res) +{ + if (!res) + return NULL; + return res->cmdStatus; +} + +/* + * PQoidStatus - + * if the last command was an INSERT, return the oid string + * if not, return "" + */ +char * +PQoidStatus(const PGresult *res) +{ + /* + * This must be enough to hold the result. Don't laugh, this is better + * than what this function used to do. + */ + static char buf[24]; + + size_t len; + + if (!res || strncmp(res->cmdStatus, "INSERT ", 7) != 0) + return ""; + + len = strspn(res->cmdStatus + 7, "0123456789"); + if (len > sizeof(buf) - 1) + len = sizeof(buf) - 1; + memcpy(buf, res->cmdStatus + 7, len); + buf[len] = '\0'; + + return buf; +} + +/* + * PQoidValue - + * a perhaps preferable form of the above which just returns + * an Oid type + */ +Oid +PQoidValue(const PGresult *res) +{ + char *endptr = NULL; + unsigned long result; + + if (!res || + strncmp(res->cmdStatus, "INSERT ", 7) != 0 || + res->cmdStatus[7] < '0' || + res->cmdStatus[7] > '9') + return InvalidOid; + + result = strtoul(res->cmdStatus + 7, &endptr, 10); + + if (!endptr || (*endptr != ' ' && *endptr != '\0')) + return InvalidOid; + else + return (Oid) result; +} + + +/* + * PQcmdTuples - + * If the last command was INSERT/UPDATE/DELETE/MERGE/MOVE/FETCH/COPY, + * return a string containing the number of inserted/affected tuples. + * If not, return "". + * + * XXX: this should probably return an int + */ +char * +PQcmdTuples(PGresult *res) +{ + char *p, + *c; + + if (!res) + return ""; + + if (strncmp(res->cmdStatus, "INSERT ", 7) == 0) + { + p = res->cmdStatus + 7; + /* INSERT: skip oid and space */ + while (*p && *p != ' ') + p++; + if (*p == 0) + goto interpret_error; /* no space? */ + p++; + } + else if (strncmp(res->cmdStatus, "SELECT ", 7) == 0 || + strncmp(res->cmdStatus, "DELETE ", 7) == 0 || + strncmp(res->cmdStatus, "UPDATE ", 7) == 0) + p = res->cmdStatus + 7; + else if (strncmp(res->cmdStatus, "FETCH ", 6) == 0 || + strncmp(res->cmdStatus, "MERGE ", 6) == 0) + p = res->cmdStatus + 6; + else if (strncmp(res->cmdStatus, "MOVE ", 5) == 0 || + strncmp(res->cmdStatus, "COPY ", 5) == 0) + p = res->cmdStatus + 5; + else + return ""; + + /* check that we have an integer (at least one digit, nothing else) */ + for (c = p; *c; c++) + { + if (!isdigit((unsigned char) *c)) + goto interpret_error; + } + if (c == p) + goto interpret_error; + + return p; + +interpret_error: + pqInternalNotice(&res->noticeHooks, + "could not interpret result from server: %s", + res->cmdStatus); + return ""; +} + +/* + * PQgetvalue: + * return the value of field 'field_num' of row 'tup_num' + */ +char * +PQgetvalue(const PGresult *res, int tup_num, int field_num) +{ + if (!check_tuple_field_number(res, tup_num, field_num)) + return NULL; + return res->tuples[tup_num][field_num].value; +} + +/* PQgetlength: + * returns the actual length of a field value in bytes. + */ +int +PQgetlength(const PGresult *res, int tup_num, int field_num) +{ + if (!check_tuple_field_number(res, tup_num, field_num)) + return 0; + if (res->tuples[tup_num][field_num].len != NULL_LEN) + return res->tuples[tup_num][field_num].len; + else + return 0; +} + +/* PQgetisnull: + * returns the null status of a field value. + */ +int +PQgetisnull(const PGresult *res, int tup_num, int field_num) +{ + if (!check_tuple_field_number(res, tup_num, field_num)) + return 1; /* pretend it is null */ + if (res->tuples[tup_num][field_num].len == NULL_LEN) + return 1; + else + return 0; +} + +/* PQnparams: + * returns the number of input parameters of a prepared statement. + */ +int +PQnparams(const PGresult *res) +{ + if (!res) + return 0; + return res->numParameters; +} + +/* PQparamtype: + * returns type Oid of the specified statement parameter. + */ +Oid +PQparamtype(const PGresult *res, int param_num) +{ + if (!check_param_number(res, param_num)) + return InvalidOid; + if (res->paramDescs) + return res->paramDescs[param_num].typid; + else + return InvalidOid; +} + + +/* PQsetnonblocking: + * sets the PGconn's database connection non-blocking if the arg is true + * or makes it blocking if the arg is false, this will not protect + * you from PQexec(), you'll only be safe when using the non-blocking API. + * Needs to be called only on a connected database connection. + */ +int +PQsetnonblocking(PGconn *conn, int arg) +{ + bool barg; + + if (!conn || conn->status == CONNECTION_BAD) + return -1; + + barg = (arg ? true : false); + + /* early out if the socket is already in the state requested */ + if (barg == conn->nonblocking) + return 0; + + /* + * to guarantee constancy for flushing/query/result-polling behavior we + * need to flush the send queue at this point in order to guarantee proper + * behavior. this is ok because either they are making a transition _from_ + * or _to_ blocking mode, either way we can block them. + * + * Clear error state in case pqFlush adds to it, unless we're actively + * pipelining, in which case it seems best not to. + */ + if (conn->cmd_queue_head == NULL) + pqClearConnErrorState(conn); + + /* if we are going from blocking to non-blocking flush here */ + if (pqFlush(conn)) + return -1; + + conn->nonblocking = barg; + + return 0; +} + +/* + * return the blocking status of the database connection + * true == nonblocking, false == blocking + */ +int +PQisnonblocking(const PGconn *conn) +{ + if (!conn || conn->status == CONNECTION_BAD) + return false; + return pqIsnonblocking(conn); +} + +/* libpq is thread-safe? */ +int +PQisthreadsafe(void) +{ +#ifdef ENABLE_THREAD_SAFETY + return true; +#else + return false; +#endif +} + + +/* try to force data out, really only useful for non-blocking users */ +int +PQflush(PGconn *conn) +{ + if (!conn || conn->status == CONNECTION_BAD) + return -1; + return pqFlush(conn); +} + +/* + * pqPipelineFlush + * + * In pipeline mode, data will be flushed only when the out buffer reaches the + * threshold value. In non-pipeline mode, it behaves as stock pqFlush. + * + * Returns 0 on success. + */ +static int +pqPipelineFlush(PGconn *conn) +{ + if ((conn->pipelineStatus != PQ_PIPELINE_ON) || + (conn->outCount >= OUTBUFFER_THRESHOLD)) + return pqFlush(conn); + return 0; +} + + +/* + * PQfreemem - safely frees memory allocated + * + * Needed mostly by Win32, unless multithreaded DLL (/MD in VC6) + * Used for freeing memory from PQescapeBytea()/PQunescapeBytea() + */ +void +PQfreemem(void *ptr) +{ + free(ptr); +} + +/* + * PQfreeNotify - free's the memory associated with a PGnotify + * + * This function is here only for binary backward compatibility. + * New code should use PQfreemem(). A macro will automatically map + * calls to PQfreemem. It should be removed in the future. bjm 2003-03-24 + */ + +#undef PQfreeNotify +void PQfreeNotify(PGnotify *notify); + +void +PQfreeNotify(PGnotify *notify) +{ + PQfreemem(notify); +} + + +/* + * Escaping arbitrary strings to get valid SQL literal strings. + * + * Replaces "'" with "''", and if not std_strings, replaces "\" with "\\". + * + * length is the length of the source string. (Note: if a terminating NUL + * is encountered sooner, PQescapeString stops short of "length"; the behavior + * is thus rather like strncpy.) + * + * For safety the buffer at "to" must be at least 2*length + 1 bytes long. + * A terminating NUL character is added to the output string, whether the + * input is NUL-terminated or not. + * + * Returns the actual length of the output (not counting the terminating NUL). + */ +static size_t +PQescapeStringInternal(PGconn *conn, + char *to, const char *from, size_t length, + int *error, + int encoding, bool std_strings) +{ + const char *source = from; + char *target = to; + size_t remaining = length; + + if (error) + *error = 0; + + while (remaining > 0 && *source != '\0') + { + char c = *source; + int len; + int i; + + /* Fast path for plain ASCII */ + if (!IS_HIGHBIT_SET(c)) + { + /* Apply quoting if needed */ + if (SQL_STR_DOUBLE(c, !std_strings)) + *target++ = c; + /* Copy the character */ + *target++ = c; + source++; + remaining--; + continue; + } + + /* Slow path for possible multibyte characters */ + len = pg_encoding_mblen(encoding, source); + + /* Copy the character */ + for (i = 0; i < len; i++) + { + if (remaining == 0 || *source == '\0') + break; + *target++ = *source++; + remaining--; + } + + /* + * If we hit premature end of string (ie, incomplete multibyte + * character), try to pad out to the correct length with spaces. We + * may not be able to pad completely, but we will always be able to + * insert at least one pad space (since we'd not have quoted a + * multibyte character). This should be enough to make a string that + * the server will error out on. + */ + if (i < len) + { + if (error) + *error = 1; + if (conn) + libpq_append_conn_error(conn, "incomplete multibyte character"); + for (; i < len; i++) + { + if (((size_t) (target - to)) / 2 >= length) + break; + *target++ = ' '; + } + break; + } + } + + /* Write the terminating NUL character. */ + *target = '\0'; + + return target - to; +} + +size_t +PQescapeStringConn(PGconn *conn, + char *to, const char *from, size_t length, + int *error) +{ + if (!conn) + { + /* force empty-string result */ + *to = '\0'; + if (error) + *error = 1; + return 0; + } + + if (conn->cmd_queue_head == NULL) + pqClearConnErrorState(conn); + + return PQescapeStringInternal(conn, to, from, length, error, + conn->client_encoding, + conn->std_strings); +} + +size_t +PQescapeString(char *to, const char *from, size_t length) +{ + return PQescapeStringInternal(NULL, to, from, length, NULL, + static_client_encoding, + static_std_strings); +} + + +/* + * Escape arbitrary strings. If as_ident is true, we escape the result + * as an identifier; if false, as a literal. The result is returned in + * a newly allocated buffer. If we fail due to an encoding violation or out + * of memory condition, we return NULL, storing an error message into conn. + */ +static char * +PQescapeInternal(PGconn *conn, const char *str, size_t len, bool as_ident) +{ + const char *s; + char *result; + char *rp; + int num_quotes = 0; /* single or double, depending on as_ident */ + int num_backslashes = 0; + int input_len; + int result_size; + char quote_char = as_ident ? '"' : '\''; + + /* We must have a connection, else fail immediately. */ + if (!conn) + return NULL; + + if (conn->cmd_queue_head == NULL) + pqClearConnErrorState(conn); + + /* Scan the string for characters that must be escaped. */ + for (s = str; (s - str) < len && *s != '\0'; ++s) + { + if (*s == quote_char) + ++num_quotes; + else if (*s == '\\') + ++num_backslashes; + else if (IS_HIGHBIT_SET(*s)) + { + int charlen; + + /* Slow path for possible multibyte characters */ + charlen = pg_encoding_mblen(conn->client_encoding, s); + + /* Multibyte character overruns allowable length. */ + if ((s - str) + charlen > len || memchr(s, 0, charlen) != NULL) + { + libpq_append_conn_error(conn, "incomplete multibyte character"); + return NULL; + } + + /* Adjust s, bearing in mind that for loop will increment it. */ + s += charlen - 1; + } + } + + /* Allocate output buffer. */ + input_len = s - str; + result_size = input_len + num_quotes + 3; /* two quotes, plus a NUL */ + if (!as_ident && num_backslashes > 0) + result_size += num_backslashes + 2; + result = rp = (char *) malloc(result_size); + if (rp == NULL) + { + libpq_append_conn_error(conn, "out of memory"); + return NULL; + } + + /* + * If we are escaping a literal that contains backslashes, we use the + * escape string syntax so that the result is correct under either value + * of standard_conforming_strings. We also emit a leading space in this + * case, to guard against the possibility that the result might be + * interpolated immediately following an identifier. + */ + if (!as_ident && num_backslashes > 0) + { + *rp++ = ' '; + *rp++ = 'E'; + } + + /* Opening quote. */ + *rp++ = quote_char; + + /* + * Use fast path if possible. + * + * We've already verified that the input string is well-formed in the + * current encoding. If it contains no quotes and, in the case of + * literal-escaping, no backslashes, then we can just copy it directly to + * the output buffer, adding the necessary quotes. + * + * If not, we must rescan the input and process each character + * individually. + */ + if (num_quotes == 0 && (num_backslashes == 0 || as_ident)) + { + memcpy(rp, str, input_len); + rp += input_len; + } + else + { + for (s = str; s - str < input_len; ++s) + { + if (*s == quote_char || (!as_ident && *s == '\\')) + { + *rp++ = *s; + *rp++ = *s; + } + else if (!IS_HIGHBIT_SET(*s)) + *rp++ = *s; + else + { + int i = pg_encoding_mblen(conn->client_encoding, s); + + while (1) + { + *rp++ = *s; + if (--i == 0) + break; + ++s; /* for loop will provide the final increment */ + } + } + } + } + + /* Closing quote and terminating NUL. */ + *rp++ = quote_char; + *rp = '\0'; + + return result; +} + +char * +PQescapeLiteral(PGconn *conn, const char *str, size_t len) +{ + return PQescapeInternal(conn, str, len, false); +} + +char * +PQescapeIdentifier(PGconn *conn, const char *str, size_t len) +{ + return PQescapeInternal(conn, str, len, true); +} + +/* HEX encoding support for bytea */ +static const char hextbl[] = "0123456789abcdef"; + +static const int8 hexlookup[128] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, + -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, +}; + +static inline char +get_hex(char c) +{ + int res = -1; + + if (c > 0 && c < 127) + res = hexlookup[(unsigned char) c]; + + return (char) res; +} + + +/* + * PQescapeBytea - converts from binary string to the + * minimal encoding necessary to include the string in an SQL + * INSERT statement with a bytea type column as the target. + * + * We can use either hex or escape (traditional) encoding. + * In escape mode, the following transformations are applied: + * '\0' == ASCII 0 == \000 + * '\'' == ASCII 39 == '' + * '\\' == ASCII 92 == \\ + * anything < 0x20, or > 0x7e ---> \ooo + * (where ooo is an octal expression) + * + * If not std_strings, all backslashes sent to the output are doubled. + */ +static unsigned char * +PQescapeByteaInternal(PGconn *conn, + const unsigned char *from, size_t from_length, + size_t *to_length, bool std_strings, bool use_hex) +{ + const unsigned char *vp; + unsigned char *rp; + unsigned char *result; + size_t i; + size_t len; + size_t bslash_len = (std_strings ? 1 : 2); + + /* + * empty string has 1 char ('\0') + */ + len = 1; + + if (use_hex) + { + len += bslash_len + 1 + 2 * from_length; + } + else + { + vp = from; + for (i = from_length; i > 0; i--, vp++) + { + if (*vp < 0x20 || *vp > 0x7e) + len += bslash_len + 3; + else if (*vp == '\'') + len += 2; + else if (*vp == '\\') + len += bslash_len + bslash_len; + else + len++; + } + } + + *to_length = len; + rp = result = (unsigned char *) malloc(len); + if (rp == NULL) + { + if (conn) + libpq_append_conn_error(conn, "out of memory"); + return NULL; + } + + if (use_hex) + { + if (!std_strings) + *rp++ = '\\'; + *rp++ = '\\'; + *rp++ = 'x'; + } + + vp = from; + for (i = from_length; i > 0; i--, vp++) + { + unsigned char c = *vp; + + if (use_hex) + { + *rp++ = hextbl[(c >> 4) & 0xF]; + *rp++ = hextbl[c & 0xF]; + } + else if (c < 0x20 || c > 0x7e) + { + if (!std_strings) + *rp++ = '\\'; + *rp++ = '\\'; + *rp++ = (c >> 6) + '0'; + *rp++ = ((c >> 3) & 07) + '0'; + *rp++ = (c & 07) + '0'; + } + else if (c == '\'') + { + *rp++ = '\''; + *rp++ = '\''; + } + else if (c == '\\') + { + if (!std_strings) + { + *rp++ = '\\'; + *rp++ = '\\'; + } + *rp++ = '\\'; + *rp++ = '\\'; + } + else + *rp++ = c; + } + *rp = '\0'; + + return result; +} + +unsigned char * +PQescapeByteaConn(PGconn *conn, + const unsigned char *from, size_t from_length, + size_t *to_length) +{ + if (!conn) + return NULL; + + if (conn->cmd_queue_head == NULL) + pqClearConnErrorState(conn); + + return PQescapeByteaInternal(conn, from, from_length, to_length, + conn->std_strings, + (conn->sversion >= 90000)); +} + +unsigned char * +PQescapeBytea(const unsigned char *from, size_t from_length, size_t *to_length) +{ + return PQescapeByteaInternal(NULL, from, from_length, to_length, + static_std_strings, + false /* can't use hex */ ); +} + + +#define ISFIRSTOCTDIGIT(CH) ((CH) >= '0' && (CH) <= '3') +#define ISOCTDIGIT(CH) ((CH) >= '0' && (CH) <= '7') +#define OCTVAL(CH) ((CH) - '0') + +/* + * PQunescapeBytea - converts the null terminated string representation + * of a bytea, strtext, into binary, filling a buffer. It returns a + * pointer to the buffer (or NULL on error), and the size of the + * buffer in retbuflen. The pointer may subsequently be used as an + * argument to the function PQfreemem. + * + * The following transformations are made: + * \\ == ASCII 92 == \ + * \ooo == a byte whose value = ooo (ooo is an octal number) + * \x == x (x is any character not matched by the above transformations) + */ +unsigned char * +PQunescapeBytea(const unsigned char *strtext, size_t *retbuflen) +{ + size_t strtextlen, + buflen; + unsigned char *buffer, + *tmpbuf; + size_t i, + j; + + if (strtext == NULL) + return NULL; + + strtextlen = strlen((const char *) strtext); + + if (strtext[0] == '\\' && strtext[1] == 'x') + { + const unsigned char *s; + unsigned char *p; + + buflen = (strtextlen - 2) / 2; + /* Avoid unportable malloc(0) */ + buffer = (unsigned char *) malloc(buflen > 0 ? buflen : 1); + if (buffer == NULL) + return NULL; + + s = strtext + 2; + p = buffer; + while (*s) + { + char v1, + v2; + + /* + * Bad input is silently ignored. Note that this includes + * whitespace between hex pairs, which is allowed by byteain. + */ + v1 = get_hex(*s++); + if (!*s || v1 == (char) -1) + continue; + v2 = get_hex(*s++); + if (v2 != (char) -1) + *p++ = (v1 << 4) | v2; + } + + buflen = p - buffer; + } + else + { + /* + * Length of input is max length of output, but add one to avoid + * unportable malloc(0) if input is zero-length. + */ + buffer = (unsigned char *) malloc(strtextlen + 1); + if (buffer == NULL) + return NULL; + + for (i = j = 0; i < strtextlen;) + { + switch (strtext[i]) + { + case '\\': + i++; + if (strtext[i] == '\\') + buffer[j++] = strtext[i++]; + else + { + if ((ISFIRSTOCTDIGIT(strtext[i])) && + (ISOCTDIGIT(strtext[i + 1])) && + (ISOCTDIGIT(strtext[i + 2]))) + { + int byte; + + byte = OCTVAL(strtext[i++]); + byte = (byte << 3) + OCTVAL(strtext[i++]); + byte = (byte << 3) + OCTVAL(strtext[i++]); + buffer[j++] = byte; + } + } + + /* + * Note: if we see '\' followed by something that isn't a + * recognized escape sequence, we loop around having done + * nothing except advance i. Therefore the something will + * be emitted as ordinary data on the next cycle. Corner + * case: '\' at end of string will just be discarded. + */ + break; + + default: + buffer[j++] = strtext[i++]; + break; + } + } + buflen = j; /* buflen is the length of the dequoted data */ + } + + /* Shrink the buffer to be no larger than necessary */ + /* +1 avoids unportable behavior when buflen==0 */ + tmpbuf = realloc(buffer, buflen + 1); + + /* It would only be a very brain-dead realloc that could fail, but... */ + if (!tmpbuf) + { + free(buffer); + return NULL; + } + + *retbuflen = buflen; + return tmpbuf; +} diff --git a/src/interfaces/libpq/fe-gssapi-common.c b/src/interfaces/libpq/fe-gssapi-common.c new file mode 100644 index 0000000..f17ce09 --- /dev/null +++ b/src/interfaces/libpq/fe-gssapi-common.c @@ -0,0 +1,128 @@ +/*------------------------------------------------------------------------- + * + * fe-gssapi-common.c + * The front-end (client) GSSAPI common code + * + * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/interfaces/libpq/fe-gssapi-common.c + *------------------------------------------------------------------------- + */ + +#include "postgres_fe.h" + +#include "fe-gssapi-common.h" + +#include "libpq-int.h" +#include "pqexpbuffer.h" + +/* + * Fetch all errors of a specific type and append to "str". + * Each error string is preceded by a space. + */ +static void +pg_GSS_error_int(PQExpBuffer str, OM_uint32 stat, int type) +{ + OM_uint32 lmin_s; + gss_buffer_desc lmsg; + OM_uint32 msg_ctx = 0; + + do + { + if (gss_display_status(&lmin_s, stat, type, GSS_C_NO_OID, + &msg_ctx, &lmsg) != GSS_S_COMPLETE) + break; + appendPQExpBufferChar(str, ' '); + appendBinaryPQExpBuffer(str, lmsg.value, lmsg.length); + gss_release_buffer(&lmin_s, &lmsg); + } while (msg_ctx); +} + +/* + * GSSAPI errors contain two parts; put both into conn->errorMessage. + */ +void +pg_GSS_error(const char *mprefix, PGconn *conn, + OM_uint32 maj_stat, OM_uint32 min_stat) +{ + appendPQExpBuffer(&conn->errorMessage, "%s:", mprefix); + pg_GSS_error_int(&conn->errorMessage, maj_stat, GSS_C_GSS_CODE); + appendPQExpBufferChar(&conn->errorMessage, ':'); + pg_GSS_error_int(&conn->errorMessage, min_stat, GSS_C_MECH_CODE); + appendPQExpBufferChar(&conn->errorMessage, '\n'); +} + +/* + * Check if we can acquire credentials at all (and yield them if so). + */ +bool +pg_GSS_have_cred_cache(gss_cred_id_t *cred_out) +{ + OM_uint32 major, + minor; + gss_cred_id_t cred = GSS_C_NO_CREDENTIAL; + + major = gss_acquire_cred(&minor, GSS_C_NO_NAME, 0, GSS_C_NO_OID_SET, + GSS_C_INITIATE, &cred, NULL, NULL); + if (major != GSS_S_COMPLETE) + { + *cred_out = NULL; + return false; + } + *cred_out = cred; + return true; +} + +/* + * Try to load service name for a connection + */ +int +pg_GSS_load_servicename(PGconn *conn) +{ + OM_uint32 maj_stat, + min_stat; + int maxlen; + gss_buffer_desc temp_gbuf; + char *host; + + if (conn->gtarg_nam != NULL) + /* Already taken care of - move along */ + return STATUS_OK; + + host = PQhost(conn); + if (!(host && host[0] != '\0')) + { + libpq_append_conn_error(conn, "host name must be specified"); + return STATUS_ERROR; + } + + /* + * Import service principal name so the proper ticket can be acquired by + * the GSSAPI system. + */ + maxlen = strlen(conn->krbsrvname) + strlen(host) + 2; + temp_gbuf.value = (char *) malloc(maxlen); + if (!temp_gbuf.value) + { + libpq_append_conn_error(conn, "out of memory"); + return STATUS_ERROR; + } + snprintf(temp_gbuf.value, maxlen, "%s@%s", + conn->krbsrvname, host); + temp_gbuf.length = strlen(temp_gbuf.value); + + maj_stat = gss_import_name(&min_stat, &temp_gbuf, + GSS_C_NT_HOSTBASED_SERVICE, &conn->gtarg_nam); + free(temp_gbuf.value); + + if (maj_stat != GSS_S_COMPLETE) + { + pg_GSS_error(libpq_gettext("GSSAPI name import error"), + conn, + maj_stat, min_stat); + return STATUS_ERROR; + } + return STATUS_OK; +} diff --git a/src/interfaces/libpq/fe-gssapi-common.h b/src/interfaces/libpq/fe-gssapi-common.h new file mode 100644 index 0000000..5f93b7e --- /dev/null +++ b/src/interfaces/libpq/fe-gssapi-common.h @@ -0,0 +1,28 @@ +/*------------------------------------------------------------------------- + * + * fe-gssapi-common.h + * + * Definitions for GSSAPI common routines + * + * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/interfaces/libpq/fe-gssapi-common.h + */ + +#ifndef FE_GSSAPI_COMMON_H +#define FE_GSSAPI_COMMON_H + +#include "libpq-fe.h" +#include "libpq-int.h" + +#ifdef ENABLE_GSS + +void pg_GSS_error(const char *mprefix, PGconn *conn, + OM_uint32 maj_stat, OM_uint32 min_stat); +bool pg_GSS_have_cred_cache(gss_cred_id_t *cred_out); +int pg_GSS_load_servicename(PGconn *conn); + +#endif + +#endif /* FE_GSSAPI_COMMON_H */ diff --git a/src/interfaces/libpq/fe-lobj.c b/src/interfaces/libpq/fe-lobj.c new file mode 100644 index 0000000..206266f --- /dev/null +++ b/src/interfaces/libpq/fe-lobj.c @@ -0,0 +1,1064 @@ +/*------------------------------------------------------------------------- + * + * fe-lobj.c + * Front-end large object interface + * + * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * src/interfaces/libpq/fe-lobj.c + * + *------------------------------------------------------------------------- + */ + +#ifdef WIN32 +/* + * As unlink/rename are #define'd in port.h (via postgres_fe.h), io.h + * must be included first on MS C. Might as well do it for all WIN32's + * here. + */ +#include <io.h> +#endif + +#include "postgres_fe.h" + +#ifdef WIN32 +#include "win32.h" +#else +#include <unistd.h> +#endif + +#include <fcntl.h> +#include <limits.h> +#include <sys/stat.h> + +#include "libpq-fe.h" +#include "libpq-int.h" +#include "libpq/libpq-fs.h" /* must come after sys/stat.h */ +#include "port/pg_bswap.h" + +#define LO_BUFSIZE 8192 + +static int lo_initialize(PGconn *conn); +static Oid lo_import_internal(PGconn *conn, const char *filename, Oid oid); +static pg_int64 lo_hton64(pg_int64 host64); +static pg_int64 lo_ntoh64(pg_int64 net64); + +/* + * lo_open + * opens an existing large object + * + * returns the file descriptor for use in later lo_* calls + * return -1 upon failure. + */ +int +lo_open(PGconn *conn, Oid lobjId, int mode) +{ + int fd; + int result_len; + PQArgBlock argv[2]; + PGresult *res; + + if (lo_initialize(conn) < 0) + return -1; + + argv[0].isint = 1; + argv[0].len = 4; + argv[0].u.integer = lobjId; + + argv[1].isint = 1; + argv[1].len = 4; + argv[1].u.integer = mode; + + res = PQfn(conn, conn->lobjfuncs->fn_lo_open, &fd, &result_len, 1, argv, 2); + if (PQresultStatus(res) == PGRES_COMMAND_OK) + { + PQclear(res); + return fd; + } + else + { + PQclear(res); + return -1; + } +} + +/* + * lo_close + * closes an existing large object + * + * returns 0 upon success + * returns -1 upon failure. + */ +int +lo_close(PGconn *conn, int fd) +{ + PQArgBlock argv[1]; + PGresult *res; + int retval; + int result_len; + + if (lo_initialize(conn) < 0) + return -1; + + argv[0].isint = 1; + argv[0].len = 4; + argv[0].u.integer = fd; + res = PQfn(conn, conn->lobjfuncs->fn_lo_close, + &retval, &result_len, 1, argv, 1); + if (PQresultStatus(res) == PGRES_COMMAND_OK) + { + PQclear(res); + return retval; + } + else + { + PQclear(res); + return -1; + } +} + +/* + * lo_truncate + * truncates an existing large object to the given size + * + * returns 0 upon success + * returns -1 upon failure + */ +int +lo_truncate(PGconn *conn, int fd, size_t len) +{ + PQArgBlock argv[2]; + PGresult *res; + int retval; + int result_len; + + if (lo_initialize(conn) < 0) + return -1; + + /* Must check this on-the-fly because it's not there pre-8.3 */ + if (conn->lobjfuncs->fn_lo_truncate == 0) + { + libpq_append_conn_error(conn, "cannot determine OID of function %s", + "lo_truncate"); + return -1; + } + + /* + * Long ago, somebody thought it'd be a good idea to declare this function + * as taking size_t ... but the underlying backend function only accepts a + * signed int32 length. So throw error if the given value overflows + * int32. (A possible alternative is to automatically redirect the call + * to lo_truncate64; but if the caller wanted to rely on that backend + * function being available, he could have called lo_truncate64 for + * himself.) + */ + if (len > (size_t) INT_MAX) + { + libpq_append_conn_error(conn, "argument of lo_truncate exceeds integer range"); + return -1; + } + + argv[0].isint = 1; + argv[0].len = 4; + argv[0].u.integer = fd; + + argv[1].isint = 1; + argv[1].len = 4; + argv[1].u.integer = (int) len; + + res = PQfn(conn, conn->lobjfuncs->fn_lo_truncate, + &retval, &result_len, 1, argv, 2); + + if (PQresultStatus(res) == PGRES_COMMAND_OK) + { + PQclear(res); + return retval; + } + else + { + PQclear(res); + return -1; + } +} + +/* + * lo_truncate64 + * truncates an existing large object to the given size + * + * returns 0 upon success + * returns -1 upon failure + */ +int +lo_truncate64(PGconn *conn, int fd, pg_int64 len) +{ + PQArgBlock argv[2]; + PGresult *res; + int retval; + int result_len; + + if (lo_initialize(conn) < 0) + return -1; + + if (conn->lobjfuncs->fn_lo_truncate64 == 0) + { + libpq_append_conn_error(conn, "cannot determine OID of function %s", + "lo_truncate64"); + return -1; + } + + argv[0].isint = 1; + argv[0].len = 4; + argv[0].u.integer = fd; + + len = lo_hton64(len); + argv[1].isint = 0; + argv[1].len = 8; + argv[1].u.ptr = (int *) &len; + + res = PQfn(conn, conn->lobjfuncs->fn_lo_truncate64, + &retval, &result_len, 1, argv, 2); + + if (PQresultStatus(res) == PGRES_COMMAND_OK) + { + PQclear(res); + return retval; + } + else + { + PQclear(res); + return -1; + } +} + +/* + * lo_read + * read len bytes of the large object into buf + * + * returns the number of bytes read, or -1 on failure. + * the CALLER must have allocated enough space to hold the result returned + */ + +int +lo_read(PGconn *conn, int fd, char *buf, size_t len) +{ + PQArgBlock argv[2]; + PGresult *res; + int result_len; + + if (lo_initialize(conn) < 0) + return -1; + + /* + * Long ago, somebody thought it'd be a good idea to declare this function + * as taking size_t ... but the underlying backend function only accepts a + * signed int32 length. So throw error if the given value overflows + * int32. + */ + if (len > (size_t) INT_MAX) + { + libpq_append_conn_error(conn, "argument of lo_read exceeds integer range"); + return -1; + } + + argv[0].isint = 1; + argv[0].len = 4; + argv[0].u.integer = fd; + + argv[1].isint = 1; + argv[1].len = 4; + argv[1].u.integer = (int) len; + + res = PQfn(conn, conn->lobjfuncs->fn_lo_read, + (void *) buf, &result_len, 0, argv, 2); + if (PQresultStatus(res) == PGRES_COMMAND_OK) + { + PQclear(res); + return result_len; + } + else + { + PQclear(res); + return -1; + } +} + +/* + * lo_write + * write len bytes of buf into the large object fd + * + * returns the number of bytes written, or -1 on failure. + */ +int +lo_write(PGconn *conn, int fd, const char *buf, size_t len) +{ + PQArgBlock argv[2]; + PGresult *res; + int result_len; + int retval; + + if (lo_initialize(conn) < 0) + return -1; + + /* + * Long ago, somebody thought it'd be a good idea to declare this function + * as taking size_t ... but the underlying backend function only accepts a + * signed int32 length. So throw error if the given value overflows + * int32. + */ + if (len > (size_t) INT_MAX) + { + libpq_append_conn_error(conn, "argument of lo_write exceeds integer range"); + return -1; + } + + argv[0].isint = 1; + argv[0].len = 4; + argv[0].u.integer = fd; + + argv[1].isint = 0; + argv[1].len = (int) len; + argv[1].u.ptr = (int *) unconstify(char *, buf); + + res = PQfn(conn, conn->lobjfuncs->fn_lo_write, + &retval, &result_len, 1, argv, 2); + if (PQresultStatus(res) == PGRES_COMMAND_OK) + { + PQclear(res); + return retval; + } + else + { + PQclear(res); + return -1; + } +} + +/* + * lo_lseek + * change the current read or write location on a large object + */ +int +lo_lseek(PGconn *conn, int fd, int offset, int whence) +{ + PQArgBlock argv[3]; + PGresult *res; + int retval; + int result_len; + + if (lo_initialize(conn) < 0) + return -1; + + argv[0].isint = 1; + argv[0].len = 4; + argv[0].u.integer = fd; + + argv[1].isint = 1; + argv[1].len = 4; + argv[1].u.integer = offset; + + argv[2].isint = 1; + argv[2].len = 4; + argv[2].u.integer = whence; + + res = PQfn(conn, conn->lobjfuncs->fn_lo_lseek, + &retval, &result_len, 1, argv, 3); + if (PQresultStatus(res) == PGRES_COMMAND_OK) + { + PQclear(res); + return retval; + } + else + { + PQclear(res); + return -1; + } +} + +/* + * lo_lseek64 + * change the current read or write location on a large object + */ +pg_int64 +lo_lseek64(PGconn *conn, int fd, pg_int64 offset, int whence) +{ + PQArgBlock argv[3]; + PGresult *res; + pg_int64 retval; + int result_len; + + if (lo_initialize(conn) < 0) + return -1; + + if (conn->lobjfuncs->fn_lo_lseek64 == 0) + { + libpq_append_conn_error(conn, "cannot determine OID of function %s", + "lo_lseek64"); + return -1; + } + + argv[0].isint = 1; + argv[0].len = 4; + argv[0].u.integer = fd; + + offset = lo_hton64(offset); + argv[1].isint = 0; + argv[1].len = 8; + argv[1].u.ptr = (int *) &offset; + + argv[2].isint = 1; + argv[2].len = 4; + argv[2].u.integer = whence; + + res = PQfn(conn, conn->lobjfuncs->fn_lo_lseek64, + (void *) &retval, &result_len, 0, argv, 3); + if (PQresultStatus(res) == PGRES_COMMAND_OK && result_len == 8) + { + PQclear(res); + return lo_ntoh64(retval); + } + else + { + PQclear(res); + return -1; + } +} + +/* + * lo_creat + * create a new large object + * the mode is ignored (once upon a time it had a use) + * + * returns the oid of the large object created or + * InvalidOid upon failure + */ +Oid +lo_creat(PGconn *conn, int mode) +{ + PQArgBlock argv[1]; + PGresult *res; + int retval; + int result_len; + + if (lo_initialize(conn) < 0) + return InvalidOid; + + argv[0].isint = 1; + argv[0].len = 4; + argv[0].u.integer = mode; + res = PQfn(conn, conn->lobjfuncs->fn_lo_creat, + &retval, &result_len, 1, argv, 1); + if (PQresultStatus(res) == PGRES_COMMAND_OK) + { + PQclear(res); + return (Oid) retval; + } + else + { + PQclear(res); + return InvalidOid; + } +} + +/* + * lo_create + * create a new large object + * if lobjId isn't InvalidOid, it specifies the OID to (attempt to) create + * + * returns the oid of the large object created or + * InvalidOid upon failure + */ +Oid +lo_create(PGconn *conn, Oid lobjId) +{ + PQArgBlock argv[1]; + PGresult *res; + int retval; + int result_len; + + if (lo_initialize(conn) < 0) + return InvalidOid; + + /* Must check this on-the-fly because it's not there pre-8.1 */ + if (conn->lobjfuncs->fn_lo_create == 0) + { + libpq_append_conn_error(conn, "cannot determine OID of function %s", + "lo_create"); + return InvalidOid; + } + + argv[0].isint = 1; + argv[0].len = 4; + argv[0].u.integer = lobjId; + res = PQfn(conn, conn->lobjfuncs->fn_lo_create, + &retval, &result_len, 1, argv, 1); + if (PQresultStatus(res) == PGRES_COMMAND_OK) + { + PQclear(res); + return (Oid) retval; + } + else + { + PQclear(res); + return InvalidOid; + } +} + + +/* + * lo_tell + * returns the current seek location of the large object + */ +int +lo_tell(PGconn *conn, int fd) +{ + int retval; + PQArgBlock argv[1]; + PGresult *res; + int result_len; + + if (lo_initialize(conn) < 0) + return -1; + + argv[0].isint = 1; + argv[0].len = 4; + argv[0].u.integer = fd; + + res = PQfn(conn, conn->lobjfuncs->fn_lo_tell, + &retval, &result_len, 1, argv, 1); + if (PQresultStatus(res) == PGRES_COMMAND_OK) + { + PQclear(res); + return retval; + } + else + { + PQclear(res); + return -1; + } +} + +/* + * lo_tell64 + * returns the current seek location of the large object + */ +pg_int64 +lo_tell64(PGconn *conn, int fd) +{ + pg_int64 retval; + PQArgBlock argv[1]; + PGresult *res; + int result_len; + + if (lo_initialize(conn) < 0) + return -1; + + if (conn->lobjfuncs->fn_lo_tell64 == 0) + { + libpq_append_conn_error(conn, "cannot determine OID of function %s", + "lo_tell64"); + return -1; + } + + argv[0].isint = 1; + argv[0].len = 4; + argv[0].u.integer = fd; + + res = PQfn(conn, conn->lobjfuncs->fn_lo_tell64, + (void *) &retval, &result_len, 0, argv, 1); + if (PQresultStatus(res) == PGRES_COMMAND_OK && result_len == 8) + { + PQclear(res); + return lo_ntoh64(retval); + } + else + { + PQclear(res); + return -1; + } +} + +/* + * lo_unlink + * delete a file + */ + +int +lo_unlink(PGconn *conn, Oid lobjId) +{ + PQArgBlock argv[1]; + PGresult *res; + int result_len; + int retval; + + if (lo_initialize(conn) < 0) + return -1; + + argv[0].isint = 1; + argv[0].len = 4; + argv[0].u.integer = lobjId; + + res = PQfn(conn, conn->lobjfuncs->fn_lo_unlink, + &retval, &result_len, 1, argv, 1); + if (PQresultStatus(res) == PGRES_COMMAND_OK) + { + PQclear(res); + return retval; + } + else + { + PQclear(res); + return -1; + } +} + +/* + * lo_import - + * imports a file as an (inversion) large object. + * + * returns the oid of that object upon success, + * returns InvalidOid upon failure + */ + +Oid +lo_import(PGconn *conn, const char *filename) +{ + return lo_import_internal(conn, filename, InvalidOid); +} + +/* + * lo_import_with_oid - + * imports a file as an (inversion) large object. + * large object id can be specified. + * + * returns the oid of that object upon success, + * returns InvalidOid upon failure + */ + +Oid +lo_import_with_oid(PGconn *conn, const char *filename, Oid lobjId) +{ + return lo_import_internal(conn, filename, lobjId); +} + +static Oid +lo_import_internal(PGconn *conn, const char *filename, Oid oid) +{ + int fd; + int nbytes, + tmp; + char buf[LO_BUFSIZE]; + Oid lobjOid; + int lobj; + char sebuf[PG_STRERROR_R_BUFLEN]; + + if (conn == NULL) + return InvalidOid; + + /* Since this is the beginning of a query cycle, reset the error state */ + pqClearConnErrorState(conn); + + /* + * open the file to be read in + */ + fd = open(filename, O_RDONLY | PG_BINARY, 0666); + if (fd < 0) + { /* error */ + libpq_append_conn_error(conn, "could not open file \"%s\": %s", + filename, strerror_r(errno, sebuf, sizeof(sebuf))); + return InvalidOid; + } + + /* + * create an inversion object + */ + if (oid == InvalidOid) + lobjOid = lo_creat(conn, INV_READ | INV_WRITE); + else + lobjOid = lo_create(conn, oid); + + if (lobjOid == InvalidOid) + { + /* we assume lo_create() already set a suitable error message */ + (void) close(fd); + return InvalidOid; + } + + lobj = lo_open(conn, lobjOid, INV_WRITE); + if (lobj == -1) + { + /* we assume lo_open() already set a suitable error message */ + (void) close(fd); + return InvalidOid; + } + + /* + * read in from the file and write to the large object + */ + while ((nbytes = read(fd, buf, LO_BUFSIZE)) > 0) + { + tmp = lo_write(conn, lobj, buf, nbytes); + if (tmp != nbytes) + { + /* + * If lo_write() failed, we are now in an aborted transaction so + * there's no need for lo_close(); furthermore, if we tried it + * we'd overwrite the useful error result with a useless one. So + * just nail the doors shut and get out of town. + */ + (void) close(fd); + return InvalidOid; + } + } + + if (nbytes < 0) + { + /* We must do lo_close before setting the errorMessage */ + int save_errno = errno; + + (void) lo_close(conn, lobj); + (void) close(fd); + /* deliberately overwrite any error from lo_close */ + pqClearConnErrorState(conn); + libpq_append_conn_error(conn, "could not read from file \"%s\": %s", + filename, + strerror_r(save_errno, sebuf, sizeof(sebuf))); + return InvalidOid; + } + + (void) close(fd); + + if (lo_close(conn, lobj) != 0) + { + /* we assume lo_close() already set a suitable error message */ + return InvalidOid; + } + + return lobjOid; +} + +/* + * lo_export - + * exports an (inversion) large object. + * returns -1 upon failure, 1 if OK + */ +int +lo_export(PGconn *conn, Oid lobjId, const char *filename) +{ + int result = 1; + int fd; + int nbytes, + tmp; + char buf[LO_BUFSIZE]; + int lobj; + char sebuf[PG_STRERROR_R_BUFLEN]; + + /* + * open the large object. + */ + lobj = lo_open(conn, lobjId, INV_READ); + if (lobj == -1) + { + /* we assume lo_open() already set a suitable error message */ + return -1; + } + + /* + * create the file to be written to + */ + fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC | PG_BINARY, 0666); + if (fd < 0) + { + /* We must do lo_close before setting the errorMessage */ + int save_errno = errno; + + (void) lo_close(conn, lobj); + /* deliberately overwrite any error from lo_close */ + pqClearConnErrorState(conn); + libpq_append_conn_error(conn, "could not open file \"%s\": %s", + filename, + strerror_r(save_errno, sebuf, sizeof(sebuf))); + return -1; + } + + /* + * read in from the large object and write to the file + */ + while ((nbytes = lo_read(conn, lobj, buf, LO_BUFSIZE)) > 0) + { + tmp = write(fd, buf, nbytes); + if (tmp != nbytes) + { + /* We must do lo_close before setting the errorMessage */ + int save_errno = errno; + + (void) lo_close(conn, lobj); + (void) close(fd); + /* deliberately overwrite any error from lo_close */ + pqClearConnErrorState(conn); + libpq_append_conn_error(conn, "could not write to file \"%s\": %s", + filename, + strerror_r(save_errno, sebuf, sizeof(sebuf))); + return -1; + } + } + + /* + * If lo_read() failed, we are now in an aborted transaction so there's no + * need for lo_close(); furthermore, if we tried it we'd overwrite the + * useful error result with a useless one. So skip lo_close() if we got a + * failure result. + */ + if (nbytes < 0 || + lo_close(conn, lobj) != 0) + { + /* assume lo_read() or lo_close() left a suitable error message */ + result = -1; + } + + /* if we already failed, don't overwrite that msg with a close error */ + if (close(fd) != 0 && result >= 0) + { + libpq_append_conn_error(conn, "could not write to file \"%s\": %s", + filename, strerror_r(errno, sebuf, sizeof(sebuf))); + result = -1; + } + + return result; +} + + +/* + * lo_initialize + * + * Initialize for a new large-object operation on an existing connection. + * Return 0 if OK, -1 on failure. + * + * If we haven't previously done so, we collect the function OIDs from + * pg_proc for all functions that are required for large object operations. + */ +static int +lo_initialize(PGconn *conn) +{ + PGresult *res; + PGlobjfuncs *lobjfuncs; + int n; + const char *query; + const char *fname; + Oid foid; + + /* Nothing we can do with no connection */ + if (conn == NULL) + return -1; + + /* Since this is the beginning of a query cycle, reset the error state */ + pqClearConnErrorState(conn); + + /* Nothing else to do if we already collected info */ + if (conn->lobjfuncs != NULL) + return 0; + + /* + * Allocate the structure to hold the function OIDs. We don't store it + * into the PGconn until it's successfully filled. + */ + lobjfuncs = (PGlobjfuncs *) malloc(sizeof(PGlobjfuncs)); + if (lobjfuncs == NULL) + { + libpq_append_conn_error(conn, "out of memory"); + return -1; + } + MemSet((char *) lobjfuncs, 0, sizeof(PGlobjfuncs)); + + /* + * Execute the query to get all the functions at once. (Not all of them + * may exist in older server versions.) + */ + query = "select proname, oid from pg_catalog.pg_proc " + "where proname in (" + "'lo_open', " + "'lo_close', " + "'lo_creat', " + "'lo_create', " + "'lo_unlink', " + "'lo_lseek', " + "'lo_lseek64', " + "'lo_tell', " + "'lo_tell64', " + "'lo_truncate', " + "'lo_truncate64', " + "'loread', " + "'lowrite') " + "and pronamespace = (select oid from pg_catalog.pg_namespace " + "where nspname = 'pg_catalog')"; + + res = PQexec(conn, query); + if (res == NULL) + { + free(lobjfuncs); + return -1; + } + + if (res->resultStatus != PGRES_TUPLES_OK) + { + free(lobjfuncs); + PQclear(res); + libpq_append_conn_error(conn, "query to initialize large object functions did not return data"); + return -1; + } + + /* + * Examine the result and put the OID's into the struct + */ + for (n = 0; n < PQntuples(res); n++) + { + fname = PQgetvalue(res, n, 0); + foid = (Oid) atoi(PQgetvalue(res, n, 1)); + if (strcmp(fname, "lo_open") == 0) + lobjfuncs->fn_lo_open = foid; + else if (strcmp(fname, "lo_close") == 0) + lobjfuncs->fn_lo_close = foid; + else if (strcmp(fname, "lo_creat") == 0) + lobjfuncs->fn_lo_creat = foid; + else if (strcmp(fname, "lo_create") == 0) + lobjfuncs->fn_lo_create = foid; + else if (strcmp(fname, "lo_unlink") == 0) + lobjfuncs->fn_lo_unlink = foid; + else if (strcmp(fname, "lo_lseek") == 0) + lobjfuncs->fn_lo_lseek = foid; + else if (strcmp(fname, "lo_lseek64") == 0) + lobjfuncs->fn_lo_lseek64 = foid; + else if (strcmp(fname, "lo_tell") == 0) + lobjfuncs->fn_lo_tell = foid; + else if (strcmp(fname, "lo_tell64") == 0) + lobjfuncs->fn_lo_tell64 = foid; + else if (strcmp(fname, "lo_truncate") == 0) + lobjfuncs->fn_lo_truncate = foid; + else if (strcmp(fname, "lo_truncate64") == 0) + lobjfuncs->fn_lo_truncate64 = foid; + else if (strcmp(fname, "loread") == 0) + lobjfuncs->fn_lo_read = foid; + else if (strcmp(fname, "lowrite") == 0) + lobjfuncs->fn_lo_write = foid; + } + + PQclear(res); + + /* + * Finally check that we got all required large object interface functions + * (ones that have been added later than the stone age are instead checked + * only if used) + */ + if (lobjfuncs->fn_lo_open == 0) + { + libpq_append_conn_error(conn, "cannot determine OID of function %s", + "lo_open"); + free(lobjfuncs); + return -1; + } + if (lobjfuncs->fn_lo_close == 0) + { + libpq_append_conn_error(conn, "cannot determine OID of function %s", + "lo_close"); + free(lobjfuncs); + return -1; + } + if (lobjfuncs->fn_lo_creat == 0) + { + libpq_append_conn_error(conn, "cannot determine OID of function %s", + "lo_creat"); + free(lobjfuncs); + return -1; + } + if (lobjfuncs->fn_lo_unlink == 0) + { + libpq_append_conn_error(conn, "cannot determine OID of function %s", + "lo_unlink"); + free(lobjfuncs); + return -1; + } + if (lobjfuncs->fn_lo_lseek == 0) + { + libpq_append_conn_error(conn, "cannot determine OID of function %s", + "lo_lseek"); + free(lobjfuncs); + return -1; + } + if (lobjfuncs->fn_lo_tell == 0) + { + libpq_append_conn_error(conn, "cannot determine OID of function %s", + "lo_tell"); + free(lobjfuncs); + return -1; + } + if (lobjfuncs->fn_lo_read == 0) + { + libpq_append_conn_error(conn, "cannot determine OID of function %s", + "loread"); + free(lobjfuncs); + return -1; + } + if (lobjfuncs->fn_lo_write == 0) + { + libpq_append_conn_error(conn, "cannot determine OID of function %s", + "lowrite"); + free(lobjfuncs); + return -1; + } + + /* + * Put the structure into the connection control + */ + conn->lobjfuncs = lobjfuncs; + return 0; +} + +/* + * lo_hton64 + * converts a 64-bit integer from host byte order to network byte order + */ +static pg_int64 +lo_hton64(pg_int64 host64) +{ + union + { + pg_int64 i64; + uint32 i32[2]; + } swap; + uint32 t; + + /* High order half first, since we're doing MSB-first */ + t = (uint32) (host64 >> 32); + swap.i32[0] = pg_hton32(t); + + /* Now the low order half */ + t = (uint32) host64; + swap.i32[1] = pg_hton32(t); + + return swap.i64; +} + +/* + * lo_ntoh64 + * converts a 64-bit integer from network byte order to host byte order + */ +static pg_int64 +lo_ntoh64(pg_int64 net64) +{ + union + { + pg_int64 i64; + uint32 i32[2]; + } swap; + pg_int64 result; + + swap.i64 = net64; + + result = (uint32) pg_ntoh32(swap.i32[0]); + result <<= 32; + result |= (uint32) pg_ntoh32(swap.i32[1]); + + return result; +} diff --git a/src/interfaces/libpq/fe-misc.c b/src/interfaces/libpq/fe-misc.c new file mode 100644 index 0000000..660cdec --- /dev/null +++ b/src/interfaces/libpq/fe-misc.c @@ -0,0 +1,1333 @@ +/*------------------------------------------------------------------------- + * + * FILE + * fe-misc.c + * + * DESCRIPTION + * miscellaneous useful functions + * + * The communication routines here are analogous to the ones in + * backend/libpq/pqcomm.c and backend/libpq/pqformat.c, but operate + * in the considerably different environment of the frontend libpq. + * In particular, we work with a bare nonblock-mode socket, rather than + * a stdio stream, so that we can avoid unwanted blocking of the application. + * + * XXX: MOVE DEBUG PRINTOUT TO HIGHER LEVEL. As is, block and restart + * will cause repeat printouts. + * + * We must speak the same transmitted data representations as the backend + * routines. + * + * + * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/interfaces/libpq/fe-misc.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres_fe.h" + +#include <signal.h> +#include <time.h> + +#ifdef WIN32 +#include "win32.h" +#else +#include <unistd.h> +#include <sys/select.h> +#include <sys/time.h> +#endif + +#ifdef HAVE_POLL_H +#include <poll.h> +#endif + +#include "libpq-fe.h" +#include "libpq-int.h" +#include "mb/pg_wchar.h" +#include "pg_config_paths.h" +#include "port/pg_bswap.h" + +static int pqPutMsgBytes(const void *buf, size_t len, PGconn *conn); +static int pqSendSome(PGconn *conn, int len); +static int pqSocketCheck(PGconn *conn, int forRead, int forWrite, + time_t end_time); +static int pqSocketPoll(int sock, int forRead, int forWrite, time_t end_time); + +/* + * PQlibVersion: return the libpq version number + */ +int +PQlibVersion(void) +{ + return PG_VERSION_NUM; +} + + +/* + * pqGetc: get 1 character from the connection + * + * All these routines return 0 on success, EOF on error. + * Note that for the Get routines, EOF only means there is not enough + * data in the buffer, not that there is necessarily a hard error. + */ +int +pqGetc(char *result, PGconn *conn) +{ + if (conn->inCursor >= conn->inEnd) + return EOF; + + *result = conn->inBuffer[conn->inCursor++]; + + return 0; +} + + +/* + * pqPutc: write 1 char to the current message + */ +int +pqPutc(char c, PGconn *conn) +{ + if (pqPutMsgBytes(&c, 1, conn)) + return EOF; + + return 0; +} + + +/* + * pqGets[_append]: + * get a null-terminated string from the connection, + * and store it in an expansible PQExpBuffer. + * If we run out of memory, all of the string is still read, + * but the excess characters are silently discarded. + */ +static int +pqGets_internal(PQExpBuffer buf, PGconn *conn, bool resetbuffer) +{ + /* Copy conn data to locals for faster search loop */ + char *inBuffer = conn->inBuffer; + int inCursor = conn->inCursor; + int inEnd = conn->inEnd; + int slen; + + while (inCursor < inEnd && inBuffer[inCursor]) + inCursor++; + + if (inCursor >= inEnd) + return EOF; + + slen = inCursor - conn->inCursor; + + if (resetbuffer) + resetPQExpBuffer(buf); + + appendBinaryPQExpBuffer(buf, inBuffer + conn->inCursor, slen); + + conn->inCursor = ++inCursor; + + return 0; +} + +int +pqGets(PQExpBuffer buf, PGconn *conn) +{ + return pqGets_internal(buf, conn, true); +} + +int +pqGets_append(PQExpBuffer buf, PGconn *conn) +{ + return pqGets_internal(buf, conn, false); +} + + +/* + * pqPuts: write a null-terminated string to the current message + */ +int +pqPuts(const char *s, PGconn *conn) +{ + if (pqPutMsgBytes(s, strlen(s) + 1, conn)) + return EOF; + + return 0; +} + +/* + * pqGetnchar: + * get a string of exactly len bytes in buffer s, no null termination + */ +int +pqGetnchar(char *s, size_t len, PGconn *conn) +{ + if (len > (size_t) (conn->inEnd - conn->inCursor)) + return EOF; + + memcpy(s, conn->inBuffer + conn->inCursor, len); + /* no terminating null */ + + conn->inCursor += len; + + return 0; +} + +/* + * pqSkipnchar: + * skip over len bytes in input buffer. + * + * Note: this is primarily useful for its debug output, which should + * be exactly the same as for pqGetnchar. We assume the data in question + * will actually be used, but just isn't getting copied anywhere as yet. + */ +int +pqSkipnchar(size_t len, PGconn *conn) +{ + if (len > (size_t) (conn->inEnd - conn->inCursor)) + return EOF; + + conn->inCursor += len; + + return 0; +} + +/* + * pqPutnchar: + * write exactly len bytes to the current message + */ +int +pqPutnchar(const char *s, size_t len, PGconn *conn) +{ + if (pqPutMsgBytes(s, len, conn)) + return EOF; + + return 0; +} + +/* + * pqGetInt + * read a 2 or 4 byte integer and convert from network byte order + * to local byte order + */ +int +pqGetInt(int *result, size_t bytes, PGconn *conn) +{ + uint16 tmp2; + uint32 tmp4; + + switch (bytes) + { + case 2: + if (conn->inCursor + 2 > conn->inEnd) + return EOF; + memcpy(&tmp2, conn->inBuffer + conn->inCursor, 2); + conn->inCursor += 2; + *result = (int) pg_ntoh16(tmp2); + break; + case 4: + if (conn->inCursor + 4 > conn->inEnd) + return EOF; + memcpy(&tmp4, conn->inBuffer + conn->inCursor, 4); + conn->inCursor += 4; + *result = (int) pg_ntoh32(tmp4); + break; + default: + pqInternalNotice(&conn->noticeHooks, + "integer of size %lu not supported by pqGetInt", + (unsigned long) bytes); + return EOF; + } + + return 0; +} + +/* + * pqPutInt + * write an integer of 2 or 4 bytes, converting from host byte order + * to network byte order. + */ +int +pqPutInt(int value, size_t bytes, PGconn *conn) +{ + uint16 tmp2; + uint32 tmp4; + + switch (bytes) + { + case 2: + tmp2 = pg_hton16((uint16) value); + if (pqPutMsgBytes((const char *) &tmp2, 2, conn)) + return EOF; + break; + case 4: + tmp4 = pg_hton32((uint32) value); + if (pqPutMsgBytes((const char *) &tmp4, 4, conn)) + return EOF; + break; + default: + pqInternalNotice(&conn->noticeHooks, + "integer of size %lu not supported by pqPutInt", + (unsigned long) bytes); + return EOF; + } + + return 0; +} + +/* + * Make sure conn's output buffer can hold bytes_needed bytes (caller must + * include already-stored data into the value!) + * + * Returns 0 on success, EOF if failed to enlarge buffer + */ +int +pqCheckOutBufferSpace(size_t bytes_needed, PGconn *conn) +{ + int newsize = conn->outBufSize; + char *newbuf; + + /* Quick exit if we have enough space */ + if (bytes_needed <= (size_t) newsize) + return 0; + + /* + * If we need to enlarge the buffer, we first try to double it in size; if + * that doesn't work, enlarge in multiples of 8K. This avoids thrashing + * the malloc pool by repeated small enlargements. + * + * Note: tests for newsize > 0 are to catch integer overflow. + */ + do + { + newsize *= 2; + } while (newsize > 0 && bytes_needed > (size_t) newsize); + + if (newsize > 0 && bytes_needed <= (size_t) newsize) + { + newbuf = realloc(conn->outBuffer, newsize); + if (newbuf) + { + /* realloc succeeded */ + conn->outBuffer = newbuf; + conn->outBufSize = newsize; + return 0; + } + } + + newsize = conn->outBufSize; + do + { + newsize += 8192; + } while (newsize > 0 && bytes_needed > (size_t) newsize); + + if (newsize > 0 && bytes_needed <= (size_t) newsize) + { + newbuf = realloc(conn->outBuffer, newsize); + if (newbuf) + { + /* realloc succeeded */ + conn->outBuffer = newbuf; + conn->outBufSize = newsize; + return 0; + } + } + + /* realloc failed. Probably out of memory */ + appendPQExpBufferStr(&conn->errorMessage, + "cannot allocate memory for output buffer\n"); + return EOF; +} + +/* + * Make sure conn's input buffer can hold bytes_needed bytes (caller must + * include already-stored data into the value!) + * + * Returns 0 on success, EOF if failed to enlarge buffer + */ +int +pqCheckInBufferSpace(size_t bytes_needed, PGconn *conn) +{ + int newsize = conn->inBufSize; + char *newbuf; + + /* Quick exit if we have enough space */ + if (bytes_needed <= (size_t) newsize) + return 0; + + /* + * Before concluding that we need to enlarge the buffer, left-justify + * whatever is in it and recheck. The caller's value of bytes_needed + * includes any data to the left of inStart, but we can delete that in + * preference to enlarging the buffer. It's slightly ugly to have this + * function do this, but it's better than making callers worry about it. + */ + bytes_needed -= conn->inStart; + + if (conn->inStart < conn->inEnd) + { + if (conn->inStart > 0) + { + memmove(conn->inBuffer, conn->inBuffer + conn->inStart, + conn->inEnd - conn->inStart); + conn->inEnd -= conn->inStart; + conn->inCursor -= conn->inStart; + conn->inStart = 0; + } + } + else + { + /* buffer is logically empty, reset it */ + conn->inStart = conn->inCursor = conn->inEnd = 0; + } + + /* Recheck whether we have enough space */ + if (bytes_needed <= (size_t) newsize) + return 0; + + /* + * If we need to enlarge the buffer, we first try to double it in size; if + * that doesn't work, enlarge in multiples of 8K. This avoids thrashing + * the malloc pool by repeated small enlargements. + * + * Note: tests for newsize > 0 are to catch integer overflow. + */ + do + { + newsize *= 2; + } while (newsize > 0 && bytes_needed > (size_t) newsize); + + if (newsize > 0 && bytes_needed <= (size_t) newsize) + { + newbuf = realloc(conn->inBuffer, newsize); + if (newbuf) + { + /* realloc succeeded */ + conn->inBuffer = newbuf; + conn->inBufSize = newsize; + return 0; + } + } + + newsize = conn->inBufSize; + do + { + newsize += 8192; + } while (newsize > 0 && bytes_needed > (size_t) newsize); + + if (newsize > 0 && bytes_needed <= (size_t) newsize) + { + newbuf = realloc(conn->inBuffer, newsize); + if (newbuf) + { + /* realloc succeeded */ + conn->inBuffer = newbuf; + conn->inBufSize = newsize; + return 0; + } + } + + /* realloc failed. Probably out of memory */ + appendPQExpBufferStr(&conn->errorMessage, + "cannot allocate memory for input buffer\n"); + return EOF; +} + +/* + * pqPutMsgStart: begin construction of a message to the server + * + * msg_type is the message type byte, or 0 for a message without type byte + * (only startup messages have no type byte) + * + * Returns 0 on success, EOF on error + * + * The idea here is that we construct the message in conn->outBuffer, + * beginning just past any data already in outBuffer (ie, at + * outBuffer+outCount). We enlarge the buffer as needed to hold the message. + * When the message is complete, we fill in the length word (if needed) and + * then advance outCount past the message, making it eligible to send. + * + * The state variable conn->outMsgStart points to the incomplete message's + * length word: it is either outCount or outCount+1 depending on whether + * there is a type byte. The state variable conn->outMsgEnd is the end of + * the data collected so far. + */ +int +pqPutMsgStart(char msg_type, PGconn *conn) +{ + int lenPos; + int endPos; + + /* allow room for message type byte */ + if (msg_type) + endPos = conn->outCount + 1; + else + endPos = conn->outCount; + + /* do we want a length word? */ + lenPos = endPos; + /* allow room for message length */ + endPos += 4; + + /* make sure there is room for message header */ + if (pqCheckOutBufferSpace(endPos, conn)) + return EOF; + /* okay, save the message type byte if any */ + if (msg_type) + conn->outBuffer[conn->outCount] = msg_type; + /* set up the message pointers */ + conn->outMsgStart = lenPos; + conn->outMsgEnd = endPos; + /* length word, if needed, will be filled in by pqPutMsgEnd */ + + return 0; +} + +/* + * pqPutMsgBytes: add bytes to a partially-constructed message + * + * Returns 0 on success, EOF on error + */ +static int +pqPutMsgBytes(const void *buf, size_t len, PGconn *conn) +{ + /* make sure there is room for it */ + if (pqCheckOutBufferSpace(conn->outMsgEnd + len, conn)) + return EOF; + /* okay, save the data */ + memcpy(conn->outBuffer + conn->outMsgEnd, buf, len); + conn->outMsgEnd += len; + /* no Pfdebug call here, caller should do it */ + return 0; +} + +/* + * pqPutMsgEnd: finish constructing a message and possibly send it + * + * Returns 0 on success, EOF on error + * + * We don't actually send anything here unless we've accumulated at least + * 8K worth of data (the typical size of a pipe buffer on Unix systems). + * This avoids sending small partial packets. The caller must use pqFlush + * when it's important to flush all the data out to the server. + */ +int +pqPutMsgEnd(PGconn *conn) +{ + /* Fill in length word if needed */ + if (conn->outMsgStart >= 0) + { + uint32 msgLen = conn->outMsgEnd - conn->outMsgStart; + + msgLen = pg_hton32(msgLen); + memcpy(conn->outBuffer + conn->outMsgStart, &msgLen, 4); + } + + /* trace client-to-server message */ + if (conn->Pfdebug) + { + if (conn->outCount < conn->outMsgStart) + pqTraceOutputMessage(conn, conn->outBuffer + conn->outCount, true); + else + pqTraceOutputNoTypeByteMessage(conn, + conn->outBuffer + conn->outMsgStart); + } + + /* Make message eligible to send */ + conn->outCount = conn->outMsgEnd; + + if (conn->outCount >= 8192) + { + int toSend = conn->outCount - (conn->outCount % 8192); + + if (pqSendSome(conn, toSend) < 0) + return EOF; + /* in nonblock mode, don't complain if unable to send it all */ + } + + return 0; +} + +/* ---------- + * pqReadData: read more data, if any is available + * Possible return values: + * 1: successfully loaded at least one more byte + * 0: no data is presently available, but no error detected + * -1: error detected (including EOF = connection closure); + * conn->errorMessage set + * NOTE: callers must not assume that pointers or indexes into conn->inBuffer + * remain valid across this call! + * ---------- + */ +int +pqReadData(PGconn *conn) +{ + int someread = 0; + int nread; + + if (conn->sock == PGINVALID_SOCKET) + { + libpq_append_conn_error(conn, "connection not open"); + return -1; + } + + /* Left-justify any data in the buffer to make room */ + if (conn->inStart < conn->inEnd) + { + if (conn->inStart > 0) + { + memmove(conn->inBuffer, conn->inBuffer + conn->inStart, + conn->inEnd - conn->inStart); + conn->inEnd -= conn->inStart; + conn->inCursor -= conn->inStart; + conn->inStart = 0; + } + } + else + { + /* buffer is logically empty, reset it */ + conn->inStart = conn->inCursor = conn->inEnd = 0; + } + + /* + * If the buffer is fairly full, enlarge it. We need to be able to enlarge + * the buffer in case a single message exceeds the initial buffer size. We + * enlarge before filling the buffer entirely so as to avoid asking the + * kernel for a partial packet. The magic constant here should be large + * enough for a TCP packet or Unix pipe bufferload. 8K is the usual pipe + * buffer size, so... + */ + if (conn->inBufSize - conn->inEnd < 8192) + { + if (pqCheckInBufferSpace(conn->inEnd + (size_t) 8192, conn)) + { + /* + * We don't insist that the enlarge worked, but we need some room + */ + if (conn->inBufSize - conn->inEnd < 100) + return -1; /* errorMessage already set */ + } + } + + /* OK, try to read some data */ +retry3: + nread = pqsecure_read(conn, conn->inBuffer + conn->inEnd, + conn->inBufSize - conn->inEnd); + if (nread < 0) + { + switch (SOCK_ERRNO) + { + case EINTR: + goto retry3; + + /* Some systems return EAGAIN/EWOULDBLOCK for no data */ +#ifdef EAGAIN + case EAGAIN: + return someread; +#endif +#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN)) + case EWOULDBLOCK: + return someread; +#endif + + /* We might get ECONNRESET etc here if connection failed */ + case ALL_CONNECTION_FAILURE_ERRNOS: + goto definitelyFailed; + + default: + /* pqsecure_read set the error message for us */ + return -1; + } + } + if (nread > 0) + { + conn->inEnd += nread; + + /* + * Hack to deal with the fact that some kernels will only give us back + * 1 packet per recv() call, even if we asked for more and there is + * more available. If it looks like we are reading a long message, + * loop back to recv() again immediately, until we run out of data or + * buffer space. Without this, the block-and-restart behavior of + * libpq's higher levels leads to O(N^2) performance on long messages. + * + * Since we left-justified the data above, conn->inEnd gives the + * amount of data already read in the current message. We consider + * the message "long" once we have acquired 32k ... + */ + if (conn->inEnd > 32768 && + (conn->inBufSize - conn->inEnd) >= 8192) + { + someread = 1; + goto retry3; + } + return 1; + } + + if (someread) + return 1; /* got a zero read after successful tries */ + + /* + * A return value of 0 could mean just that no data is now available, or + * it could mean EOF --- that is, the server has closed the connection. + * Since we have the socket in nonblock mode, the only way to tell the + * difference is to see if select() is saying that the file is ready. + * Grumble. Fortunately, we don't expect this path to be taken much, + * since in normal practice we should not be trying to read data unless + * the file selected for reading already. + * + * In SSL mode it's even worse: SSL_read() could say WANT_READ and then + * data could arrive before we make the pqReadReady() test, but the second + * SSL_read() could still say WANT_READ because the data received was not + * a complete SSL record. So we must play dumb and assume there is more + * data, relying on the SSL layer to detect true EOF. + */ + +#ifdef USE_SSL + if (conn->ssl_in_use) + return 0; +#endif + + switch (pqReadReady(conn)) + { + case 0: + /* definitely no data available */ + return 0; + case 1: + /* ready for read */ + break; + default: + /* we override pqReadReady's message with something more useful */ + goto definitelyEOF; + } + + /* + * Still not sure that it's EOF, because some data could have just + * arrived. + */ +retry4: + nread = pqsecure_read(conn, conn->inBuffer + conn->inEnd, + conn->inBufSize - conn->inEnd); + if (nread < 0) + { + switch (SOCK_ERRNO) + { + case EINTR: + goto retry4; + + /* Some systems return EAGAIN/EWOULDBLOCK for no data */ +#ifdef EAGAIN + case EAGAIN: + return 0; +#endif +#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN)) + case EWOULDBLOCK: + return 0; +#endif + + /* We might get ECONNRESET etc here if connection failed */ + case ALL_CONNECTION_FAILURE_ERRNOS: + goto definitelyFailed; + + default: + /* pqsecure_read set the error message for us */ + return -1; + } + } + if (nread > 0) + { + conn->inEnd += nread; + return 1; + } + + /* + * OK, we are getting a zero read even though select() says ready. This + * means the connection has been closed. Cope. + */ +definitelyEOF: + libpq_append_conn_error(conn, "server closed the connection unexpectedly\n" + "\tThis probably means the server terminated abnormally\n" + "\tbefore or while processing the request."); + + /* Come here if lower-level code already set a suitable errorMessage */ +definitelyFailed: + /* Do *not* drop any already-read data; caller still wants it */ + pqDropConnection(conn, false); + conn->status = CONNECTION_BAD; /* No more connection to backend */ + return -1; +} + +/* + * pqSendSome: send data waiting in the output buffer. + * + * len is how much to try to send (typically equal to outCount, but may + * be less). + * + * Return 0 on success, -1 on failure and 1 when not all data could be sent + * because the socket would block and the connection is non-blocking. + * + * Note that this is also responsible for consuming data from the socket + * (putting it in conn->inBuffer) in any situation where we can't send + * all the specified data immediately. + * + * If a socket-level write failure occurs, conn->write_failed is set and the + * error message is saved in conn->write_err_msg, but we clear the output + * buffer and return zero anyway; this is because callers should soldier on + * until we have read what we can from the server and checked for an error + * message. write_err_msg should be reported only when we are unable to + * obtain a server error first. Much of that behavior is implemented at + * lower levels, but this function deals with some edge cases. + */ +static int +pqSendSome(PGconn *conn, int len) +{ + char *ptr = conn->outBuffer; + int remaining = conn->outCount; + int result = 0; + + /* + * If we already had a write failure, we will never again try to send data + * on that connection. Even if the kernel would let us, we've probably + * lost message boundary sync with the server. conn->write_failed + * therefore persists until the connection is reset, and we just discard + * all data presented to be written. However, as long as we still have a + * valid socket, we should continue to absorb data from the backend, so + * that we can collect any final error messages. + */ + if (conn->write_failed) + { + /* conn->write_err_msg should be set up already */ + conn->outCount = 0; + /* Absorb input data if any, and detect socket closure */ + if (conn->sock != PGINVALID_SOCKET) + { + if (pqReadData(conn) < 0) + return -1; + } + return 0; + } + + if (conn->sock == PGINVALID_SOCKET) + { + conn->write_failed = true; + /* Store error message in conn->write_err_msg, if possible */ + /* (strdup failure is OK, we'll cope later) */ + conn->write_err_msg = strdup(libpq_gettext("connection not open\n")); + /* Discard queued data; no chance it'll ever be sent */ + conn->outCount = 0; + return 0; + } + + /* while there's still data to send */ + while (len > 0) + { + int sent; + +#ifndef WIN32 + sent = pqsecure_write(conn, ptr, len); +#else + + /* + * Windows can fail on large sends, per KB article Q201213. The + * failure-point appears to be different in different versions of + * Windows, but 64k should always be safe. + */ + sent = pqsecure_write(conn, ptr, Min(len, 65536)); +#endif + + if (sent < 0) + { + /* Anything except EAGAIN/EWOULDBLOCK/EINTR is trouble */ + switch (SOCK_ERRNO) + { +#ifdef EAGAIN + case EAGAIN: + break; +#endif +#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN)) + case EWOULDBLOCK: + break; +#endif + case EINTR: + continue; + + default: + /* Discard queued data; no chance it'll ever be sent */ + conn->outCount = 0; + + /* Absorb input data if any, and detect socket closure */ + if (conn->sock != PGINVALID_SOCKET) + { + if (pqReadData(conn) < 0) + return -1; + } + + /* + * Lower-level code should already have filled + * conn->write_err_msg (and set conn->write_failed) or + * conn->errorMessage. In the former case, we pretend + * there's no problem; the write_failed condition will be + * dealt with later. Otherwise, report the error now. + */ + if (conn->write_failed) + return 0; + else + return -1; + } + } + else + { + ptr += sent; + len -= sent; + remaining -= sent; + } + + if (len > 0) + { + /* + * We didn't send it all, wait till we can send more. + * + * There are scenarios in which we can't send data because the + * communications channel is full, but we cannot expect the server + * to clear the channel eventually because it's blocked trying to + * send data to us. (This can happen when we are sending a large + * amount of COPY data, and the server has generated lots of + * NOTICE responses.) To avoid a deadlock situation, we must be + * prepared to accept and buffer incoming data before we try + * again. Furthermore, it is possible that such incoming data + * might not arrive until after we've gone to sleep. Therefore, + * we wait for either read ready or write ready. + * + * In non-blocking mode, we don't wait here directly, but return 1 + * to indicate that data is still pending. The caller should wait + * for both read and write ready conditions, and call + * PQconsumeInput() on read ready, but just in case it doesn't, we + * call pqReadData() ourselves before returning. That's not + * enough if the data has not arrived yet, but it's the best we + * can do, and works pretty well in practice. (The documentation + * used to say that you only need to wait for write-ready, so + * there are still plenty of applications like that out there.) + * + * Note that errors here don't result in write_failed becoming + * set. + */ + if (pqReadData(conn) < 0) + { + result = -1; /* error message already set up */ + break; + } + + if (pqIsnonblocking(conn)) + { + result = 1; + break; + } + + if (pqWait(true, true, conn)) + { + result = -1; + break; + } + } + } + + /* shift the remaining contents of the buffer */ + if (remaining > 0) + memmove(conn->outBuffer, ptr, remaining); + conn->outCount = remaining; + + return result; +} + + +/* + * pqFlush: send any data waiting in the output buffer + * + * Return 0 on success, -1 on failure and 1 when not all data could be sent + * because the socket would block and the connection is non-blocking. + * (See pqSendSome comments about how failure should be handled.) + */ +int +pqFlush(PGconn *conn) +{ + if (conn->outCount > 0) + { + if (conn->Pfdebug) + fflush(conn->Pfdebug); + + return pqSendSome(conn, conn->outCount); + } + + return 0; +} + + +/* + * pqWait: wait until we can read or write the connection socket + * + * JAB: If SSL enabled and used and forRead, buffered bytes short-circuit the + * call to select(). + * + * We also stop waiting and return if the kernel flags an exception condition + * on the socket. The actual error condition will be detected and reported + * when the caller tries to read or write the socket. + */ +int +pqWait(int forRead, int forWrite, PGconn *conn) +{ + return pqWaitTimed(forRead, forWrite, conn, (time_t) -1); +} + +/* + * pqWaitTimed: wait, but not past finish_time. + * + * finish_time = ((time_t) -1) disables the wait limit. + * + * Returns -1 on failure, 0 if the socket is readable/writable, 1 if it timed out. + */ +int +pqWaitTimed(int forRead, int forWrite, PGconn *conn, time_t finish_time) +{ + int result; + + result = pqSocketCheck(conn, forRead, forWrite, finish_time); + + if (result < 0) + return -1; /* errorMessage is already set */ + + if (result == 0) + { + libpq_append_conn_error(conn, "timeout expired"); + return 1; + } + + return 0; +} + +/* + * pqReadReady: is select() saying the file is ready to read? + * Returns -1 on failure, 0 if not ready, 1 if ready. + */ +int +pqReadReady(PGconn *conn) +{ + return pqSocketCheck(conn, 1, 0, (time_t) 0); +} + +/* + * pqWriteReady: is select() saying the file is ready to write? + * Returns -1 on failure, 0 if not ready, 1 if ready. + */ +int +pqWriteReady(PGconn *conn) +{ + return pqSocketCheck(conn, 0, 1, (time_t) 0); +} + +/* + * Checks a socket, using poll or select, for data to be read, written, + * or both. Returns >0 if one or more conditions are met, 0 if it timed + * out, -1 if an error occurred. + * + * If SSL is in use, the SSL buffer is checked prior to checking the socket + * for read data directly. + */ +static int +pqSocketCheck(PGconn *conn, int forRead, int forWrite, time_t end_time) +{ + int result; + + if (!conn) + return -1; + if (conn->sock == PGINVALID_SOCKET) + { + libpq_append_conn_error(conn, "invalid socket"); + return -1; + } + +#ifdef USE_SSL + /* Check for SSL library buffering read bytes */ + if (forRead && conn->ssl_in_use && pgtls_read_pending(conn)) + { + /* short-circuit the select */ + return 1; + } +#endif + + /* We will retry as long as we get EINTR */ + do + result = pqSocketPoll(conn->sock, forRead, forWrite, end_time); + while (result < 0 && SOCK_ERRNO == EINTR); + + if (result < 0) + { + char sebuf[PG_STRERROR_R_BUFLEN]; + + libpq_append_conn_error(conn, "%s() failed: %s", "select", + SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf))); + } + + return result; +} + + +/* + * Check a file descriptor for read and/or write data, possibly waiting. + * If neither forRead nor forWrite are set, immediately return a timeout + * condition (without waiting). Return >0 if condition is met, 0 + * if a timeout occurred, -1 if an error or interrupt occurred. + * + * Timeout is infinite if end_time is -1. Timeout is immediate (no blocking) + * if end_time is 0 (or indeed, any time before now). + */ +static int +pqSocketPoll(int sock, int forRead, int forWrite, time_t end_time) +{ + /* We use poll(2) if available, otherwise select(2) */ +#ifdef HAVE_POLL + struct pollfd input_fd; + int timeout_ms; + + if (!forRead && !forWrite) + return 0; + + input_fd.fd = sock; + input_fd.events = POLLERR; + input_fd.revents = 0; + + if (forRead) + input_fd.events |= POLLIN; + if (forWrite) + input_fd.events |= POLLOUT; + + /* Compute appropriate timeout interval */ + if (end_time == ((time_t) -1)) + timeout_ms = -1; + else + { + time_t now = time(NULL); + + if (end_time > now) + timeout_ms = (end_time - now) * 1000; + else + timeout_ms = 0; + } + + return poll(&input_fd, 1, timeout_ms); +#else /* !HAVE_POLL */ + + fd_set input_mask; + fd_set output_mask; + fd_set except_mask; + struct timeval timeout; + struct timeval *ptr_timeout; + + if (!forRead && !forWrite) + return 0; + + FD_ZERO(&input_mask); + FD_ZERO(&output_mask); + FD_ZERO(&except_mask); + if (forRead) + FD_SET(sock, &input_mask); + + if (forWrite) + FD_SET(sock, &output_mask); + FD_SET(sock, &except_mask); + + /* Compute appropriate timeout interval */ + if (end_time == ((time_t) -1)) + ptr_timeout = NULL; + else + { + time_t now = time(NULL); + + if (end_time > now) + timeout.tv_sec = end_time - now; + else + timeout.tv_sec = 0; + timeout.tv_usec = 0; + ptr_timeout = &timeout; + } + + return select(sock + 1, &input_mask, &output_mask, + &except_mask, ptr_timeout); +#endif /* HAVE_POLL */ +} + + +/* + * A couple of "miscellaneous" multibyte related functions. They used + * to be in fe-print.c but that file is doomed. + */ + +/* + * Returns the byte length of the character beginning at s, using the + * specified encoding. + * + * Caution: when dealing with text that is not certainly valid in the + * specified encoding, the result may exceed the actual remaining + * string length. Callers that are not prepared to deal with that + * should use PQmblenBounded() instead. + */ +int +PQmblen(const char *s, int encoding) +{ + return pg_encoding_mblen(encoding, s); +} + +/* + * Returns the byte length of the character beginning at s, using the + * specified encoding; but not more than the distance to end of string. + */ +int +PQmblenBounded(const char *s, int encoding) +{ + return strnlen(s, pg_encoding_mblen(encoding, s)); +} + +/* + * Returns the display length of the character beginning at s, using the + * specified encoding. + */ +int +PQdsplen(const char *s, int encoding) +{ + return pg_encoding_dsplen(encoding, s); +} + +/* + * Get encoding id from environment variable PGCLIENTENCODING. + */ +int +PQenv2encoding(void) +{ + char *str; + int encoding = PG_SQL_ASCII; + + str = getenv("PGCLIENTENCODING"); + if (str && *str != '\0') + { + encoding = pg_char_to_encoding(str); + if (encoding < 0) + encoding = PG_SQL_ASCII; + } + return encoding; +} + + +#ifdef ENABLE_NLS + +static void +libpq_binddomain(void) +{ + /* + * If multiple threads come through here at about the same time, it's okay + * for more than one of them to call bindtextdomain(). But it's not okay + * for any of them to return to caller before bindtextdomain() is + * complete, so don't set the flag till that's done. Use "volatile" just + * to be sure the compiler doesn't try to get cute. + */ + static volatile bool already_bound = false; + + if (!already_bound) + { + /* bindtextdomain() does not preserve errno */ +#ifdef WIN32 + int save_errno = GetLastError(); +#else + int save_errno = errno; +#endif + const char *ldir; + + /* No relocatable lookup here because the binary could be anywhere */ + ldir = getenv("PGLOCALEDIR"); + if (!ldir) + ldir = LOCALEDIR; + bindtextdomain(PG_TEXTDOMAIN("libpq"), ldir); + already_bound = true; +#ifdef WIN32 + SetLastError(save_errno); +#else + errno = save_errno; +#endif + } +} + +char * +libpq_gettext(const char *msgid) +{ + libpq_binddomain(); + return dgettext(PG_TEXTDOMAIN("libpq"), msgid); +} + +char * +libpq_ngettext(const char *msgid, const char *msgid_plural, unsigned long n) +{ + libpq_binddomain(); + return dngettext(PG_TEXTDOMAIN("libpq"), msgid, msgid_plural, n); +} + +#endif /* ENABLE_NLS */ + + +/* + * Append a formatted string to the given buffer, after translating it. A + * newline is automatically appended; the format should not end with a + * newline. + */ +void +libpq_append_error(PQExpBuffer errorMessage, const char *fmt,...) +{ + int save_errno = errno; + bool done; + va_list args; + + Assert(fmt[strlen(fmt) - 1] != '\n'); + + if (PQExpBufferBroken(errorMessage)) + return; /* already failed */ + + /* Loop in case we have to retry after enlarging the buffer. */ + do + { + errno = save_errno; + va_start(args, fmt); + done = appendPQExpBufferVA(errorMessage, libpq_gettext(fmt), args); + va_end(args); + } while (!done); + + appendPQExpBufferChar(errorMessage, '\n'); +} + +/* + * Append a formatted string to the error message buffer of the given + * connection, after translating it. A newline is automatically appended; the + * format should not end with a newline. + */ +void +libpq_append_conn_error(PGconn *conn, const char *fmt,...) +{ + int save_errno = errno; + bool done; + va_list args; + + Assert(fmt[strlen(fmt) - 1] != '\n'); + + if (PQExpBufferBroken(&conn->errorMessage)) + return; /* already failed */ + + /* Loop in case we have to retry after enlarging the buffer. */ + do + { + errno = save_errno; + va_start(args, fmt); + done = appendPQExpBufferVA(&conn->errorMessage, libpq_gettext(fmt), args); + va_end(args); + } while (!done); + + appendPQExpBufferChar(&conn->errorMessage, '\n'); +} diff --git a/src/interfaces/libpq/fe-print.c b/src/interfaces/libpq/fe-print.c new file mode 100644 index 0000000..40620b4 --- /dev/null +++ b/src/interfaces/libpq/fe-print.c @@ -0,0 +1,773 @@ +/*------------------------------------------------------------------------- + * + * fe-print.c + * functions for pretty-printing query results + * + * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * These functions were formerly part of fe-exec.c, but they + * didn't really belong there. + * + * IDENTIFICATION + * src/interfaces/libpq/fe-print.c + * + *------------------------------------------------------------------------- + */ +#include "postgres_fe.h" + +#include <signal.h> + +#ifdef WIN32 +#include "win32.h" +#else +#include <unistd.h> +#include <sys/ioctl.h> +#endif + +#ifdef HAVE_TERMIOS_H +#include <termios.h> +#else +#ifndef WIN32 +#include <sys/termios.h> +#endif +#endif + +#include "libpq-fe.h" +#include "libpq-int.h" + + +static bool do_field(const PQprintOpt *po, const PGresult *res, + const int i, const int j, const int fs_len, + char **fields, + const int nFields, const char **fieldNames, + unsigned char *fieldNotNum, int *fieldMax, + const int fieldMaxLen, FILE *fout); +static char *do_header(FILE *fout, const PQprintOpt *po, const int nFields, + int *fieldMax, const char **fieldNames, unsigned char *fieldNotNum, + const int fs_len, const PGresult *res); +static void output_row(FILE *fout, const PQprintOpt *po, const int nFields, char **fields, + unsigned char *fieldNotNum, int *fieldMax, char *border, + const int row_index); +static void fill(int length, int max, char filler, FILE *fp); + +/* + * PQprint() + * + * Format results of a query for printing. + * + * PQprintOpt is a typedef (structure) that contains + * various flags and options. consult libpq-fe.h for + * details + * + * This function should probably be removed sometime since psql + * doesn't use it anymore. It is unclear to what extent this is used + * by external clients, however. + */ +void +PQprint(FILE *fout, const PGresult *res, const PQprintOpt *po) +{ + int nFields; + + nFields = PQnfields(res); + + if (nFields > 0) + { /* only print rows with at least 1 field. */ + int i, + j; + int nTups; + int *fieldMax = NULL; /* in case we don't use them */ + unsigned char *fieldNotNum = NULL; + char *border = NULL; + char **fields = NULL; + const char **fieldNames = NULL; + int fieldMaxLen = 0; + int numFieldName; + int fs_len = strlen(po->fieldSep); + int total_line_length = 0; + bool usePipe = false; + char *pagerenv; + +#if defined(ENABLE_THREAD_SAFETY) && !defined(WIN32) + sigset_t osigset; + bool sigpipe_masked = false; + bool sigpipe_pending; +#endif +#if !defined(ENABLE_THREAD_SAFETY) && !defined(WIN32) + pqsigfunc oldsigpipehandler = NULL; +#endif + +#ifdef TIOCGWINSZ + struct winsize screen_size; +#else + struct winsize + { + int ws_row; + int ws_col; + } screen_size; +#endif + + nTups = PQntuples(res); + fieldNames = (const char **) calloc(nFields, sizeof(char *)); + fieldNotNum = (unsigned char *) calloc(nFields, 1); + fieldMax = (int *) calloc(nFields, sizeof(int)); + if (!fieldNames || !fieldNotNum || !fieldMax) + { + fprintf(stderr, libpq_gettext("out of memory\n")); + goto exit; + } + for (numFieldName = 0; + po->fieldName && po->fieldName[numFieldName]; + numFieldName++) + ; + for (j = 0; j < nFields; j++) + { + int len; + const char *s = (j < numFieldName && po->fieldName[j][0]) ? + po->fieldName[j] : PQfname(res, j); + + fieldNames[j] = s; + len = s ? strlen(s) : 0; + fieldMax[j] = len; + len += fs_len; + if (len > fieldMaxLen) + fieldMaxLen = len; + total_line_length += len; + } + + total_line_length += nFields * strlen(po->fieldSep) + 1; + + if (fout == NULL) + fout = stdout; + if (po->pager && fout == stdout && isatty(fileno(stdin)) && + isatty(fileno(stdout))) + { + /* + * If we think there'll be more than one screen of output, try to + * pipe to the pager program. + */ +#ifdef TIOCGWINSZ + if (ioctl(fileno(stdout), TIOCGWINSZ, &screen_size) == -1 || + screen_size.ws_col == 0 || + screen_size.ws_row == 0) + { + screen_size.ws_row = 24; + screen_size.ws_col = 80; + } +#else + screen_size.ws_row = 24; + screen_size.ws_col = 80; +#endif + + /* + * Since this function is no longer used by psql, we don't examine + * PSQL_PAGER. It's possible that the hypothetical external users + * of the function would like that to happen, but in the name of + * backwards compatibility, we'll stick to just examining PAGER. + */ + pagerenv = getenv("PAGER"); + /* if PAGER is unset, empty or all-white-space, don't use pager */ + if (pagerenv != NULL && + strspn(pagerenv, " \t\r\n") != strlen(pagerenv) && + !po->html3 && + ((po->expanded && + nTups * (nFields + 1) >= screen_size.ws_row) || + (!po->expanded && + nTups * (total_line_length / screen_size.ws_col + 1) * + (1 + (po->standard != 0)) >= screen_size.ws_row - + (po->header != 0) * + (total_line_length / screen_size.ws_col + 1) * 2 + - (po->header != 0) * 2 /* row count and newline */ + ))) + { + fflush(NULL); + fout = popen(pagerenv, "w"); + if (fout) + { + usePipe = true; +#ifndef WIN32 +#ifdef ENABLE_THREAD_SAFETY + if (pq_block_sigpipe(&osigset, &sigpipe_pending) == 0) + sigpipe_masked = true; +#else + oldsigpipehandler = pqsignal(SIGPIPE, SIG_IGN); +#endif /* ENABLE_THREAD_SAFETY */ +#endif /* WIN32 */ + } + else + fout = stdout; + } + } + + if (!po->expanded && (po->align || po->html3)) + { + fields = (char **) calloc((size_t) nTups + 1, + nFields * sizeof(char *)); + if (!fields) + { + fprintf(stderr, libpq_gettext("out of memory\n")); + goto exit; + } + } + else if (po->header && !po->html3) + { + if (po->expanded) + { + if (po->align) + fprintf(fout, libpq_gettext("%-*s%s Value\n"), + fieldMaxLen - fs_len, libpq_gettext("Field"), po->fieldSep); + else + fprintf(fout, libpq_gettext("%s%sValue\n"), libpq_gettext("Field"), po->fieldSep); + } + else + { + int len = 0; + + for (j = 0; j < nFields; j++) + { + const char *s = fieldNames[j]; + + fputs(s, fout); + len += strlen(s) + fs_len; + if ((j + 1) < nFields) + fputs(po->fieldSep, fout); + } + fputc('\n', fout); + for (len -= fs_len; len--; fputc('-', fout)); + fputc('\n', fout); + } + } + if (po->expanded && po->html3) + { + if (po->caption) + fprintf(fout, "<center><h2>%s</h2></center>\n", po->caption); + else + fprintf(fout, + "<center><h2>" + "Query retrieved %d rows * %d fields" + "</h2></center>\n", + nTups, nFields); + } + for (i = 0; i < nTups; i++) + { + if (po->expanded) + { + if (po->html3) + fprintf(fout, + "<table %s><caption align=\"top\">%d</caption>\n", + po->tableOpt ? po->tableOpt : "", i); + else + fprintf(fout, libpq_gettext("-- RECORD %d --\n"), i); + } + for (j = 0; j < nFields; j++) + { + if (!do_field(po, res, i, j, fs_len, fields, nFields, + fieldNames, fieldNotNum, + fieldMax, fieldMaxLen, fout)) + goto exit; + } + if (po->html3 && po->expanded) + fputs("</table>\n", fout); + } + if (!po->expanded && (po->align || po->html3)) + { + if (po->html3) + { + if (po->header) + { + if (po->caption) + fprintf(fout, + "<table %s><caption align=\"top\">%s</caption>\n", + po->tableOpt ? po->tableOpt : "", + po->caption); + else + fprintf(fout, + "<table %s><caption align=\"top\">" + "Retrieved %d rows * %d fields" + "</caption>\n", + po->tableOpt ? po->tableOpt : "", nTups, nFields); + } + else + fprintf(fout, "<table %s>", po->tableOpt ? po->tableOpt : ""); + } + if (po->header) + border = do_header(fout, po, nFields, fieldMax, fieldNames, + fieldNotNum, fs_len, res); + for (i = 0; i < nTups; i++) + output_row(fout, po, nFields, fields, + fieldNotNum, fieldMax, border, i); + } + if (po->header && !po->html3) + fprintf(fout, "(%d row%s)\n\n", PQntuples(res), + (PQntuples(res) == 1) ? "" : "s"); + if (po->html3 && !po->expanded) + fputs("</table>\n", fout); + +exit: + free(fieldMax); + free(fieldNotNum); + free(border); + if (fields) + { + /* if calloc succeeded, this shouldn't overflow size_t */ + size_t numfields = ((size_t) nTups + 1) * (size_t) nFields; + + while (numfields-- > 0) + free(fields[numfields]); + free(fields); + } + free(fieldNames); + if (usePipe) + { +#ifdef WIN32 + _pclose(fout); +#else + pclose(fout); + +#ifdef ENABLE_THREAD_SAFETY + /* we can't easily verify if EPIPE occurred, so say it did */ + if (sigpipe_masked) + pq_reset_sigpipe(&osigset, sigpipe_pending, true); +#else + pqsignal(SIGPIPE, oldsigpipehandler); +#endif /* ENABLE_THREAD_SAFETY */ +#endif /* WIN32 */ + } + } +} + + +static bool +do_field(const PQprintOpt *po, const PGresult *res, + const int i, const int j, const int fs_len, + char **fields, + const int nFields, char const **fieldNames, + unsigned char *fieldNotNum, int *fieldMax, + const int fieldMaxLen, FILE *fout) +{ + const char *pval, + *p; + int plen; + bool skipit; + + plen = PQgetlength(res, i, j); + pval = PQgetvalue(res, i, j); + + if (plen < 1 || !pval || !*pval) + { + if (po->align || po->expanded) + skipit = true; + else + { + skipit = false; + goto efield; + } + } + else + skipit = false; + + if (!skipit) + { + if (po->align && !fieldNotNum[j]) + { + /* Detect whether field contains non-numeric data */ + char ch = '0'; + + for (p = pval; *p; p += PQmblenBounded(p, res->client_encoding)) + { + ch = *p; + if (!((ch >= '0' && ch <= '9') || + ch == '.' || + ch == 'E' || + ch == 'e' || + ch == ' ' || + ch == '-')) + { + fieldNotNum[j] = 1; + break; + } + } + + /* + * Above loop will believe E in first column is numeric; also, we + * insist on a digit in the last column for a numeric. This test + * is still not bulletproof but it handles most cases. + */ + if (*pval == 'E' || *pval == 'e' || + !(ch >= '0' && ch <= '9')) + fieldNotNum[j] = 1; + } + + if (!po->expanded && (po->align || po->html3)) + { + if (plen > fieldMax[j]) + fieldMax[j] = plen; + if (!(fields[i * nFields + j] = (char *) malloc(plen + 1))) + { + fprintf(stderr, libpq_gettext("out of memory\n")); + return false; + } + strcpy(fields[i * nFields + j], pval); + } + else + { + if (po->expanded) + { + if (po->html3) + fprintf(fout, + "<tr><td align=\"left\"><b>%s</b></td>" + "<td align=\"%s\">%s</td></tr>\n", + fieldNames[j], + fieldNotNum[j] ? "left" : "right", + pval); + else + { + if (po->align) + fprintf(fout, + "%-*s%s %s\n", + fieldMaxLen - fs_len, fieldNames[j], + po->fieldSep, + pval); + else + fprintf(fout, + "%s%s%s\n", + fieldNames[j], po->fieldSep, pval); + } + } + else + { + if (!po->html3) + { + fputs(pval, fout); + efield: + if ((j + 1) < nFields) + fputs(po->fieldSep, fout); + else + fputc('\n', fout); + } + } + } + } + return true; +} + + +static char * +do_header(FILE *fout, const PQprintOpt *po, const int nFields, int *fieldMax, + const char **fieldNames, unsigned char *fieldNotNum, + const int fs_len, const PGresult *res) +{ + int j; /* for loop index */ + char *border = NULL; + + if (po->html3) + fputs("<tr>", fout); + else + { + int tot = 0; + int n = 0; + char *p = NULL; + + for (; n < nFields; n++) + tot += fieldMax[n] + fs_len + (po->standard ? 2 : 0); + if (po->standard) + tot += fs_len * 2 + 2; + border = malloc(tot + 1); + if (!border) + { + fprintf(stderr, libpq_gettext("out of memory\n")); + return NULL; + } + p = border; + if (po->standard) + { + char *fs = po->fieldSep; + + while (*fs++) + *p++ = '+'; + } + for (j = 0; j < nFields; j++) + { + int len; + + for (len = fieldMax[j] + (po->standard ? 2 : 0); len--; *p++ = '-'); + if (po->standard || (j + 1) < nFields) + { + char *fs = po->fieldSep; + + while (*fs++) + *p++ = '+'; + } + } + *p = '\0'; + if (po->standard) + fprintf(fout, "%s\n", border); + } + if (po->standard) + fputs(po->fieldSep, fout); + for (j = 0; j < nFields; j++) + { + const char *s = PQfname(res, j); + + if (po->html3) + { + fprintf(fout, "<th align=\"%s\">%s</th>", + fieldNotNum[j] ? "left" : "right", fieldNames[j]); + } + else + { + int n = strlen(s); + + if (n > fieldMax[j]) + fieldMax[j] = n; + if (po->standard) + fprintf(fout, + fieldNotNum[j] ? " %-*s " : " %*s ", + fieldMax[j], s); + else + fprintf(fout, fieldNotNum[j] ? "%-*s" : "%*s", fieldMax[j], s); + if (po->standard || (j + 1) < nFields) + fputs(po->fieldSep, fout); + } + } + if (po->html3) + fputs("</tr>\n", fout); + else + fprintf(fout, "\n%s\n", border); + return border; +} + + +static void +output_row(FILE *fout, const PQprintOpt *po, const int nFields, char **fields, + unsigned char *fieldNotNum, int *fieldMax, char *border, + const int row_index) +{ + int field_index; /* for loop index */ + + if (po->html3) + fputs("<tr>", fout); + else if (po->standard) + fputs(po->fieldSep, fout); + for (field_index = 0; field_index < nFields; field_index++) + { + char *p = fields[row_index * nFields + field_index]; + + if (po->html3) + fprintf(fout, "<td align=\"%s\">%s</td>", + fieldNotNum[field_index] ? "left" : "right", p ? p : ""); + else + { + fprintf(fout, + fieldNotNum[field_index] ? + (po->standard ? " %-*s " : "%-*s") : + (po->standard ? " %*s " : "%*s"), + fieldMax[field_index], + p ? p : ""); + if (po->standard || field_index + 1 < nFields) + fputs(po->fieldSep, fout); + } + } + if (po->html3) + fputs("</tr>", fout); + else if (po->standard) + fprintf(fout, "\n%s", border); + fputc('\n', fout); +} + + + +/* + * really old printing routines + */ + +void +PQdisplayTuples(const PGresult *res, + FILE *fp, /* where to send the output */ + int fillAlign, /* pad the fields with spaces */ + const char *fieldSep, /* field separator */ + int printHeader, /* display headers? */ + int quiet +) +{ +#define DEFAULT_FIELD_SEP " " + + int i, + j; + int nFields; + int nTuples; + int *fLength = NULL; + + if (fieldSep == NULL) + fieldSep = DEFAULT_FIELD_SEP; + + /* Get some useful info about the results */ + nFields = PQnfields(res); + nTuples = PQntuples(res); + + if (fp == NULL) + fp = stdout; + + /* Figure the field lengths to align to */ + /* will be somewhat time consuming for very large results */ + if (fillAlign) + { + fLength = (int *) malloc(nFields * sizeof(int)); + if (!fLength) + { + fprintf(stderr, libpq_gettext("out of memory\n")); + return; + } + + for (j = 0; j < nFields; j++) + { + fLength[j] = strlen(PQfname(res, j)); + for (i = 0; i < nTuples; i++) + { + int flen = PQgetlength(res, i, j); + + if (flen > fLength[j]) + fLength[j] = flen; + } + } + } + + if (printHeader) + { + /* first, print out the attribute names */ + for (i = 0; i < nFields; i++) + { + fputs(PQfname(res, i), fp); + if (fillAlign) + fill(strlen(PQfname(res, i)), fLength[i], ' ', fp); + fputs(fieldSep, fp); + } + fprintf(fp, "\n"); + + /* Underline the attribute names */ + for (i = 0; i < nFields; i++) + { + if (fillAlign) + fill(0, fLength[i], '-', fp); + fputs(fieldSep, fp); + } + fprintf(fp, "\n"); + } + + /* next, print out the instances */ + for (i = 0; i < nTuples; i++) + { + for (j = 0; j < nFields; j++) + { + fprintf(fp, "%s", PQgetvalue(res, i, j)); + if (fillAlign) + fill(strlen(PQgetvalue(res, i, j)), fLength[j], ' ', fp); + fputs(fieldSep, fp); + } + fprintf(fp, "\n"); + } + + if (!quiet) + fprintf(fp, "\nQuery returned %d row%s.\n", PQntuples(res), + (PQntuples(res) == 1) ? "" : "s"); + + fflush(fp); + + free(fLength); +} + + + +void +PQprintTuples(const PGresult *res, + FILE *fout, /* output stream */ + int PrintAttNames, /* print attribute names or not */ + int TerseOutput, /* delimiter bars or not? */ + int colWidth /* width of column, if 0, use variable width */ +) +{ + int nFields; + int nTups; + int i, + j; + char formatString[80]; + char *tborder = NULL; + + nFields = PQnfields(res); + nTups = PQntuples(res); + + if (colWidth > 0) + sprintf(formatString, "%%s %%-%ds", colWidth); + else + sprintf(formatString, "%%s %%s"); + + if (nFields > 0) + { /* only print rows with at least 1 field. */ + + if (!TerseOutput) + { + int width; + + width = nFields * 14; + tborder = (char *) malloc(width + 1); + if (!tborder) + { + fprintf(stderr, libpq_gettext("out of memory\n")); + return; + } + for (i = 0; i < width; i++) + tborder[i] = '-'; + tborder[width] = '\0'; + fprintf(fout, "%s\n", tborder); + } + + for (i = 0; i < nFields; i++) + { + if (PrintAttNames) + { + fprintf(fout, formatString, + TerseOutput ? "" : "|", + PQfname(res, i)); + } + } + + if (PrintAttNames) + { + if (TerseOutput) + fprintf(fout, "\n"); + else + fprintf(fout, "|\n%s\n", tborder); + } + + for (i = 0; i < nTups; i++) + { + for (j = 0; j < nFields; j++) + { + const char *pval = PQgetvalue(res, i, j); + + fprintf(fout, formatString, + TerseOutput ? "" : "|", + pval ? pval : ""); + } + if (TerseOutput) + fprintf(fout, "\n"); + else + fprintf(fout, "|\n%s\n", tborder); + } + } + + free(tborder); +} + + +/* simply send out max-length number of filler characters to fp */ + +static void +fill(int length, int max, char filler, FILE *fp) +{ + int count; + + count = max - length; + while (count-- >= 0) + putc(filler, fp); +} diff --git a/src/interfaces/libpq/fe-protocol3.c b/src/interfaces/libpq/fe-protocol3.c new file mode 100644 index 0000000..9c4aa7e --- /dev/null +++ b/src/interfaces/libpq/fe-protocol3.c @@ -0,0 +1,2301 @@ +/*------------------------------------------------------------------------- + * + * fe-protocol3.c + * functions that are specific to frontend/backend protocol version 3 + * + * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * src/interfaces/libpq/fe-protocol3.c + * + *------------------------------------------------------------------------- + */ +#include "postgres_fe.h" + +#include <ctype.h> +#include <fcntl.h> + +#ifdef WIN32 +#include "win32.h" +#else +#include <unistd.h> +#include <netinet/tcp.h> +#endif + +#include "libpq-fe.h" +#include "libpq-int.h" +#include "mb/pg_wchar.h" +#include "port/pg_bswap.h" + +/* + * This macro lists the backend message types that could be "long" (more + * than a couple of kilobytes). + */ +#define VALID_LONG_MESSAGE_TYPE(id) \ + ((id) == 'T' || (id) == 'D' || (id) == 'd' || (id) == 'V' || \ + (id) == 'E' || (id) == 'N' || (id) == 'A') + + +static void handleSyncLoss(PGconn *conn, char id, int msgLength); +static int getRowDescriptions(PGconn *conn, int msgLength); +static int getParamDescriptions(PGconn *conn, int msgLength); +static int getAnotherTuple(PGconn *conn, int msgLength); +static int getParameterStatus(PGconn *conn); +static int getNotify(PGconn *conn); +static int getCopyStart(PGconn *conn, ExecStatusType copytype); +static int getReadyForQuery(PGconn *conn); +static void reportErrorPosition(PQExpBuffer msg, const char *query, + int loc, int encoding); +static int build_startup_packet(const PGconn *conn, char *packet, + const PQEnvironmentOption *options); + + +/* + * parseInput: if appropriate, parse input data from backend + * until input is exhausted or a stopping state is reached. + * Note that this function will NOT attempt to read more data from the backend. + */ +void +pqParseInput3(PGconn *conn) +{ + char id; + int msgLength; + int avail; + + /* + * Loop to parse successive complete messages available in the buffer. + */ + for (;;) + { + /* + * Try to read a message. First get the type code and length. Return + * if not enough data. + */ + conn->inCursor = conn->inStart; + if (pqGetc(&id, conn)) + return; + if (pqGetInt(&msgLength, 4, conn)) + return; + + /* + * Try to validate message type/length here. A length less than 4 is + * definitely broken. Large lengths should only be believed for a few + * message types. + */ + if (msgLength < 4) + { + handleSyncLoss(conn, id, msgLength); + return; + } + if (msgLength > 30000 && !VALID_LONG_MESSAGE_TYPE(id)) + { + handleSyncLoss(conn, id, msgLength); + return; + } + + /* + * Can't process if message body isn't all here yet. + */ + msgLength -= 4; + avail = conn->inEnd - conn->inCursor; + if (avail < msgLength) + { + /* + * Before returning, enlarge the input buffer if needed to hold + * the whole message. This is better than leaving it to + * pqReadData because we can avoid multiple cycles of realloc() + * when the message is large; also, we can implement a reasonable + * recovery strategy if we are unable to make the buffer big + * enough. + */ + if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength, + conn)) + { + /* + * XXX add some better recovery code... plan is to skip over + * the message using its length, then report an error. For the + * moment, just treat this like loss of sync (which indeed it + * might be!) + */ + handleSyncLoss(conn, id, msgLength); + } + return; + } + + /* + * NOTIFY and NOTICE messages can happen in any state; always process + * them right away. + * + * Most other messages should only be processed while in BUSY state. + * (In particular, in READY state we hold off further parsing until + * the application collects the current PGresult.) + * + * However, if the state is IDLE then we got trouble; we need to deal + * with the unexpected message somehow. + * + * ParameterStatus ('S') messages are a special case: in IDLE state we + * must process 'em (this case could happen if a new value was adopted + * from config file due to SIGHUP), but otherwise we hold off until + * BUSY state. + */ + if (id == 'A') + { + if (getNotify(conn)) + return; + } + else if (id == 'N') + { + if (pqGetErrorNotice3(conn, false)) + return; + } + else if (conn->asyncStatus != PGASYNC_BUSY) + { + /* If not IDLE state, just wait ... */ + if (conn->asyncStatus != PGASYNC_IDLE) + return; + + /* + * Unexpected message in IDLE state; need to recover somehow. + * ERROR messages are handled using the notice processor; + * ParameterStatus is handled normally; anything else is just + * dropped on the floor after displaying a suitable warning + * notice. (An ERROR is very possibly the backend telling us why + * it is about to close the connection, so we don't want to just + * discard it...) + */ + if (id == 'E') + { + if (pqGetErrorNotice3(conn, false /* treat as notice */ )) + return; + } + else if (id == 'S') + { + if (getParameterStatus(conn)) + return; + } + else + { + /* Any other case is unexpected and we summarily skip it */ + pqInternalNotice(&conn->noticeHooks, + "message type 0x%02x arrived from server while idle", + id); + /* Discard the unexpected message */ + conn->inCursor += msgLength; + } + } + else + { + /* + * In BUSY state, we can process everything. + */ + switch (id) + { + case 'C': /* command complete */ + if (pqGets(&conn->workBuffer, conn)) + return; + if (!pgHavePendingResult(conn)) + { + conn->result = PQmakeEmptyPGresult(conn, + PGRES_COMMAND_OK); + if (!conn->result) + { + libpq_append_conn_error(conn, "out of memory"); + pqSaveErrorResult(conn); + } + } + if (conn->result) + strlcpy(conn->result->cmdStatus, conn->workBuffer.data, + CMDSTATUS_LEN); + conn->asyncStatus = PGASYNC_READY; + break; + case 'E': /* error return */ + if (pqGetErrorNotice3(conn, true)) + return; + conn->asyncStatus = PGASYNC_READY; + break; + case 'Z': /* sync response, backend is ready for new + * query */ + if (getReadyForQuery(conn)) + return; + if (conn->pipelineStatus != PQ_PIPELINE_OFF) + { + conn->result = PQmakeEmptyPGresult(conn, + PGRES_PIPELINE_SYNC); + if (!conn->result) + { + libpq_append_conn_error(conn, "out of memory"); + pqSaveErrorResult(conn); + } + else + { + conn->pipelineStatus = PQ_PIPELINE_ON; + conn->asyncStatus = PGASYNC_READY; + } + } + else + { + /* Advance the command queue and set us idle */ + pqCommandQueueAdvance(conn, true, false); + conn->asyncStatus = PGASYNC_IDLE; + } + break; + case 'I': /* empty query */ + if (!pgHavePendingResult(conn)) + { + conn->result = PQmakeEmptyPGresult(conn, + PGRES_EMPTY_QUERY); + if (!conn->result) + { + libpq_append_conn_error(conn, "out of memory"); + pqSaveErrorResult(conn); + } + } + conn->asyncStatus = PGASYNC_READY; + break; + case '1': /* Parse Complete */ + /* If we're doing PQprepare, we're done; else ignore */ + if (conn->cmd_queue_head && + conn->cmd_queue_head->queryclass == PGQUERY_PREPARE) + { + if (!pgHavePendingResult(conn)) + { + conn->result = PQmakeEmptyPGresult(conn, + PGRES_COMMAND_OK); + if (!conn->result) + { + libpq_append_conn_error(conn, "out of memory"); + pqSaveErrorResult(conn); + } + } + conn->asyncStatus = PGASYNC_READY; + } + break; + case '2': /* Bind Complete */ + case '3': /* Close Complete */ + /* Nothing to do for these message types */ + break; + case 'S': /* parameter status */ + if (getParameterStatus(conn)) + return; + break; + case 'K': /* secret key data from the backend */ + + /* + * This is expected only during backend startup, but it's + * just as easy to handle it as part of the main loop. + * Save the data and continue processing. + */ + if (pqGetInt(&(conn->be_pid), 4, conn)) + return; + if (pqGetInt(&(conn->be_key), 4, conn)) + return; + break; + case 'T': /* Row Description */ + if (conn->error_result || + (conn->result != NULL && + conn->result->resultStatus == PGRES_FATAL_ERROR)) + { + /* + * We've already choked for some reason. Just discard + * the data till we get to the end of the query. + */ + conn->inCursor += msgLength; + } + else if (conn->result == NULL || + (conn->cmd_queue_head && + conn->cmd_queue_head->queryclass == PGQUERY_DESCRIBE)) + { + /* First 'T' in a query sequence */ + if (getRowDescriptions(conn, msgLength)) + return; + } + else + { + /* + * A new 'T' message is treated as the start of + * another PGresult. (It is not clear that this is + * really possible with the current backend.) We stop + * parsing until the application accepts the current + * result. + */ + conn->asyncStatus = PGASYNC_READY; + return; + } + break; + case 'n': /* No Data */ + + /* + * NoData indicates that we will not be seeing a + * RowDescription message because the statement or portal + * inquired about doesn't return rows. + * + * If we're doing a Describe, we have to pass something + * back to the client, so set up a COMMAND_OK result, + * instead of PGRES_TUPLES_OK. Otherwise we can just + * ignore this message. + */ + if (conn->cmd_queue_head && + conn->cmd_queue_head->queryclass == PGQUERY_DESCRIBE) + { + if (!pgHavePendingResult(conn)) + { + conn->result = PQmakeEmptyPGresult(conn, + PGRES_COMMAND_OK); + if (!conn->result) + { + libpq_append_conn_error(conn, "out of memory"); + pqSaveErrorResult(conn); + } + } + conn->asyncStatus = PGASYNC_READY; + } + break; + case 't': /* Parameter Description */ + if (getParamDescriptions(conn, msgLength)) + return; + break; + case 'D': /* Data Row */ + if (conn->result != NULL && + conn->result->resultStatus == PGRES_TUPLES_OK) + { + /* Read another tuple of a normal query response */ + if (getAnotherTuple(conn, msgLength)) + return; + } + else if (conn->error_result || + (conn->result != NULL && + conn->result->resultStatus == PGRES_FATAL_ERROR)) + { + /* + * We've already choked for some reason. Just discard + * tuples till we get to the end of the query. + */ + conn->inCursor += msgLength; + } + else + { + /* Set up to report error at end of query */ + libpq_append_conn_error(conn, "server sent data (\"D\" message) without prior row description (\"T\" message)"); + pqSaveErrorResult(conn); + /* Discard the unexpected message */ + conn->inCursor += msgLength; + } + break; + case 'G': /* Start Copy In */ + if (getCopyStart(conn, PGRES_COPY_IN)) + return; + conn->asyncStatus = PGASYNC_COPY_IN; + break; + case 'H': /* Start Copy Out */ + if (getCopyStart(conn, PGRES_COPY_OUT)) + return; + conn->asyncStatus = PGASYNC_COPY_OUT; + conn->copy_already_done = 0; + break; + case 'W': /* Start Copy Both */ + if (getCopyStart(conn, PGRES_COPY_BOTH)) + return; + conn->asyncStatus = PGASYNC_COPY_BOTH; + conn->copy_already_done = 0; + break; + case 'd': /* Copy Data */ + + /* + * If we see Copy Data, just silently drop it. This would + * only occur if application exits COPY OUT mode too + * early. + */ + conn->inCursor += msgLength; + break; + case 'c': /* Copy Done */ + + /* + * If we see Copy Done, just silently drop it. This is + * the normal case during PQendcopy. We will keep + * swallowing data, expecting to see command-complete for + * the COPY command. + */ + break; + default: + libpq_append_conn_error(conn, "unexpected response from server; first received character was \"%c\"", id); + /* build an error result holding the error message */ + pqSaveErrorResult(conn); + /* not sure if we will see more, so go to ready state */ + conn->asyncStatus = PGASYNC_READY; + /* Discard the unexpected message */ + conn->inCursor += msgLength; + break; + } /* switch on protocol character */ + } + /* Successfully consumed this message */ + if (conn->inCursor == conn->inStart + 5 + msgLength) + { + /* trace server-to-client message */ + if (conn->Pfdebug) + pqTraceOutputMessage(conn, conn->inBuffer + conn->inStart, false); + + /* Normal case: parsing agrees with specified length */ + conn->inStart = conn->inCursor; + } + else + { + /* Trouble --- report it */ + libpq_append_conn_error(conn, "message contents do not agree with length in message type \"%c\"", id); + /* build an error result holding the error message */ + pqSaveErrorResult(conn); + conn->asyncStatus = PGASYNC_READY; + /* trust the specified message length as what to skip */ + conn->inStart += 5 + msgLength; + } + } +} + +/* + * handleSyncLoss: clean up after loss of message-boundary sync + * + * There isn't really a lot we can do here except abandon the connection. + */ +static void +handleSyncLoss(PGconn *conn, char id, int msgLength) +{ + libpq_append_conn_error(conn, "lost synchronization with server: got message type \"%c\", length %d", + id, msgLength); + /* build an error result holding the error message */ + pqSaveErrorResult(conn); + conn->asyncStatus = PGASYNC_READY; /* drop out of PQgetResult wait loop */ + /* flush input data since we're giving up on processing it */ + pqDropConnection(conn, true); + conn->status = CONNECTION_BAD; /* No more connection to backend */ +} + +/* + * parseInput subroutine to read a 'T' (row descriptions) message. + * We'll build a new PGresult structure (unless called for a Describe + * command for a prepared statement) containing the attribute data. + * Returns: 0 if processed message successfully, EOF to suspend parsing + * (the latter case is not actually used currently). + */ +static int +getRowDescriptions(PGconn *conn, int msgLength) +{ + PGresult *result; + int nfields; + const char *errmsg; + int i; + + /* + * When doing Describe for a prepared statement, there'll already be a + * PGresult created by getParamDescriptions, and we should fill data into + * that. Otherwise, create a new, empty PGresult. + */ + if (!conn->cmd_queue_head || + (conn->cmd_queue_head && + conn->cmd_queue_head->queryclass == PGQUERY_DESCRIBE)) + { + if (conn->result) + result = conn->result; + else + result = PQmakeEmptyPGresult(conn, PGRES_COMMAND_OK); + } + else + result = PQmakeEmptyPGresult(conn, PGRES_TUPLES_OK); + if (!result) + { + errmsg = NULL; /* means "out of memory", see below */ + goto advance_and_error; + } + + /* parseInput already read the 'T' label and message length. */ + /* the next two bytes are the number of fields */ + if (pqGetInt(&(result->numAttributes), 2, conn)) + { + /* We should not run out of data here, so complain */ + errmsg = libpq_gettext("insufficient data in \"T\" message"); + goto advance_and_error; + } + nfields = result->numAttributes; + + /* allocate space for the attribute descriptors */ + if (nfields > 0) + { + result->attDescs = (PGresAttDesc *) + pqResultAlloc(result, nfields * sizeof(PGresAttDesc), true); + if (!result->attDescs) + { + errmsg = NULL; /* means "out of memory", see below */ + goto advance_and_error; + } + MemSet(result->attDescs, 0, nfields * sizeof(PGresAttDesc)); + } + + /* result->binary is true only if ALL columns are binary */ + result->binary = (nfields > 0) ? 1 : 0; + + /* get type info */ + for (i = 0; i < nfields; i++) + { + int tableid; + int columnid; + int typid; + int typlen; + int atttypmod; + int format; + + if (pqGets(&conn->workBuffer, conn) || + pqGetInt(&tableid, 4, conn) || + pqGetInt(&columnid, 2, conn) || + pqGetInt(&typid, 4, conn) || + pqGetInt(&typlen, 2, conn) || + pqGetInt(&atttypmod, 4, conn) || + pqGetInt(&format, 2, conn)) + { + /* We should not run out of data here, so complain */ + errmsg = libpq_gettext("insufficient data in \"T\" message"); + goto advance_and_error; + } + + /* + * Since pqGetInt treats 2-byte integers as unsigned, we need to + * coerce these results to signed form. + */ + columnid = (int) ((int16) columnid); + typlen = (int) ((int16) typlen); + format = (int) ((int16) format); + + result->attDescs[i].name = pqResultStrdup(result, + conn->workBuffer.data); + if (!result->attDescs[i].name) + { + errmsg = NULL; /* means "out of memory", see below */ + goto advance_and_error; + } + result->attDescs[i].tableid = tableid; + result->attDescs[i].columnid = columnid; + result->attDescs[i].format = format; + result->attDescs[i].typid = typid; + result->attDescs[i].typlen = typlen; + result->attDescs[i].atttypmod = atttypmod; + + if (format != 1) + result->binary = 0; + } + + /* Success! */ + conn->result = result; + + /* + * If we're doing a Describe, we're done, and ready to pass the result + * back to the client. + */ + if ((!conn->cmd_queue_head) || + (conn->cmd_queue_head && + conn->cmd_queue_head->queryclass == PGQUERY_DESCRIBE)) + { + conn->asyncStatus = PGASYNC_READY; + return 0; + } + + /* + * We could perform additional setup for the new result set here, but for + * now there's nothing else to do. + */ + + /* And we're done. */ + return 0; + +advance_and_error: + /* Discard unsaved result, if any */ + if (result && result != conn->result) + PQclear(result); + + /* + * Replace partially constructed result with an error result. First + * discard the old result to try to win back some memory. + */ + pqClearAsyncResult(conn); + + /* + * If preceding code didn't provide an error message, assume "out of + * memory" was meant. The advantage of having this special case is that + * freeing the old result first greatly improves the odds that gettext() + * will succeed in providing a translation. + */ + if (!errmsg) + errmsg = libpq_gettext("out of memory for query result"); + + appendPQExpBuffer(&conn->errorMessage, "%s\n", errmsg); + pqSaveErrorResult(conn); + + /* + * Show the message as fully consumed, else pqParseInput3 will overwrite + * our error with a complaint about that. + */ + conn->inCursor = conn->inStart + 5 + msgLength; + + /* + * Return zero to allow input parsing to continue. Subsequent "D" + * messages will be ignored until we get to end of data, since an error + * result is already set up. + */ + return 0; +} + +/* + * parseInput subroutine to read a 't' (ParameterDescription) message. + * We'll build a new PGresult structure containing the parameter data. + * Returns: 0 if processed message successfully, EOF to suspend parsing + * (the latter case is not actually used currently). + */ +static int +getParamDescriptions(PGconn *conn, int msgLength) +{ + PGresult *result; + const char *errmsg = NULL; /* means "out of memory", see below */ + int nparams; + int i; + + result = PQmakeEmptyPGresult(conn, PGRES_COMMAND_OK); + if (!result) + goto advance_and_error; + + /* parseInput already read the 't' label and message length. */ + /* the next two bytes are the number of parameters */ + if (pqGetInt(&(result->numParameters), 2, conn)) + goto not_enough_data; + nparams = result->numParameters; + + /* allocate space for the parameter descriptors */ + if (nparams > 0) + { + result->paramDescs = (PGresParamDesc *) + pqResultAlloc(result, nparams * sizeof(PGresParamDesc), true); + if (!result->paramDescs) + goto advance_and_error; + MemSet(result->paramDescs, 0, nparams * sizeof(PGresParamDesc)); + } + + /* get parameter info */ + for (i = 0; i < nparams; i++) + { + int typid; + + if (pqGetInt(&typid, 4, conn)) + goto not_enough_data; + result->paramDescs[i].typid = typid; + } + + /* Success! */ + conn->result = result; + + return 0; + +not_enough_data: + errmsg = libpq_gettext("insufficient data in \"t\" message"); + +advance_and_error: + /* Discard unsaved result, if any */ + if (result && result != conn->result) + PQclear(result); + + /* + * Replace partially constructed result with an error result. First + * discard the old result to try to win back some memory. + */ + pqClearAsyncResult(conn); + + /* + * If preceding code didn't provide an error message, assume "out of + * memory" was meant. The advantage of having this special case is that + * freeing the old result first greatly improves the odds that gettext() + * will succeed in providing a translation. + */ + if (!errmsg) + errmsg = libpq_gettext("out of memory"); + appendPQExpBuffer(&conn->errorMessage, "%s\n", errmsg); + pqSaveErrorResult(conn); + + /* + * Show the message as fully consumed, else pqParseInput3 will overwrite + * our error with a complaint about that. + */ + conn->inCursor = conn->inStart + 5 + msgLength; + + /* + * Return zero to allow input parsing to continue. Essentially, we've + * replaced the COMMAND_OK result with an error result, but since this + * doesn't affect the protocol state, it's fine. + */ + return 0; +} + +/* + * parseInput subroutine to read a 'D' (row data) message. + * We fill rowbuf with column pointers and then call the row processor. + * Returns: 0 if processed message successfully, EOF to suspend parsing + * (the latter case is not actually used currently). + */ +static int +getAnotherTuple(PGconn *conn, int msgLength) +{ + PGresult *result = conn->result; + int nfields = result->numAttributes; + const char *errmsg; + PGdataValue *rowbuf; + int tupnfields; /* # fields from tuple */ + int vlen; /* length of the current field value */ + int i; + + /* Get the field count and make sure it's what we expect */ + if (pqGetInt(&tupnfields, 2, conn)) + { + /* We should not run out of data here, so complain */ + errmsg = libpq_gettext("insufficient data in \"D\" message"); + goto advance_and_error; + } + + if (tupnfields != nfields) + { + errmsg = libpq_gettext("unexpected field count in \"D\" message"); + goto advance_and_error; + } + + /* Resize row buffer if needed */ + rowbuf = conn->rowBuf; + if (nfields > conn->rowBufLen) + { + rowbuf = (PGdataValue *) realloc(rowbuf, + nfields * sizeof(PGdataValue)); + if (!rowbuf) + { + errmsg = NULL; /* means "out of memory", see below */ + goto advance_and_error; + } + conn->rowBuf = rowbuf; + conn->rowBufLen = nfields; + } + + /* Scan the fields */ + for (i = 0; i < nfields; i++) + { + /* get the value length */ + if (pqGetInt(&vlen, 4, conn)) + { + /* We should not run out of data here, so complain */ + errmsg = libpq_gettext("insufficient data in \"D\" message"); + goto advance_and_error; + } + rowbuf[i].len = vlen; + + /* + * rowbuf[i].value always points to the next address in the data + * buffer even if the value is NULL. This allows row processors to + * estimate data sizes more easily. + */ + rowbuf[i].value = conn->inBuffer + conn->inCursor; + + /* Skip over the data value */ + if (vlen > 0) + { + if (pqSkipnchar(vlen, conn)) + { + /* We should not run out of data here, so complain */ + errmsg = libpq_gettext("insufficient data in \"D\" message"); + goto advance_and_error; + } + } + } + + /* Process the collected row */ + errmsg = NULL; + if (pqRowProcessor(conn, &errmsg)) + return 0; /* normal, successful exit */ + + /* pqRowProcessor failed, fall through to report it */ + +advance_and_error: + + /* + * Replace partially constructed result with an error result. First + * discard the old result to try to win back some memory. + */ + pqClearAsyncResult(conn); + + /* + * If preceding code didn't provide an error message, assume "out of + * memory" was meant. The advantage of having this special case is that + * freeing the old result first greatly improves the odds that gettext() + * will succeed in providing a translation. + */ + if (!errmsg) + errmsg = libpq_gettext("out of memory for query result"); + + appendPQExpBuffer(&conn->errorMessage, "%s\n", errmsg); + pqSaveErrorResult(conn); + + /* + * Show the message as fully consumed, else pqParseInput3 will overwrite + * our error with a complaint about that. + */ + conn->inCursor = conn->inStart + 5 + msgLength; + + /* + * Return zero to allow input parsing to continue. Subsequent "D" + * messages will be ignored until we get to end of data, since an error + * result is already set up. + */ + return 0; +} + + +/* + * Attempt to read an Error or Notice response message. + * This is possible in several places, so we break it out as a subroutine. + * Entry: 'E' or 'N' message type and length have already been consumed. + * Exit: returns 0 if successfully consumed message. + * returns EOF if not enough data. + */ +int +pqGetErrorNotice3(PGconn *conn, bool isError) +{ + PGresult *res = NULL; + bool have_position = false; + PQExpBufferData workBuf; + char id; + + /* If in pipeline mode, set error indicator for it */ + if (isError && conn->pipelineStatus != PQ_PIPELINE_OFF) + conn->pipelineStatus = PQ_PIPELINE_ABORTED; + + /* + * If this is an error message, pre-emptively clear any incomplete query + * result we may have. We'd just throw it away below anyway, and + * releasing it before collecting the error might avoid out-of-memory. + */ + if (isError) + pqClearAsyncResult(conn); + + /* + * Since the fields might be pretty long, we create a temporary + * PQExpBuffer rather than using conn->workBuffer. workBuffer is intended + * for stuff that is expected to be short. We shouldn't use + * conn->errorMessage either, since this might be only a notice. + */ + initPQExpBuffer(&workBuf); + + /* + * Make a PGresult to hold the accumulated fields. We temporarily lie + * about the result status, so that PQmakeEmptyPGresult doesn't uselessly + * copy conn->errorMessage. + * + * NB: This allocation can fail, if you run out of memory. The rest of the + * function handles that gracefully, and we still try to set the error + * message as the connection's error message. + */ + res = PQmakeEmptyPGresult(conn, PGRES_EMPTY_QUERY); + if (res) + res->resultStatus = isError ? PGRES_FATAL_ERROR : PGRES_NONFATAL_ERROR; + + /* + * Read the fields and save into res. + * + * While at it, save the SQLSTATE in conn->last_sqlstate, and note whether + * we saw a PG_DIAG_STATEMENT_POSITION field. + */ + for (;;) + { + if (pqGetc(&id, conn)) + goto fail; + if (id == '\0') + break; /* terminator found */ + if (pqGets(&workBuf, conn)) + goto fail; + pqSaveMessageField(res, id, workBuf.data); + if (id == PG_DIAG_SQLSTATE) + strlcpy(conn->last_sqlstate, workBuf.data, + sizeof(conn->last_sqlstate)); + else if (id == PG_DIAG_STATEMENT_POSITION) + have_position = true; + } + + /* + * Save the active query text, if any, into res as well; but only if we + * might need it for an error cursor display, which is only true if there + * is a PG_DIAG_STATEMENT_POSITION field. + */ + if (have_position && res && conn->cmd_queue_head && conn->cmd_queue_head->query) + res->errQuery = pqResultStrdup(res, conn->cmd_queue_head->query); + + /* + * Now build the "overall" error message for PQresultErrorMessage. + */ + resetPQExpBuffer(&workBuf); + pqBuildErrorMessage3(&workBuf, res, conn->verbosity, conn->show_context); + + /* + * Either save error as current async result, or just emit the notice. + */ + if (isError) + { + pqClearAsyncResult(conn); /* redundant, but be safe */ + if (res) + { + pqSetResultError(res, &workBuf, 0); + conn->result = res; + } + else + { + /* Fall back to using the internal-error processing paths */ + conn->error_result = true; + } + + if (PQExpBufferDataBroken(workBuf)) + libpq_append_conn_error(conn, "out of memory"); + else + appendPQExpBufferStr(&conn->errorMessage, workBuf.data); + } + else + { + /* if we couldn't allocate the result set, just discard the NOTICE */ + if (res) + { + /* + * We can cheat a little here and not copy the message. But if we + * were unlucky enough to run out of memory while filling workBuf, + * insert "out of memory", as in pqSetResultError. + */ + if (PQExpBufferDataBroken(workBuf)) + res->errMsg = libpq_gettext("out of memory\n"); + else + res->errMsg = workBuf.data; + if (res->noticeHooks.noticeRec != NULL) + res->noticeHooks.noticeRec(res->noticeHooks.noticeRecArg, res); + PQclear(res); + } + } + + termPQExpBuffer(&workBuf); + return 0; + +fail: + PQclear(res); + termPQExpBuffer(&workBuf); + return EOF; +} + +/* + * Construct an error message from the fields in the given PGresult, + * appending it to the contents of "msg". + */ +void +pqBuildErrorMessage3(PQExpBuffer msg, const PGresult *res, + PGVerbosity verbosity, PGContextVisibility show_context) +{ + const char *val; + const char *querytext = NULL; + int querypos = 0; + + /* If we couldn't allocate a PGresult, just say "out of memory" */ + if (res == NULL) + { + appendPQExpBufferStr(msg, libpq_gettext("out of memory\n")); + return; + } + + /* + * If we don't have any broken-down fields, just return the base message. + * This mainly applies if we're given a libpq-generated error result. + */ + if (res->errFields == NULL) + { + if (res->errMsg && res->errMsg[0]) + appendPQExpBufferStr(msg, res->errMsg); + else + appendPQExpBufferStr(msg, libpq_gettext("no error message available\n")); + return; + } + + /* Else build error message from relevant fields */ + val = PQresultErrorField(res, PG_DIAG_SEVERITY); + if (val) + appendPQExpBuffer(msg, "%s: ", val); + + if (verbosity == PQERRORS_SQLSTATE) + { + /* + * If we have a SQLSTATE, print that and nothing else. If not (which + * shouldn't happen for server-generated errors, but might possibly + * happen for libpq-generated ones), fall back to TERSE format, as + * that seems better than printing nothing at all. + */ + val = PQresultErrorField(res, PG_DIAG_SQLSTATE); + if (val) + { + appendPQExpBuffer(msg, "%s\n", val); + return; + } + verbosity = PQERRORS_TERSE; + } + + if (verbosity == PQERRORS_VERBOSE) + { + val = PQresultErrorField(res, PG_DIAG_SQLSTATE); + if (val) + appendPQExpBuffer(msg, "%s: ", val); + } + val = PQresultErrorField(res, PG_DIAG_MESSAGE_PRIMARY); + if (val) + appendPQExpBufferStr(msg, val); + val = PQresultErrorField(res, PG_DIAG_STATEMENT_POSITION); + if (val) + { + if (verbosity != PQERRORS_TERSE && res->errQuery != NULL) + { + /* emit position as a syntax cursor display */ + querytext = res->errQuery; + querypos = atoi(val); + } + else + { + /* emit position as text addition to primary message */ + /* translator: %s represents a digit string */ + appendPQExpBuffer(msg, libpq_gettext(" at character %s"), + val); + } + } + else + { + val = PQresultErrorField(res, PG_DIAG_INTERNAL_POSITION); + if (val) + { + querytext = PQresultErrorField(res, PG_DIAG_INTERNAL_QUERY); + if (verbosity != PQERRORS_TERSE && querytext != NULL) + { + /* emit position as a syntax cursor display */ + querypos = atoi(val); + } + else + { + /* emit position as text addition to primary message */ + /* translator: %s represents a digit string */ + appendPQExpBuffer(msg, libpq_gettext(" at character %s"), + val); + } + } + } + appendPQExpBufferChar(msg, '\n'); + if (verbosity != PQERRORS_TERSE) + { + if (querytext && querypos > 0) + reportErrorPosition(msg, querytext, querypos, + res->client_encoding); + val = PQresultErrorField(res, PG_DIAG_MESSAGE_DETAIL); + if (val) + appendPQExpBuffer(msg, libpq_gettext("DETAIL: %s\n"), val); + val = PQresultErrorField(res, PG_DIAG_MESSAGE_HINT); + if (val) + appendPQExpBuffer(msg, libpq_gettext("HINT: %s\n"), val); + val = PQresultErrorField(res, PG_DIAG_INTERNAL_QUERY); + if (val) + appendPQExpBuffer(msg, libpq_gettext("QUERY: %s\n"), val); + if (show_context == PQSHOW_CONTEXT_ALWAYS || + (show_context == PQSHOW_CONTEXT_ERRORS && + res->resultStatus == PGRES_FATAL_ERROR)) + { + val = PQresultErrorField(res, PG_DIAG_CONTEXT); + if (val) + appendPQExpBuffer(msg, libpq_gettext("CONTEXT: %s\n"), + val); + } + } + if (verbosity == PQERRORS_VERBOSE) + { + val = PQresultErrorField(res, PG_DIAG_SCHEMA_NAME); + if (val) + appendPQExpBuffer(msg, + libpq_gettext("SCHEMA NAME: %s\n"), val); + val = PQresultErrorField(res, PG_DIAG_TABLE_NAME); + if (val) + appendPQExpBuffer(msg, + libpq_gettext("TABLE NAME: %s\n"), val); + val = PQresultErrorField(res, PG_DIAG_COLUMN_NAME); + if (val) + appendPQExpBuffer(msg, + libpq_gettext("COLUMN NAME: %s\n"), val); + val = PQresultErrorField(res, PG_DIAG_DATATYPE_NAME); + if (val) + appendPQExpBuffer(msg, + libpq_gettext("DATATYPE NAME: %s\n"), val); + val = PQresultErrorField(res, PG_DIAG_CONSTRAINT_NAME); + if (val) + appendPQExpBuffer(msg, + libpq_gettext("CONSTRAINT NAME: %s\n"), val); + } + if (verbosity == PQERRORS_VERBOSE) + { + const char *valf; + const char *vall; + + valf = PQresultErrorField(res, PG_DIAG_SOURCE_FILE); + vall = PQresultErrorField(res, PG_DIAG_SOURCE_LINE); + val = PQresultErrorField(res, PG_DIAG_SOURCE_FUNCTION); + if (val || valf || vall) + { + appendPQExpBufferStr(msg, libpq_gettext("LOCATION: ")); + if (val) + appendPQExpBuffer(msg, libpq_gettext("%s, "), val); + if (valf && vall) /* unlikely we'd have just one */ + appendPQExpBuffer(msg, libpq_gettext("%s:%s"), + valf, vall); + appendPQExpBufferChar(msg, '\n'); + } + } +} + +/* + * Add an error-location display to the error message under construction. + * + * The cursor location is measured in logical characters; the query string + * is presumed to be in the specified encoding. + */ +static void +reportErrorPosition(PQExpBuffer msg, const char *query, int loc, int encoding) +{ +#define DISPLAY_SIZE 60 /* screen width limit, in screen cols */ +#define MIN_RIGHT_CUT 10 /* try to keep this far away from EOL */ + + char *wquery; + int slen, + cno, + i, + *qidx, + *scridx, + qoffset, + scroffset, + ibeg, + iend, + loc_line; + bool mb_encoding, + beg_trunc, + end_trunc; + + /* Convert loc from 1-based to 0-based; no-op if out of range */ + loc--; + if (loc < 0) + return; + + /* Need a writable copy of the query */ + wquery = strdup(query); + if (wquery == NULL) + return; /* fail silently if out of memory */ + + /* + * Each character might occupy multiple physical bytes in the string, and + * in some Far Eastern character sets it might take more than one screen + * column as well. We compute the starting byte offset and starting + * screen column of each logical character, and store these in qidx[] and + * scridx[] respectively. + */ + + /* we need a safe allocation size... */ + slen = strlen(wquery) + 1; + + qidx = (int *) malloc(slen * sizeof(int)); + if (qidx == NULL) + { + free(wquery); + return; + } + scridx = (int *) malloc(slen * sizeof(int)); + if (scridx == NULL) + { + free(qidx); + free(wquery); + return; + } + + /* We can optimize a bit if it's a single-byte encoding */ + mb_encoding = (pg_encoding_max_length(encoding) != 1); + + /* + * Within the scanning loop, cno is the current character's logical + * number, qoffset is its offset in wquery, and scroffset is its starting + * logical screen column (all indexed from 0). "loc" is the logical + * character number of the error location. We scan to determine loc_line + * (the 1-based line number containing loc) and ibeg/iend (first character + * number and last+1 character number of the line containing loc). Note + * that qidx[] and scridx[] are filled only as far as iend. + */ + qoffset = 0; + scroffset = 0; + loc_line = 1; + ibeg = 0; + iend = -1; /* -1 means not set yet */ + + for (cno = 0; wquery[qoffset] != '\0'; cno++) + { + char ch = wquery[qoffset]; + + qidx[cno] = qoffset; + scridx[cno] = scroffset; + + /* + * Replace tabs with spaces in the writable copy. (Later we might + * want to think about coping with their variable screen width, but + * not today.) + */ + if (ch == '\t') + wquery[qoffset] = ' '; + + /* + * If end-of-line, count lines and mark positions. Each \r or \n + * counts as a line except when \r \n appear together. + */ + else if (ch == '\r' || ch == '\n') + { + if (cno < loc) + { + if (ch == '\r' || + cno == 0 || + wquery[qidx[cno - 1]] != '\r') + loc_line++; + /* extract beginning = last line start before loc. */ + ibeg = cno + 1; + } + else + { + /* set extract end. */ + iend = cno; + /* done scanning. */ + break; + } + } + + /* Advance */ + if (mb_encoding) + { + int w; + + w = pg_encoding_dsplen(encoding, &wquery[qoffset]); + /* treat any non-tab control chars as width 1 */ + if (w <= 0) + w = 1; + scroffset += w; + qoffset += PQmblenBounded(&wquery[qoffset], encoding); + } + else + { + /* We assume wide chars only exist in multibyte encodings */ + scroffset++; + qoffset++; + } + } + /* Fix up if we didn't find an end-of-line after loc */ + if (iend < 0) + { + iend = cno; /* query length in chars, +1 */ + qidx[iend] = qoffset; + scridx[iend] = scroffset; + } + + /* Print only if loc is within computed query length */ + if (loc <= cno) + { + /* If the line extracted is too long, we truncate it. */ + beg_trunc = false; + end_trunc = false; + if (scridx[iend] - scridx[ibeg] > DISPLAY_SIZE) + { + /* + * We first truncate right if it is enough. This code might be + * off a space or so on enforcing MIN_RIGHT_CUT if there's a wide + * character right there, but that should be okay. + */ + if (scridx[ibeg] + DISPLAY_SIZE >= scridx[loc] + MIN_RIGHT_CUT) + { + while (scridx[iend] - scridx[ibeg] > DISPLAY_SIZE) + iend--; + end_trunc = true; + } + else + { + /* Truncate right if not too close to loc. */ + while (scridx[loc] + MIN_RIGHT_CUT < scridx[iend]) + { + iend--; + end_trunc = true; + } + + /* Truncate left if still too long. */ + while (scridx[iend] - scridx[ibeg] > DISPLAY_SIZE) + { + ibeg++; + beg_trunc = true; + } + } + } + + /* truncate working copy at desired endpoint */ + wquery[qidx[iend]] = '\0'; + + /* Begin building the finished message. */ + i = msg->len; + appendPQExpBuffer(msg, libpq_gettext("LINE %d: "), loc_line); + if (beg_trunc) + appendPQExpBufferStr(msg, "..."); + + /* + * While we have the prefix in the msg buffer, compute its screen + * width. + */ + scroffset = 0; + for (; i < msg->len; i += PQmblenBounded(&msg->data[i], encoding)) + { + int w = pg_encoding_dsplen(encoding, &msg->data[i]); + + if (w <= 0) + w = 1; + scroffset += w; + } + + /* Finish up the LINE message line. */ + appendPQExpBufferStr(msg, &wquery[qidx[ibeg]]); + if (end_trunc) + appendPQExpBufferStr(msg, "..."); + appendPQExpBufferChar(msg, '\n'); + + /* Now emit the cursor marker line. */ + scroffset += scridx[loc] - scridx[ibeg]; + for (i = 0; i < scroffset; i++) + appendPQExpBufferChar(msg, ' '); + appendPQExpBufferChar(msg, '^'); + appendPQExpBufferChar(msg, '\n'); + } + + /* Clean up. */ + free(scridx); + free(qidx); + free(wquery); +} + + +/* + * Attempt to read a NegotiateProtocolVersion message. + * Entry: 'v' message type and length have already been consumed. + * Exit: returns 0 if successfully consumed message. + * returns EOF if not enough data. + */ +int +pqGetNegotiateProtocolVersion3(PGconn *conn) +{ + int tmp; + ProtocolVersion their_version; + int num; + PQExpBufferData buf; + + if (pqGetInt(&tmp, 4, conn) != 0) + return EOF; + their_version = tmp; + + if (pqGetInt(&num, 4, conn) != 0) + return EOF; + + initPQExpBuffer(&buf); + for (int i = 0; i < num; i++) + { + if (pqGets(&conn->workBuffer, conn)) + { + termPQExpBuffer(&buf); + return EOF; + } + if (buf.len > 0) + appendPQExpBufferChar(&buf, ' '); + appendPQExpBufferStr(&buf, conn->workBuffer.data); + } + + if (their_version < conn->pversion) + libpq_append_conn_error(conn, "protocol version not supported by server: client uses %u.%u, server supports up to %u.%u", + PG_PROTOCOL_MAJOR(conn->pversion), PG_PROTOCOL_MINOR(conn->pversion), + PG_PROTOCOL_MAJOR(their_version), PG_PROTOCOL_MINOR(their_version)); + if (num > 0) + { + appendPQExpBuffer(&conn->errorMessage, + libpq_ngettext("protocol extension not supported by server: %s", + "protocol extensions not supported by server: %s", num), + buf.data); + appendPQExpBufferChar(&conn->errorMessage, '\n'); + } + + /* neither -- server shouldn't have sent it */ + if (!(their_version < conn->pversion) && !(num > 0)) + libpq_append_conn_error(conn, "invalid %s message", "NegotiateProtocolVersion"); + + termPQExpBuffer(&buf); + return 0; +} + + +/* + * Attempt to read a ParameterStatus message. + * This is possible in several places, so we break it out as a subroutine. + * Entry: 'S' message type and length have already been consumed. + * Exit: returns 0 if successfully consumed message. + * returns EOF if not enough data. + */ +static int +getParameterStatus(PGconn *conn) +{ + PQExpBufferData valueBuf; + + /* Get the parameter name */ + if (pqGets(&conn->workBuffer, conn)) + return EOF; + /* Get the parameter value (could be large) */ + initPQExpBuffer(&valueBuf); + if (pqGets(&valueBuf, conn)) + { + termPQExpBuffer(&valueBuf); + return EOF; + } + /* And save it */ + pqSaveParameterStatus(conn, conn->workBuffer.data, valueBuf.data); + termPQExpBuffer(&valueBuf); + return 0; +} + + +/* + * Attempt to read a Notify response message. + * This is possible in several places, so we break it out as a subroutine. + * Entry: 'A' message type and length have already been consumed. + * Exit: returns 0 if successfully consumed Notify message. + * returns EOF if not enough data. + */ +static int +getNotify(PGconn *conn) +{ + int be_pid; + char *svname; + int nmlen; + int extralen; + PGnotify *newNotify; + + if (pqGetInt(&be_pid, 4, conn)) + return EOF; + if (pqGets(&conn->workBuffer, conn)) + return EOF; + /* must save name while getting extra string */ + svname = strdup(conn->workBuffer.data); + if (!svname) + return EOF; + if (pqGets(&conn->workBuffer, conn)) + { + free(svname); + return EOF; + } + + /* + * Store the strings right after the PGnotify structure so it can all be + * freed at once. We don't use NAMEDATALEN because we don't want to tie + * this interface to a specific server name length. + */ + nmlen = strlen(svname); + extralen = strlen(conn->workBuffer.data); + newNotify = (PGnotify *) malloc(sizeof(PGnotify) + nmlen + extralen + 2); + if (newNotify) + { + newNotify->relname = (char *) newNotify + sizeof(PGnotify); + strcpy(newNotify->relname, svname); + newNotify->extra = newNotify->relname + nmlen + 1; + strcpy(newNotify->extra, conn->workBuffer.data); + newNotify->be_pid = be_pid; + newNotify->next = NULL; + if (conn->notifyTail) + conn->notifyTail->next = newNotify; + else + conn->notifyHead = newNotify; + conn->notifyTail = newNotify; + } + + free(svname); + return 0; +} + +/* + * getCopyStart - process CopyInResponse, CopyOutResponse or + * CopyBothResponse message + * + * parseInput already read the message type and length. + */ +static int +getCopyStart(PGconn *conn, ExecStatusType copytype) +{ + PGresult *result; + int nfields; + int i; + + result = PQmakeEmptyPGresult(conn, copytype); + if (!result) + goto failure; + + if (pqGetc(&conn->copy_is_binary, conn)) + goto failure; + result->binary = conn->copy_is_binary; + /* the next two bytes are the number of fields */ + if (pqGetInt(&(result->numAttributes), 2, conn)) + goto failure; + nfields = result->numAttributes; + + /* allocate space for the attribute descriptors */ + if (nfields > 0) + { + result->attDescs = (PGresAttDesc *) + pqResultAlloc(result, nfields * sizeof(PGresAttDesc), true); + if (!result->attDescs) + goto failure; + MemSet(result->attDescs, 0, nfields * sizeof(PGresAttDesc)); + } + + for (i = 0; i < nfields; i++) + { + int format; + + if (pqGetInt(&format, 2, conn)) + goto failure; + + /* + * Since pqGetInt treats 2-byte integers as unsigned, we need to + * coerce these results to signed form. + */ + format = (int) ((int16) format); + result->attDescs[i].format = format; + } + + /* Success! */ + conn->result = result; + return 0; + +failure: + PQclear(result); + return EOF; +} + +/* + * getReadyForQuery - process ReadyForQuery message + */ +static int +getReadyForQuery(PGconn *conn) +{ + char xact_status; + + if (pqGetc(&xact_status, conn)) + return EOF; + switch (xact_status) + { + case 'I': + conn->xactStatus = PQTRANS_IDLE; + break; + case 'T': + conn->xactStatus = PQTRANS_INTRANS; + break; + case 'E': + conn->xactStatus = PQTRANS_INERROR; + break; + default: + conn->xactStatus = PQTRANS_UNKNOWN; + break; + } + + return 0; +} + +/* + * getCopyDataMessage - fetch next CopyData message, process async messages + * + * Returns length word of CopyData message (> 0), or 0 if no complete + * message available, -1 if end of copy, -2 if error. + */ +static int +getCopyDataMessage(PGconn *conn) +{ + char id; + int msgLength; + int avail; + + for (;;) + { + /* + * Do we have the next input message? To make life simpler for async + * callers, we keep returning 0 until the next message is fully + * available, even if it is not Copy Data. + */ + conn->inCursor = conn->inStart; + if (pqGetc(&id, conn)) + return 0; + if (pqGetInt(&msgLength, 4, conn)) + return 0; + if (msgLength < 4) + { + handleSyncLoss(conn, id, msgLength); + return -2; + } + avail = conn->inEnd - conn->inCursor; + if (avail < msgLength - 4) + { + /* + * Before returning, enlarge the input buffer if needed to hold + * the whole message. See notes in parseInput. + */ + if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength - 4, + conn)) + { + /* + * XXX add some better recovery code... plan is to skip over + * the message using its length, then report an error. For the + * moment, just treat this like loss of sync (which indeed it + * might be!) + */ + handleSyncLoss(conn, id, msgLength); + return -2; + } + return 0; + } + + /* + * If it's a legitimate async message type, process it. (NOTIFY + * messages are not currently possible here, but we handle them for + * completeness.) Otherwise, if it's anything except Copy Data, + * report end-of-copy. + */ + switch (id) + { + case 'A': /* NOTIFY */ + if (getNotify(conn)) + return 0; + break; + case 'N': /* NOTICE */ + if (pqGetErrorNotice3(conn, false)) + return 0; + break; + case 'S': /* ParameterStatus */ + if (getParameterStatus(conn)) + return 0; + break; + case 'd': /* Copy Data, pass it back to caller */ + return msgLength; + case 'c': + + /* + * If this is a CopyDone message, exit COPY_OUT mode and let + * caller read status with PQgetResult(). If we're in + * COPY_BOTH mode, return to COPY_IN mode. + */ + if (conn->asyncStatus == PGASYNC_COPY_BOTH) + conn->asyncStatus = PGASYNC_COPY_IN; + else + conn->asyncStatus = PGASYNC_BUSY; + return -1; + default: /* treat as end of copy */ + + /* + * Any other message terminates either COPY_IN or COPY_BOTH + * mode. + */ + conn->asyncStatus = PGASYNC_BUSY; + return -1; + } + + /* trace server-to-client message */ + if (conn->Pfdebug) + pqTraceOutputMessage(conn, conn->inBuffer + conn->inStart, false); + + /* Drop the processed message and loop around for another */ + conn->inStart = conn->inCursor; + } +} + +/* + * PQgetCopyData - read a row of data from the backend during COPY OUT + * or COPY BOTH + * + * If successful, sets *buffer to point to a malloc'd row of data, and + * returns row length (always > 0) as result. + * Returns 0 if no row available yet (only possible if async is true), + * -1 if end of copy (consult PQgetResult), or -2 if error (consult + * PQerrorMessage). + */ +int +pqGetCopyData3(PGconn *conn, char **buffer, int async) +{ + int msgLength; + + for (;;) + { + /* + * Collect the next input message. To make life simpler for async + * callers, we keep returning 0 until the next message is fully + * available, even if it is not Copy Data. + */ + msgLength = getCopyDataMessage(conn); + if (msgLength < 0) + return msgLength; /* end-of-copy or error */ + if (msgLength == 0) + { + /* Don't block if async read requested */ + if (async) + return 0; + /* Need to load more data */ + if (pqWait(true, false, conn) || + pqReadData(conn) < 0) + return -2; + continue; + } + + /* + * Drop zero-length messages (shouldn't happen anyway). Otherwise + * pass the data back to the caller. + */ + msgLength -= 4; + if (msgLength > 0) + { + *buffer = (char *) malloc(msgLength + 1); + if (*buffer == NULL) + { + libpq_append_conn_error(conn, "out of memory"); + return -2; + } + memcpy(*buffer, &conn->inBuffer[conn->inCursor], msgLength); + (*buffer)[msgLength] = '\0'; /* Add terminating null */ + + /* Mark message consumed */ + conn->inStart = conn->inCursor + msgLength; + + return msgLength; + } + + /* Empty, so drop it and loop around for another */ + conn->inStart = conn->inCursor; + } +} + +/* + * PQgetline - gets a newline-terminated string from the backend. + * + * See fe-exec.c for documentation. + */ +int +pqGetline3(PGconn *conn, char *s, int maxlen) +{ + int status; + + if (conn->sock == PGINVALID_SOCKET || + (conn->asyncStatus != PGASYNC_COPY_OUT && + conn->asyncStatus != PGASYNC_COPY_BOTH) || + conn->copy_is_binary) + { + libpq_append_conn_error(conn, "PQgetline: not doing text COPY OUT"); + *s = '\0'; + return EOF; + } + + while ((status = PQgetlineAsync(conn, s, maxlen - 1)) == 0) + { + /* need to load more data */ + if (pqWait(true, false, conn) || + pqReadData(conn) < 0) + { + *s = '\0'; + return EOF; + } + } + + if (status < 0) + { + /* End of copy detected; gin up old-style terminator */ + strcpy(s, "\\."); + return 0; + } + + /* Add null terminator, and strip trailing \n if present */ + if (s[status - 1] == '\n') + { + s[status - 1] = '\0'; + return 0; + } + else + { + s[status] = '\0'; + return 1; + } +} + +/* + * PQgetlineAsync - gets a COPY data row without blocking. + * + * See fe-exec.c for documentation. + */ +int +pqGetlineAsync3(PGconn *conn, char *buffer, int bufsize) +{ + int msgLength; + int avail; + + if (conn->asyncStatus != PGASYNC_COPY_OUT + && conn->asyncStatus != PGASYNC_COPY_BOTH) + return -1; /* we are not doing a copy... */ + + /* + * Recognize the next input message. To make life simpler for async + * callers, we keep returning 0 until the next message is fully available + * even if it is not Copy Data. This should keep PQendcopy from blocking. + * (Note: unlike pqGetCopyData3, we do not change asyncStatus here.) + */ + msgLength = getCopyDataMessage(conn); + if (msgLength < 0) + return -1; /* end-of-copy or error */ + if (msgLength == 0) + return 0; /* no data yet */ + + /* + * Move data from libpq's buffer to the caller's. In the case where a + * prior call found the caller's buffer too small, we use + * conn->copy_already_done to remember how much of the row was already + * returned to the caller. + */ + conn->inCursor += conn->copy_already_done; + avail = msgLength - 4 - conn->copy_already_done; + if (avail <= bufsize) + { + /* Able to consume the whole message */ + memcpy(buffer, &conn->inBuffer[conn->inCursor], avail); + /* Mark message consumed */ + conn->inStart = conn->inCursor + avail; + /* Reset state for next time */ + conn->copy_already_done = 0; + return avail; + } + else + { + /* We must return a partial message */ + memcpy(buffer, &conn->inBuffer[conn->inCursor], bufsize); + /* The message is NOT consumed from libpq's buffer */ + conn->copy_already_done += bufsize; + return bufsize; + } +} + +/* + * PQendcopy + * + * See fe-exec.c for documentation. + */ +int +pqEndcopy3(PGconn *conn) +{ + PGresult *result; + + if (conn->asyncStatus != PGASYNC_COPY_IN && + conn->asyncStatus != PGASYNC_COPY_OUT && + conn->asyncStatus != PGASYNC_COPY_BOTH) + { + libpq_append_conn_error(conn, "no COPY in progress"); + return 1; + } + + /* Send the CopyDone message if needed */ + if (conn->asyncStatus == PGASYNC_COPY_IN || + conn->asyncStatus == PGASYNC_COPY_BOTH) + { + if (pqPutMsgStart('c', conn) < 0 || + pqPutMsgEnd(conn) < 0) + return 1; + + /* + * If we sent the COPY command in extended-query mode, we must issue a + * Sync as well. + */ + if (conn->cmd_queue_head && + conn->cmd_queue_head->queryclass != PGQUERY_SIMPLE) + { + if (pqPutMsgStart('S', conn) < 0 || + pqPutMsgEnd(conn) < 0) + return 1; + } + } + + /* + * make sure no data is waiting to be sent, abort if we are non-blocking + * and the flush fails + */ + if (pqFlush(conn) && pqIsnonblocking(conn)) + return 1; + + /* Return to active duty */ + conn->asyncStatus = PGASYNC_BUSY; + + /* + * Non blocking connections may have to abort at this point. If everyone + * played the game there should be no problem, but in error scenarios the + * expected messages may not have arrived yet. (We are assuming that the + * backend's packetizing will ensure that CommandComplete arrives along + * with the CopyDone; are there corner cases where that doesn't happen?) + */ + if (pqIsnonblocking(conn) && PQisBusy(conn)) + return 1; + + /* Wait for the completion response */ + result = PQgetResult(conn); + + /* Expecting a successful result */ + if (result && result->resultStatus == PGRES_COMMAND_OK) + { + PQclear(result); + return 0; + } + + /* + * Trouble. For backwards-compatibility reasons, we issue the error + * message as if it were a notice (would be nice to get rid of this + * silliness, but too many apps probably don't handle errors from + * PQendcopy reasonably). Note that the app can still obtain the error + * status from the PGconn object. + */ + if (conn->errorMessage.len > 0) + { + /* We have to strip the trailing newline ... pain in neck... */ + char svLast = conn->errorMessage.data[conn->errorMessage.len - 1]; + + if (svLast == '\n') + conn->errorMessage.data[conn->errorMessage.len - 1] = '\0'; + pqInternalNotice(&conn->noticeHooks, "%s", conn->errorMessage.data); + conn->errorMessage.data[conn->errorMessage.len - 1] = svLast; + } + + PQclear(result); + + return 1; +} + + +/* + * PQfn - Send a function call to the POSTGRES backend. + * + * See fe-exec.c for documentation. + */ +PGresult * +pqFunctionCall3(PGconn *conn, Oid fnid, + int *result_buf, int *actual_result_len, + int result_is_int, + const PQArgBlock *args, int nargs) +{ + bool needInput = false; + ExecStatusType status = PGRES_FATAL_ERROR; + char id; + int msgLength; + int avail; + int i; + + /* already validated by PQfn */ + Assert(conn->pipelineStatus == PQ_PIPELINE_OFF); + + /* PQfn already validated connection state */ + + if (pqPutMsgStart('F', conn) < 0 || /* function call msg */ + pqPutInt(fnid, 4, conn) < 0 || /* function id */ + pqPutInt(1, 2, conn) < 0 || /* # of format codes */ + pqPutInt(1, 2, conn) < 0 || /* format code: BINARY */ + pqPutInt(nargs, 2, conn) < 0) /* # of args */ + { + /* error message should be set up already */ + return NULL; + } + + for (i = 0; i < nargs; ++i) + { /* len.int4 + contents */ + if (pqPutInt(args[i].len, 4, conn)) + return NULL; + if (args[i].len == -1) + continue; /* it's NULL */ + + if (args[i].isint) + { + if (pqPutInt(args[i].u.integer, args[i].len, conn)) + return NULL; + } + else + { + if (pqPutnchar((char *) args[i].u.ptr, args[i].len, conn)) + return NULL; + } + } + + if (pqPutInt(1, 2, conn) < 0) /* result format code: BINARY */ + return NULL; + + if (pqPutMsgEnd(conn) < 0 || + pqFlush(conn)) + return NULL; + + for (;;) + { + if (needInput) + { + /* Wait for some data to arrive (or for the channel to close) */ + if (pqWait(true, false, conn) || + pqReadData(conn) < 0) + break; + } + + /* + * Scan the message. If we run out of data, loop around to try again. + */ + needInput = true; + + conn->inCursor = conn->inStart; + if (pqGetc(&id, conn)) + continue; + if (pqGetInt(&msgLength, 4, conn)) + continue; + + /* + * Try to validate message type/length here. A length less than 4 is + * definitely broken. Large lengths should only be believed for a few + * message types. + */ + if (msgLength < 4) + { + handleSyncLoss(conn, id, msgLength); + break; + } + if (msgLength > 30000 && !VALID_LONG_MESSAGE_TYPE(id)) + { + handleSyncLoss(conn, id, msgLength); + break; + } + + /* + * Can't process if message body isn't all here yet. + */ + msgLength -= 4; + avail = conn->inEnd - conn->inCursor; + if (avail < msgLength) + { + /* + * Before looping, enlarge the input buffer if needed to hold the + * whole message. See notes in parseInput. + */ + if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength, + conn)) + { + /* + * XXX add some better recovery code... plan is to skip over + * the message using its length, then report an error. For the + * moment, just treat this like loss of sync (which indeed it + * might be!) + */ + handleSyncLoss(conn, id, msgLength); + break; + } + continue; + } + + /* + * We should see V or E response to the command, but might get N + * and/or A notices first. We also need to swallow the final Z before + * returning. + */ + switch (id) + { + case 'V': /* function result */ + if (pqGetInt(actual_result_len, 4, conn)) + continue; + if (*actual_result_len != -1) + { + if (result_is_int) + { + if (pqGetInt(result_buf, *actual_result_len, conn)) + continue; + } + else + { + if (pqGetnchar((char *) result_buf, + *actual_result_len, + conn)) + continue; + } + } + /* correctly finished function result message */ + status = PGRES_COMMAND_OK; + break; + case 'E': /* error return */ + if (pqGetErrorNotice3(conn, true)) + continue; + status = PGRES_FATAL_ERROR; + break; + case 'A': /* notify message */ + /* handle notify and go back to processing return values */ + if (getNotify(conn)) + continue; + break; + case 'N': /* notice */ + /* handle notice and go back to processing return values */ + if (pqGetErrorNotice3(conn, false)) + continue; + break; + case 'Z': /* backend is ready for new query */ + if (getReadyForQuery(conn)) + continue; + /* consume the message and exit */ + conn->inStart += 5 + msgLength; + + /* + * If we already have a result object (probably an error), use + * that. Otherwise, if we saw a function result message, + * report COMMAND_OK. Otherwise, the backend violated the + * protocol, so complain. + */ + if (!pgHavePendingResult(conn)) + { + if (status == PGRES_COMMAND_OK) + { + conn->result = PQmakeEmptyPGresult(conn, status); + if (!conn->result) + { + libpq_append_conn_error(conn, "out of memory"); + pqSaveErrorResult(conn); + } + } + else + { + libpq_append_conn_error(conn, "protocol error: no function result"); + pqSaveErrorResult(conn); + } + } + return pqPrepareAsyncResult(conn); + case 'S': /* parameter status */ + if (getParameterStatus(conn)) + continue; + break; + default: + /* The backend violates the protocol. */ + libpq_append_conn_error(conn, "protocol error: id=0x%x", id); + pqSaveErrorResult(conn); + /* trust the specified message length as what to skip */ + conn->inStart += 5 + msgLength; + return pqPrepareAsyncResult(conn); + } + + /* trace server-to-client message */ + if (conn->Pfdebug) + pqTraceOutputMessage(conn, conn->inBuffer + conn->inStart, false); + + /* Completed this message, keep going */ + /* trust the specified message length as what to skip */ + conn->inStart += 5 + msgLength; + needInput = false; + } + + /* + * We fall out of the loop only upon failing to read data. + * conn->errorMessage has been set by pqWait or pqReadData. We want to + * append it to any already-received error message. + */ + pqSaveErrorResult(conn); + return pqPrepareAsyncResult(conn); +} + + +/* + * Construct startup packet + * + * Returns a malloc'd packet buffer, or NULL if out of memory + */ +char * +pqBuildStartupPacket3(PGconn *conn, int *packetlen, + const PQEnvironmentOption *options) +{ + char *startpacket; + + *packetlen = build_startup_packet(conn, NULL, options); + startpacket = (char *) malloc(*packetlen); + if (!startpacket) + return NULL; + *packetlen = build_startup_packet(conn, startpacket, options); + return startpacket; +} + +/* + * Build a startup packet given a filled-in PGconn structure. + * + * We need to figure out how much space is needed, then fill it in. + * To avoid duplicate logic, this routine is called twice: the first time + * (with packet == NULL) just counts the space needed, the second time + * (with packet == allocated space) fills it in. Return value is the number + * of bytes used. + */ +static int +build_startup_packet(const PGconn *conn, char *packet, + const PQEnvironmentOption *options) +{ + int packet_len = 0; + const PQEnvironmentOption *next_eo; + const char *val; + + /* Protocol version comes first. */ + if (packet) + { + ProtocolVersion pv = pg_hton32(conn->pversion); + + memcpy(packet + packet_len, &pv, sizeof(ProtocolVersion)); + } + packet_len += sizeof(ProtocolVersion); + + /* Add user name, database name, options */ + +#define ADD_STARTUP_OPTION(optname, optval) \ + do { \ + if (packet) \ + strcpy(packet + packet_len, optname); \ + packet_len += strlen(optname) + 1; \ + if (packet) \ + strcpy(packet + packet_len, optval); \ + packet_len += strlen(optval) + 1; \ + } while(0) + + if (conn->pguser && conn->pguser[0]) + ADD_STARTUP_OPTION("user", conn->pguser); + if (conn->dbName && conn->dbName[0]) + ADD_STARTUP_OPTION("database", conn->dbName); + if (conn->replication && conn->replication[0]) + ADD_STARTUP_OPTION("replication", conn->replication); + if (conn->pgoptions && conn->pgoptions[0]) + ADD_STARTUP_OPTION("options", conn->pgoptions); + if (conn->send_appname) + { + /* Use appname if present, otherwise use fallback */ + val = conn->appname ? conn->appname : conn->fbappname; + if (val && val[0]) + ADD_STARTUP_OPTION("application_name", val); + } + + if (conn->client_encoding_initial && conn->client_encoding_initial[0]) + ADD_STARTUP_OPTION("client_encoding", conn->client_encoding_initial); + + /* Add any environment-driven GUC settings needed */ + for (next_eo = options; next_eo->envName; next_eo++) + { + if ((val = getenv(next_eo->envName)) != NULL) + { + if (pg_strcasecmp(val, "default") != 0) + ADD_STARTUP_OPTION(next_eo->pgName, val); + } + } + + /* Add trailing terminator */ + if (packet) + packet[packet_len] = '\0'; + packet_len++; + + return packet_len; +} diff --git a/src/interfaces/libpq/fe-secure-common.c b/src/interfaces/libpq/fe-secure-common.c new file mode 100644 index 0000000..3ecc7bf --- /dev/null +++ b/src/interfaces/libpq/fe-secure-common.c @@ -0,0 +1,307 @@ +/*------------------------------------------------------------------------- + * + * fe-secure-common.c + * + * common implementation-independent SSL support code + * + * While fe-secure.c contains the interfaces that the rest of libpq call, this + * file contains support routines that are used by the library-specific + * implementations such as fe-secure-openssl.c. + * + * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/interfaces/libpq/fe-secure-common.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres_fe.h" + +#include <arpa/inet.h> + +#include "fe-secure-common.h" + +#include "libpq-int.h" +#include "pqexpbuffer.h" + +/* + * Check if a wildcard certificate matches the server hostname. + * + * The rule for this is: + * 1. We only match the '*' character as wildcard + * 2. We match only wildcards at the start of the string + * 3. The '*' character does *not* match '.', meaning that we match only + * a single pathname component. + * 4. We don't support more than one '*' in a single pattern. + * + * This is roughly in line with RFC2818, but contrary to what most browsers + * appear to be implementing (point 3 being the difference) + * + * Matching is always case-insensitive, since DNS is case insensitive. + */ +static bool +wildcard_certificate_match(const char *pattern, const char *string) +{ + int lenpat = strlen(pattern); + int lenstr = strlen(string); + + /* If we don't start with a wildcard, it's not a match (rule 1 & 2) */ + if (lenpat < 3 || + pattern[0] != '*' || + pattern[1] != '.') + return false; + + /* If pattern is longer than the string, we can never match */ + if (lenpat > lenstr) + return false; + + /* + * If string does not end in pattern (minus the wildcard), we don't match + */ + if (pg_strcasecmp(pattern + 1, string + lenstr - lenpat + 1) != 0) + return false; + + /* + * If there is a dot left of where the pattern started to match, we don't + * match (rule 3) + */ + if (strchr(string, '.') < string + lenstr - lenpat) + return false; + + /* String ended with pattern, and didn't have a dot before, so we match */ + return true; +} + +/* + * Check if a name from a server's certificate matches the peer's hostname. + * + * Returns 1 if the name matches, and 0 if it does not. On error, returns + * -1, and sets the libpq error message. + * + * The name extracted from the certificate is returned in *store_name. The + * caller is responsible for freeing it. + */ +int +pq_verify_peer_name_matches_certificate_name(PGconn *conn, + const char *namedata, size_t namelen, + char **store_name) +{ + char *name; + int result; + char *host = conn->connhost[conn->whichhost].host; + + *store_name = NULL; + + if (!(host && host[0] != '\0')) + { + libpq_append_conn_error(conn, "host name must be specified"); + return -1; + } + + /* + * There is no guarantee the string returned from the certificate is + * NULL-terminated, so make a copy that is. + */ + name = malloc(namelen + 1); + if (name == NULL) + { + libpq_append_conn_error(conn, "out of memory"); + return -1; + } + memcpy(name, namedata, namelen); + name[namelen] = '\0'; + + /* + * Reject embedded NULLs in certificate common or alternative name to + * prevent attacks like CVE-2009-4034. + */ + if (namelen != strlen(name)) + { + free(name); + libpq_append_conn_error(conn, "SSL certificate's name contains embedded null"); + return -1; + } + + if (pg_strcasecmp(name, host) == 0) + { + /* Exact name match */ + result = 1; + } + else if (wildcard_certificate_match(name, host)) + { + /* Matched wildcard name */ + result = 1; + } + else + { + result = 0; + } + + *store_name = name; + return result; +} + +/* + * Check if an IP address from a server's certificate matches the peer's + * hostname (which must itself be an IPv4/6 address). + * + * Returns 1 if the address matches, and 0 if it does not. On error, returns + * -1, and sets the libpq error message. + * + * A string representation of the certificate's IP address is returned in + * *store_name. The caller is responsible for freeing it. + */ +int +pq_verify_peer_name_matches_certificate_ip(PGconn *conn, + const unsigned char *ipdata, + size_t iplen, + char **store_name) +{ + char *addrstr; + int match = 0; + char *host = conn->connhost[conn->whichhost].host; + int family; + char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"]; + char sebuf[PG_STRERROR_R_BUFLEN]; + + *store_name = NULL; + + if (!(host && host[0] != '\0')) + { + libpq_append_conn_error(conn, "host name must be specified"); + return -1; + } + + /* + * The data from the certificate is in network byte order. Convert our + * host string to network-ordered bytes as well, for comparison. (The host + * string isn't guaranteed to actually be an IP address, so if this + * conversion fails we need to consider it a mismatch rather than an + * error.) + */ + if (iplen == 4) + { + /* IPv4 */ + struct in_addr addr; + + family = AF_INET; + + /* + * The use of inet_aton() is deliberate; we accept alternative IPv4 + * address notations that are accepted by inet_aton() but not + * inet_pton() as server addresses. + */ + if (inet_aton(host, &addr)) + { + if (memcmp(ipdata, &addr.s_addr, iplen) == 0) + match = 1; + } + } + + /* + * If they don't have inet_pton(), skip this. Then, an IPv6 address in a + * certificate will cause an error. + */ +#ifdef HAVE_INET_PTON + else if (iplen == 16) + { + /* IPv6 */ + struct in6_addr addr; + + family = AF_INET6; + + if (inet_pton(AF_INET6, host, &addr) == 1) + { + if (memcmp(ipdata, &addr.s6_addr, iplen) == 0) + match = 1; + } + } +#endif + else + { + /* + * Not IPv4 or IPv6. We could ignore the field, but leniency seems + * wrong given the subject matter. + */ + libpq_append_conn_error(conn, "certificate contains IP address with invalid length %zu", + iplen); + return -1; + } + + /* Generate a human-readable representation of the certificate's IP. */ + addrstr = pg_inet_net_ntop(family, ipdata, 8 * iplen, tmp, sizeof(tmp)); + if (!addrstr) + { + libpq_append_conn_error(conn, "could not convert certificate's IP address to string: %s", + strerror_r(errno, sebuf, sizeof(sebuf))); + return -1; + } + + *store_name = strdup(addrstr); + return match; +} + +/* + * Verify that the server certificate matches the hostname we connected to. + * + * The certificate's Common Name and Subject Alternative Names are considered. + */ +bool +pq_verify_peer_name_matches_certificate(PGconn *conn) +{ + char *host = conn->connhost[conn->whichhost].host; + int rc; + int names_examined = 0; + char *first_name = NULL; + + /* + * If told not to verify the peer name, don't do it. Return true + * indicating that the verification was successful. + */ + if (strcmp(conn->sslmode, "verify-full") != 0) + return true; + + /* Check that we have a hostname to compare with. */ + if (!(host && host[0] != '\0')) + { + libpq_append_conn_error(conn, "host name must be specified for a verified SSL connection"); + return false; + } + + rc = pgtls_verify_peer_name_matches_certificate_guts(conn, &names_examined, &first_name); + + if (rc == 0) + { + /* + * No match. Include the name from the server certificate in the error + * message, to aid debugging broken configurations. If there are + * multiple names, only print the first one to avoid an overly long + * error message. + */ + if (names_examined > 1) + { + appendPQExpBuffer(&conn->errorMessage, + libpq_ngettext("server certificate for \"%s\" (and %d other name) does not match host name \"%s\"", + "server certificate for \"%s\" (and %d other names) does not match host name \"%s\"", + names_examined - 1), + first_name, names_examined - 1, host); + appendPQExpBufferChar(&conn->errorMessage, '\n'); + } + else if (names_examined == 1) + { + libpq_append_conn_error(conn, "server certificate for \"%s\" does not match host name \"%s\"", + first_name, host); + } + else + { + libpq_append_conn_error(conn, "could not get server's host name from server certificate"); + } + } + + /* clean up */ + free(first_name); + + return (rc == 1); +} diff --git a/src/interfaces/libpq/fe-secure-common.h b/src/interfaces/libpq/fe-secure-common.h new file mode 100644 index 0000000..e048f97 --- /dev/null +++ b/src/interfaces/libpq/fe-secure-common.h @@ -0,0 +1,30 @@ +/*------------------------------------------------------------------------- + * + * fe-secure-common.h + * + * common implementation-independent SSL support code + * + * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/interfaces/libpq/fe-secure-common.h + * + *------------------------------------------------------------------------- + */ + +#ifndef FE_SECURE_COMMON_H +#define FE_SECURE_COMMON_H + +#include "libpq-fe.h" + +extern int pq_verify_peer_name_matches_certificate_name(PGconn *conn, + const char *namedata, size_t namelen, + char **store_name); +extern int pq_verify_peer_name_matches_certificate_ip(PGconn *conn, + const unsigned char *ipdata, + size_t iplen, + char **store_name); +extern bool pq_verify_peer_name_matches_certificate(PGconn *conn); + +#endif /* FE_SECURE_COMMON_H */ diff --git a/src/interfaces/libpq/fe-secure-gssapi.c b/src/interfaces/libpq/fe-secure-gssapi.c new file mode 100644 index 0000000..ea8b002 --- /dev/null +++ b/src/interfaces/libpq/fe-secure-gssapi.c @@ -0,0 +1,742 @@ +/*------------------------------------------------------------------------- + * + * fe-secure-gssapi.c + * The front-end (client) encryption support for GSSAPI + * + * Portions Copyright (c) 2016-2023, PostgreSQL Global Development Group + * + * IDENTIFICATION + * src/interfaces/libpq/fe-secure-gssapi.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres_fe.h" + +#include "fe-gssapi-common.h" +#include "libpq-fe.h" +#include "libpq-int.h" +#include "port/pg_bswap.h" + + +/* + * Require encryption support, as well as mutual authentication and + * tamperproofing measures. + */ +#define GSS_REQUIRED_FLAGS GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | \ + GSS_C_SEQUENCE_FLAG | GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG + +/* + * Handle the encryption/decryption of data using GSSAPI. + * + * In the encrypted data stream on the wire, we break up the data + * into packets where each packet starts with a uint32-size length + * word (in network byte order), then encrypted data of that length + * immediately following. Decryption yields the same data stream + * that would appear when not using encryption. + * + * Encrypted data typically ends up being larger than the same data + * unencrypted, so we use fixed-size buffers for handling the + * encryption/decryption which are larger than PQComm's buffer will + * typically be to minimize the times where we have to make multiple + * packets (and therefore multiple recv/send calls for a single + * read/write call to us). + * + * NOTE: The client and server have to agree on the max packet size, + * because we have to pass an entire packet to GSSAPI at a time and we + * don't want the other side to send arbitrarily huge packets as we + * would have to allocate memory for them to then pass them to GSSAPI. + * + * Therefore, these two #define's are effectively part of the protocol + * spec and can't ever be changed. + */ +#define PQ_GSS_SEND_BUFFER_SIZE 16384 +#define PQ_GSS_RECV_BUFFER_SIZE 16384 + +/* + * We need these state variables per-connection. To allow the functions + * in this file to look mostly like those in be-secure-gssapi.c, set up + * these macros. + */ +#define PqGSSSendBuffer (conn->gss_SendBuffer) +#define PqGSSSendLength (conn->gss_SendLength) +#define PqGSSSendNext (conn->gss_SendNext) +#define PqGSSSendConsumed (conn->gss_SendConsumed) +#define PqGSSRecvBuffer (conn->gss_RecvBuffer) +#define PqGSSRecvLength (conn->gss_RecvLength) +#define PqGSSResultBuffer (conn->gss_ResultBuffer) +#define PqGSSResultLength (conn->gss_ResultLength) +#define PqGSSResultNext (conn->gss_ResultNext) +#define PqGSSMaxPktSize (conn->gss_MaxPktSize) + + +/* + * Attempt to write len bytes of data from ptr to a GSSAPI-encrypted connection. + * + * The connection must be already set up for GSSAPI encryption (i.e., GSSAPI + * transport negotiation is complete). + * + * On success, returns the number of data bytes consumed (possibly less than + * len). On failure, returns -1 with errno set appropriately. If the errno + * indicates a non-retryable error, a message is added to conn->errorMessage. + * For retryable errors, caller should call again (passing the same or more + * data) once the socket is ready. + */ +ssize_t +pg_GSS_write(PGconn *conn, const void *ptr, size_t len) +{ + OM_uint32 major, + minor; + gss_buffer_desc input, + output = GSS_C_EMPTY_BUFFER; + ssize_t ret = -1; + size_t bytes_to_encrypt; + size_t bytes_encrypted; + gss_ctx_id_t gctx = conn->gctx; + + /* + * When we get a retryable failure, we must not tell the caller we have + * successfully transmitted everything, else it won't retry. For + * simplicity, we claim we haven't transmitted anything until we have + * successfully transmitted all "len" bytes. Between calls, the amount of + * the current input data that's already been encrypted and placed into + * PqGSSSendBuffer (and perhaps transmitted) is remembered in + * PqGSSSendConsumed. On a retry, the caller *must* be sending that data + * again, so if it offers a len less than that, something is wrong. + * + * Note: it may seem attractive to report partial write completion once + * we've successfully sent any encrypted packets. However, that can cause + * problems for callers; notably, pqPutMsgEnd's heuristic to send only + * full 8K blocks interacts badly with such a hack. We won't save much, + * typically, by letting callers discard data early, so don't risk it. + */ + if (len < PqGSSSendConsumed) + { + appendPQExpBufferStr(&conn->errorMessage, + "GSSAPI caller failed to retransmit all data needing to be retried\n"); + errno = EINVAL; + return -1; + } + + /* Discount whatever source data we already encrypted. */ + bytes_to_encrypt = len - PqGSSSendConsumed; + bytes_encrypted = PqGSSSendConsumed; + + /* + * Loop through encrypting data and sending it out until it's all done or + * pqsecure_raw_write() complains (which would likely mean that the socket + * is non-blocking and the requested send() would block, or there was some + * kind of actual error). + */ + while (bytes_to_encrypt || PqGSSSendLength) + { + int conf_state = 0; + uint32 netlen; + + /* + * Check if we have data in the encrypted output buffer that needs to + * be sent (possibly left over from a previous call), and if so, try + * to send it. If we aren't able to, return that fact back up to the + * caller. + */ + if (PqGSSSendLength) + { + ssize_t retval; + ssize_t amount = PqGSSSendLength - PqGSSSendNext; + + retval = pqsecure_raw_write(conn, PqGSSSendBuffer + PqGSSSendNext, amount); + if (retval <= 0) + return retval; + + /* + * Check if this was a partial write, and if so, move forward that + * far in our buffer and try again. + */ + if (retval < amount) + { + PqGSSSendNext += retval; + continue; + } + + /* We've successfully sent whatever data was in the buffer. */ + PqGSSSendLength = PqGSSSendNext = 0; + } + + /* + * Check if there are any bytes left to encrypt. If not, we're done. + */ + if (!bytes_to_encrypt) + break; + + /* + * Check how much we are being asked to send, if it's too much, then + * we will have to loop and possibly be called multiple times to get + * through all the data. + */ + if (bytes_to_encrypt > PqGSSMaxPktSize) + input.length = PqGSSMaxPktSize; + else + input.length = bytes_to_encrypt; + + input.value = (char *) ptr + bytes_encrypted; + + output.value = NULL; + output.length = 0; + + /* + * Create the next encrypted packet. Any failure here is considered a + * hard failure, so we return -1 even if some data has been sent. + */ + major = gss_wrap(&minor, gctx, 1, GSS_C_QOP_DEFAULT, + &input, &conf_state, &output); + if (major != GSS_S_COMPLETE) + { + pg_GSS_error(libpq_gettext("GSSAPI wrap error"), conn, major, minor); + errno = EIO; /* for lack of a better idea */ + goto cleanup; + } + + if (conf_state == 0) + { + libpq_append_conn_error(conn, "outgoing GSSAPI message would not use confidentiality"); + errno = EIO; /* for lack of a better idea */ + goto cleanup; + } + + if (output.length > PQ_GSS_SEND_BUFFER_SIZE - sizeof(uint32)) + { + libpq_append_conn_error(conn, "client tried to send oversize GSSAPI packet (%zu > %zu)", + (size_t) output.length, + PQ_GSS_SEND_BUFFER_SIZE - sizeof(uint32)); + errno = EIO; /* for lack of a better idea */ + goto cleanup; + } + + bytes_encrypted += input.length; + bytes_to_encrypt -= input.length; + PqGSSSendConsumed += input.length; + + /* 4 network-order bytes of length, then payload */ + netlen = pg_hton32(output.length); + memcpy(PqGSSSendBuffer + PqGSSSendLength, &netlen, sizeof(uint32)); + PqGSSSendLength += sizeof(uint32); + + memcpy(PqGSSSendBuffer + PqGSSSendLength, output.value, output.length); + PqGSSSendLength += output.length; + + /* Release buffer storage allocated by GSSAPI */ + gss_release_buffer(&minor, &output); + } + + /* If we get here, our counters should all match up. */ + Assert(len == PqGSSSendConsumed); + Assert(len == bytes_encrypted); + + /* We're reporting all the data as sent, so reset PqGSSSendConsumed. */ + PqGSSSendConsumed = 0; + + ret = bytes_encrypted; + +cleanup: + /* Release GSSAPI buffer storage, if we didn't already */ + if (output.value != NULL) + gss_release_buffer(&minor, &output); + return ret; +} + +/* + * Read up to len bytes of data into ptr from a GSSAPI-encrypted connection. + * + * The connection must be already set up for GSSAPI encryption (i.e., GSSAPI + * transport negotiation is complete). + * + * Returns the number of data bytes read, or on failure, returns -1 + * with errno set appropriately. If the errno indicates a non-retryable + * error, a message is added to conn->errorMessage. For retryable errors, + * caller should call again once the socket is ready. + */ +ssize_t +pg_GSS_read(PGconn *conn, void *ptr, size_t len) +{ + OM_uint32 major, + minor; + gss_buffer_desc input = GSS_C_EMPTY_BUFFER, + output = GSS_C_EMPTY_BUFFER; + ssize_t ret; + size_t bytes_returned = 0; + gss_ctx_id_t gctx = conn->gctx; + + /* + * The plan here is to read one incoming encrypted packet into + * PqGSSRecvBuffer, decrypt it into PqGSSResultBuffer, and then dole out + * data from there to the caller. When we exhaust the current input + * packet, read another. + */ + while (bytes_returned < len) + { + int conf_state = 0; + + /* Check if we have data in our buffer that we can return immediately */ + if (PqGSSResultNext < PqGSSResultLength) + { + size_t bytes_in_buffer = PqGSSResultLength - PqGSSResultNext; + size_t bytes_to_copy = Min(bytes_in_buffer, len - bytes_returned); + + /* + * Copy the data from our result buffer into the caller's buffer, + * at the point where we last left off filling their buffer. + */ + memcpy((char *) ptr + bytes_returned, PqGSSResultBuffer + PqGSSResultNext, bytes_to_copy); + PqGSSResultNext += bytes_to_copy; + bytes_returned += bytes_to_copy; + + /* + * At this point, we've either filled the caller's buffer or + * emptied our result buffer. Either way, return to caller. In + * the second case, we could try to read another encrypted packet, + * but the odds are good that there isn't one available. (If this + * isn't true, we chose too small a max packet size.) In any + * case, there's no harm letting the caller process the data we've + * already returned. + */ + break; + } + + /* Result buffer is empty, so reset buffer pointers */ + PqGSSResultLength = PqGSSResultNext = 0; + + /* + * Because we chose above to return immediately as soon as we emit + * some data, bytes_returned must be zero at this point. Therefore + * the failure exits below can just return -1 without worrying about + * whether we already emitted some data. + */ + Assert(bytes_returned == 0); + + /* + * At this point, our result buffer is empty with more bytes being + * requested to be read. We are now ready to load the next packet and + * decrypt it (entirely) into our result buffer. + */ + + /* Collect the length if we haven't already */ + if (PqGSSRecvLength < sizeof(uint32)) + { + ret = pqsecure_raw_read(conn, PqGSSRecvBuffer + PqGSSRecvLength, + sizeof(uint32) - PqGSSRecvLength); + + /* If ret <= 0, pqsecure_raw_read already set the correct errno */ + if (ret <= 0) + return ret; + + PqGSSRecvLength += ret; + + /* If we still haven't got the length, return to the caller */ + if (PqGSSRecvLength < sizeof(uint32)) + { + errno = EWOULDBLOCK; + return -1; + } + } + + /* Decode the packet length and check for overlength packet */ + input.length = pg_ntoh32(*(uint32 *) PqGSSRecvBuffer); + + if (input.length > PQ_GSS_RECV_BUFFER_SIZE - sizeof(uint32)) + { + libpq_append_conn_error(conn, "oversize GSSAPI packet sent by the server (%zu > %zu)", + (size_t) input.length, + PQ_GSS_RECV_BUFFER_SIZE - sizeof(uint32)); + errno = EIO; /* for lack of a better idea */ + return -1; + } + + /* + * Read as much of the packet as we are able to on this call into + * wherever we left off from the last time we were called. + */ + ret = pqsecure_raw_read(conn, PqGSSRecvBuffer + PqGSSRecvLength, + input.length - (PqGSSRecvLength - sizeof(uint32))); + /* If ret <= 0, pqsecure_raw_read already set the correct errno */ + if (ret <= 0) + return ret; + + PqGSSRecvLength += ret; + + /* If we don't yet have the whole packet, return to the caller */ + if (PqGSSRecvLength - sizeof(uint32) < input.length) + { + errno = EWOULDBLOCK; + return -1; + } + + /* + * We now have the full packet and we can perform the decryption and + * refill our result buffer, then loop back up to pass data back to + * the caller. Note that error exits below here must take care of + * releasing the gss output buffer. + */ + output.value = NULL; + output.length = 0; + input.value = PqGSSRecvBuffer + sizeof(uint32); + + major = gss_unwrap(&minor, gctx, &input, &output, &conf_state, NULL); + if (major != GSS_S_COMPLETE) + { + pg_GSS_error(libpq_gettext("GSSAPI unwrap error"), conn, + major, minor); + ret = -1; + errno = EIO; /* for lack of a better idea */ + goto cleanup; + } + + if (conf_state == 0) + { + libpq_append_conn_error(conn, "incoming GSSAPI message did not use confidentiality"); + ret = -1; + errno = EIO; /* for lack of a better idea */ + goto cleanup; + } + + memcpy(PqGSSResultBuffer, output.value, output.length); + PqGSSResultLength = output.length; + + /* Our receive buffer is now empty, reset it */ + PqGSSRecvLength = 0; + + /* Release buffer storage allocated by GSSAPI */ + gss_release_buffer(&minor, &output); + } + + ret = bytes_returned; + +cleanup: + /* Release GSSAPI buffer storage, if we didn't already */ + if (output.value != NULL) + gss_release_buffer(&minor, &output); + return ret; +} + +/* + * Simple wrapper for reading from pqsecure_raw_read. + * + * This takes the same arguments as pqsecure_raw_read, plus an output parameter + * to return the number of bytes read. This handles if blocking would occur and + * if we detect EOF on the connection. + */ +static PostgresPollingStatusType +gss_read(PGconn *conn, void *recv_buffer, size_t length, ssize_t *ret) +{ + *ret = pqsecure_raw_read(conn, recv_buffer, length); + if (*ret < 0) + { + if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) + return PGRES_POLLING_READING; + else + return PGRES_POLLING_FAILED; + } + + /* Check for EOF */ + if (*ret == 0) + { + int result = pqReadReady(conn); + + if (result < 0) + return PGRES_POLLING_FAILED; + + if (!result) + return PGRES_POLLING_READING; + + *ret = pqsecure_raw_read(conn, recv_buffer, length); + if (*ret < 0) + { + if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) + return PGRES_POLLING_READING; + else + return PGRES_POLLING_FAILED; + } + if (*ret == 0) + return PGRES_POLLING_FAILED; + } + + return PGRES_POLLING_OK; +} + +/* + * Negotiate GSSAPI transport for a connection. When complete, returns + * PGRES_POLLING_OK. Will return PGRES_POLLING_READING or + * PGRES_POLLING_WRITING as appropriate whenever it would block, and + * PGRES_POLLING_FAILED if transport could not be negotiated. + */ +PostgresPollingStatusType +pqsecure_open_gss(PGconn *conn) +{ + ssize_t ret; + OM_uint32 major, + minor, + gss_flags = GSS_REQUIRED_FLAGS; + uint32 netlen; + PostgresPollingStatusType result; + gss_buffer_desc input = GSS_C_EMPTY_BUFFER, + output = GSS_C_EMPTY_BUFFER; + + /* + * If first time through for this connection, allocate buffers and + * initialize state variables. By malloc'ing the buffers separately, we + * ensure that they are sufficiently aligned for the length-word accesses + * that we do in some places in this file. + */ + if (PqGSSSendBuffer == NULL) + { + PqGSSSendBuffer = malloc(PQ_GSS_SEND_BUFFER_SIZE); + PqGSSRecvBuffer = malloc(PQ_GSS_RECV_BUFFER_SIZE); + PqGSSResultBuffer = malloc(PQ_GSS_RECV_BUFFER_SIZE); + if (!PqGSSSendBuffer || !PqGSSRecvBuffer || !PqGSSResultBuffer) + { + libpq_append_conn_error(conn, "out of memory"); + return PGRES_POLLING_FAILED; + } + PqGSSSendLength = PqGSSSendNext = PqGSSSendConsumed = 0; + PqGSSRecvLength = PqGSSResultLength = PqGSSResultNext = 0; + } + + /* + * Check if we have anything to send from a prior call and if so, send it. + */ + if (PqGSSSendLength) + { + ssize_t amount = PqGSSSendLength - PqGSSSendNext; + + ret = pqsecure_raw_write(conn, PqGSSSendBuffer + PqGSSSendNext, amount); + if (ret < 0) + { + if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) + return PGRES_POLLING_WRITING; + else + return PGRES_POLLING_FAILED; + } + + if (ret < amount) + { + PqGSSSendNext += ret; + return PGRES_POLLING_WRITING; + } + + PqGSSSendLength = PqGSSSendNext = 0; + } + + /* + * Client sends first, and sending creates a context, therefore this will + * be false the first time through, and then when we get called again we + * will check for incoming data. + */ + if (conn->gctx) + { + /* Process any incoming data we might have */ + + /* See if we are still trying to get the length */ + if (PqGSSRecvLength < sizeof(uint32)) + { + /* Attempt to get the length first */ + result = gss_read(conn, PqGSSRecvBuffer + PqGSSRecvLength, sizeof(uint32) - PqGSSRecvLength, &ret); + if (result != PGRES_POLLING_OK) + return result; + + PqGSSRecvLength += ret; + + if (PqGSSRecvLength < sizeof(uint32)) + return PGRES_POLLING_READING; + } + + /* + * Check if we got an error packet + * + * This is safe to do because we shouldn't ever get a packet over 8192 + * and therefore the actual length bytes, being that they are in + * network byte order, for any real packet will start with two zero + * bytes. + */ + if (PqGSSRecvBuffer[0] == 'E') + { + /* + * For an error packet during startup, we don't get a length, so + * simply read as much as we can fit into our buffer (as a string, + * so leave a spot at the end for a NULL byte too) and report that + * back to the caller. + */ + result = gss_read(conn, PqGSSRecvBuffer + PqGSSRecvLength, PQ_GSS_RECV_BUFFER_SIZE - PqGSSRecvLength - 1, &ret); + if (result != PGRES_POLLING_OK) + return result; + + PqGSSRecvLength += ret; + + Assert(PqGSSRecvLength < PQ_GSS_RECV_BUFFER_SIZE); + PqGSSRecvBuffer[PqGSSRecvLength] = '\0'; + appendPQExpBuffer(&conn->errorMessage, "%s\n", PqGSSRecvBuffer + 1); + + return PGRES_POLLING_FAILED; + } + + /* + * We should have the whole length at this point, so pull it out and + * then read whatever we have left of the packet + */ + + /* Get the length and check for over-length packet */ + input.length = pg_ntoh32(*(uint32 *) PqGSSRecvBuffer); + if (input.length > PQ_GSS_RECV_BUFFER_SIZE - sizeof(uint32)) + { + libpq_append_conn_error(conn, "oversize GSSAPI packet sent by the server (%zu > %zu)", + (size_t) input.length, + PQ_GSS_RECV_BUFFER_SIZE - sizeof(uint32)); + return PGRES_POLLING_FAILED; + } + + /* + * Read as much of the packet as we are able to on this call into + * wherever we left off from the last time we were called. + */ + result = gss_read(conn, PqGSSRecvBuffer + PqGSSRecvLength, + input.length - (PqGSSRecvLength - sizeof(uint32)), &ret); + if (result != PGRES_POLLING_OK) + return result; + + PqGSSRecvLength += ret; + + /* + * If we got less than the rest of the packet then we need to return + * and be called again. + */ + if (PqGSSRecvLength - sizeof(uint32) < input.length) + return PGRES_POLLING_READING; + + input.value = PqGSSRecvBuffer + sizeof(uint32); + } + + /* Load the service name (no-op if already done */ + ret = pg_GSS_load_servicename(conn); + if (ret != STATUS_OK) + return PGRES_POLLING_FAILED; + + if (conn->gssdelegation && conn->gssdelegation[0] == '1') + { + /* Acquire credentials if possible */ + if (conn->gcred == GSS_C_NO_CREDENTIAL) + (void) pg_GSS_have_cred_cache(&conn->gcred); + + /* + * We have credentials and gssdelegation is enabled, so request + * credential delegation. This may or may not actually result in + * credentials being delegated- it depends on if the forwardable flag + * has been set in the credential and if the server is configured to + * accept delegated credentials. + */ + if (conn->gcred != GSS_C_NO_CREDENTIAL) + gss_flags |= GSS_C_DELEG_FLAG; + } + + /* + * Call GSS init context, either with an empty input, or with a complete + * packet from the server. + */ + major = gss_init_sec_context(&minor, conn->gcred, &conn->gctx, + conn->gtarg_nam, GSS_C_NO_OID, + gss_flags, 0, 0, &input, NULL, + &output, NULL, NULL); + + /* GSS Init Sec Context uses the whole packet, so clear it */ + PqGSSRecvLength = 0; + + if (GSS_ERROR(major)) + { + pg_GSS_error(libpq_gettext("could not initiate GSSAPI security context"), + conn, major, minor); + return PGRES_POLLING_FAILED; + } + + if (output.length == 0) + { + /* + * We're done - hooray! Set flag to tell the low-level I/O routines + * to do GSS wrapping/unwrapping. + */ + conn->gssenc = true; + conn->gssapi_used = true; + + /* Clean up */ + gss_release_cred(&minor, &conn->gcred); + conn->gcred = GSS_C_NO_CREDENTIAL; + gss_release_buffer(&minor, &output); + + /* + * Determine the max packet size which will fit in our buffer, after + * accounting for the length. pg_GSS_write will need this. + */ + major = gss_wrap_size_limit(&minor, conn->gctx, 1, GSS_C_QOP_DEFAULT, + PQ_GSS_SEND_BUFFER_SIZE - sizeof(uint32), + &PqGSSMaxPktSize); + + if (GSS_ERROR(major)) + { + pg_GSS_error(libpq_gettext("GSSAPI size check error"), conn, + major, minor); + return PGRES_POLLING_FAILED; + } + + return PGRES_POLLING_OK; + } + + /* Must have output.length > 0 */ + if (output.length > PQ_GSS_SEND_BUFFER_SIZE - sizeof(uint32)) + { + pg_GSS_error(libpq_gettext("GSSAPI context establishment error"), + conn, major, minor); + gss_release_buffer(&minor, &output); + return PGRES_POLLING_FAILED; + } + + /* Queue the token for writing */ + netlen = pg_hton32(output.length); + + memcpy(PqGSSSendBuffer, (char *) &netlen, sizeof(uint32)); + PqGSSSendLength += sizeof(uint32); + + memcpy(PqGSSSendBuffer + PqGSSSendLength, output.value, output.length); + PqGSSSendLength += output.length; + + /* We don't bother with PqGSSSendConsumed here */ + + /* Release buffer storage allocated by GSSAPI */ + gss_release_buffer(&minor, &output); + + /* Ask to be called again to write data */ + return PGRES_POLLING_WRITING; +} + +/* + * GSSAPI Information functions. + */ + +/* + * Return the GSSAPI Context itself. + */ +void * +PQgetgssctx(PGconn *conn) +{ + if (!conn) + return NULL; + + return conn->gctx; +} + +/* + * Return true if GSSAPI encryption is in use. + */ +int +PQgssEncInUse(PGconn *conn) +{ + if (!conn || !conn->gctx) + return 0; + + return conn->gssenc; +} diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c new file mode 100644 index 0000000..25569e6 --- /dev/null +++ b/src/interfaces/libpq/fe-secure-openssl.c @@ -0,0 +1,2089 @@ +/*------------------------------------------------------------------------- + * + * fe-secure-openssl.c + * OpenSSL support + * + * + * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * src/interfaces/libpq/fe-secure-openssl.c + * + * NOTES + * + * We don't provide informational callbacks here (like + * info_cb() in be-secure-openssl.c), since there's no good mechanism to + * display such information to the user. + * + *------------------------------------------------------------------------- + */ + +#include "postgres_fe.h" + +#include <signal.h> +#include <fcntl.h> +#include <ctype.h> + +#include "libpq-fe.h" +#include "fe-auth.h" +#include "fe-secure-common.h" +#include "libpq-int.h" + +#ifdef WIN32 +#include "win32.h" +#else +#include <sys/socket.h> +#include <unistd.h> +#include <netdb.h> +#include <netinet/in.h> +#include <netinet/tcp.h> +#include <arpa/inet.h> +#endif + +#include <sys/stat.h> + +#ifdef ENABLE_THREAD_SAFETY +#ifdef WIN32 +#include "pthread-win32.h" +#else +#include <pthread.h> +#endif +#endif + +/* + * These SSL-related #includes must come after all system-provided headers. + * This ensures that OpenSSL can take care of conflicts with Windows' + * <wincrypt.h> by #undef'ing the conflicting macros. (We don't directly + * include <wincrypt.h>, but some other Windows headers do.) + */ +#include "common/openssl.h" +#include <openssl/conf.h> +#ifdef USE_SSL_ENGINE +#include <openssl/engine.h> +#endif +#include <openssl/x509v3.h> + + +static int verify_cb(int ok, X509_STORE_CTX *ctx); +static int openssl_verify_peer_name_matches_certificate_name(PGconn *conn, + ASN1_STRING *name_entry, + char **store_name); +static int openssl_verify_peer_name_matches_certificate_ip(PGconn *conn, + ASN1_OCTET_STRING *addr_entry, + char **store_name); +static void destroy_ssl_system(void); +static int initialize_SSL(PGconn *conn); +static PostgresPollingStatusType open_client_SSL(PGconn *conn); +static char *SSLerrmessage(unsigned long ecode); +static void SSLerrfree(char *buf); +static int PQssl_passwd_cb(char *buf, int size, int rwflag, void *userdata); + +static int my_sock_read(BIO *h, char *buf, int size); +static int my_sock_write(BIO *h, const char *buf, int size); +static BIO_METHOD *my_BIO_s_socket(void); +static int my_SSL_set_fd(PGconn *conn, int fd); + + +static bool pq_init_ssl_lib = true; +static bool pq_init_crypto_lib = true; + +static bool ssl_lib_initialized = false; + +#ifdef ENABLE_THREAD_SAFETY +static long crypto_open_connections = 0; + +#ifndef WIN32 +static pthread_mutex_t ssl_config_mutex = PTHREAD_MUTEX_INITIALIZER; +#else +static pthread_mutex_t ssl_config_mutex = NULL; +static long win32_ssl_create_mutex = 0; +#endif +#endif /* ENABLE_THREAD_SAFETY */ + +static PQsslKeyPassHook_OpenSSL_type PQsslKeyPassHook = NULL; +static int ssl_protocol_version_to_openssl(const char *protocol); + +/* ------------------------------------------------------------ */ +/* Procedures common to all secure sessions */ +/* ------------------------------------------------------------ */ + +void +pgtls_init_library(bool do_ssl, int do_crypto) +{ +#ifdef ENABLE_THREAD_SAFETY + + /* + * Disallow changing the flags while we have open connections, else we'd + * get completely confused. + */ + if (crypto_open_connections != 0) + return; +#endif + + pq_init_ssl_lib = do_ssl; + pq_init_crypto_lib = do_crypto; +} + +PostgresPollingStatusType +pgtls_open_client(PGconn *conn) +{ + /* First time through? */ + if (conn->ssl == NULL) + { + /* + * Create a connection-specific SSL object, and load client + * certificate, private key, and trusted CA certs. + */ + if (initialize_SSL(conn) != 0) + { + /* initialize_SSL already put a message in conn->errorMessage */ + pgtls_close(conn); + return PGRES_POLLING_FAILED; + } + } + + /* Begin or continue the actual handshake */ + return open_client_SSL(conn); +} + +ssize_t +pgtls_read(PGconn *conn, void *ptr, size_t len) +{ + ssize_t n; + int result_errno = 0; + char sebuf[PG_STRERROR_R_BUFLEN]; + int err; + unsigned long ecode; + +rloop: + + /* + * Prepare to call SSL_get_error() by clearing thread's OpenSSL error + * queue. In general, the current thread's error queue must be empty + * before the TLS/SSL I/O operation is attempted, or SSL_get_error() will + * not work reliably. Since the possibility exists that other OpenSSL + * clients running in the same thread but not under our control will fail + * to call ERR_get_error() themselves (after their own I/O operations), + * pro-actively clear the per-thread error queue now. + */ + SOCK_ERRNO_SET(0); + ERR_clear_error(); + n = SSL_read(conn->ssl, ptr, len); + err = SSL_get_error(conn->ssl, n); + + /* + * Other clients of OpenSSL may fail to call ERR_get_error(), but we + * always do, so as to not cause problems for OpenSSL clients that don't + * call ERR_clear_error() defensively. Be sure that this happens by + * calling now. SSL_get_error() relies on the OpenSSL per-thread error + * queue being intact, so this is the earliest possible point + * ERR_get_error() may be called. + */ + ecode = (err != SSL_ERROR_NONE || n < 0) ? ERR_get_error() : 0; + switch (err) + { + case SSL_ERROR_NONE: + if (n < 0) + { + /* Not supposed to happen, so we don't translate the msg */ + appendPQExpBufferStr(&conn->errorMessage, + "SSL_read failed but did not provide error information\n"); + /* assume the connection is broken */ + result_errno = ECONNRESET; + } + break; + case SSL_ERROR_WANT_READ: + n = 0; + break; + case SSL_ERROR_WANT_WRITE: + + /* + * Returning 0 here would cause caller to wait for read-ready, + * which is not correct since what SSL wants is wait for + * write-ready. The former could get us stuck in an infinite + * wait, so don't risk it; busy-loop instead. + */ + goto rloop; + case SSL_ERROR_SYSCALL: + if (n < 0 && SOCK_ERRNO != 0) + { + result_errno = SOCK_ERRNO; + if (result_errno == EPIPE || + result_errno == ECONNRESET) + libpq_append_conn_error(conn, "server closed the connection unexpectedly\n" + "\tThis probably means the server terminated abnormally\n" + "\tbefore or while processing the request."); + else + libpq_append_conn_error(conn, "SSL SYSCALL error: %s", + SOCK_STRERROR(result_errno, + sebuf, sizeof(sebuf))); + } + else + { + libpq_append_conn_error(conn, "SSL SYSCALL error: EOF detected"); + /* assume the connection is broken */ + result_errno = ECONNRESET; + n = -1; + } + break; + case SSL_ERROR_SSL: + { + char *errm = SSLerrmessage(ecode); + + libpq_append_conn_error(conn, "SSL error: %s", errm); + SSLerrfree(errm); + /* assume the connection is broken */ + result_errno = ECONNRESET; + n = -1; + break; + } + case SSL_ERROR_ZERO_RETURN: + + /* + * Per OpenSSL documentation, this error code is only returned for + * a clean connection closure, so we should not report it as a + * server crash. + */ + libpq_append_conn_error(conn, "SSL connection has been closed unexpectedly"); + result_errno = ECONNRESET; + n = -1; + break; + default: + libpq_append_conn_error(conn, "unrecognized SSL error code: %d", err); + /* assume the connection is broken */ + result_errno = ECONNRESET; + n = -1; + break; + } + + /* ensure we return the intended errno to caller */ + SOCK_ERRNO_SET(result_errno); + + return n; +} + +bool +pgtls_read_pending(PGconn *conn) +{ + return SSL_pending(conn->ssl) > 0; +} + +ssize_t +pgtls_write(PGconn *conn, const void *ptr, size_t len) +{ + ssize_t n; + int result_errno = 0; + char sebuf[PG_STRERROR_R_BUFLEN]; + int err; + unsigned long ecode; + + SOCK_ERRNO_SET(0); + ERR_clear_error(); + n = SSL_write(conn->ssl, ptr, len); + err = SSL_get_error(conn->ssl, n); + ecode = (err != SSL_ERROR_NONE || n < 0) ? ERR_get_error() : 0; + switch (err) + { + case SSL_ERROR_NONE: + if (n < 0) + { + /* Not supposed to happen, so we don't translate the msg */ + appendPQExpBufferStr(&conn->errorMessage, + "SSL_write failed but did not provide error information\n"); + /* assume the connection is broken */ + result_errno = ECONNRESET; + } + break; + case SSL_ERROR_WANT_READ: + + /* + * Returning 0 here causes caller to wait for write-ready, which + * is not really the right thing, but it's the best we can do. + */ + n = 0; + break; + case SSL_ERROR_WANT_WRITE: + n = 0; + break; + case SSL_ERROR_SYSCALL: + + /* + * If errno is still zero then assume it's a read EOF situation, + * and report EOF. (This seems possible because SSL_write can + * also do reads.) + */ + if (n < 0 && SOCK_ERRNO != 0) + { + result_errno = SOCK_ERRNO; + if (result_errno == EPIPE || result_errno == ECONNRESET) + libpq_append_conn_error(conn, "server closed the connection unexpectedly\n" + "\tThis probably means the server terminated abnormally\n" + "\tbefore or while processing the request."); + else + libpq_append_conn_error(conn, "SSL SYSCALL error: %s", + SOCK_STRERROR(result_errno, + sebuf, sizeof(sebuf))); + } + else + { + libpq_append_conn_error(conn, "SSL SYSCALL error: EOF detected"); + /* assume the connection is broken */ + result_errno = ECONNRESET; + n = -1; + } + break; + case SSL_ERROR_SSL: + { + char *errm = SSLerrmessage(ecode); + + libpq_append_conn_error(conn, "SSL error: %s", errm); + SSLerrfree(errm); + /* assume the connection is broken */ + result_errno = ECONNRESET; + n = -1; + break; + } + case SSL_ERROR_ZERO_RETURN: + + /* + * Per OpenSSL documentation, this error code is only returned for + * a clean connection closure, so we should not report it as a + * server crash. + */ + libpq_append_conn_error(conn, "SSL connection has been closed unexpectedly"); + result_errno = ECONNRESET; + n = -1; + break; + default: + libpq_append_conn_error(conn, "unrecognized SSL error code: %d", err); + /* assume the connection is broken */ + result_errno = ECONNRESET; + n = -1; + break; + } + + /* ensure we return the intended errno to caller */ + SOCK_ERRNO_SET(result_errno); + + return n; +} + +#if defined(HAVE_X509_GET_SIGNATURE_NID) || defined(HAVE_X509_GET_SIGNATURE_INFO) +char * +pgtls_get_peer_certificate_hash(PGconn *conn, size_t *len) +{ + X509 *peer_cert; + const EVP_MD *algo_type; + unsigned char hash[EVP_MAX_MD_SIZE]; /* size for SHA-512 */ + unsigned int hash_size; + int algo_nid; + char *cert_hash; + + *len = 0; + + if (!conn->peer) + return NULL; + + peer_cert = conn->peer; + + /* + * Get the signature algorithm of the certificate to determine the hash + * algorithm to use for the result. Prefer X509_get_signature_info(), + * introduced in OpenSSL 1.1.1, which can handle RSA-PSS signatures. + */ +#if HAVE_X509_GET_SIGNATURE_INFO + if (!X509_get_signature_info(peer_cert, &algo_nid, NULL, NULL, NULL)) +#else + if (!OBJ_find_sigid_algs(X509_get_signature_nid(peer_cert), + &algo_nid, NULL)) +#endif + { + libpq_append_conn_error(conn, "could not determine server certificate signature algorithm"); + return NULL; + } + + /* + * The TLS server's certificate bytes need to be hashed with SHA-256 if + * its signature algorithm is MD5 or SHA-1 as per RFC 5929 + * (https://tools.ietf.org/html/rfc5929#section-4.1). If something else + * is used, the same hash as the signature algorithm is used. + */ + switch (algo_nid) + { + case NID_md5: + case NID_sha1: + algo_type = EVP_sha256(); + break; + default: + algo_type = EVP_get_digestbynid(algo_nid); + if (algo_type == NULL) + { + libpq_append_conn_error(conn, "could not find digest for NID %s", + OBJ_nid2sn(algo_nid)); + return NULL; + } + break; + } + + if (!X509_digest(peer_cert, algo_type, hash, &hash_size)) + { + libpq_append_conn_error(conn, "could not generate peer certificate hash"); + return NULL; + } + + /* save result */ + cert_hash = malloc(hash_size); + if (cert_hash == NULL) + { + libpq_append_conn_error(conn, "out of memory"); + return NULL; + } + memcpy(cert_hash, hash, hash_size); + *len = hash_size; + + return cert_hash; +} +#endif /* HAVE_X509_GET_SIGNATURE_NID */ + +/* ------------------------------------------------------------ */ +/* OpenSSL specific code */ +/* ------------------------------------------------------------ */ + +/* + * Certificate verification callback + * + * This callback allows us to log intermediate problems during + * verification, but there doesn't seem to be a clean way to get + * our PGconn * structure. So we can't log anything! + * + * This callback also allows us to override the default acceptance + * criteria (e.g., accepting self-signed or expired certs), but + * for now we accept the default checks. + */ +static int +verify_cb(int ok, X509_STORE_CTX *ctx) +{ + return ok; +} + +#ifdef HAVE_SSL_CTX_SET_CERT_CB +/* + * Certificate selection callback + * + * This callback lets us choose the client certificate we send to the server + * after seeing its CertificateRequest. We only support sending a single + * hard-coded certificate via sslcert, so we don't actually set any certificates + * here; we just use it to record whether or not the server has actually asked + * for one and whether we have one to send. + */ +static int +cert_cb(SSL *ssl, void *arg) +{ + PGconn *conn = arg; + + conn->ssl_cert_requested = true; + + /* Do we have a certificate loaded to send back? */ + if (SSL_get_certificate(ssl)) + conn->ssl_cert_sent = true; + + /* + * Tell OpenSSL that the callback succeeded; we're not required to + * actually make any changes to the SSL handle. + */ + return 1; +} +#endif + +/* + * OpenSSL-specific wrapper around + * pq_verify_peer_name_matches_certificate_name(), converting the ASN1_STRING + * into a plain C string. + */ +static int +openssl_verify_peer_name_matches_certificate_name(PGconn *conn, ASN1_STRING *name_entry, + char **store_name) +{ + int len; + const unsigned char *namedata; + + /* Should not happen... */ + if (name_entry == NULL) + { + libpq_append_conn_error(conn, "SSL certificate's name entry is missing"); + return -1; + } + + /* + * GEN_DNS can be only IA5String, equivalent to US ASCII. + */ +#ifdef HAVE_ASN1_STRING_GET0_DATA + namedata = ASN1_STRING_get0_data(name_entry); +#else + namedata = ASN1_STRING_data(name_entry); +#endif + len = ASN1_STRING_length(name_entry); + + /* OK to cast from unsigned to plain char, since it's all ASCII. */ + return pq_verify_peer_name_matches_certificate_name(conn, (const char *) namedata, len, store_name); +} + +/* + * OpenSSL-specific wrapper around + * pq_verify_peer_name_matches_certificate_ip(), converting the + * ASN1_OCTET_STRING into a plain C string. + */ +static int +openssl_verify_peer_name_matches_certificate_ip(PGconn *conn, + ASN1_OCTET_STRING *addr_entry, + char **store_name) +{ + int len; + const unsigned char *addrdata; + + /* Should not happen... */ + if (addr_entry == NULL) + { + libpq_append_conn_error(conn, "SSL certificate's address entry is missing"); + return -1; + } + + /* + * GEN_IPADD is an OCTET STRING containing an IP address in network byte + * order. + */ +#ifdef HAVE_ASN1_STRING_GET0_DATA + addrdata = ASN1_STRING_get0_data(addr_entry); +#else + addrdata = ASN1_STRING_data(addr_entry); +#endif + len = ASN1_STRING_length(addr_entry); + + return pq_verify_peer_name_matches_certificate_ip(conn, addrdata, len, store_name); +} + +static bool +is_ip_address(const char *host) +{ + struct in_addr dummy4; +#ifdef HAVE_INET_PTON + struct in6_addr dummy6; +#endif + + return inet_aton(host, &dummy4) +#ifdef HAVE_INET_PTON + || (inet_pton(AF_INET6, host, &dummy6) == 1) +#endif + ; +} + +/* + * Verify that the server certificate matches the hostname we connected to. + * + * The certificate's Common Name and Subject Alternative Names are considered. + */ +int +pgtls_verify_peer_name_matches_certificate_guts(PGconn *conn, + int *names_examined, + char **first_name) +{ + STACK_OF(GENERAL_NAME) * peer_san; + int i; + int rc = 0; + char *host = conn->connhost[conn->whichhost].host; + int host_type; + bool check_cn = true; + + Assert(host && host[0]); /* should be guaranteed by caller */ + + /* + * We try to match the NSS behavior here, which is a slight departure from + * the spec but seems to make more intuitive sense: + * + * If connhost contains a DNS name, and the certificate's SANs contain any + * dNSName entries, then we'll ignore the Subject Common Name entirely; + * otherwise, we fall back to checking the CN. (This behavior matches the + * RFC.) + * + * If connhost contains an IP address, and the SANs contain iPAddress + * entries, we again ignore the CN. Otherwise, we allow the CN to match, + * EVEN IF there is a dNSName in the SANs. (RFC 6125 prohibits this: "A + * client MUST NOT seek a match for a reference identifier of CN-ID if the + * presented identifiers include a DNS-ID, SRV-ID, URI-ID, or any + * application-specific identifier types supported by the client.") + * + * NOTE: Prior versions of libpq did not consider iPAddress entries at + * all, so this new behavior might break a certificate that has different + * IP addresses in the Subject CN and the SANs. + */ + if (is_ip_address(host)) + host_type = GEN_IPADD; + else + host_type = GEN_DNS; + + /* + * First, get the Subject Alternative Names (SANs) from the certificate, + * and compare them against the originally given hostname. + */ + peer_san = (STACK_OF(GENERAL_NAME) *) + X509_get_ext_d2i(conn->peer, NID_subject_alt_name, NULL, NULL); + + if (peer_san) + { + int san_len = sk_GENERAL_NAME_num(peer_san); + + for (i = 0; i < san_len; i++) + { + const GENERAL_NAME *name = sk_GENERAL_NAME_value(peer_san, i); + char *alt_name = NULL; + + if (name->type == host_type) + { + /* + * This SAN is of the same type (IP or DNS) as our host name, + * so don't allow a fallback check of the CN. + */ + check_cn = false; + } + + if (name->type == GEN_DNS) + { + (*names_examined)++; + rc = openssl_verify_peer_name_matches_certificate_name(conn, + name->d.dNSName, + &alt_name); + } + else if (name->type == GEN_IPADD) + { + (*names_examined)++; + rc = openssl_verify_peer_name_matches_certificate_ip(conn, + name->d.iPAddress, + &alt_name); + } + + if (alt_name) + { + if (!*first_name) + *first_name = alt_name; + else + free(alt_name); + } + + if (rc != 0) + { + /* + * Either we hit an error or a match, and either way we should + * not fall back to the CN. + */ + check_cn = false; + break; + } + } + sk_GENERAL_NAME_pop_free(peer_san, GENERAL_NAME_free); + } + + /* + * If there is no subjectAltName extension of the matching type, check the + * Common Name. + * + * (Per RFC 2818 and RFC 6125, if the subjectAltName extension of type + * dNSName is present, the CN must be ignored. We break this rule if host + * is an IP address; see the comment above.) + */ + if (check_cn) + { + X509_NAME *subject_name; + + subject_name = X509_get_subject_name(conn->peer); + if (subject_name != NULL) + { + int cn_index; + + cn_index = X509_NAME_get_index_by_NID(subject_name, + NID_commonName, -1); + if (cn_index >= 0) + { + char *common_name = NULL; + + (*names_examined)++; + rc = openssl_verify_peer_name_matches_certificate_name(conn, + X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subject_name, cn_index)), + &common_name); + + if (common_name) + { + if (!*first_name) + *first_name = common_name; + else + free(common_name); + } + } + } + } + + return rc; +} + +#if defined(ENABLE_THREAD_SAFETY) && defined(HAVE_CRYPTO_LOCK) +/* + * Callback functions for OpenSSL internal locking. (OpenSSL 1.1.0 + * does its own locking, and doesn't need these anymore. The + * CRYPTO_lock() function was removed in 1.1.0, when the callbacks + * were made obsolete, so we assume that if CRYPTO_lock() exists, + * the callbacks are still required.) + */ + +static unsigned long +pq_threadidcallback(void) +{ + /* + * This is not standards-compliant. pthread_self() returns pthread_t, and + * shouldn't be cast to unsigned long, but CRYPTO_set_id_callback requires + * it, so we have to do it. + */ + return (unsigned long) pthread_self(); +} + +static pthread_mutex_t *pq_lockarray; + +static void +pq_lockingcallback(int mode, int n, const char *file, int line) +{ + /* + * There's no way to report a mutex-primitive failure, so we just Assert + * in development builds, and ignore any errors otherwise. Fortunately + * this is all obsolete in modern OpenSSL. + */ + if (mode & CRYPTO_LOCK) + { + if (pthread_mutex_lock(&pq_lockarray[n])) + Assert(false); + } + else + { + if (pthread_mutex_unlock(&pq_lockarray[n])) + Assert(false); + } +} +#endif /* ENABLE_THREAD_SAFETY && HAVE_CRYPTO_LOCK */ + +/* + * Initialize SSL library. + * + * In threadsafe mode, this includes setting up libcrypto callback functions + * to do thread locking. + * + * If the caller has told us (through PQinitOpenSSL) that he's taking care + * of libcrypto, we expect that callbacks are already set, and won't try to + * override it. + */ +int +pgtls_init(PGconn *conn, bool do_ssl, bool do_crypto) +{ +#ifdef ENABLE_THREAD_SAFETY +#ifdef WIN32 + /* Also see similar code in fe-connect.c, default_threadlock() */ + if (ssl_config_mutex == NULL) + { + while (InterlockedExchange(&win32_ssl_create_mutex, 1) == 1) + /* loop, another thread own the lock */ ; + if (ssl_config_mutex == NULL) + { + if (pthread_mutex_init(&ssl_config_mutex, NULL)) + return -1; + } + InterlockedExchange(&win32_ssl_create_mutex, 0); + } +#endif + if (pthread_mutex_lock(&ssl_config_mutex)) + return -1; + +#ifdef HAVE_CRYPTO_LOCK + if (pq_init_crypto_lib) + { + /* + * If necessary, set up an array to hold locks for libcrypto. + * libcrypto will tell us how big to make this array. + */ + if (pq_lockarray == NULL) + { + int i; + + pq_lockarray = malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks()); + if (!pq_lockarray) + { + pthread_mutex_unlock(&ssl_config_mutex); + return -1; + } + for (i = 0; i < CRYPTO_num_locks(); i++) + { + if (pthread_mutex_init(&pq_lockarray[i], NULL)) + { + free(pq_lockarray); + pq_lockarray = NULL; + pthread_mutex_unlock(&ssl_config_mutex); + return -1; + } + } + } + + if (do_crypto && !conn->crypto_loaded) + { + if (crypto_open_connections++ == 0) + { + /* + * These are only required for threaded libcrypto + * applications, but make sure we don't stomp on them if + * they're already set. + */ + if (CRYPTO_get_id_callback() == NULL) + CRYPTO_set_id_callback(pq_threadidcallback); + if (CRYPTO_get_locking_callback() == NULL) + CRYPTO_set_locking_callback(pq_lockingcallback); + } + + conn->crypto_loaded = true; + } + } +#endif /* HAVE_CRYPTO_LOCK */ +#endif /* ENABLE_THREAD_SAFETY */ + + if (!ssl_lib_initialized && do_ssl) + { + if (pq_init_ssl_lib) + { +#ifdef HAVE_OPENSSL_INIT_SSL + OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL); +#else + OPENSSL_config(NULL); + SSL_library_init(); + SSL_load_error_strings(); +#endif + } + ssl_lib_initialized = true; + } + +#ifdef ENABLE_THREAD_SAFETY + pthread_mutex_unlock(&ssl_config_mutex); +#endif + return 0; +} + +/* + * This function is needed because if the libpq library is unloaded + * from the application, the callback functions will no longer exist when + * libcrypto is used by other parts of the system. For this reason, + * we unregister the callback functions when the last libpq + * connection is closed. (The same would apply for OpenSSL callbacks + * if we had any.) + * + * Callbacks are only set when we're compiled in threadsafe mode, so + * we only need to remove them in this case. They are also not needed + * with OpenSSL 1.1.0 anymore. + */ +static void +destroy_ssl_system(void) +{ +#if defined(ENABLE_THREAD_SAFETY) && defined(HAVE_CRYPTO_LOCK) + /* Mutex is created in pgtls_init() */ + if (pthread_mutex_lock(&ssl_config_mutex)) + return; + + if (pq_init_crypto_lib && crypto_open_connections > 0) + --crypto_open_connections; + + if (pq_init_crypto_lib && crypto_open_connections == 0) + { + /* + * No connections left, unregister libcrypto callbacks, if no one + * registered different ones in the meantime. + */ + if (CRYPTO_get_locking_callback() == pq_lockingcallback) + CRYPTO_set_locking_callback(NULL); + if (CRYPTO_get_id_callback() == pq_threadidcallback) + CRYPTO_set_id_callback(NULL); + + /* + * We don't free the lock array. If we get another connection in this + * process, we will just re-use them with the existing mutexes. + * + * This means we leak a little memory on repeated load/unload of the + * library. + */ + } + + pthread_mutex_unlock(&ssl_config_mutex); +#endif +} + +/* + * Create per-connection SSL object, and load the client certificate, + * private key, and trusted CA certs. + * + * Returns 0 if OK, -1 on failure (with a message in conn->errorMessage). + */ +static int +initialize_SSL(PGconn *conn) +{ + SSL_CTX *SSL_context; + struct stat buf; + char homedir[MAXPGPATH]; + char fnbuf[MAXPGPATH]; + char sebuf[PG_STRERROR_R_BUFLEN]; + bool have_homedir; + bool have_cert; + bool have_rootcert; + EVP_PKEY *pkey = NULL; + + /* + * We'll need the home directory if any of the relevant parameters are + * defaulted. If pqGetHomeDirectory fails, act as though none of the + * files could be found. + */ + if (!(conn->sslcert && strlen(conn->sslcert) > 0) || + !(conn->sslkey && strlen(conn->sslkey) > 0) || + !(conn->sslrootcert && strlen(conn->sslrootcert) > 0) || + !((conn->sslcrl && strlen(conn->sslcrl) > 0) || + (conn->sslcrldir && strlen(conn->sslcrldir) > 0))) + have_homedir = pqGetHomeDirectory(homedir, sizeof(homedir)); + else /* won't need it */ + have_homedir = false; + + /* + * Create a new SSL_CTX object. + * + * We used to share a single SSL_CTX between all connections, but it was + * complicated if connections used different certificates. So now we + * create a separate context for each connection, and accept the overhead. + */ + SSL_context = SSL_CTX_new(SSLv23_method()); + if (!SSL_context) + { + char *err = SSLerrmessage(ERR_get_error()); + + libpq_append_conn_error(conn, "could not create SSL context: %s", err); + SSLerrfree(err); + return -1; + } + + /* + * Delegate the client cert password prompt to the libpq wrapper callback + * if any is defined. + * + * If the application hasn't installed its own and the sslpassword + * parameter is non-null, we install ours now to make sure we supply + * PGconn->sslpassword to OpenSSL instead of letting it prompt on stdin. + * + * This will replace OpenSSL's default PEM_def_callback (which prompts on + * stdin), but we're only setting it for this SSL context so it's + * harmless. + */ + if (PQsslKeyPassHook + || (conn->sslpassword && strlen(conn->sslpassword) > 0)) + { + SSL_CTX_set_default_passwd_cb(SSL_context, PQssl_passwd_cb); + SSL_CTX_set_default_passwd_cb_userdata(SSL_context, conn); + } + +#ifdef HAVE_SSL_CTX_SET_CERT_CB + /* Set up a certificate selection callback. */ + SSL_CTX_set_cert_cb(SSL_context, cert_cb, conn); +#endif + + /* Disable old protocol versions */ + SSL_CTX_set_options(SSL_context, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); + + /* Set the minimum and maximum protocol versions if necessary */ + if (conn->ssl_min_protocol_version && + strlen(conn->ssl_min_protocol_version) != 0) + { + int ssl_min_ver; + + ssl_min_ver = ssl_protocol_version_to_openssl(conn->ssl_min_protocol_version); + + if (ssl_min_ver == -1) + { + libpq_append_conn_error(conn, "invalid value \"%s\" for minimum SSL protocol version", + conn->ssl_min_protocol_version); + SSL_CTX_free(SSL_context); + return -1; + } + + if (!SSL_CTX_set_min_proto_version(SSL_context, ssl_min_ver)) + { + char *err = SSLerrmessage(ERR_get_error()); + + libpq_append_conn_error(conn, "could not set minimum SSL protocol version: %s", err); + SSLerrfree(err); + SSL_CTX_free(SSL_context); + return -1; + } + } + + if (conn->ssl_max_protocol_version && + strlen(conn->ssl_max_protocol_version) != 0) + { + int ssl_max_ver; + + ssl_max_ver = ssl_protocol_version_to_openssl(conn->ssl_max_protocol_version); + + if (ssl_max_ver == -1) + { + libpq_append_conn_error(conn, "invalid value \"%s\" for maximum SSL protocol version", + conn->ssl_max_protocol_version); + SSL_CTX_free(SSL_context); + return -1; + } + + if (!SSL_CTX_set_max_proto_version(SSL_context, ssl_max_ver)) + { + char *err = SSLerrmessage(ERR_get_error()); + + libpq_append_conn_error(conn, "could not set maximum SSL protocol version: %s", err); + SSLerrfree(err); + SSL_CTX_free(SSL_context); + return -1; + } + } + + /* + * Disable OpenSSL's moving-write-buffer sanity check, because it causes + * unnecessary failures in nonblocking send cases. + */ + SSL_CTX_set_mode(SSL_context, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); + + /* + * If the root cert file exists, load it so we can perform certificate + * verification. If sslmode is "verify-full" we will also do further + * verification after the connection has been completed. + */ + if (conn->sslrootcert && strlen(conn->sslrootcert) > 0) + strlcpy(fnbuf, conn->sslrootcert, sizeof(fnbuf)); + else if (have_homedir) + snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, ROOT_CERT_FILE); + else + fnbuf[0] = '\0'; + + if (strcmp(fnbuf, "system") == 0) + { + /* + * The "system" sentinel value indicates that we should load whatever + * root certificates are installed for use by OpenSSL; these locations + * differ by platform. Note that the default system locations may be + * further overridden by the SSL_CERT_DIR and SSL_CERT_FILE + * environment variables. + */ + if (SSL_CTX_set_default_verify_paths(SSL_context) != 1) + { + char *err = SSLerrmessage(ERR_get_error()); + + libpq_append_conn_error(conn, "could not load system root certificate paths: %s", + err); + SSLerrfree(err); + SSL_CTX_free(SSL_context); + return -1; + } + have_rootcert = true; + } + else if (fnbuf[0] != '\0' && + stat(fnbuf, &buf) == 0) + { + X509_STORE *cvstore; + + if (SSL_CTX_load_verify_locations(SSL_context, fnbuf, NULL) != 1) + { + char *err = SSLerrmessage(ERR_get_error()); + + libpq_append_conn_error(conn, "could not read root certificate file \"%s\": %s", + fnbuf, err); + SSLerrfree(err); + SSL_CTX_free(SSL_context); + return -1; + } + + if ((cvstore = SSL_CTX_get_cert_store(SSL_context)) != NULL) + { + char *fname = NULL; + char *dname = NULL; + + if (conn->sslcrl && strlen(conn->sslcrl) > 0) + fname = conn->sslcrl; + if (conn->sslcrldir && strlen(conn->sslcrldir) > 0) + dname = conn->sslcrldir; + + /* defaults to use the default CRL file */ + if (!fname && !dname && have_homedir) + { + snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, ROOT_CRL_FILE); + fname = fnbuf; + } + + /* Set the flags to check against the complete CRL chain */ + if ((fname || dname) && + X509_STORE_load_locations(cvstore, fname, dname) == 1) + { + X509_STORE_set_flags(cvstore, + X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); + } + + /* if not found, silently ignore; we do not require CRL */ + ERR_clear_error(); + } + have_rootcert = true; + } + else + { + /* + * stat() failed; assume root file doesn't exist. If sslmode is + * verify-ca or verify-full, this is an error. Otherwise, continue + * without performing any server cert verification. + */ + if (conn->sslmode[0] == 'v') /* "verify-ca" or "verify-full" */ + { + /* + * The only way to reach here with an empty filename is if + * pqGetHomeDirectory failed. That's a sufficiently unusual case + * that it seems worth having a specialized error message for it. + */ + if (fnbuf[0] == '\0') + libpq_append_conn_error(conn, "could not get home directory to locate root certificate file\n" + "Either provide the file, use the system's trusted roots with sslrootcert=system, or change sslmode to disable server certificate verification."); + else + libpq_append_conn_error(conn, "root certificate file \"%s\" does not exist\n" + "Either provide the file, use the system's trusted roots with sslrootcert=system, or change sslmode to disable server certificate verification.", fnbuf); + SSL_CTX_free(SSL_context); + return -1; + } + have_rootcert = false; + } + + /* Read the client certificate file */ + if (conn->sslcert && strlen(conn->sslcert) > 0) + strlcpy(fnbuf, conn->sslcert, sizeof(fnbuf)); + else if (have_homedir) + snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_CERT_FILE); + else + fnbuf[0] = '\0'; + + if (conn->sslcertmode[0] == 'd') /* disable */ + { + /* don't send a client cert even if we have one */ + have_cert = false; + } + else if (fnbuf[0] == '\0') + { + /* no home directory, proceed without a client cert */ + have_cert = false; + } + else if (stat(fnbuf, &buf) != 0) + { + /* + * If file is not present, just go on without a client cert; server + * might or might not accept the connection. Any other error, + * however, is grounds for complaint. + */ + if (errno != ENOENT && errno != ENOTDIR) + { + libpq_append_conn_error(conn, "could not open certificate file \"%s\": %s", + fnbuf, strerror_r(errno, sebuf, sizeof(sebuf))); + SSL_CTX_free(SSL_context); + return -1; + } + have_cert = false; + } + else + { + /* + * Cert file exists, so load it. Since OpenSSL doesn't provide the + * equivalent of "SSL_use_certificate_chain_file", we have to load it + * into the SSL context, rather than the SSL object. + */ + if (SSL_CTX_use_certificate_chain_file(SSL_context, fnbuf) != 1) + { + char *err = SSLerrmessage(ERR_get_error()); + + libpq_append_conn_error(conn, "could not read certificate file \"%s\": %s", + fnbuf, err); + SSLerrfree(err); + SSL_CTX_free(SSL_context); + return -1; + } + + /* need to load the associated private key, too */ + have_cert = true; + } + + /* + * The SSL context is now loaded with the correct root and client + * certificates. Create a connection-specific SSL object. The private key + * is loaded directly into the SSL object. (We could load the private key + * into the context, too, but we have done it this way historically, and + * it doesn't really matter.) + */ + if (!(conn->ssl = SSL_new(SSL_context)) || + !SSL_set_app_data(conn->ssl, conn) || + !my_SSL_set_fd(conn, conn->sock)) + { + char *err = SSLerrmessage(ERR_get_error()); + + libpq_append_conn_error(conn, "could not establish SSL connection: %s", err); + SSLerrfree(err); + SSL_CTX_free(SSL_context); + return -1; + } + conn->ssl_in_use = true; + + /* + * SSL contexts are reference counted by OpenSSL. We can free it as soon + * as we have created the SSL object, and it will stick around for as long + * as it's actually needed. + */ + SSL_CTX_free(SSL_context); + SSL_context = NULL; + + /* + * Set Server Name Indication (SNI), if enabled by connection parameters. + * Per RFC 6066, do not set it if the host is a literal IP address (IPv4 + * or IPv6). + */ + if (conn->sslsni && conn->sslsni[0] == '1') + { + const char *host = conn->connhost[conn->whichhost].host; + + if (host && host[0] && + !(strspn(host, "0123456789.") == strlen(host) || + strchr(host, ':'))) + { + if (SSL_set_tlsext_host_name(conn->ssl, host) != 1) + { + char *err = SSLerrmessage(ERR_get_error()); + + libpq_append_conn_error(conn, "could not set SSL Server Name Indication (SNI): %s", err); + SSLerrfree(err); + return -1; + } + } + } + + /* + * Read the SSL key. If a key is specified, treat it as an engine:key + * combination if there is colon present - we don't support files with + * colon in the name. The exception is if the second character is a colon, + * in which case it can be a Windows filename with drive specification. + */ + if (have_cert && conn->sslkey && strlen(conn->sslkey) > 0) + { +#ifdef USE_SSL_ENGINE + if (strchr(conn->sslkey, ':') +#ifdef WIN32 + && conn->sslkey[1] != ':' +#endif + ) + { + /* Colon, but not in second character, treat as engine:key */ + char *engine_str = strdup(conn->sslkey); + char *engine_colon; + + if (engine_str == NULL) + { + libpq_append_conn_error(conn, "out of memory"); + return -1; + } + + /* cannot return NULL because we already checked before strdup */ + engine_colon = strchr(engine_str, ':'); + + *engine_colon = '\0'; /* engine_str now has engine name */ + engine_colon++; /* engine_colon now has key name */ + + conn->engine = ENGINE_by_id(engine_str); + if (conn->engine == NULL) + { + char *err = SSLerrmessage(ERR_get_error()); + + libpq_append_conn_error(conn, "could not load SSL engine \"%s\": %s", + engine_str, err); + SSLerrfree(err); + free(engine_str); + return -1; + } + + if (ENGINE_init(conn->engine) == 0) + { + char *err = SSLerrmessage(ERR_get_error()); + + libpq_append_conn_error(conn, "could not initialize SSL engine \"%s\": %s", + engine_str, err); + SSLerrfree(err); + ENGINE_free(conn->engine); + conn->engine = NULL; + free(engine_str); + return -1; + } + + pkey = ENGINE_load_private_key(conn->engine, engine_colon, + NULL, NULL); + if (pkey == NULL) + { + char *err = SSLerrmessage(ERR_get_error()); + + libpq_append_conn_error(conn, "could not read private SSL key \"%s\" from engine \"%s\": %s", + engine_colon, engine_str, err); + SSLerrfree(err); + ENGINE_finish(conn->engine); + ENGINE_free(conn->engine); + conn->engine = NULL; + free(engine_str); + return -1; + } + if (SSL_use_PrivateKey(conn->ssl, pkey) != 1) + { + char *err = SSLerrmessage(ERR_get_error()); + + libpq_append_conn_error(conn, "could not load private SSL key \"%s\" from engine \"%s\": %s", + engine_colon, engine_str, err); + SSLerrfree(err); + ENGINE_finish(conn->engine); + ENGINE_free(conn->engine); + conn->engine = NULL; + free(engine_str); + return -1; + } + + free(engine_str); + + fnbuf[0] = '\0'; /* indicate we're not going to load from a + * file */ + } + else +#endif /* USE_SSL_ENGINE */ + { + /* PGSSLKEY is not an engine, treat it as a filename */ + strlcpy(fnbuf, conn->sslkey, sizeof(fnbuf)); + } + } + else if (have_homedir) + { + /* No PGSSLKEY specified, load default file */ + snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_KEY_FILE); + } + else + fnbuf[0] = '\0'; + + if (have_cert && fnbuf[0] != '\0') + { + /* read the client key from file */ + + if (stat(fnbuf, &buf) != 0) + { + if (errno == ENOENT) + libpq_append_conn_error(conn, "certificate present, but not private key file \"%s\"", + fnbuf); + else + libpq_append_conn_error(conn, "could not stat private key file \"%s\": %m", + fnbuf); + return -1; + } + + /* Key file must be a regular file */ + if (!S_ISREG(buf.st_mode)) + { + libpq_append_conn_error(conn, "private key file \"%s\" is not a regular file", + fnbuf); + return -1; + } + + /* + * Refuse to load world-readable key files. We accept root-owned + * files with mode 0640 or less, so that we can access system-wide + * certificates if we have a supplementary group membership that + * allows us to read 'em. For files with non-root ownership, require + * mode 0600 or less. We need not check the file's ownership exactly; + * if we're able to read it despite it having such restrictive + * permissions, it must have the right ownership. + * + * Note: be very careful about tightening these rules. Some people + * expect, for example, that a client process running as root should + * be able to use a non-root-owned key file. + * + * Note that roughly similar checks are performed in + * src/backend/libpq/be-secure-common.c so any changes here may need + * to be made there as well. However, this code caters for the case + * of current user == root, while that code does not. + * + * Ideally we would do similar permissions checks on Windows, but it + * is not clear how that would work since Unix-style permissions may + * not be available. + */ +#if !defined(WIN32) && !defined(__CYGWIN__) + if (buf.st_uid == 0 ? + buf.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO) : + buf.st_mode & (S_IRWXG | S_IRWXO)) + { + libpq_append_conn_error(conn, + "private key file \"%s\" has group or world access; file must have permissions u=rw (0600) or less if owned by the current user, or permissions u=rw,g=r (0640) or less if owned by root", + fnbuf); + return -1; + } +#endif + + if (SSL_use_PrivateKey_file(conn->ssl, fnbuf, SSL_FILETYPE_PEM) != 1) + { + char *err = SSLerrmessage(ERR_get_error()); + + /* + * We'll try to load the file in DER (binary ASN.1) format, and if + * that fails too, report the original error. This could mask + * issues where there's something wrong with a DER-format cert, + * but we'd have to duplicate openssl's format detection to be + * smarter than this. We can't just probe for a leading -----BEGIN + * because PEM can have leading non-matching lines and blanks. + * OpenSSL doesn't expose its get_name(...) and its PEM routines + * don't differentiate between failure modes in enough detail to + * let us tell the difference between "not PEM, try DER" and + * "wrong password". + */ + if (SSL_use_PrivateKey_file(conn->ssl, fnbuf, SSL_FILETYPE_ASN1) != 1) + { + libpq_append_conn_error(conn, "could not load private key file \"%s\": %s", + fnbuf, err); + SSLerrfree(err); + return -1; + } + + SSLerrfree(err); + } + } + + /* verify that the cert and key go together */ + if (have_cert && + SSL_check_private_key(conn->ssl) != 1) + { + char *err = SSLerrmessage(ERR_get_error()); + + libpq_append_conn_error(conn, "certificate does not match private key file \"%s\": %s", + fnbuf, err); + SSLerrfree(err); + return -1; + } + + /* + * If a root cert was loaded, also set our certificate verification + * callback. + */ + if (have_rootcert) + SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, verify_cb); + + /* + * Set compression option if necessary. + */ + if (conn->sslcompression && conn->sslcompression[0] == '0') + SSL_set_options(conn->ssl, SSL_OP_NO_COMPRESSION); + else + SSL_clear_options(conn->ssl, SSL_OP_NO_COMPRESSION); + + return 0; +} + +/* + * Attempt to negotiate SSL connection. + */ +static PostgresPollingStatusType +open_client_SSL(PGconn *conn) +{ + int r; + + SOCK_ERRNO_SET(0); + ERR_clear_error(); + r = SSL_connect(conn->ssl); + if (r <= 0) + { + int save_errno = SOCK_ERRNO; + int err = SSL_get_error(conn->ssl, r); + unsigned long ecode; + + ecode = ERR_get_error(); + switch (err) + { + case SSL_ERROR_WANT_READ: + return PGRES_POLLING_READING; + + case SSL_ERROR_WANT_WRITE: + return PGRES_POLLING_WRITING; + + case SSL_ERROR_SYSCALL: + { + char sebuf[PG_STRERROR_R_BUFLEN]; + unsigned long vcode; + + vcode = SSL_get_verify_result(conn->ssl); + + /* + * If we get an X509 error here for failing to load the + * local issuer cert, without an error in the socket layer + * it means that verification failed due to a missing + * system CA pool without it being a protocol error. We + * inspect the sslrootcert setting to ensure that the user + * was using the system CA pool. For other errors, log + * them using the normal SYSCALL logging. + */ + if (save_errno == 0 && + vcode == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY && + strcmp(conn->sslrootcert, "system") == 0) + libpq_append_conn_error(conn, "SSL error: certificate verify failed: %s", + X509_verify_cert_error_string(vcode)); + else if (r == -1 && save_errno != 0) + libpq_append_conn_error(conn, "SSL SYSCALL error: %s", + SOCK_STRERROR(save_errno, sebuf, sizeof(sebuf))); + else + libpq_append_conn_error(conn, "SSL SYSCALL error: EOF detected"); + pgtls_close(conn); + return PGRES_POLLING_FAILED; + } + case SSL_ERROR_SSL: + { + char *err = SSLerrmessage(ecode); + + libpq_append_conn_error(conn, "SSL error: %s", err); + SSLerrfree(err); + switch (ERR_GET_REASON(ecode)) + { + /* + * UNSUPPORTED_PROTOCOL, WRONG_VERSION_NUMBER, and + * TLSV1_ALERT_PROTOCOL_VERSION have been observed + * when trying to communicate with an old OpenSSL + * library, or when the client and server specify + * disjoint protocol ranges. + * NO_PROTOCOLS_AVAILABLE occurs if there's a + * local misconfiguration (which can happen + * despite our checks, if openssl.cnf injects a + * limit we didn't account for). It's not very + * clear what would make OpenSSL return the other + * codes listed here, but a hint about protocol + * versions seems like it's appropriate for all. + */ + case SSL_R_NO_PROTOCOLS_AVAILABLE: + case SSL_R_UNSUPPORTED_PROTOCOL: + case SSL_R_BAD_PROTOCOL_VERSION_NUMBER: + case SSL_R_UNKNOWN_PROTOCOL: + case SSL_R_UNKNOWN_SSL_VERSION: + case SSL_R_UNSUPPORTED_SSL_VERSION: + case SSL_R_WRONG_SSL_VERSION: + case SSL_R_WRONG_VERSION_NUMBER: + case SSL_R_TLSV1_ALERT_PROTOCOL_VERSION: +#ifdef SSL_R_VERSION_TOO_HIGH + case SSL_R_VERSION_TOO_HIGH: + case SSL_R_VERSION_TOO_LOW: +#endif + libpq_append_conn_error(conn, "This may indicate that the server does not support any SSL protocol version between %s and %s.", + conn->ssl_min_protocol_version ? + conn->ssl_min_protocol_version : + MIN_OPENSSL_TLS_VERSION, + conn->ssl_max_protocol_version ? + conn->ssl_max_protocol_version : + MAX_OPENSSL_TLS_VERSION); + break; + default: + break; + } + pgtls_close(conn); + return PGRES_POLLING_FAILED; + } + + default: + libpq_append_conn_error(conn, "unrecognized SSL error code: %d", err); + pgtls_close(conn); + return PGRES_POLLING_FAILED; + } + } + + /* + * We already checked the server certificate in initialize_SSL() using + * SSL_CTX_set_verify(), if root.crt exists. + */ + + /* get server certificate */ + conn->peer = SSL_get_peer_certificate(conn->ssl); + if (conn->peer == NULL) + { + char *err = SSLerrmessage(ERR_get_error()); + + libpq_append_conn_error(conn, "certificate could not be obtained: %s", err); + SSLerrfree(err); + pgtls_close(conn); + return PGRES_POLLING_FAILED; + } + + if (!pq_verify_peer_name_matches_certificate(conn)) + { + pgtls_close(conn); + return PGRES_POLLING_FAILED; + } + + /* SSL handshake is complete */ + return PGRES_POLLING_OK; +} + +void +pgtls_close(PGconn *conn) +{ + bool destroy_needed = false; + + if (conn->ssl_in_use) + { + if (conn->ssl) + { + /* + * We can't destroy everything SSL-related here due to the + * possible later calls to OpenSSL routines which may need our + * thread callbacks, so set a flag here and check at the end. + */ + + SSL_shutdown(conn->ssl); + SSL_free(conn->ssl); + conn->ssl = NULL; + conn->ssl_in_use = false; + + destroy_needed = true; + } + + if (conn->peer) + { + X509_free(conn->peer); + conn->peer = NULL; + } + +#ifdef USE_SSL_ENGINE + if (conn->engine) + { + ENGINE_finish(conn->engine); + ENGINE_free(conn->engine); + conn->engine = NULL; + } +#endif + } + else + { + /* + * In the non-SSL case, just remove the crypto callbacks if the + * connection has then loaded. This code path has no dependency on + * any pending SSL calls. + */ + if (conn->crypto_loaded) + destroy_needed = true; + } + + /* + * This will remove our crypto locking hooks if this is the last + * connection using libcrypto which means we must wait to call it until + * after all the potential SSL calls have been made, otherwise we can end + * up with a race condition and possible deadlocks. + * + * See comments above destroy_ssl_system(). + */ + if (destroy_needed) + { + destroy_ssl_system(); + conn->crypto_loaded = false; + } +} + + +/* + * Obtain reason string for passed SSL errcode + * + * ERR_get_error() is used by caller to get errcode to pass here. + * + * Some caution is needed here since ERR_reason_error_string will + * return NULL if it doesn't recognize the error code. We don't + * want to return NULL ever. + */ +static char ssl_nomem[] = "out of memory allocating error description"; + +#define SSL_ERR_LEN 128 + +static char * +SSLerrmessage(unsigned long ecode) +{ + const char *errreason; + char *errbuf; + + errbuf = malloc(SSL_ERR_LEN); + if (!errbuf) + return ssl_nomem; + if (ecode == 0) + { + snprintf(errbuf, SSL_ERR_LEN, libpq_gettext("no SSL error reported")); + return errbuf; + } + errreason = ERR_reason_error_string(ecode); + if (errreason != NULL) + { + strlcpy(errbuf, errreason, SSL_ERR_LEN); + return errbuf; + } + snprintf(errbuf, SSL_ERR_LEN, libpq_gettext("SSL error code %lu"), ecode); + return errbuf; +} + +static void +SSLerrfree(char *buf) +{ + if (buf != ssl_nomem) + free(buf); +} + +/* ------------------------------------------------------------ */ +/* SSL information functions */ +/* ------------------------------------------------------------ */ + +/* + * Return pointer to OpenSSL object. + */ +void * +PQgetssl(PGconn *conn) +{ + if (!conn) + return NULL; + return conn->ssl; +} + +void * +PQsslStruct(PGconn *conn, const char *struct_name) +{ + if (!conn) + return NULL; + if (strcmp(struct_name, "OpenSSL") == 0) + return conn->ssl; + return NULL; +} + +const char *const * +PQsslAttributeNames(PGconn *conn) +{ + static const char *const openssl_attrs[] = { + "library", + "key_bits", + "cipher", + "compression", + "protocol", + NULL + }; + static const char *const empty_attrs[] = {NULL}; + + if (!conn) + { + /* Return attributes of default SSL library */ + return openssl_attrs; + } + + /* No attrs for unencrypted connection */ + if (conn->ssl == NULL) + return empty_attrs; + + return openssl_attrs; +} + +const char * +PQsslAttribute(PGconn *conn, const char *attribute_name) +{ + if (!conn) + { + /* PQsslAttribute(NULL, "library") reports the default SSL library */ + if (strcmp(attribute_name, "library") == 0) + return "OpenSSL"; + return NULL; + } + + /* All attributes read as NULL for a non-encrypted connection */ + if (conn->ssl == NULL) + return NULL; + + if (strcmp(attribute_name, "library") == 0) + return "OpenSSL"; + + if (strcmp(attribute_name, "key_bits") == 0) + { + static char sslbits_str[12]; + int sslbits; + + SSL_get_cipher_bits(conn->ssl, &sslbits); + snprintf(sslbits_str, sizeof(sslbits_str), "%d", sslbits); + return sslbits_str; + } + + if (strcmp(attribute_name, "cipher") == 0) + return SSL_get_cipher(conn->ssl); + + if (strcmp(attribute_name, "compression") == 0) + return SSL_get_current_compression(conn->ssl) ? "on" : "off"; + + if (strcmp(attribute_name, "protocol") == 0) + return SSL_get_version(conn->ssl); + + return NULL; /* unknown attribute */ +} + +/* + * Private substitute BIO: this does the sending and receiving using + * pqsecure_raw_write() and pqsecure_raw_read() instead, to allow those + * functions to disable SIGPIPE and give better error messages on I/O errors. + * + * These functions are closely modelled on the standard socket BIO in OpenSSL; + * see sock_read() and sock_write() in OpenSSL's crypto/bio/bss_sock.c. + * XXX OpenSSL 1.0.1e considers many more errcodes than just EINTR as reasons + * to retry; do we need to adopt their logic for that? + */ + +/* protected by ssl_config_mutex */ +static BIO_METHOD *my_bio_methods; + +static int +my_sock_read(BIO *h, char *buf, int size) +{ + int res; + + res = pqsecure_raw_read((PGconn *) BIO_get_app_data(h), buf, size); + BIO_clear_retry_flags(h); + if (res < 0) + { + /* If we were interrupted, tell caller to retry */ + switch (SOCK_ERRNO) + { +#ifdef EAGAIN + case EAGAIN: +#endif +#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN)) + case EWOULDBLOCK: +#endif + case EINTR: + BIO_set_retry_read(h); + break; + + default: + break; + } + } + + return res; +} + +static int +my_sock_write(BIO *h, const char *buf, int size) +{ + int res; + + res = pqsecure_raw_write((PGconn *) BIO_get_app_data(h), buf, size); + BIO_clear_retry_flags(h); + if (res < 0) + { + /* If we were interrupted, tell caller to retry */ + switch (SOCK_ERRNO) + { +#ifdef EAGAIN + case EAGAIN: +#endif +#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN)) + case EWOULDBLOCK: +#endif + case EINTR: + BIO_set_retry_write(h); + break; + + default: + break; + } + } + + return res; +} + +static BIO_METHOD * +my_BIO_s_socket(void) +{ + BIO_METHOD *res; + +#ifdef ENABLE_THREAD_SAFETY + if (pthread_mutex_lock(&ssl_config_mutex)) + return NULL; +#endif + + res = my_bio_methods; + + if (!my_bio_methods) + { + BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket(); +#ifdef HAVE_BIO_METH_NEW + int my_bio_index; + + my_bio_index = BIO_get_new_index(); + if (my_bio_index == -1) + goto err; + my_bio_index |= (BIO_TYPE_DESCRIPTOR | BIO_TYPE_SOURCE_SINK); + res = BIO_meth_new(my_bio_index, "libpq socket"); + if (!res) + goto err; + + /* + * As of this writing, these functions never fail. But check anyway, + * like OpenSSL's own examples do. + */ + if (!BIO_meth_set_write(res, my_sock_write) || + !BIO_meth_set_read(res, my_sock_read) || + !BIO_meth_set_gets(res, BIO_meth_get_gets(biom)) || + !BIO_meth_set_puts(res, BIO_meth_get_puts(biom)) || + !BIO_meth_set_ctrl(res, BIO_meth_get_ctrl(biom)) || + !BIO_meth_set_create(res, BIO_meth_get_create(biom)) || + !BIO_meth_set_destroy(res, BIO_meth_get_destroy(biom)) || + !BIO_meth_set_callback_ctrl(res, BIO_meth_get_callback_ctrl(biom))) + { + goto err; + } +#else + res = malloc(sizeof(BIO_METHOD)); + if (!res) + goto err; + memcpy(res, biom, sizeof(BIO_METHOD)); + res->bread = my_sock_read; + res->bwrite = my_sock_write; +#endif + } + + my_bio_methods = res; + +#ifdef ENABLE_THREAD_SAFETY + pthread_mutex_unlock(&ssl_config_mutex); +#endif + + return res; + +err: +#ifdef HAVE_BIO_METH_NEW + if (res) + BIO_meth_free(res); +#else + if (res) + free(res); +#endif + +#ifdef ENABLE_THREAD_SAFETY + pthread_mutex_unlock(&ssl_config_mutex); +#endif + return NULL; +} + +/* This should exactly match OpenSSL's SSL_set_fd except for using my BIO */ +static int +my_SSL_set_fd(PGconn *conn, int fd) +{ + int ret = 0; + BIO *bio; + BIO_METHOD *bio_method; + + bio_method = my_BIO_s_socket(); + if (bio_method == NULL) + { + SSLerr(SSL_F_SSL_SET_FD, ERR_R_BUF_LIB); + goto err; + } + bio = BIO_new(bio_method); + if (bio == NULL) + { + SSLerr(SSL_F_SSL_SET_FD, ERR_R_BUF_LIB); + goto err; + } + BIO_set_app_data(bio, conn); + + SSL_set_bio(conn->ssl, bio, bio); + BIO_set_fd(bio, fd, BIO_NOCLOSE); + ret = 1; +err: + return ret; +} + +/* + * This is the default handler to return a client cert password from + * conn->sslpassword. Apps may install it explicitly if they want to + * prevent openssl from ever prompting on stdin. + */ +int +PQdefaultSSLKeyPassHook_OpenSSL(char *buf, int size, PGconn *conn) +{ + if (conn && conn->sslpassword) + { + if (strlen(conn->sslpassword) + 1 > size) + fprintf(stderr, libpq_gettext("WARNING: sslpassword truncated\n")); + strncpy(buf, conn->sslpassword, size); + buf[size - 1] = '\0'; + return strlen(buf); + } + else + { + buf[0] = '\0'; + return 0; + } +} + +PQsslKeyPassHook_OpenSSL_type +PQgetSSLKeyPassHook_OpenSSL(void) +{ + return PQsslKeyPassHook; +} + +void +PQsetSSLKeyPassHook_OpenSSL(PQsslKeyPassHook_OpenSSL_type hook) +{ + PQsslKeyPassHook = hook; +} + +/* + * Supply a password to decrypt a client certificate. + * + * This must match OpenSSL type pem_password_cb. + */ +static int +PQssl_passwd_cb(char *buf, int size, int rwflag, void *userdata) +{ + PGconn *conn = userdata; + + if (PQsslKeyPassHook) + return PQsslKeyPassHook(buf, size, conn); + else + return PQdefaultSSLKeyPassHook_OpenSSL(buf, size, conn); +} + +/* + * Convert TLS protocol version string to OpenSSL values + * + * If a version is passed that is not supported by the current OpenSSL version, + * then we return -1. If a non-negative value is returned, subsequent code can + * assume it is working with a supported version. + * + * Note: this is rather similar to the backend routine in be-secure-openssl.c, + * so make sure to update both routines if changing this one. + */ +static int +ssl_protocol_version_to_openssl(const char *protocol) +{ + if (pg_strcasecmp("TLSv1", protocol) == 0) + return TLS1_VERSION; + +#ifdef TLS1_1_VERSION + if (pg_strcasecmp("TLSv1.1", protocol) == 0) + return TLS1_1_VERSION; +#endif + +#ifdef TLS1_2_VERSION + if (pg_strcasecmp("TLSv1.2", protocol) == 0) + return TLS1_2_VERSION; +#endif + +#ifdef TLS1_3_VERSION + if (pg_strcasecmp("TLSv1.3", protocol) == 0) + return TLS1_3_VERSION; +#endif + + return -1; +} diff --git a/src/interfaces/libpq/fe-secure.c b/src/interfaces/libpq/fe-secure.c new file mode 100644 index 0000000..8444f19 --- /dev/null +++ b/src/interfaces/libpq/fe-secure.c @@ -0,0 +1,618 @@ +/*------------------------------------------------------------------------- + * + * fe-secure.c + * functions related to setting up a secure connection to the backend. + * Secure connections are expected to provide confidentiality, + * message integrity and endpoint authentication. + * + * + * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * src/interfaces/libpq/fe-secure.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres_fe.h" + +#include <signal.h> +#include <fcntl.h> +#include <ctype.h> + +#ifdef WIN32 +#include "win32.h" +#else +#include <sys/socket.h> +#include <unistd.h> +#include <netdb.h> +#include <netinet/in.h> +#include <netinet/tcp.h> +#include <arpa/inet.h> +#endif + +#include <sys/stat.h> + +#ifdef ENABLE_THREAD_SAFETY +#ifdef WIN32 +#include "pthread-win32.h" +#else +#include <pthread.h> +#endif +#endif + +#include "fe-auth.h" +#include "libpq-fe.h" +#include "libpq-int.h" + +/* + * Macros to handle disabling and then restoring the state of SIGPIPE handling. + * On Windows, these are all no-ops since there's no SIGPIPEs. + */ + +#ifndef WIN32 + +#define SIGPIPE_MASKED(conn) ((conn)->sigpipe_so || (conn)->sigpipe_flag) + +#ifdef ENABLE_THREAD_SAFETY + +struct sigpipe_info +{ + sigset_t oldsigmask; + bool sigpipe_pending; + bool got_epipe; +}; + +#define DECLARE_SIGPIPE_INFO(spinfo) struct sigpipe_info spinfo + +#define DISABLE_SIGPIPE(conn, spinfo, failaction) \ + do { \ + (spinfo).got_epipe = false; \ + if (!SIGPIPE_MASKED(conn)) \ + { \ + if (pq_block_sigpipe(&(spinfo).oldsigmask, \ + &(spinfo).sigpipe_pending) < 0) \ + failaction; \ + } \ + } while (0) + +#define REMEMBER_EPIPE(spinfo, cond) \ + do { \ + if (cond) \ + (spinfo).got_epipe = true; \ + } while (0) + +#define RESTORE_SIGPIPE(conn, spinfo) \ + do { \ + if (!SIGPIPE_MASKED(conn)) \ + pq_reset_sigpipe(&(spinfo).oldsigmask, (spinfo).sigpipe_pending, \ + (spinfo).got_epipe); \ + } while (0) +#else /* !ENABLE_THREAD_SAFETY */ + +#define DECLARE_SIGPIPE_INFO(spinfo) pqsigfunc spinfo = NULL + +#define DISABLE_SIGPIPE(conn, spinfo, failaction) \ + do { \ + if (!SIGPIPE_MASKED(conn)) \ + spinfo = pqsignal(SIGPIPE, SIG_IGN); \ + } while (0) + +#define REMEMBER_EPIPE(spinfo, cond) + +#define RESTORE_SIGPIPE(conn, spinfo) \ + do { \ + if (!SIGPIPE_MASKED(conn)) \ + pqsignal(SIGPIPE, spinfo); \ + } while (0) +#endif /* ENABLE_THREAD_SAFETY */ +#else /* WIN32 */ + +#define DECLARE_SIGPIPE_INFO(spinfo) +#define DISABLE_SIGPIPE(conn, spinfo, failaction) +#define REMEMBER_EPIPE(spinfo, cond) +#define RESTORE_SIGPIPE(conn, spinfo) +#endif /* WIN32 */ + +/* ------------------------------------------------------------ */ +/* Procedures common to all secure sessions */ +/* ------------------------------------------------------------ */ + + +int +PQsslInUse(PGconn *conn) +{ + if (!conn) + return 0; + return conn->ssl_in_use; +} + +/* + * Exported function to allow application to tell us it's already + * initialized OpenSSL. + */ +void +PQinitSSL(int do_init) +{ +#ifdef USE_SSL + pgtls_init_library(do_init, do_init); +#endif +} + +/* + * Exported function to allow application to tell us it's already + * initialized OpenSSL and/or libcrypto. + */ +void +PQinitOpenSSL(int do_ssl, int do_crypto) +{ +#ifdef USE_SSL + pgtls_init_library(do_ssl, do_crypto); +#endif +} + +/* + * Initialize global SSL context + */ +int +pqsecure_initialize(PGconn *conn, bool do_ssl, bool do_crypto) +{ + int r = 0; + +#ifdef USE_SSL + r = pgtls_init(conn, do_ssl, do_crypto); +#endif + + return r; +} + +/* + * Begin or continue negotiating a secure session. + */ +PostgresPollingStatusType +pqsecure_open_client(PGconn *conn) +{ +#ifdef USE_SSL + return pgtls_open_client(conn); +#else + /* shouldn't get here */ + return PGRES_POLLING_FAILED; +#endif +} + +/* + * Close secure session. + */ +void +pqsecure_close(PGconn *conn) +{ +#ifdef USE_SSL + pgtls_close(conn); +#endif +} + +/* + * Read data from a secure connection. + * + * On failure, this function is responsible for appending a suitable message + * to conn->errorMessage. The caller must still inspect errno, but only + * to determine whether to continue/retry after error. + */ +ssize_t +pqsecure_read(PGconn *conn, void *ptr, size_t len) +{ + ssize_t n; + +#ifdef USE_SSL + if (conn->ssl_in_use) + { + n = pgtls_read(conn, ptr, len); + } + else +#endif +#ifdef ENABLE_GSS + if (conn->gssenc) + { + n = pg_GSS_read(conn, ptr, len); + } + else +#endif + { + n = pqsecure_raw_read(conn, ptr, len); + } + + return n; +} + +ssize_t +pqsecure_raw_read(PGconn *conn, void *ptr, size_t len) +{ + ssize_t n; + int result_errno = 0; + char sebuf[PG_STRERROR_R_BUFLEN]; + + SOCK_ERRNO_SET(0); + + n = recv(conn->sock, ptr, len, 0); + + if (n < 0) + { + result_errno = SOCK_ERRNO; + + /* Set error message if appropriate */ + switch (result_errno) + { +#ifdef EAGAIN + case EAGAIN: +#endif +#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN)) + case EWOULDBLOCK: +#endif + case EINTR: + /* no error message, caller is expected to retry */ + break; + + case EPIPE: + case ECONNRESET: + libpq_append_conn_error(conn, "server closed the connection unexpectedly\n" + "\tThis probably means the server terminated abnormally\n" + "\tbefore or while processing the request."); + break; + + case 0: + /* If errno didn't get set, treat it as regular EOF */ + n = 0; + break; + + default: + libpq_append_conn_error(conn, "could not receive data from server: %s", + SOCK_STRERROR(result_errno, + sebuf, sizeof(sebuf))); + break; + } + } + + /* ensure we return the intended errno to caller */ + SOCK_ERRNO_SET(result_errno); + + return n; +} + +/* + * Write data to a secure connection. + * + * Returns the number of bytes written, or a negative value (with errno + * set) upon failure. The write count could be less than requested. + * + * Note that socket-level hard failures are masked from the caller, + * instead setting conn->write_failed and storing an error message + * in conn->write_err_msg; see pqsecure_raw_write. This allows us to + * postpone reporting of write failures until we're sure no error + * message is available from the server. + * + * However, errors detected in the SSL or GSS management level are reported + * via a negative result, with message appended to conn->errorMessage. + * It's frequently unclear whether such errors should be considered read or + * write errors, so we don't attempt to postpone reporting them. + * + * The caller must still inspect errno upon failure, but only to determine + * whether to continue/retry; a message has been saved someplace in any case. + */ +ssize_t +pqsecure_write(PGconn *conn, const void *ptr, size_t len) +{ + ssize_t n; + +#ifdef USE_SSL + if (conn->ssl_in_use) + { + n = pgtls_write(conn, ptr, len); + } + else +#endif +#ifdef ENABLE_GSS + if (conn->gssenc) + { + n = pg_GSS_write(conn, ptr, len); + } + else +#endif + { + n = pqsecure_raw_write(conn, ptr, len); + } + + return n; +} + +/* + * Low-level implementation of pqsecure_write. + * + * This is used directly for an unencrypted connection. For encrypted + * connections, this does the physical I/O on behalf of pgtls_write or + * pg_GSS_write. + * + * This function reports failure (i.e., returns a negative result) only + * for retryable errors such as EINTR. Looping for such cases is to be + * handled at some outer level, maybe all the way up to the application. + * For hard failures, we set conn->write_failed and store an error message + * in conn->write_err_msg, but then claim to have written the data anyway. + * This is because we don't want to report write failures so long as there + * is a possibility of reading from the server and getting an error message + * that could explain why the connection dropped. Many TCP stacks have + * race conditions such that a write failure may or may not be reported + * before all incoming data has been read. + * + * Note that this error behavior happens below the SSL management level when + * we are using SSL. That's because at least some versions of OpenSSL are + * too quick to report a write failure when there's still a possibility to + * get a more useful error from the server. + */ +ssize_t +pqsecure_raw_write(PGconn *conn, const void *ptr, size_t len) +{ + ssize_t n; + int flags = 0; + int result_errno = 0; + char msgbuf[1024]; + char sebuf[PG_STRERROR_R_BUFLEN]; + + DECLARE_SIGPIPE_INFO(spinfo); + + /* + * If we already had a write failure, we will never again try to send data + * on that connection. Even if the kernel would let us, we've probably + * lost message boundary sync with the server. conn->write_failed + * therefore persists until the connection is reset, and we just discard + * all data presented to be written. + */ + if (conn->write_failed) + return len; + +#ifdef MSG_NOSIGNAL + if (conn->sigpipe_flag) + flags |= MSG_NOSIGNAL; + +retry_masked: +#endif /* MSG_NOSIGNAL */ + + DISABLE_SIGPIPE(conn, spinfo, return -1); + + n = send(conn->sock, ptr, len, flags); + + if (n < 0) + { + result_errno = SOCK_ERRNO; + + /* + * If we see an EINVAL, it may be because MSG_NOSIGNAL isn't available + * on this machine. So, clear sigpipe_flag so we don't try the flag + * again, and retry the send(). + */ +#ifdef MSG_NOSIGNAL + if (flags != 0 && result_errno == EINVAL) + { + conn->sigpipe_flag = false; + flags = 0; + goto retry_masked; + } +#endif /* MSG_NOSIGNAL */ + + /* Set error message if appropriate */ + switch (result_errno) + { +#ifdef EAGAIN + case EAGAIN: +#endif +#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN)) + case EWOULDBLOCK: +#endif + case EINTR: + /* no error message, caller is expected to retry */ + break; + + case EPIPE: + /* Set flag for EPIPE */ + REMEMBER_EPIPE(spinfo, true); + + /* FALL THRU */ + + case ECONNRESET: + conn->write_failed = true; + /* Store error message in conn->write_err_msg, if possible */ + /* (strdup failure is OK, we'll cope later) */ + snprintf(msgbuf, sizeof(msgbuf), + libpq_gettext("server closed the connection unexpectedly\n" + "\tThis probably means the server terminated abnormally\n" + "\tbefore or while processing the request.")); + /* keep newline out of translated string */ + strlcat(msgbuf, "\n", sizeof(msgbuf)); + conn->write_err_msg = strdup(msgbuf); + /* Now claim the write succeeded */ + n = len; + break; + + default: + conn->write_failed = true; + /* Store error message in conn->write_err_msg, if possible */ + /* (strdup failure is OK, we'll cope later) */ + snprintf(msgbuf, sizeof(msgbuf), + libpq_gettext("could not send data to server: %s"), + SOCK_STRERROR(result_errno, + sebuf, sizeof(sebuf))); + /* keep newline out of translated string */ + strlcat(msgbuf, "\n", sizeof(msgbuf)); + conn->write_err_msg = strdup(msgbuf); + /* Now claim the write succeeded */ + n = len; + break; + } + } + + RESTORE_SIGPIPE(conn, spinfo); + + /* ensure we return the intended errno to caller */ + SOCK_ERRNO_SET(result_errno); + + return n; +} + +/* Dummy versions of SSL info functions, when built without SSL support */ +#ifndef USE_SSL + +void * +PQgetssl(PGconn *conn) +{ + return NULL; +} + +void * +PQsslStruct(PGconn *conn, const char *struct_name) +{ + return NULL; +} + +const char * +PQsslAttribute(PGconn *conn, const char *attribute_name) +{ + return NULL; +} + +const char *const * +PQsslAttributeNames(PGconn *conn) +{ + static const char *const result[] = {NULL}; + + return result; +} +#endif /* USE_SSL */ + +/* + * Dummy versions of OpenSSL key password hook functions, when built without + * OpenSSL. + */ +#ifndef USE_OPENSSL + +PQsslKeyPassHook_OpenSSL_type +PQgetSSLKeyPassHook_OpenSSL(void) +{ + return NULL; +} + +void +PQsetSSLKeyPassHook_OpenSSL(PQsslKeyPassHook_OpenSSL_type hook) +{ + return; +} + +int +PQdefaultSSLKeyPassHook_OpenSSL(char *buf, int size, PGconn *conn) +{ + return 0; +} +#endif /* USE_OPENSSL */ + +/* Dummy version of GSSAPI information functions, when built without GSS support */ +#ifndef ENABLE_GSS + +void * +PQgetgssctx(PGconn *conn) +{ + return NULL; +} + +int +PQgssEncInUse(PGconn *conn) +{ + return 0; +} + +#endif /* ENABLE_GSS */ + + +#if defined(ENABLE_THREAD_SAFETY) && !defined(WIN32) + +/* + * Block SIGPIPE for this thread. This prevents send()/write() from exiting + * the application. + */ +int +pq_block_sigpipe(sigset_t *osigset, bool *sigpipe_pending) +{ + sigset_t sigpipe_sigset; + sigset_t sigset; + + sigemptyset(&sigpipe_sigset); + sigaddset(&sigpipe_sigset, SIGPIPE); + + /* Block SIGPIPE and save previous mask for later reset */ + SOCK_ERRNO_SET(pthread_sigmask(SIG_BLOCK, &sigpipe_sigset, osigset)); + if (SOCK_ERRNO) + return -1; + + /* We can have a pending SIGPIPE only if it was blocked before */ + if (sigismember(osigset, SIGPIPE)) + { + /* Is there a pending SIGPIPE? */ + if (sigpending(&sigset) != 0) + return -1; + + if (sigismember(&sigset, SIGPIPE)) + *sigpipe_pending = true; + else + *sigpipe_pending = false; + } + else + *sigpipe_pending = false; + + return 0; +} + +/* + * Discard any pending SIGPIPE and reset the signal mask. + * + * Note: we are effectively assuming here that the C library doesn't queue + * up multiple SIGPIPE events. If it did, then we'd accidentally leave + * ours in the queue when an event was already pending and we got another. + * As long as it doesn't queue multiple events, we're OK because the caller + * can't tell the difference. + * + * The caller should say got_epipe = false if it is certain that it + * didn't get an EPIPE error; in that case we'll skip the clear operation + * and things are definitely OK, queuing or no. If it got one or might have + * gotten one, pass got_epipe = true. + * + * We do not want this to change errno, since if it did that could lose + * the error code from a preceding send(). We essentially assume that if + * we were able to do pq_block_sigpipe(), this can't fail. + */ +void +pq_reset_sigpipe(sigset_t *osigset, bool sigpipe_pending, bool got_epipe) +{ + int save_errno = SOCK_ERRNO; + int signo; + sigset_t sigset; + + /* Clear SIGPIPE only if none was pending */ + if (got_epipe && !sigpipe_pending) + { + if (sigpending(&sigset) == 0 && + sigismember(&sigset, SIGPIPE)) + { + sigset_t sigpipe_sigset; + + sigemptyset(&sigpipe_sigset); + sigaddset(&sigpipe_sigset, SIGPIPE); + + sigwait(&sigpipe_sigset, &signo); + } + } + + /* Restore saved block mask */ + pthread_sigmask(SIG_SETMASK, osigset, NULL); + + SOCK_ERRNO_SET(save_errno); +} + +#endif /* ENABLE_THREAD_SAFETY && !WIN32 */ diff --git a/src/interfaces/libpq/fe-trace.c b/src/interfaces/libpq/fe-trace.c new file mode 100644 index 0000000..402784f --- /dev/null +++ b/src/interfaces/libpq/fe-trace.c @@ -0,0 +1,729 @@ +/*------------------------------------------------------------------------- + * + * fe-trace.c + * functions for libpq protocol tracing + * + * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/interfaces/libpq/fe-trace.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres_fe.h" + +#include <ctype.h> +#include <limits.h> +#include <sys/time.h> +#include <time.h> + +#ifdef WIN32 +#include "win32.h" +#else +#include <unistd.h> +#endif + +#include "libpq-fe.h" +#include "libpq-int.h" +#include "port/pg_bswap.h" + + +/* Enable tracing */ +void +PQtrace(PGconn *conn, FILE *debug_port) +{ + if (conn == NULL) + return; + PQuntrace(conn); + if (debug_port == NULL) + return; + + conn->Pfdebug = debug_port; + conn->traceFlags = 0; +} + +/* Disable tracing */ +void +PQuntrace(PGconn *conn) +{ + if (conn == NULL) + return; + if (conn->Pfdebug) + { + fflush(conn->Pfdebug); + conn->Pfdebug = NULL; + } + + conn->traceFlags = 0; +} + +/* Set flags for current tracing session */ +void +PQsetTraceFlags(PGconn *conn, int flags) +{ + if (conn == NULL) + return; + /* If PQtrace() failed, do nothing. */ + if (conn->Pfdebug == NULL) + return; + conn->traceFlags = flags; +} + +/* + * Print the current time, with microseconds, into a caller-supplied + * buffer. + * Cribbed from get_formatted_log_time, but much simpler. + */ +static void +pqTraceFormatTimestamp(char *timestr, size_t ts_len) +{ + struct timeval tval; + time_t now; + + gettimeofday(&tval, NULL); + + /* + * MSVC's implementation of timeval uses a long for tv_sec, however, + * localtime() expects a time_t pointer. Here we'll assign tv_sec to a + * local time_t variable so that we pass localtime() the correct pointer + * type. + */ + now = tval.tv_sec; + strftime(timestr, ts_len, + "%Y-%m-%d %H:%M:%S", + localtime(&now)); + /* append microseconds */ + snprintf(timestr + strlen(timestr), ts_len - strlen(timestr), + ".%06u", (unsigned int) (tval.tv_usec)); +} + +/* + * pqTraceOutputByte1: output a 1-char message to the log + */ +static void +pqTraceOutputByte1(FILE *pfdebug, const char *data, int *cursor) +{ + const char *v = data + *cursor; + + /* + * Show non-printable data in hex format, including the terminating \0 + * that completes ErrorResponse and NoticeResponse messages. + */ + if (!isprint((unsigned char) *v)) + fprintf(pfdebug, " \\x%02x", *v); + else + fprintf(pfdebug, " %c", *v); + *cursor += 1; +} + +/* + * pqTraceOutputInt16: output a 2-byte integer message to the log + */ +static int +pqTraceOutputInt16(FILE *pfdebug, const char *data, int *cursor) +{ + uint16 tmp; + int result; + + memcpy(&tmp, data + *cursor, 2); + *cursor += 2; + result = (int) pg_ntoh16(tmp); + fprintf(pfdebug, " %d", result); + + return result; +} + +/* + * pqTraceOutputInt32: output a 4-byte integer message to the log + * + * If 'suppress' is true, print a literal NNNN instead of the actual number. + */ +static int +pqTraceOutputInt32(FILE *pfdebug, const char *data, int *cursor, bool suppress) +{ + int result; + + memcpy(&result, data + *cursor, 4); + *cursor += 4; + result = (int) pg_ntoh32(result); + if (suppress) + fprintf(pfdebug, " NNNN"); + else + fprintf(pfdebug, " %d", result); + + return result; +} + +/* + * pqTraceOutputString: output a string message to the log + */ +static void +pqTraceOutputString(FILE *pfdebug, const char *data, int *cursor, bool suppress) +{ + int len; + + if (suppress) + { + fprintf(pfdebug, " \"SSSS\""); + *cursor += strlen(data + *cursor) + 1; + } + else + { + len = fprintf(pfdebug, " \"%s\"", data + *cursor); + + /* + * This is a null-terminated string. So add 1 after subtracting 3 + * which is the double quotes and space length from len. + */ + *cursor += (len - 3 + 1); + } +} + +/* + * pqTraceOutputNchar: output a string of exactly len bytes message to the log + */ +static void +pqTraceOutputNchar(FILE *pfdebug, int len, const char *data, int *cursor) +{ + int i, + next; /* first char not yet printed */ + const char *v = data + *cursor; + + fprintf(pfdebug, " \'"); + + for (next = i = 0; i < len; ++i) + { + if (isprint((unsigned char) v[i])) + continue; + else + { + fwrite(v + next, 1, i - next, pfdebug); + fprintf(pfdebug, "\\x%02x", v[i]); + next = i + 1; + } + } + if (next < len) + fwrite(v + next, 1, len - next, pfdebug); + + fprintf(pfdebug, "\'"); + *cursor += len; +} + +/* + * Output functions by protocol message type + */ + +/* NotificationResponse */ +static void +pqTraceOutputA(FILE *f, const char *message, int *cursor, bool regress) +{ + fprintf(f, "NotificationResponse\t"); + pqTraceOutputInt32(f, message, cursor, regress); + pqTraceOutputString(f, message, cursor, false); + pqTraceOutputString(f, message, cursor, false); +} + +/* Bind */ +static void +pqTraceOutputB(FILE *f, const char *message, int *cursor) +{ + int nparams; + + fprintf(f, "Bind\t"); + pqTraceOutputString(f, message, cursor, false); + pqTraceOutputString(f, message, cursor, false); + nparams = pqTraceOutputInt16(f, message, cursor); + + for (int i = 0; i < nparams; i++) + pqTraceOutputInt16(f, message, cursor); + + nparams = pqTraceOutputInt16(f, message, cursor); + + for (int i = 0; i < nparams; i++) + { + int nbytes; + + nbytes = pqTraceOutputInt32(f, message, cursor, false); + if (nbytes == -1) + continue; + pqTraceOutputNchar(f, nbytes, message, cursor); + } + + nparams = pqTraceOutputInt16(f, message, cursor); + for (int i = 0; i < nparams; i++) + pqTraceOutputInt16(f, message, cursor); +} + +/* Close(F) or CommandComplete(B) */ +static void +pqTraceOutputC(FILE *f, bool toServer, const char *message, int *cursor) +{ + if (toServer) + { + fprintf(f, "Close\t"); + pqTraceOutputByte1(f, message, cursor); + pqTraceOutputString(f, message, cursor, false); + } + else + { + fprintf(f, "CommandComplete\t"); + pqTraceOutputString(f, message, cursor, false); + } +} + +/* Describe(F) or DataRow(B) */ +static void +pqTraceOutputD(FILE *f, bool toServer, const char *message, int *cursor) +{ + if (toServer) + { + fprintf(f, "Describe\t"); + pqTraceOutputByte1(f, message, cursor); + pqTraceOutputString(f, message, cursor, false); + } + else + { + int nfields; + int len; + int i; + + fprintf(f, "DataRow\t"); + nfields = pqTraceOutputInt16(f, message, cursor); + for (i = 0; i < nfields; i++) + { + len = pqTraceOutputInt32(f, message, cursor, false); + if (len == -1) + continue; + pqTraceOutputNchar(f, len, message, cursor); + } + } +} + +/* NoticeResponse / ErrorResponse */ +static void +pqTraceOutputNR(FILE *f, const char *type, const char *message, int *cursor, + bool regress) +{ + fprintf(f, "%s\t", type); + for (;;) + { + char field; + bool suppress; + + pqTraceOutputByte1(f, message, cursor); + field = message[*cursor - 1]; + if (field == '\0') + break; + + suppress = regress && (field == 'L' || field == 'F' || field == 'R'); + pqTraceOutputString(f, message, cursor, suppress); + } +} + +/* Execute(F) or ErrorResponse(B) */ +static void +pqTraceOutputE(FILE *f, bool toServer, const char *message, int *cursor, bool regress) +{ + if (toServer) + { + fprintf(f, "Execute\t"); + pqTraceOutputString(f, message, cursor, false); + pqTraceOutputInt32(f, message, cursor, false); + } + else + pqTraceOutputNR(f, "ErrorResponse", message, cursor, regress); +} + +/* CopyFail */ +static void +pqTraceOutputf(FILE *f, const char *message, int *cursor) +{ + fprintf(f, "CopyFail\t"); + pqTraceOutputString(f, message, cursor, false); +} + +/* FunctionCall */ +static void +pqTraceOutputF(FILE *f, const char *message, int *cursor, bool regress) +{ + int nfields; + int nbytes; + + fprintf(f, "FunctionCall\t"); + pqTraceOutputInt32(f, message, cursor, regress); + nfields = pqTraceOutputInt16(f, message, cursor); + + for (int i = 0; i < nfields; i++) + pqTraceOutputInt16(f, message, cursor); + + nfields = pqTraceOutputInt16(f, message, cursor); + + for (int i = 0; i < nfields; i++) + { + nbytes = pqTraceOutputInt32(f, message, cursor, false); + if (nbytes == -1) + continue; + pqTraceOutputNchar(f, nbytes, message, cursor); + } + + pqTraceOutputInt16(f, message, cursor); +} + +/* CopyInResponse */ +static void +pqTraceOutputG(FILE *f, const char *message, int *cursor) +{ + int nfields; + + fprintf(f, "CopyInResponse\t"); + pqTraceOutputByte1(f, message, cursor); + nfields = pqTraceOutputInt16(f, message, cursor); + + for (int i = 0; i < nfields; i++) + pqTraceOutputInt16(f, message, cursor); +} + +/* CopyOutResponse */ +static void +pqTraceOutputH(FILE *f, const char *message, int *cursor) +{ + int nfields; + + fprintf(f, "CopyOutResponse\t"); + pqTraceOutputByte1(f, message, cursor); + nfields = pqTraceOutputInt16(f, message, cursor); + + for (int i = 0; i < nfields; i++) + pqTraceOutputInt16(f, message, cursor); +} + +/* BackendKeyData */ +static void +pqTraceOutputK(FILE *f, const char *message, int *cursor, bool regress) +{ + fprintf(f, "BackendKeyData\t"); + pqTraceOutputInt32(f, message, cursor, regress); + pqTraceOutputInt32(f, message, cursor, regress); +} + +/* Parse */ +static void +pqTraceOutputP(FILE *f, const char *message, int *cursor, bool regress) +{ + int nparams; + + fprintf(f, "Parse\t"); + pqTraceOutputString(f, message, cursor, false); + pqTraceOutputString(f, message, cursor, false); + nparams = pqTraceOutputInt16(f, message, cursor); + + for (int i = 0; i < nparams; i++) + pqTraceOutputInt32(f, message, cursor, regress); +} + +/* Query */ +static void +pqTraceOutputQ(FILE *f, const char *message, int *cursor) +{ + fprintf(f, "Query\t"); + pqTraceOutputString(f, message, cursor, false); +} + +/* Authentication */ +static void +pqTraceOutputR(FILE *f, const char *message, int *cursor) +{ + fprintf(f, "Authentication\t"); + pqTraceOutputInt32(f, message, cursor, false); +} + +/* ParameterStatus */ +static void +pqTraceOutputS(FILE *f, const char *message, int *cursor) +{ + fprintf(f, "ParameterStatus\t"); + pqTraceOutputString(f, message, cursor, false); + pqTraceOutputString(f, message, cursor, false); +} + +/* ParameterDescription */ +static void +pqTraceOutputt(FILE *f, const char *message, int *cursor, bool regress) +{ + int nfields; + + fprintf(f, "ParameterDescription\t"); + nfields = pqTraceOutputInt16(f, message, cursor); + + for (int i = 0; i < nfields; i++) + pqTraceOutputInt32(f, message, cursor, regress); +} + +/* RowDescription */ +static void +pqTraceOutputT(FILE *f, const char *message, int *cursor, bool regress) +{ + int nfields; + + fprintf(f, "RowDescription\t"); + nfields = pqTraceOutputInt16(f, message, cursor); + + for (int i = 0; i < nfields; i++) + { + pqTraceOutputString(f, message, cursor, false); + pqTraceOutputInt32(f, message, cursor, regress); + pqTraceOutputInt16(f, message, cursor); + pqTraceOutputInt32(f, message, cursor, regress); + pqTraceOutputInt16(f, message, cursor); + pqTraceOutputInt32(f, message, cursor, false); + pqTraceOutputInt16(f, message, cursor); + } +} + +/* NegotiateProtocolVersion */ +static void +pqTraceOutputv(FILE *f, const char *message, int *cursor) +{ + fprintf(f, "NegotiateProtocolVersion\t"); + pqTraceOutputInt32(f, message, cursor, false); + pqTraceOutputInt32(f, message, cursor, false); +} + +/* FunctionCallResponse */ +static void +pqTraceOutputV(FILE *f, const char *message, int *cursor) +{ + int len; + + fprintf(f, "FunctionCallResponse\t"); + len = pqTraceOutputInt32(f, message, cursor, false); + if (len != -1) + pqTraceOutputNchar(f, len, message, cursor); +} + +/* CopyBothResponse */ +static void +pqTraceOutputW(FILE *f, const char *message, int *cursor, int length) +{ + fprintf(f, "CopyBothResponse\t"); + pqTraceOutputByte1(f, message, cursor); + + while (length > *cursor) + pqTraceOutputInt16(f, message, cursor); +} + +/* ReadyForQuery */ +static void +pqTraceOutputZ(FILE *f, const char *message, int *cursor) +{ + fprintf(f, "ReadyForQuery\t"); + pqTraceOutputByte1(f, message, cursor); +} + +/* + * Print the given message to the trace output stream. + */ +void +pqTraceOutputMessage(PGconn *conn, const char *message, bool toServer) +{ + char id; + int length; + char *prefix = toServer ? "F" : "B"; + int logCursor = 0; + bool regress; + + if ((conn->traceFlags & PQTRACE_SUPPRESS_TIMESTAMPS) == 0) + { + char timestr[128]; + + pqTraceFormatTimestamp(timestr, sizeof(timestr)); + fprintf(conn->Pfdebug, "%s\t", timestr); + } + regress = (conn->traceFlags & PQTRACE_REGRESS_MODE) != 0; + + id = message[logCursor++]; + + memcpy(&length, message + logCursor, 4); + length = (int) pg_ntoh32(length); + logCursor += 4; + + /* + * In regress mode, suppress the length of ErrorResponse and + * NoticeResponse. The F (file name), L (line number) and R (routine + * name) fields can change as server code is modified, and if their + * lengths differ from the originals, that would break tests. + */ + if (regress && !toServer && (id == 'E' || id == 'N')) + fprintf(conn->Pfdebug, "%s\tNN\t", prefix); + else + fprintf(conn->Pfdebug, "%s\t%d\t", prefix, length); + + switch (id) + { + case '1': + fprintf(conn->Pfdebug, "ParseComplete"); + /* No message content */ + break; + case '2': + fprintf(conn->Pfdebug, "BindComplete"); + /* No message content */ + break; + case '3': + fprintf(conn->Pfdebug, "CloseComplete"); + /* No message content */ + break; + case 'A': /* Notification Response */ + pqTraceOutputA(conn->Pfdebug, message, &logCursor, regress); + break; + case 'B': /* Bind */ + pqTraceOutputB(conn->Pfdebug, message, &logCursor); + break; + case 'c': + fprintf(conn->Pfdebug, "CopyDone"); + /* No message content */ + break; + case 'C': /* Close(F) or Command Complete(B) */ + pqTraceOutputC(conn->Pfdebug, toServer, message, &logCursor); + break; + case 'd': /* Copy Data */ + /* Drop COPY data to reduce the overhead of logging. */ + break; + case 'D': /* Describe(F) or Data Row(B) */ + pqTraceOutputD(conn->Pfdebug, toServer, message, &logCursor); + break; + case 'E': /* Execute(F) or Error Response(B) */ + pqTraceOutputE(conn->Pfdebug, toServer, message, &logCursor, + regress); + break; + case 'f': /* Copy Fail */ + pqTraceOutputf(conn->Pfdebug, message, &logCursor); + break; + case 'F': /* Function Call */ + pqTraceOutputF(conn->Pfdebug, message, &logCursor, regress); + break; + case 'G': /* Start Copy In */ + pqTraceOutputG(conn->Pfdebug, message, &logCursor); + break; + case 'H': /* Flush(F) or Start Copy Out(B) */ + if (!toServer) + pqTraceOutputH(conn->Pfdebug, message, &logCursor); + else + fprintf(conn->Pfdebug, "Flush"); /* no message content */ + break; + case 'I': + fprintf(conn->Pfdebug, "EmptyQueryResponse"); + /* No message content */ + break; + case 'K': /* secret key data from the backend */ + pqTraceOutputK(conn->Pfdebug, message, &logCursor, regress); + break; + case 'n': + fprintf(conn->Pfdebug, "NoData"); + /* No message content */ + break; + case 'N': + pqTraceOutputNR(conn->Pfdebug, "NoticeResponse", message, + &logCursor, regress); + break; + case 'P': /* Parse */ + pqTraceOutputP(conn->Pfdebug, message, &logCursor, regress); + break; + case 'Q': /* Query */ + pqTraceOutputQ(conn->Pfdebug, message, &logCursor); + break; + case 'R': /* Authentication */ + pqTraceOutputR(conn->Pfdebug, message, &logCursor); + break; + case 's': + fprintf(conn->Pfdebug, "PortalSuspended"); + /* No message content */ + break; + case 'S': /* Parameter Status(B) or Sync(F) */ + if (!toServer) + pqTraceOutputS(conn->Pfdebug, message, &logCursor); + else + fprintf(conn->Pfdebug, "Sync"); /* no message content */ + break; + case 't': /* Parameter Description */ + pqTraceOutputt(conn->Pfdebug, message, &logCursor, regress); + break; + case 'T': /* Row Description */ + pqTraceOutputT(conn->Pfdebug, message, &logCursor, regress); + break; + case 'v': /* Negotiate Protocol Version */ + pqTraceOutputv(conn->Pfdebug, message, &logCursor); + break; + case 'V': /* Function Call response */ + pqTraceOutputV(conn->Pfdebug, message, &logCursor); + break; + case 'W': /* Start Copy Both */ + pqTraceOutputW(conn->Pfdebug, message, &logCursor, length); + break; + case 'X': + fprintf(conn->Pfdebug, "Terminate"); + /* No message content */ + break; + case 'Z': /* Ready For Query */ + pqTraceOutputZ(conn->Pfdebug, message, &logCursor); + break; + default: + fprintf(conn->Pfdebug, "Unknown message: %02x", id); + break; + } + + fputc('\n', conn->Pfdebug); + + /* + * Verify the printing routine did it right. Note that the one-byte + * message identifier is not included in the length, but our cursor does + * include it. + */ + if (logCursor - 1 != length) + fprintf(conn->Pfdebug, + "mismatched message length: consumed %d, expected %d\n", + logCursor - 1, length); +} + +/* + * Print special messages (those containing no type byte) to the trace output + * stream. + */ +void +pqTraceOutputNoTypeByteMessage(PGconn *conn, const char *message) +{ + int length; + int logCursor = 0; + + if ((conn->traceFlags & PQTRACE_SUPPRESS_TIMESTAMPS) == 0) + { + char timestr[128]; + + pqTraceFormatTimestamp(timestr, sizeof(timestr)); + fprintf(conn->Pfdebug, "%s\t", timestr); + } + + memcpy(&length, message + logCursor, 4); + length = (int) pg_ntoh32(length); + logCursor += 4; + + fprintf(conn->Pfdebug, "F\t%d\t", length); + + switch (length) + { + case 16: /* CancelRequest */ + fprintf(conn->Pfdebug, "CancelRequest\t"); + pqTraceOutputInt32(conn->Pfdebug, message, &logCursor, false); + pqTraceOutputInt32(conn->Pfdebug, message, &logCursor, false); + pqTraceOutputInt32(conn->Pfdebug, message, &logCursor, false); + break; + case 8: /* GSSENCRequest or SSLRequest */ + /* These messages do not reach here. */ + default: + fprintf(conn->Pfdebug, "Unknown message: length is %d", length); + break; + } + + fputc('\n', conn->Pfdebug); +} diff --git a/src/interfaces/libpq/legacy-pqsignal.c b/src/interfaces/libpq/legacy-pqsignal.c new file mode 100644 index 0000000..790ab5a --- /dev/null +++ b/src/interfaces/libpq/legacy-pqsignal.c @@ -0,0 +1,57 @@ +/*------------------------------------------------------------------------- + * + * legacy-pqsignal.c + * reliable BSD-style signal(2) routine stolen from RWW who stole it + * from Stevens... + * + * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * src/interfaces/libpq/legacy-pqsignal.c + * + *------------------------------------------------------------------------- + */ +#include "postgres_fe.h" + +#include <signal.h> + + +/* + * This version of pqsignal() exists only because pre-9.3 releases + * of libpq exported pqsignal(), and some old client programs still + * depend on that. (Since 9.3, clients are supposed to get it from + * libpgport instead.) + * + * Because it is only intended for backwards compatibility, we freeze it + * with the semantics it had in 9.2; in particular, this has different + * behavior for SIGALRM than the version in src/port/pqsignal.c. + * + * libpq itself uses this only for SIGPIPE (and even then, only in + * non-ENABLE_THREAD_SAFETY builds), so the incompatibility isn't + * troublesome for internal references. + */ +pqsigfunc +pqsignal(int signo, pqsigfunc func) +{ +#ifndef WIN32 + struct sigaction act, + oact; + + act.sa_handler = func; + sigemptyset(&act.sa_mask); + act.sa_flags = 0; + if (signo != SIGALRM) + act.sa_flags |= SA_RESTART; +#ifdef SA_NOCLDSTOP + if (signo == SIGCHLD) + act.sa_flags |= SA_NOCLDSTOP; +#endif + if (sigaction(signo, &act, &oact) < 0) + return SIG_ERR; + return oact.sa_handler; +#else /* WIN32 */ + return signal(signo, func); +#endif +} diff --git a/src/interfaces/libpq/libpq-events.c b/src/interfaces/libpq/libpq-events.c new file mode 100644 index 0000000..229bed9 --- /dev/null +++ b/src/interfaces/libpq/libpq-events.c @@ -0,0 +1,211 @@ +/*------------------------------------------------------------------------- + * + * libpq-events.c + * functions for supporting the libpq "events" API + * + * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * src/interfaces/libpq/libpq-events.c + * + *------------------------------------------------------------------------- + */ +#include "postgres_fe.h" + +#include "libpq-fe.h" +#include "libpq-int.h" + + +/* + * Registers an event proc with the given PGconn. + * + * The same proc can't be registered more than once in a PGconn. This + * restriction is required because we use the proc address to identify + * the event for purposes such as PQinstanceData(). + * + * The name argument is used within error messages to aid in debugging. + * A name must be supplied, but it needn't be unique. The string is + * copied, so the passed value needn't be long-lived. + * + * The passThrough argument is an application specific pointer and can be set + * to NULL if not required. It is passed through to the event proc whenever + * the event proc is called, and is not otherwise touched by libpq. + * + * The function returns a non-zero if successful. If the function fails, + * zero is returned. + */ +int +PQregisterEventProc(PGconn *conn, PGEventProc proc, + const char *name, void *passThrough) +{ + int i; + PGEventRegister regevt; + + if (!proc || !conn || !name || !*name) + return false; /* bad arguments */ + + for (i = 0; i < conn->nEvents; i++) + { + if (conn->events[i].proc == proc) + return false; /* already registered */ + } + + if (conn->nEvents >= conn->eventArraySize) + { + PGEvent *e; + int newSize; + + newSize = conn->eventArraySize ? conn->eventArraySize * 2 : 8; + if (conn->events) + e = (PGEvent *) realloc(conn->events, newSize * sizeof(PGEvent)); + else + e = (PGEvent *) malloc(newSize * sizeof(PGEvent)); + + if (!e) + return false; + + conn->eventArraySize = newSize; + conn->events = e; + } + + conn->events[conn->nEvents].proc = proc; + conn->events[conn->nEvents].name = strdup(name); + if (!conn->events[conn->nEvents].name) + return false; + conn->events[conn->nEvents].passThrough = passThrough; + conn->events[conn->nEvents].data = NULL; + conn->events[conn->nEvents].resultInitialized = false; + conn->nEvents++; + + regevt.conn = conn; + if (!proc(PGEVT_REGISTER, ®evt, passThrough)) + { + conn->nEvents--; + free(conn->events[conn->nEvents].name); + return false; + } + + return true; +} + +/* + * Set some "instance data" for an event within a PGconn. + * Returns nonzero on success, zero on failure. + */ +int +PQsetInstanceData(PGconn *conn, PGEventProc proc, void *data) +{ + int i; + + if (!conn || !proc) + return false; + + for (i = 0; i < conn->nEvents; i++) + { + if (conn->events[i].proc == proc) + { + conn->events[i].data = data; + return true; + } + } + + return false; +} + +/* + * Obtain the "instance data", if any, for the event. + */ +void * +PQinstanceData(const PGconn *conn, PGEventProc proc) +{ + int i; + + if (!conn || !proc) + return NULL; + + for (i = 0; i < conn->nEvents; i++) + { + if (conn->events[i].proc == proc) + return conn->events[i].data; + } + + return NULL; +} + +/* + * Set some "instance data" for an event within a PGresult. + * Returns nonzero on success, zero on failure. + */ +int +PQresultSetInstanceData(PGresult *result, PGEventProc proc, void *data) +{ + int i; + + if (!result || !proc) + return false; + + for (i = 0; i < result->nEvents; i++) + { + if (result->events[i].proc == proc) + { + result->events[i].data = data; + return true; + } + } + + return false; +} + +/* + * Obtain the "instance data", if any, for the event. + */ +void * +PQresultInstanceData(const PGresult *result, PGEventProc proc) +{ + int i; + + if (!result || !proc) + return NULL; + + for (i = 0; i < result->nEvents; i++) + if (result->events[i].proc == proc) + return result->events[i].data; + + return NULL; +} + +/* + * Fire RESULTCREATE events for an application-created PGresult. + * + * The conn argument can be NULL if event procedures won't use it. + */ +int +PQfireResultCreateEvents(PGconn *conn, PGresult *res) +{ + int result = true; + int i; + + if (!res) + return false; + + for (i = 0; i < res->nEvents; i++) + { + /* It's possible event was already fired, if so don't repeat it */ + if (!res->events[i].resultInitialized) + { + PGEventResultCreate evt; + + evt.conn = conn; + evt.result = res; + if (res->events[i].proc(PGEVT_RESULTCREATE, &evt, + res->events[i].passThrough)) + res->events[i].resultInitialized = true; + else + result = false; + } + } + + return result; +} diff --git a/src/interfaces/libpq/libpq-events.h b/src/interfaces/libpq/libpq-events.h new file mode 100644 index 0000000..b9d5137 --- /dev/null +++ b/src/interfaces/libpq/libpq-events.h @@ -0,0 +1,94 @@ +/*------------------------------------------------------------------------- + * + * libpq-events.h + * This file contains definitions that are useful to applications + * that invoke the libpq "events" API, but are not interesting to + * ordinary users of libpq. + * + * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/interfaces/libpq/libpq-events.h + * + *------------------------------------------------------------------------- + */ + +#ifndef LIBPQ_EVENTS_H +#define LIBPQ_EVENTS_H + +#include "libpq-fe.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Callback Event Ids */ +typedef enum +{ + PGEVT_REGISTER, + PGEVT_CONNRESET, + PGEVT_CONNDESTROY, + PGEVT_RESULTCREATE, + PGEVT_RESULTCOPY, + PGEVT_RESULTDESTROY +} PGEventId; + +typedef struct +{ + PGconn *conn; +} PGEventRegister; + +typedef struct +{ + PGconn *conn; +} PGEventConnReset; + +typedef struct +{ + PGconn *conn; +} PGEventConnDestroy; + +typedef struct +{ + PGconn *conn; + PGresult *result; +} PGEventResultCreate; + +typedef struct +{ + const PGresult *src; + PGresult *dest; +} PGEventResultCopy; + +typedef struct +{ + PGresult *result; +} PGEventResultDestroy; + +typedef int (*PGEventProc) (PGEventId evtId, void *evtInfo, void *passThrough); + +/* Registers an event proc with the given PGconn. */ +extern int PQregisterEventProc(PGconn *conn, PGEventProc proc, + const char *name, void *passThrough); + +/* Sets the PGconn instance data for the provided proc to data. */ +extern int PQsetInstanceData(PGconn *conn, PGEventProc proc, void *data); + +/* Gets the PGconn instance data for the provided proc. */ +extern void *PQinstanceData(const PGconn *conn, PGEventProc proc); + +/* Sets the PGresult instance data for the provided proc to data. */ +extern int PQresultSetInstanceData(PGresult *result, PGEventProc proc, void *data); + +/* Gets the PGresult instance data for the provided proc. */ +extern void *PQresultInstanceData(const PGresult *result, PGEventProc proc); + +/* Fires RESULTCREATE events for an application-created PGresult. */ +extern int PQfireResultCreateEvents(PGconn *conn, PGresult *res); + +#ifdef __cplusplus +} +#endif + +#endif /* LIBPQ_EVENTS_H */ diff --git a/src/interfaces/libpq/libpq-fe.h b/src/interfaces/libpq/libpq-fe.h new file mode 100644 index 0000000..7476dbe --- /dev/null +++ b/src/interfaces/libpq/libpq-fe.h @@ -0,0 +1,675 @@ +/*------------------------------------------------------------------------- + * + * libpq-fe.h + * This file contains definitions for structures and + * externs for functions used by frontend postgres applications. + * + * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/interfaces/libpq/libpq-fe.h + * + *------------------------------------------------------------------------- + */ + +#ifndef LIBPQ_FE_H +#define LIBPQ_FE_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <stdio.h> + +/* + * postgres_ext.h defines the backend's externally visible types, + * such as Oid. + */ +#include "postgres_ext.h" + +/* + * These symbols may be used in compile-time #ifdef tests for the availability + * of newer libpq features. + */ +/* Indicates presence of PQenterPipelineMode and friends */ +#define LIBPQ_HAS_PIPELINING 1 +/* Indicates presence of PQsetTraceFlags; also new PQtrace output format */ +#define LIBPQ_HAS_TRACE_FLAGS 1 +/* Indicates that PQsslAttribute(NULL, "library") is useful */ +#define LIBPQ_HAS_SSL_LIBRARY_DETECTION 1 + +/* + * Option flags for PQcopyResult + */ +#define PG_COPYRES_ATTRS 0x01 +#define PG_COPYRES_TUPLES 0x02 /* Implies PG_COPYRES_ATTRS */ +#define PG_COPYRES_EVENTS 0x04 +#define PG_COPYRES_NOTICEHOOKS 0x08 + +/* Application-visible enum types */ + +/* + * Although it is okay to add to these lists, values which become unused + * should never be removed, nor should constants be redefined - that would + * break compatibility with existing code. + */ + +typedef enum +{ + CONNECTION_OK, + CONNECTION_BAD, + /* Non-blocking mode only below here */ + + /* + * The existence of these should never be relied upon - they should only + * be used for user feedback or similar purposes. + */ + CONNECTION_STARTED, /* Waiting for connection to be made. */ + CONNECTION_MADE, /* Connection OK; waiting to send. */ + CONNECTION_AWAITING_RESPONSE, /* Waiting for a response from the + * postmaster. */ + CONNECTION_AUTH_OK, /* Received authentication; waiting for + * backend startup. */ + CONNECTION_SETENV, /* This state is no longer used. */ + CONNECTION_SSL_STARTUP, /* Negotiating SSL. */ + CONNECTION_NEEDED, /* Internal state: connect() needed */ + CONNECTION_CHECK_WRITABLE, /* Checking if session is read-write. */ + CONNECTION_CONSUME, /* Consuming any extra messages. */ + CONNECTION_GSS_STARTUP, /* Negotiating GSSAPI. */ + CONNECTION_CHECK_TARGET, /* Checking target server properties. */ + CONNECTION_CHECK_STANDBY /* Checking if server is in standby mode. */ +} ConnStatusType; + +typedef enum +{ + PGRES_POLLING_FAILED = 0, + PGRES_POLLING_READING, /* These two indicate that one may */ + PGRES_POLLING_WRITING, /* use select before polling again. */ + PGRES_POLLING_OK, + PGRES_POLLING_ACTIVE /* unused; keep for awhile for backwards + * compatibility */ +} PostgresPollingStatusType; + +typedef enum +{ + PGRES_EMPTY_QUERY = 0, /* empty query string was executed */ + PGRES_COMMAND_OK, /* a query command that doesn't return + * anything was executed properly by the + * backend */ + PGRES_TUPLES_OK, /* a query command that returns tuples was + * executed properly by the backend, PGresult + * contains the result tuples */ + PGRES_COPY_OUT, /* Copy Out data transfer in progress */ + PGRES_COPY_IN, /* Copy In data transfer in progress */ + PGRES_BAD_RESPONSE, /* an unexpected response was recv'd from the + * backend */ + PGRES_NONFATAL_ERROR, /* notice or warning message */ + PGRES_FATAL_ERROR, /* query failed */ + PGRES_COPY_BOTH, /* Copy In/Out data transfer in progress */ + PGRES_SINGLE_TUPLE, /* single tuple from larger resultset */ + PGRES_PIPELINE_SYNC, /* pipeline synchronization point */ + PGRES_PIPELINE_ABORTED /* Command didn't run because of an abort + * earlier in a pipeline */ +} ExecStatusType; + +typedef enum +{ + PQTRANS_IDLE, /* connection idle */ + PQTRANS_ACTIVE, /* command in progress */ + PQTRANS_INTRANS, /* idle, within transaction block */ + PQTRANS_INERROR, /* idle, within failed transaction */ + PQTRANS_UNKNOWN /* cannot determine status */ +} PGTransactionStatusType; + +typedef enum +{ + PQERRORS_TERSE, /* single-line error messages */ + PQERRORS_DEFAULT, /* recommended style */ + PQERRORS_VERBOSE, /* all the facts, ma'am */ + PQERRORS_SQLSTATE /* only error severity and SQLSTATE code */ +} PGVerbosity; + +typedef enum +{ + PQSHOW_CONTEXT_NEVER, /* never show CONTEXT field */ + PQSHOW_CONTEXT_ERRORS, /* show CONTEXT for errors only (default) */ + PQSHOW_CONTEXT_ALWAYS /* always show CONTEXT field */ +} PGContextVisibility; + +/* + * PGPing - The ordering of this enum should not be altered because the + * values are exposed externally via pg_isready. + */ + +typedef enum +{ + PQPING_OK, /* server is accepting connections */ + PQPING_REJECT, /* server is alive but rejecting connections */ + PQPING_NO_RESPONSE, /* could not establish connection */ + PQPING_NO_ATTEMPT /* connection not attempted (bad params) */ +} PGPing; + +/* + * PGpipelineStatus - Current status of pipeline mode + */ +typedef enum +{ + PQ_PIPELINE_OFF, + PQ_PIPELINE_ON, + PQ_PIPELINE_ABORTED +} PGpipelineStatus; + +/* PGconn encapsulates a connection to the backend. + * The contents of this struct are not supposed to be known to applications. + */ +typedef struct pg_conn PGconn; + +/* PGresult encapsulates the result of a query (or more precisely, of a single + * SQL command --- a query string given to PQsendQuery can contain multiple + * commands and thus return multiple PGresult objects). + * The contents of this struct are not supposed to be known to applications. + */ +typedef struct pg_result PGresult; + +/* PGcancel encapsulates the information needed to cancel a running + * query on an existing connection. + * The contents of this struct are not supposed to be known to applications. + */ +typedef struct pg_cancel PGcancel; + +/* PGnotify represents the occurrence of a NOTIFY message. + * Ideally this would be an opaque typedef, but it's so simple that it's + * unlikely to change. + * NOTE: in Postgres 6.4 and later, the be_pid is the notifying backend's, + * whereas in earlier versions it was always your own backend's PID. + */ +typedef struct pgNotify +{ + char *relname; /* notification condition name */ + int be_pid; /* process ID of notifying server process */ + char *extra; /* notification parameter */ + /* Fields below here are private to libpq; apps should not use 'em */ + struct pgNotify *next; /* list link */ +} PGnotify; + +/* Function types for notice-handling callbacks */ +typedef void (*PQnoticeReceiver) (void *arg, const PGresult *res); +typedef void (*PQnoticeProcessor) (void *arg, const char *message); + +/* Print options for PQprint() */ +typedef char pqbool; + +typedef struct _PQprintOpt +{ + pqbool header; /* print output field headings and row count */ + pqbool align; /* fill align the fields */ + pqbool standard; /* old brain dead format */ + pqbool html3; /* output html tables */ + pqbool expanded; /* expand tables */ + pqbool pager; /* use pager for output if needed */ + char *fieldSep; /* field separator */ + char *tableOpt; /* insert to HTML <table ...> */ + char *caption; /* HTML <caption> */ + char **fieldName; /* null terminated array of replacement field + * names */ +} PQprintOpt; + +/* ---------------- + * Structure for the conninfo parameter definitions returned by PQconndefaults + * or PQconninfoParse. + * + * All fields except "val" point at static strings which must not be altered. + * "val" is either NULL or a malloc'd current-value string. PQconninfoFree() + * will release both the val strings and the PQconninfoOption array itself. + * ---------------- + */ +typedef struct _PQconninfoOption +{ + char *keyword; /* The keyword of the option */ + char *envvar; /* Fallback environment variable name */ + char *compiled; /* Fallback compiled in default value */ + char *val; /* Option's current value, or NULL */ + char *label; /* Label for field in connect dialog */ + char *dispchar; /* Indicates how to display this field in a + * connect dialog. Values are: "" Display + * entered value as is "*" Password field - + * hide value "D" Debug option - don't show + * by default */ + int dispsize; /* Field size in characters for dialog */ +} PQconninfoOption; + +/* ---------------- + * PQArgBlock -- structure for PQfn() arguments + * ---------------- + */ +typedef struct +{ + int len; + int isint; + union + { + int *ptr; /* can't use void (dec compiler barfs) */ + int integer; + } u; +} PQArgBlock; + +/* ---------------- + * PGresAttDesc -- Data about a single attribute (column) of a query result + * ---------------- + */ +typedef struct pgresAttDesc +{ + char *name; /* column name */ + Oid tableid; /* source table, if known */ + int columnid; /* source column, if known */ + int format; /* format code for value (text/binary) */ + Oid typid; /* type id */ + int typlen; /* type size */ + int atttypmod; /* type-specific modifier info */ +} PGresAttDesc; + +/* ---------------- + * Exported functions of libpq + * ---------------- + */ + +/* === in fe-connect.c === */ + +/* make a new client connection to the backend */ +/* Asynchronous (non-blocking) */ +extern PGconn *PQconnectStart(const char *conninfo); +extern PGconn *PQconnectStartParams(const char *const *keywords, + const char *const *values, int expand_dbname); +extern PostgresPollingStatusType PQconnectPoll(PGconn *conn); + +/* Synchronous (blocking) */ +extern PGconn *PQconnectdb(const char *conninfo); +extern PGconn *PQconnectdbParams(const char *const *keywords, + const char *const *values, int expand_dbname); +extern PGconn *PQsetdbLogin(const char *pghost, const char *pgport, + const char *pgoptions, const char *pgtty, + const char *dbName, + const char *login, const char *pwd); + +#define PQsetdb(M_PGHOST,M_PGPORT,M_PGOPT,M_PGTTY,M_DBNAME) \ + PQsetdbLogin(M_PGHOST, M_PGPORT, M_PGOPT, M_PGTTY, M_DBNAME, NULL, NULL) + +/* close the current connection and free the PGconn data structure */ +extern void PQfinish(PGconn *conn); + +/* get info about connection options known to PQconnectdb */ +extern PQconninfoOption *PQconndefaults(void); + +/* parse connection options in same way as PQconnectdb */ +extern PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg); + +/* return the connection options used by a live connection */ +extern PQconninfoOption *PQconninfo(PGconn *conn); + +/* free the data structure returned by PQconndefaults() or PQconninfoParse() */ +extern void PQconninfoFree(PQconninfoOption *connOptions); + +/* + * close the current connection and reestablish a new one with the same + * parameters + */ +/* Asynchronous (non-blocking) */ +extern int PQresetStart(PGconn *conn); +extern PostgresPollingStatusType PQresetPoll(PGconn *conn); + +/* Synchronous (blocking) */ +extern void PQreset(PGconn *conn); + +/* request a cancel structure */ +extern PGcancel *PQgetCancel(PGconn *conn); + +/* free a cancel structure */ +extern void PQfreeCancel(PGcancel *cancel); + +/* issue a cancel request */ +extern int PQcancel(PGcancel *cancel, char *errbuf, int errbufsize); + +/* backwards compatible version of PQcancel; not thread-safe */ +extern int PQrequestCancel(PGconn *conn); + +/* Accessor functions for PGconn objects */ +extern char *PQdb(const PGconn *conn); +extern char *PQuser(const PGconn *conn); +extern char *PQpass(const PGconn *conn); +extern char *PQhost(const PGconn *conn); +extern char *PQhostaddr(const PGconn *conn); +extern char *PQport(const PGconn *conn); +extern char *PQtty(const PGconn *conn); +extern char *PQoptions(const PGconn *conn); +extern ConnStatusType PQstatus(const PGconn *conn); +extern PGTransactionStatusType PQtransactionStatus(const PGconn *conn); +extern const char *PQparameterStatus(const PGconn *conn, + const char *paramName); +extern int PQprotocolVersion(const PGconn *conn); +extern int PQserverVersion(const PGconn *conn); +extern char *PQerrorMessage(const PGconn *conn); +extern int PQsocket(const PGconn *conn); +extern int PQbackendPID(const PGconn *conn); +extern PGpipelineStatus PQpipelineStatus(const PGconn *conn); +extern int PQconnectionNeedsPassword(const PGconn *conn); +extern int PQconnectionUsedPassword(const PGconn *conn); +extern int PQconnectionUsedGSSAPI(const PGconn *conn); +extern int PQclientEncoding(const PGconn *conn); +extern int PQsetClientEncoding(PGconn *conn, const char *encoding); + +/* SSL information functions */ +extern int PQsslInUse(PGconn *conn); +extern void *PQsslStruct(PGconn *conn, const char *struct_name); +extern const char *PQsslAttribute(PGconn *conn, const char *attribute_name); +extern const char *const *PQsslAttributeNames(PGconn *conn); + +/* Get the OpenSSL structure associated with a connection. Returns NULL for + * unencrypted connections or if any other TLS library is in use. */ +extern void *PQgetssl(PGconn *conn); + +/* Tell libpq whether it needs to initialize OpenSSL */ +extern void PQinitSSL(int do_init); + +/* More detailed way to tell libpq whether it needs to initialize OpenSSL */ +extern void PQinitOpenSSL(int do_ssl, int do_crypto); + +/* Return true if GSSAPI encryption is in use */ +extern int PQgssEncInUse(PGconn *conn); + +/* Returns GSSAPI context if GSSAPI is in use */ +extern void *PQgetgssctx(PGconn *conn); + +/* Set verbosity for PQerrorMessage and PQresultErrorMessage */ +extern PGVerbosity PQsetErrorVerbosity(PGconn *conn, PGVerbosity verbosity); + +/* Set CONTEXT visibility for PQerrorMessage and PQresultErrorMessage */ +extern PGContextVisibility PQsetErrorContextVisibility(PGconn *conn, + PGContextVisibility show_context); + +/* Override default notice handling routines */ +extern PQnoticeReceiver PQsetNoticeReceiver(PGconn *conn, + PQnoticeReceiver proc, + void *arg); +extern PQnoticeProcessor PQsetNoticeProcessor(PGconn *conn, + PQnoticeProcessor proc, + void *arg); + +/* + * Used to set callback that prevents concurrent access to + * non-thread safe functions that libpq needs. + * The default implementation uses a libpq internal mutex. + * Only required for multithreaded apps that use kerberos + * both within their app and for postgresql connections. + */ +typedef void (*pgthreadlock_t) (int acquire); + +extern pgthreadlock_t PQregisterThreadLock(pgthreadlock_t newhandler); + +/* === in fe-trace.c === */ +extern void PQtrace(PGconn *conn, FILE *debug_port); +extern void PQuntrace(PGconn *conn); + +/* flags controlling trace output: */ +/* omit timestamps from each line */ +#define PQTRACE_SUPPRESS_TIMESTAMPS (1<<0) +/* redact portions of some messages, for testing frameworks */ +#define PQTRACE_REGRESS_MODE (1<<1) +extern void PQsetTraceFlags(PGconn *conn, int flags); + +/* === in fe-exec.c === */ + +/* Simple synchronous query */ +extern PGresult *PQexec(PGconn *conn, const char *query); +extern PGresult *PQexecParams(PGconn *conn, + const char *command, + int nParams, + const Oid *paramTypes, + const char *const *paramValues, + const int *paramLengths, + const int *paramFormats, + int resultFormat); +extern PGresult *PQprepare(PGconn *conn, const char *stmtName, + const char *query, int nParams, + const Oid *paramTypes); +extern PGresult *PQexecPrepared(PGconn *conn, + const char *stmtName, + int nParams, + const char *const *paramValues, + const int *paramLengths, + const int *paramFormats, + int resultFormat); + +/* Interface for multiple-result or asynchronous queries */ +#define PQ_QUERY_PARAM_MAX_LIMIT 65535 + +extern int PQsendQuery(PGconn *conn, const char *query); +extern int PQsendQueryParams(PGconn *conn, + const char *command, + int nParams, + const Oid *paramTypes, + const char *const *paramValues, + const int *paramLengths, + const int *paramFormats, + int resultFormat); +extern int PQsendPrepare(PGconn *conn, const char *stmtName, + const char *query, int nParams, + const Oid *paramTypes); +extern int PQsendQueryPrepared(PGconn *conn, + const char *stmtName, + int nParams, + const char *const *paramValues, + const int *paramLengths, + const int *paramFormats, + int resultFormat); +extern int PQsetSingleRowMode(PGconn *conn); +extern PGresult *PQgetResult(PGconn *conn); + +/* Routines for managing an asynchronous query */ +extern int PQisBusy(PGconn *conn); +extern int PQconsumeInput(PGconn *conn); + +/* Routines for pipeline mode management */ +extern int PQenterPipelineMode(PGconn *conn); +extern int PQexitPipelineMode(PGconn *conn); +extern int PQpipelineSync(PGconn *conn); +extern int PQsendFlushRequest(PGconn *conn); + +/* LISTEN/NOTIFY support */ +extern PGnotify *PQnotifies(PGconn *conn); + +/* Routines for copy in/out */ +extern int PQputCopyData(PGconn *conn, const char *buffer, int nbytes); +extern int PQputCopyEnd(PGconn *conn, const char *errormsg); +extern int PQgetCopyData(PGconn *conn, char **buffer, int async); + +/* Deprecated routines for copy in/out */ +extern int PQgetline(PGconn *conn, char *buffer, int length); +extern int PQputline(PGconn *conn, const char *string); +extern int PQgetlineAsync(PGconn *conn, char *buffer, int bufsize); +extern int PQputnbytes(PGconn *conn, const char *buffer, int nbytes); +extern int PQendcopy(PGconn *conn); + +/* Set blocking/nonblocking connection to the backend */ +extern int PQsetnonblocking(PGconn *conn, int arg); +extern int PQisnonblocking(const PGconn *conn); +extern int PQisthreadsafe(void); +extern PGPing PQping(const char *conninfo); +extern PGPing PQpingParams(const char *const *keywords, + const char *const *values, int expand_dbname); + +/* Force the write buffer to be written (or at least try) */ +extern int PQflush(PGconn *conn); + +/* + * "Fast path" interface --- not really recommended for application + * use + */ +extern PGresult *PQfn(PGconn *conn, + int fnid, + int *result_buf, + int *result_len, + int result_is_int, + const PQArgBlock *args, + int nargs); + +/* Accessor functions for PGresult objects */ +extern ExecStatusType PQresultStatus(const PGresult *res); +extern char *PQresStatus(ExecStatusType status); +extern char *PQresultErrorMessage(const PGresult *res); +extern char *PQresultVerboseErrorMessage(const PGresult *res, + PGVerbosity verbosity, + PGContextVisibility show_context); +extern char *PQresultErrorField(const PGresult *res, int fieldcode); +extern int PQntuples(const PGresult *res); +extern int PQnfields(const PGresult *res); +extern int PQbinaryTuples(const PGresult *res); +extern char *PQfname(const PGresult *res, int field_num); +extern int PQfnumber(const PGresult *res, const char *field_name); +extern Oid PQftable(const PGresult *res, int field_num); +extern int PQftablecol(const PGresult *res, int field_num); +extern int PQfformat(const PGresult *res, int field_num); +extern Oid PQftype(const PGresult *res, int field_num); +extern int PQfsize(const PGresult *res, int field_num); +extern int PQfmod(const PGresult *res, int field_num); +extern char *PQcmdStatus(PGresult *res); +extern char *PQoidStatus(const PGresult *res); /* old and ugly */ +extern Oid PQoidValue(const PGresult *res); /* new and improved */ +extern char *PQcmdTuples(PGresult *res); +extern char *PQgetvalue(const PGresult *res, int tup_num, int field_num); +extern int PQgetlength(const PGresult *res, int tup_num, int field_num); +extern int PQgetisnull(const PGresult *res, int tup_num, int field_num); +extern int PQnparams(const PGresult *res); +extern Oid PQparamtype(const PGresult *res, int param_num); + +/* Describe prepared statements and portals */ +extern PGresult *PQdescribePrepared(PGconn *conn, const char *stmt); +extern PGresult *PQdescribePortal(PGconn *conn, const char *portal); +extern int PQsendDescribePrepared(PGconn *conn, const char *stmt); +extern int PQsendDescribePortal(PGconn *conn, const char *portal); + +/* Delete a PGresult */ +extern void PQclear(PGresult *res); + +/* For freeing other alloc'd results, such as PGnotify structs */ +extern void PQfreemem(void *ptr); + +/* Exists for backward compatibility. bjm 2003-03-24 */ +#define PQfreeNotify(ptr) PQfreemem(ptr) + +/* Error when no password was given. */ +/* Note: depending on this is deprecated; use PQconnectionNeedsPassword(). */ +#define PQnoPasswordSupplied "fe_sendauth: no password supplied\n" + +/* Create and manipulate PGresults */ +extern PGresult *PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status); +extern PGresult *PQcopyResult(const PGresult *src, int flags); +extern int PQsetResultAttrs(PGresult *res, int numAttributes, PGresAttDesc *attDescs); +extern void *PQresultAlloc(PGresult *res, size_t nBytes); +extern size_t PQresultMemorySize(const PGresult *res); +extern int PQsetvalue(PGresult *res, int tup_num, int field_num, char *value, int len); + +/* Quoting strings before inclusion in queries. */ +extern size_t PQescapeStringConn(PGconn *conn, + char *to, const char *from, size_t length, + int *error); +extern char *PQescapeLiteral(PGconn *conn, const char *str, size_t len); +extern char *PQescapeIdentifier(PGconn *conn, const char *str, size_t len); +extern unsigned char *PQescapeByteaConn(PGconn *conn, + const unsigned char *from, size_t from_length, + size_t *to_length); +extern unsigned char *PQunescapeBytea(const unsigned char *strtext, + size_t *retbuflen); + +/* These forms are deprecated! */ +extern size_t PQescapeString(char *to, const char *from, size_t length); +extern unsigned char *PQescapeBytea(const unsigned char *from, size_t from_length, + size_t *to_length); + + + +/* === in fe-print.c === */ + +extern void PQprint(FILE *fout, /* output stream */ + const PGresult *res, + const PQprintOpt *po); /* option structure */ + +/* + * really old printing routines + */ +extern void PQdisplayTuples(const PGresult *res, + FILE *fp, /* where to send the output */ + int fillAlign, /* pad the fields with spaces */ + const char *fieldSep, /* field separator */ + int printHeader, /* display headers? */ + int quiet); + +extern void PQprintTuples(const PGresult *res, + FILE *fout, /* output stream */ + int PrintAttNames, /* print attribute names */ + int TerseOutput, /* delimiter bars */ + int colWidth); /* width of column, if 0, use + * variable width */ + + +/* === in fe-lobj.c === */ + +/* Large-object access routines */ +extern int lo_open(PGconn *conn, Oid lobjId, int mode); +extern int lo_close(PGconn *conn, int fd); +extern int lo_read(PGconn *conn, int fd, char *buf, size_t len); +extern int lo_write(PGconn *conn, int fd, const char *buf, size_t len); +extern int lo_lseek(PGconn *conn, int fd, int offset, int whence); +extern pg_int64 lo_lseek64(PGconn *conn, int fd, pg_int64 offset, int whence); +extern Oid lo_creat(PGconn *conn, int mode); +extern Oid lo_create(PGconn *conn, Oid lobjId); +extern int lo_tell(PGconn *conn, int fd); +extern pg_int64 lo_tell64(PGconn *conn, int fd); +extern int lo_truncate(PGconn *conn, int fd, size_t len); +extern int lo_truncate64(PGconn *conn, int fd, pg_int64 len); +extern int lo_unlink(PGconn *conn, Oid lobjId); +extern Oid lo_import(PGconn *conn, const char *filename); +extern Oid lo_import_with_oid(PGconn *conn, const char *filename, Oid lobjId); +extern int lo_export(PGconn *conn, Oid lobjId, const char *filename); + +/* === in fe-misc.c === */ + +/* Get the version of the libpq library in use */ +extern int PQlibVersion(void); + +/* Determine length of multibyte encoded char at *s */ +extern int PQmblen(const char *s, int encoding); + +/* Same, but not more than the distance to the end of string s */ +extern int PQmblenBounded(const char *s, int encoding); + +/* Determine display length of multibyte encoded char at *s */ +extern int PQdsplen(const char *s, int encoding); + +/* Get encoding id from environment variable PGCLIENTENCODING */ +extern int PQenv2encoding(void); + +/* === in fe-auth.c === */ + +extern char *PQencryptPassword(const char *passwd, const char *user); +extern char *PQencryptPasswordConn(PGconn *conn, const char *passwd, const char *user, const char *algorithm); + +/* === in encnames.c === */ + +extern int pg_char_to_encoding(const char *name); +extern const char *pg_encoding_to_char(int encoding); +extern int pg_valid_server_encoding_id(int encoding); + +/* === in fe-secure-openssl.c === */ + +/* Support for overriding sslpassword handling with a callback */ +typedef int (*PQsslKeyPassHook_OpenSSL_type) (char *buf, int size, PGconn *conn); +extern PQsslKeyPassHook_OpenSSL_type PQgetSSLKeyPassHook_OpenSSL(void); +extern void PQsetSSLKeyPassHook_OpenSSL(PQsslKeyPassHook_OpenSSL_type hook); +extern int PQdefaultSSLKeyPassHook_OpenSSL(char *buf, int size, PGconn *conn); + +#ifdef __cplusplus +} +#endif + +#endif /* LIBPQ_FE_H */ diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h new file mode 100644 index 0000000..a951f49 --- /dev/null +++ b/src/interfaces/libpq/libpq-int.h @@ -0,0 +1,940 @@ +/*------------------------------------------------------------------------- + * + * libpq-int.h + * This file contains internal definitions meant to be used only by + * the frontend libpq library, not by applications that call it. + * + * An application can include this file if it wants to bypass the + * official API defined by libpq-fe.h, but code that does so is much + * more likely to break across PostgreSQL releases than code that uses + * only the official API. + * + * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/interfaces/libpq/libpq-int.h + * + *------------------------------------------------------------------------- + */ + +#ifndef LIBPQ_INT_H +#define LIBPQ_INT_H + +/* We assume libpq-fe.h has already been included. */ +#include "libpq-events.h" + +#include <netdb.h> +#include <sys/socket.h> +#include <time.h> +/* MinGW has sys/time.h, but MSVC doesn't */ +#ifndef _MSC_VER +#include <sys/time.h> +#endif + +#ifdef ENABLE_THREAD_SAFETY +#ifdef WIN32 +#include "pthread-win32.h" +#else +#include <pthread.h> +#endif +#include <signal.h> +#endif + +/* include stuff common to fe and be */ +#include "libpq/pqcomm.h" +/* include stuff found in fe only */ +#include "fe-auth-sasl.h" +#include "pqexpbuffer.h" + +#ifdef ENABLE_GSS +#if defined(HAVE_GSSAPI_H) +#include <gssapi.h> +#else +#include <gssapi/gssapi.h> +#endif +#endif + +#ifdef ENABLE_SSPI +#define SECURITY_WIN32 +#if defined(WIN32) && !defined(_MSC_VER) +#include <ntsecapi.h> +#endif +#include <security.h> +#undef SECURITY_WIN32 + +#ifndef ENABLE_GSS +/* + * Define a fake structure compatible with GSSAPI on Unix. + */ +typedef struct +{ + void *value; + int length; +} gss_buffer_desc; +#endif +#endif /* ENABLE_SSPI */ + +#ifdef USE_OPENSSL +#include <openssl/ssl.h> +#include <openssl/err.h> + +#ifndef OPENSSL_NO_ENGINE +#define USE_SSL_ENGINE +#endif +#endif /* USE_OPENSSL */ + +#include "common/pg_prng.h" + +/* + * POSTGRES backend dependent Constants. + */ +#define CMDSTATUS_LEN 64 /* should match COMPLETION_TAG_BUFSIZE */ + +/* + * PGresult and the subsidiary types PGresAttDesc, PGresAttValue + * represent the result of a query (or more precisely, of a single SQL + * command --- a query string given to PQexec can contain multiple commands). + * Note we assume that a single command can return at most one tuple group, + * hence there is no need for multiple descriptor sets. + */ + +/* Subsidiary-storage management structure for PGresult. + * See space management routines in fe-exec.c for details. + * Note that space[k] refers to the k'th byte starting from the physical + * head of the block --- it's a union, not a struct! + */ +typedef union pgresult_data PGresult_data; + +union pgresult_data +{ + PGresult_data *next; /* link to next block, or NULL */ + char space[1]; /* dummy for accessing block as bytes */ +}; + +/* Data about a single parameter of a prepared statement */ +typedef struct pgresParamDesc +{ + Oid typid; /* type id */ +} PGresParamDesc; + +/* + * Data for a single attribute of a single tuple + * + * We use char* for Attribute values. + * + * The value pointer always points to a null-terminated area; we add a + * null (zero) byte after whatever the backend sends us. This is only + * particularly useful for text values ... with a binary value, the + * value might have embedded nulls, so the application can't use C string + * operators on it. But we add a null anyway for consistency. + * Note that the value itself does not contain a length word. + * + * A NULL attribute is a special case in two ways: its len field is NULL_LEN + * and its value field points to null_field in the owning PGresult. All the + * NULL attributes in a query result point to the same place (there's no need + * to store a null string separately for each one). + */ + +#define NULL_LEN (-1) /* pg_result len for NULL value */ + +typedef struct pgresAttValue +{ + int len; /* length in bytes of the value */ + char *value; /* actual value, plus terminating zero byte */ +} PGresAttValue; + +/* Typedef for message-field list entries */ +typedef struct pgMessageField +{ + struct pgMessageField *next; /* list link */ + char code; /* field code */ + char contents[FLEXIBLE_ARRAY_MEMBER]; /* value, nul-terminated */ +} PGMessageField; + +/* Fields needed for notice handling */ +typedef struct +{ + PQnoticeReceiver noticeRec; /* notice message receiver */ + void *noticeRecArg; + PQnoticeProcessor noticeProc; /* notice message processor */ + void *noticeProcArg; +} PGNoticeHooks; + +typedef struct PGEvent +{ + PGEventProc proc; /* the function to call on events */ + char *name; /* used only for error messages */ + void *passThrough; /* pointer supplied at registration time */ + void *data; /* optional state (instance) data */ + bool resultInitialized; /* T if RESULTCREATE/COPY succeeded */ +} PGEvent; + +struct pg_result +{ + int ntups; + int numAttributes; + PGresAttDesc *attDescs; + PGresAttValue **tuples; /* each PGresult tuple is an array of + * PGresAttValue's */ + int tupArrSize; /* allocated size of tuples array */ + int numParameters; + PGresParamDesc *paramDescs; + ExecStatusType resultStatus; + char cmdStatus[CMDSTATUS_LEN]; /* cmd status from the query */ + int binary; /* binary tuple values if binary == 1, + * otherwise text */ + + /* + * These fields are copied from the originating PGconn, so that operations + * on the PGresult don't have to reference the PGconn. + */ + PGNoticeHooks noticeHooks; + PGEvent *events; + int nEvents; + int client_encoding; /* encoding id */ + + /* + * Error information (all NULL if not an error result). errMsg is the + * "overall" error message returned by PQresultErrorMessage. If we have + * per-field info then it is stored in a linked list. + */ + char *errMsg; /* error message, or NULL if no error */ + PGMessageField *errFields; /* message broken into fields */ + char *errQuery; /* text of triggering query, if available */ + + /* All NULL attributes in the query result point to this null string */ + char null_field[1]; + + /* + * Space management information. Note that attDescs and error stuff, if + * not null, point into allocated blocks. But tuples points to a + * separately malloc'd block, so that we can realloc it. + */ + PGresult_data *curBlock; /* most recently allocated block */ + int curOffset; /* start offset of free space in block */ + int spaceLeft; /* number of free bytes remaining in block */ + + size_t memorySize; /* total space allocated for this PGresult */ +}; + +/* PGAsyncStatusType defines the state of the query-execution state machine */ +typedef enum +{ + PGASYNC_IDLE, /* nothing's happening, dude */ + PGASYNC_BUSY, /* query in progress */ + PGASYNC_READY, /* query done, waiting for client to fetch + * result */ + PGASYNC_READY_MORE, /* query done, waiting for client to fetch + * result, more results expected from this + * query */ + PGASYNC_COPY_IN, /* Copy In data transfer in progress */ + PGASYNC_COPY_OUT, /* Copy Out data transfer in progress */ + PGASYNC_COPY_BOTH, /* Copy In/Out data transfer in progress */ + PGASYNC_PIPELINE_IDLE, /* "Idle" between commands in pipeline mode */ +} PGAsyncStatusType; + +/* Target server type (decoded value of target_session_attrs) */ +typedef enum +{ + SERVER_TYPE_ANY = 0, /* Any server (default) */ + SERVER_TYPE_READ_WRITE, /* Read-write server */ + SERVER_TYPE_READ_ONLY, /* Read-only server */ + SERVER_TYPE_PRIMARY, /* Primary server */ + SERVER_TYPE_STANDBY, /* Standby server */ + SERVER_TYPE_PREFER_STANDBY, /* Prefer standby server */ + SERVER_TYPE_PREFER_STANDBY_PASS2 /* second pass - behaves same as ANY */ +} PGTargetServerType; + +/* Target server type (decoded value of load_balance_hosts) */ +typedef enum +{ + LOAD_BALANCE_DISABLE = 0, /* Use the existing host order (default) */ + LOAD_BALANCE_RANDOM, /* Randomly shuffle the hosts */ +} PGLoadBalanceType; + +/* Boolean value plus a not-known state, for GUCs we might have to fetch */ +typedef enum +{ + PG_BOOL_UNKNOWN = 0, /* Currently unknown */ + PG_BOOL_YES, /* Yes (true) */ + PG_BOOL_NO /* No (false) */ +} PGTernaryBool; + +/* Typedef for the EnvironmentOptions[] array */ +typedef struct PQEnvironmentOption +{ + const char *envName, /* name of an environment variable */ + *pgName; /* name of corresponding SET variable */ +} PQEnvironmentOption; + +/* Typedef for parameter-status list entries */ +typedef struct pgParameterStatus +{ + struct pgParameterStatus *next; /* list link */ + char *name; /* parameter name */ + char *value; /* parameter value */ + /* Note: name and value are stored in same malloc block as struct is */ +} pgParameterStatus; + +/* large-object-access data ... allocated only if large-object code is used. */ +typedef struct pgLobjfuncs +{ + Oid fn_lo_open; /* OID of backend function lo_open */ + Oid fn_lo_close; /* OID of backend function lo_close */ + Oid fn_lo_creat; /* OID of backend function lo_creat */ + Oid fn_lo_create; /* OID of backend function lo_create */ + Oid fn_lo_unlink; /* OID of backend function lo_unlink */ + Oid fn_lo_lseek; /* OID of backend function lo_lseek */ + Oid fn_lo_lseek64; /* OID of backend function lo_lseek64 */ + Oid fn_lo_tell; /* OID of backend function lo_tell */ + Oid fn_lo_tell64; /* OID of backend function lo_tell64 */ + Oid fn_lo_truncate; /* OID of backend function lo_truncate */ + Oid fn_lo_truncate64; /* OID of function lo_truncate64 */ + Oid fn_lo_read; /* OID of backend function LOread */ + Oid fn_lo_write; /* OID of backend function LOwrite */ +} PGlobjfuncs; + +/* PGdataValue represents a data field value being passed to a row processor. + * It could be either text or binary data; text data is not zero-terminated. + * A SQL NULL is represented by len < 0; then value is still valid but there + * are no data bytes there. + */ +typedef struct pgDataValue +{ + int len; /* data length in bytes, or <0 if NULL */ + const char *value; /* data value, without zero-termination */ +} PGdataValue; + +/* Host address type enum for struct pg_conn_host */ +typedef enum pg_conn_host_type +{ + CHT_HOST_NAME, + CHT_HOST_ADDRESS, + CHT_UNIX_SOCKET +} pg_conn_host_type; + +/* + * PGQueryClass tracks which query protocol is in use for each command queue + * entry, or special operation in execution + */ +typedef enum +{ + PGQUERY_SIMPLE, /* simple Query protocol (PQexec) */ + PGQUERY_EXTENDED, /* full Extended protocol (PQexecParams) */ + PGQUERY_PREPARE, /* Parse only (PQprepare) */ + PGQUERY_DESCRIBE, /* Describe Statement or Portal */ + PGQUERY_SYNC, /* Sync (at end of a pipeline) */ + PGQUERY_CLOSE +} PGQueryClass; + +/* + * An entry in the pending command queue. + */ +typedef struct PGcmdQueueEntry +{ + PGQueryClass queryclass; /* Query type */ + char *query; /* SQL command, or NULL if none/unknown/OOM */ + struct PGcmdQueueEntry *next; /* list link */ +} PGcmdQueueEntry; + +/* + * pg_conn_host stores all information about each of possibly several hosts + * mentioned in the connection string. Most fields are derived by splitting + * the relevant connection parameter (e.g., pghost) at commas. + */ +typedef struct pg_conn_host +{ + pg_conn_host_type type; /* type of host address */ + char *host; /* host name or socket path */ + char *hostaddr; /* host numeric IP address */ + char *port; /* port number (always provided) */ + char *password; /* password for this host, read from the + * password file; NULL if not sought or not + * found in password file. */ +} pg_conn_host; + +/* + * PGconn stores all the state data associated with a single connection + * to a backend. + */ +struct pg_conn +{ + /* Saved values of connection options */ + char *pghost; /* the machine on which the server is running, + * or a path to a UNIX-domain socket, or a + * comma-separated list of machines and/or + * paths; if NULL, use DEFAULT_PGSOCKET_DIR */ + char *pghostaddr; /* the numeric IP address of the machine on + * which the server is running, or a + * comma-separated list of same. Takes + * precedence over pghost. */ + char *pgport; /* the server's communication port number, or + * a comma-separated list of ports */ + char *connect_timeout; /* connection timeout (numeric string) */ + char *pgtcp_user_timeout; /* tcp user timeout (numeric string) */ + char *client_encoding_initial; /* encoding to use */ + char *pgoptions; /* options to start the backend with */ + char *appname; /* application name */ + char *fbappname; /* fallback application name */ + char *dbName; /* database name */ + char *replication; /* connect as the replication standby? */ + char *pguser; /* Postgres username and password, if any */ + char *pgpass; + char *pgpassfile; /* path to a file containing password(s) */ + char *channel_binding; /* channel binding mode + * (require,prefer,disable) */ + char *keepalives; /* use TCP keepalives? */ + char *keepalives_idle; /* time between TCP keepalives */ + char *keepalives_interval; /* time between TCP keepalive + * retransmits */ + char *keepalives_count; /* maximum number of TCP keepalive + * retransmits */ + char *sslmode; /* SSL mode (require,prefer,allow,disable) */ + char *sslcompression; /* SSL compression (0 or 1) */ + char *sslkey; /* client key filename */ + char *sslcert; /* client certificate filename */ + char *sslpassword; /* client key file password */ + char *sslcertmode; /* client cert mode (require,allow,disable) */ + char *sslrootcert; /* root certificate filename */ + char *sslcrl; /* certificate revocation list filename */ + char *sslcrldir; /* certificate revocation list directory name */ + char *sslsni; /* use SSL SNI extension (0 or 1) */ + char *requirepeer; /* required peer credentials for local sockets */ + char *gssencmode; /* GSS mode (require,prefer,disable) */ + char *krbsrvname; /* Kerberos service name */ + char *gsslib; /* What GSS library to use ("gssapi" or + * "sspi") */ + char *gssdelegation; /* Try to delegate GSS credentials? (0 or 1) */ + char *ssl_min_protocol_version; /* minimum TLS protocol version */ + char *ssl_max_protocol_version; /* maximum TLS protocol version */ + char *target_session_attrs; /* desired session properties */ + char *require_auth; /* name of the expected auth method */ + char *load_balance_hosts; /* load balance over hosts */ + + /* Optional file to write trace info to */ + FILE *Pfdebug; + int traceFlags; + + /* Callback procedures for notice message processing */ + PGNoticeHooks noticeHooks; + + /* Event procs registered via PQregisterEventProc */ + PGEvent *events; /* expandable array of event data */ + int nEvents; /* number of active events */ + int eventArraySize; /* allocated array size */ + + /* Status indicators */ + ConnStatusType status; + PGAsyncStatusType asyncStatus; + PGTransactionStatusType xactStatus; /* never changes to ACTIVE */ + char last_sqlstate[6]; /* last reported SQLSTATE */ + bool options_valid; /* true if OK to attempt connection */ + bool nonblocking; /* whether this connection is using nonblock + * sending semantics */ + PGpipelineStatus pipelineStatus; /* status of pipeline mode */ + bool singleRowMode; /* return current query result row-by-row? */ + char copy_is_binary; /* 1 = copy binary, 0 = copy text */ + int copy_already_done; /* # bytes already returned in COPY OUT */ + PGnotify *notifyHead; /* oldest unreported Notify msg */ + PGnotify *notifyTail; /* newest unreported Notify msg */ + + /* Support for multiple hosts in connection string */ + int nconnhost; /* # of hosts named in conn string */ + int whichhost; /* host we're currently trying/connected to */ + pg_conn_host *connhost; /* details about each named host */ + char *connip; /* IP address for current network connection */ + + /* + * The pending command queue as a singly-linked list. Head is the command + * currently in execution, tail is where new commands are added. + */ + PGcmdQueueEntry *cmd_queue_head; + PGcmdQueueEntry *cmd_queue_tail; + + /* + * To save malloc traffic, we don't free entries right away; instead we + * save them in this list for possible reuse. + */ + PGcmdQueueEntry *cmd_queue_recycle; + + /* Connection data */ + pgsocket sock; /* FD for socket, PGINVALID_SOCKET if + * unconnected */ + SockAddr laddr; /* Local address */ + SockAddr raddr; /* Remote address */ + ProtocolVersion pversion; /* FE/BE protocol version in use */ + int sversion; /* server version, e.g. 70401 for 7.4.1 */ + bool auth_req_received; /* true if any type of auth req received */ + bool password_needed; /* true if server demanded a password */ + bool gssapi_used; /* true if authenticated via gssapi */ + bool sigpipe_so; /* have we masked SIGPIPE via SO_NOSIGPIPE? */ + bool sigpipe_flag; /* can we mask SIGPIPE via MSG_NOSIGNAL? */ + bool write_failed; /* have we had a write failure on sock? */ + char *write_err_msg; /* write error message, or NULL if OOM */ + + bool auth_required; /* require an authentication challenge from + * the server? */ + uint32 allowed_auth_methods; /* bitmask of acceptable AuthRequest + * codes */ + bool client_finished_auth; /* have we finished our half of the + * authentication exchange? */ + + + /* Transient state needed while establishing connection */ + PGTargetServerType target_server_type; /* desired session properties */ + PGLoadBalanceType load_balance_type; /* desired load balancing + * algorithm */ + bool try_next_addr; /* time to advance to next address/host? */ + bool try_next_host; /* time to advance to next connhost[]? */ + int naddr; /* number of addresses returned by getaddrinfo */ + int whichaddr; /* the address currently being tried */ + AddrInfo *addr; /* the array of addresses for the currently + * tried host */ + bool send_appname; /* okay to send application_name? */ + + /* Miscellaneous stuff */ + int be_pid; /* PID of backend --- needed for cancels */ + int be_key; /* key of backend --- needed for cancels */ + pgParameterStatus *pstatus; /* ParameterStatus data */ + int client_encoding; /* encoding id */ + bool std_strings; /* standard_conforming_strings */ + PGTernaryBool default_transaction_read_only; /* default_transaction_read_only */ + PGTernaryBool in_hot_standby; /* in_hot_standby */ + PGVerbosity verbosity; /* error/notice message verbosity */ + PGContextVisibility show_context; /* whether to show CONTEXT field */ + PGlobjfuncs *lobjfuncs; /* private state for large-object access fns */ + pg_prng_state prng_state; /* prng state for load balancing connections */ + + + /* Buffer for data received from backend and not yet processed */ + char *inBuffer; /* currently allocated buffer */ + int inBufSize; /* allocated size of buffer */ + int inStart; /* offset to first unconsumed data in buffer */ + int inCursor; /* next byte to tentatively consume */ + int inEnd; /* offset to first position after avail data */ + + /* Buffer for data not yet sent to backend */ + char *outBuffer; /* currently allocated buffer */ + int outBufSize; /* allocated size of buffer */ + int outCount; /* number of chars waiting in buffer */ + + /* State for constructing messages in outBuffer */ + int outMsgStart; /* offset to msg start (length word); if -1, + * msg has no length word */ + int outMsgEnd; /* offset to msg end (so far) */ + + /* Row processor interface workspace */ + PGdataValue *rowBuf; /* array for passing values to rowProcessor */ + int rowBufLen; /* number of entries allocated in rowBuf */ + + /* + * Status for asynchronous result construction. If result isn't NULL, it + * is a result being constructed or ready to return. If result is NULL + * and error_result is true, then we need to return a PGRES_FATAL_ERROR + * result, but haven't yet constructed it; text for the error has been + * appended to conn->errorMessage. (Delaying construction simplifies + * dealing with out-of-memory cases.) If next_result isn't NULL, it is a + * PGresult that will replace "result" after we return that one. + */ + PGresult *result; /* result being constructed */ + bool error_result; /* do we need to make an ERROR result? */ + PGresult *next_result; /* next result (used in single-row mode) */ + + /* Assorted state for SASL, SSL, GSS, etc */ + const pg_fe_sasl_mech *sasl; + void *sasl_state; + int scram_sha_256_iterations; + + /* SSL structures */ + bool ssl_in_use; + bool ssl_cert_requested; /* Did the server ask us for a cert? */ + bool ssl_cert_sent; /* Did we send one in reply? */ + +#ifdef USE_SSL + bool allow_ssl_try; /* Allowed to try SSL negotiation */ + bool wait_ssl_try; /* Delay SSL negotiation until after + * attempting normal connection */ +#ifdef USE_OPENSSL + SSL *ssl; /* SSL status, if have SSL connection */ + X509 *peer; /* X509 cert of server */ +#ifdef USE_SSL_ENGINE + ENGINE *engine; /* SSL engine, if any */ +#else + void *engine; /* dummy field to keep struct the same if + * OpenSSL version changes */ +#endif + bool crypto_loaded; /* Track if libcrypto locking callbacks have + * been done for this connection. This can be + * removed once support for OpenSSL 1.0.2 is + * removed as this locking is handled + * internally in OpenSSL >= 1.1.0. */ +#endif /* USE_OPENSSL */ +#endif /* USE_SSL */ + +#ifdef ENABLE_GSS + gss_ctx_id_t gctx; /* GSS context */ + gss_name_t gtarg_nam; /* GSS target name */ + + /* The following are encryption-only */ + bool try_gss; /* GSS attempting permitted */ + bool gssenc; /* GSS encryption is usable */ + gss_cred_id_t gcred; /* GSS credential temp storage. */ + + /* GSS encryption I/O state --- see fe-secure-gssapi.c */ + char *gss_SendBuffer; /* Encrypted data waiting to be sent */ + int gss_SendLength; /* End of data available in gss_SendBuffer */ + int gss_SendNext; /* Next index to send a byte from + * gss_SendBuffer */ + int gss_SendConsumed; /* Number of source bytes encrypted but + * not yet reported as sent */ + char *gss_RecvBuffer; /* Received, encrypted data */ + int gss_RecvLength; /* End of data available in gss_RecvBuffer */ + char *gss_ResultBuffer; /* Decryption of data in gss_RecvBuffer */ + int gss_ResultLength; /* End of data available in + * gss_ResultBuffer */ + int gss_ResultNext; /* Next index to read a byte from + * gss_ResultBuffer */ + uint32 gss_MaxPktSize; /* Maximum size we can encrypt and fit the + * results into our output buffer */ +#endif + +#ifdef ENABLE_SSPI + CredHandle *sspicred; /* SSPI credentials handle */ + CtxtHandle *sspictx; /* SSPI context */ + char *sspitarget; /* SSPI target name */ + int usesspi; /* Indicate if SSPI is in use on the + * connection */ +#endif + + /* + * Buffer for current error message. This is cleared at the start of any + * connection attempt or query cycle; after that, all code should append + * messages to it, never overwrite. + * + * In some situations we might report an error more than once in a query + * cycle. If so, errorMessage accumulates text from all the errors, and + * errorReported tracks how much we've already reported, so that the + * individual error PGresult objects don't contain duplicative text. + */ + PQExpBufferData errorMessage; /* expansible string */ + int errorReported; /* # bytes of string already reported */ + + /* Buffer for receiving various parts of messages */ + PQExpBufferData workBuffer; /* expansible string */ +}; + +/* PGcancel stores all data necessary to cancel a connection. A copy of this + * data is required to safely cancel a connection running on a different + * thread. + */ +struct pg_cancel +{ + SockAddr raddr; /* Remote address */ + int be_pid; /* PID of backend --- needed for cancels */ + int be_key; /* key of backend --- needed for cancels */ + int pgtcp_user_timeout; /* tcp user timeout */ + int keepalives; /* use TCP keepalives? */ + int keepalives_idle; /* time between TCP keepalives */ + int keepalives_interval; /* time between TCP keepalive + * retransmits */ + int keepalives_count; /* maximum number of TCP keepalive + * retransmits */ +}; + + +/* String descriptions of the ExecStatusTypes. + * direct use of this array is deprecated; call PQresStatus() instead. + */ +extern char *const pgresStatus[]; + + +#ifdef USE_SSL + +#ifndef WIN32 +#define USER_CERT_FILE ".postgresql/postgresql.crt" +#define USER_KEY_FILE ".postgresql/postgresql.key" +#define ROOT_CERT_FILE ".postgresql/root.crt" +#define ROOT_CRL_FILE ".postgresql/root.crl" +#else +/* On Windows, the "home" directory is already PostgreSQL-specific */ +#define USER_CERT_FILE "postgresql.crt" +#define USER_KEY_FILE "postgresql.key" +#define ROOT_CERT_FILE "root.crt" +#define ROOT_CRL_FILE "root.crl" +#endif + +#endif /* USE_SSL */ + +/* ---------------- + * Internal functions of libpq + * Functions declared here need to be visible across files of libpq, + * but are not intended to be called by applications. We use the + * convention "pqXXX" for internal functions, vs. the "PQxxx" names + * used for application-visible routines. + * ---------------- + */ + +/* === in fe-connect.c === */ + +extern void pqDropConnection(PGconn *conn, bool flushInput); +extern int pqPacketSend(PGconn *conn, char pack_type, + const void *buf, size_t buf_len); +extern bool pqGetHomeDirectory(char *buf, int bufsize); + +#ifdef ENABLE_THREAD_SAFETY +extern pgthreadlock_t pg_g_threadlock; + +#define pglock_thread() pg_g_threadlock(true) +#define pgunlock_thread() pg_g_threadlock(false) +#else +#define pglock_thread() ((void) 0) +#define pgunlock_thread() ((void) 0) +#endif + +/* === in fe-exec.c === */ + +extern void pqSetResultError(PGresult *res, PQExpBuffer errorMessage, int offset); +extern void *pqResultAlloc(PGresult *res, size_t nBytes, bool isBinary); +extern char *pqResultStrdup(PGresult *res, const char *str); +extern void pqClearAsyncResult(PGconn *conn); +extern void pqSaveErrorResult(PGconn *conn); +extern PGresult *pqPrepareAsyncResult(PGconn *conn); +extern void pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt,...) pg_attribute_printf(2, 3); +extern void pqSaveMessageField(PGresult *res, char code, + const char *value); +extern void pqSaveParameterStatus(PGconn *conn, const char *name, + const char *value); +extern int pqRowProcessor(PGconn *conn, const char **errmsgp); +extern void pqCommandQueueAdvance(PGconn *conn, bool isReadyForQuery, + bool gotSync); +extern int PQsendQueryContinue(PGconn *conn, const char *query); + +/* === in fe-protocol3.c === */ + +extern char *pqBuildStartupPacket3(PGconn *conn, int *packetlen, + const PQEnvironmentOption *options); +extern void pqParseInput3(PGconn *conn); +extern int pqGetErrorNotice3(PGconn *conn, bool isError); +extern void pqBuildErrorMessage3(PQExpBuffer msg, const PGresult *res, + PGVerbosity verbosity, PGContextVisibility show_context); +extern int pqGetNegotiateProtocolVersion3(PGconn *conn); +extern int pqGetCopyData3(PGconn *conn, char **buffer, int async); +extern int pqGetline3(PGconn *conn, char *s, int maxlen); +extern int pqGetlineAsync3(PGconn *conn, char *buffer, int bufsize); +extern int pqEndcopy3(PGconn *conn); +extern PGresult *pqFunctionCall3(PGconn *conn, Oid fnid, + int *result_buf, int *actual_result_len, + int result_is_int, + const PQArgBlock *args, int nargs); + +/* === in fe-misc.c === */ + + /* + * "Get" and "Put" routines return 0 if successful, EOF if not. Note that for + * Get, EOF merely means the buffer is exhausted, not that there is + * necessarily any error. + */ +extern int pqCheckOutBufferSpace(size_t bytes_needed, PGconn *conn); +extern int pqCheckInBufferSpace(size_t bytes_needed, PGconn *conn); +extern int pqGetc(char *result, PGconn *conn); +extern int pqPutc(char c, PGconn *conn); +extern int pqGets(PQExpBuffer buf, PGconn *conn); +extern int pqGets_append(PQExpBuffer buf, PGconn *conn); +extern int pqPuts(const char *s, PGconn *conn); +extern int pqGetnchar(char *s, size_t len, PGconn *conn); +extern int pqSkipnchar(size_t len, PGconn *conn); +extern int pqPutnchar(const char *s, size_t len, PGconn *conn); +extern int pqGetInt(int *result, size_t bytes, PGconn *conn); +extern int pqPutInt(int value, size_t bytes, PGconn *conn); +extern int pqPutMsgStart(char msg_type, PGconn *conn); +extern int pqPutMsgEnd(PGconn *conn); +extern int pqReadData(PGconn *conn); +extern int pqFlush(PGconn *conn); +extern int pqWait(int forRead, int forWrite, PGconn *conn); +extern int pqWaitTimed(int forRead, int forWrite, PGconn *conn, + time_t finish_time); +extern int pqReadReady(PGconn *conn); +extern int pqWriteReady(PGconn *conn); + +/* === in fe-secure.c === */ + +extern int pqsecure_initialize(PGconn *, bool, bool); +extern PostgresPollingStatusType pqsecure_open_client(PGconn *); +extern void pqsecure_close(PGconn *); +extern ssize_t pqsecure_read(PGconn *, void *ptr, size_t len); +extern ssize_t pqsecure_write(PGconn *, const void *ptr, size_t len); +extern ssize_t pqsecure_raw_read(PGconn *, void *ptr, size_t len); +extern ssize_t pqsecure_raw_write(PGconn *, const void *ptr, size_t len); + +#if defined(ENABLE_THREAD_SAFETY) && !defined(WIN32) +extern int pq_block_sigpipe(sigset_t *osigset, bool *sigpipe_pending); +extern void pq_reset_sigpipe(sigset_t *osigset, bool sigpipe_pending, + bool got_epipe); +#endif + +/* === SSL === */ + +/* + * The SSL implementation provides these functions. + */ + +/* + * Implementation of PQinitSSL(). + */ +extern void pgtls_init_library(bool do_ssl, int do_crypto); + +/* + * Initialize SSL library. + * + * The conn parameter is only used to be able to pass back an error + * message - no connection-local setup is made here. do_ssl controls + * if SSL is initialized, and do_crypto does the same for the crypto + * part. + * + * Returns 0 if OK, -1 on failure (adding a message to conn->errorMessage). + */ +extern int pgtls_init(PGconn *conn, bool do_ssl, bool do_crypto); + +/* + * Begin or continue negotiating a secure session. + */ +extern PostgresPollingStatusType pgtls_open_client(PGconn *conn); + +/* + * Close SSL connection. + */ +extern void pgtls_close(PGconn *conn); + +/* + * Read data from a secure connection. + * + * On failure, this function is responsible for appending a suitable message + * to conn->errorMessage. The caller must still inspect errno, but only + * to determine whether to continue/retry after error. + */ +extern ssize_t pgtls_read(PGconn *conn, void *ptr, size_t len); + +/* + * Is there unread data waiting in the SSL read buffer? + */ +extern bool pgtls_read_pending(PGconn *conn); + +/* + * Write data to a secure connection. + * + * On failure, this function is responsible for appending a suitable message + * to conn->errorMessage. The caller must still inspect errno, but only + * to determine whether to continue/retry after error. + */ +extern ssize_t pgtls_write(PGconn *conn, const void *ptr, size_t len); + +/* + * Get the hash of the server certificate, for SCRAM channel binding type + * tls-server-end-point. + * + * NULL is sent back to the caller in the event of an error, with an + * error message for the caller to consume. + * + * This is not supported with old versions of OpenSSL that don't have + * the X509_get_signature_nid() function. + */ +#if defined(USE_OPENSSL) && (defined(HAVE_X509_GET_SIGNATURE_NID) || defined(HAVE_X509_GET_SIGNATURE_INFO)) +#define HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH +extern char *pgtls_get_peer_certificate_hash(PGconn *conn, size_t *len); +#endif + +/* + * Verify that the server certificate matches the host name we connected to. + * + * The certificate's Common Name and Subject Alternative Names are considered. + * + * Returns 1 if the name matches, and 0 if it does not. On error, returns + * -1, and sets the libpq error message. + * + */ +extern int pgtls_verify_peer_name_matches_certificate_guts(PGconn *conn, + int *names_examined, + char **first_name); + +/* === GSSAPI === */ + +#ifdef ENABLE_GSS + +/* + * Establish a GSSAPI-encrypted connection. + */ +extern PostgresPollingStatusType pqsecure_open_gss(PGconn *conn); + +/* + * Read and write functions for GSSAPI-encrypted connections, with internal + * buffering to handle nonblocking sockets. + */ +extern ssize_t pg_GSS_write(PGconn *conn, const void *ptr, size_t len); +extern ssize_t pg_GSS_read(PGconn *conn, void *ptr, size_t len); +#endif + +/* === in fe-trace.c === */ + +extern void pqTraceOutputMessage(PGconn *conn, const char *message, + bool toServer); +extern void pqTraceOutputNoTypeByteMessage(PGconn *conn, const char *message); + +/* === miscellaneous macros === */ + +/* + * Reset the conn's error-reporting state. + */ +#define pqClearConnErrorState(conn) \ + (resetPQExpBuffer(&(conn)->errorMessage), \ + (conn)->errorReported = 0) + +/* + * Check whether we have a PGresult pending to be returned --- either a + * constructed one in conn->result, or a "virtual" error result that we + * don't intend to materialize until the end of the query cycle. + */ +#define pgHavePendingResult(conn) \ + ((conn)->result != NULL || (conn)->error_result) + +/* + * this is so that we can check if a connection is non-blocking internally + * without the overhead of a function call + */ +#define pqIsnonblocking(conn) ((conn)->nonblocking) + +/* + * Connection's outbuffer threshold, for pipeline mode. + */ +#define OUTBUFFER_THRESHOLD 65536 + +#ifdef ENABLE_NLS +extern char *libpq_gettext(const char *msgid) pg_attribute_format_arg(1); +extern char *libpq_ngettext(const char *msgid, const char *msgid_plural, unsigned long n) pg_attribute_format_arg(1) pg_attribute_format_arg(2); +#else +#define libpq_gettext(x) (x) +#define libpq_ngettext(s, p, n) ((n) == 1 ? (s) : (p)) +#endif +/* + * libpq code should use the above, not _(), since that would use the + * surrounding programs's message catalog. + */ +#undef _ + +extern void libpq_append_error(PQExpBuffer errorMessage, const char *fmt,...) pg_attribute_printf(2, 3); +extern void libpq_append_conn_error(PGconn *conn, const char *fmt,...) pg_attribute_printf(2, 3); + +/* + * These macros are needed to let error-handling code be portable between + * Unix and Windows. (ugh) + */ +#ifdef WIN32 +#define SOCK_ERRNO (WSAGetLastError()) +#define SOCK_STRERROR winsock_strerror +#define SOCK_ERRNO_SET(e) WSASetLastError(e) +#else +#define SOCK_ERRNO errno +#define SOCK_STRERROR strerror_r +#define SOCK_ERRNO_SET(e) (errno = (e)) +#endif + +#endif /* LIBPQ_INT_H */ diff --git a/src/interfaces/libpq/meson.build b/src/interfaces/libpq/meson.build new file mode 100644 index 0000000..80e6a15 --- /dev/null +++ b/src/interfaces/libpq/meson.build @@ -0,0 +1,126 @@ +# Copyright (c) 2022-2023, PostgreSQL Global Development Group + +# test/ is entered via top-level meson.build, that way it can use the default +# args for executables (which depend on libpq). + +libpq_sources = files( + 'fe-auth-scram.c', + 'fe-auth.c', + 'fe-connect.c', + 'fe-exec.c', + 'fe-lobj.c', + 'fe-misc.c', + 'fe-print.c', + 'fe-protocol3.c', + 'fe-secure.c', + 'fe-trace.c', + 'legacy-pqsignal.c', + 'libpq-events.c', + 'pqexpbuffer.c', +) +libpq_so_sources = [] # for shared lib, in addition to the above + +if host_system == 'windows' + libpq_sources += files('pthread-win32.c', 'win32.c') + libpq_so_sources += rc_lib_gen.process(win32ver_rc, extra_args: [ + '--NAME', 'libpq', + '--FILEDESC', 'PostgreSQL Access Library',]) +endif + +if ssl.found() + libpq_sources += files('fe-secure-common.c') + libpq_sources += files('fe-secure-openssl.c') +endif + +if gssapi.found() + libpq_sources += files( + 'fe-gssapi-common.c', + 'fe-secure-gssapi.c', + ) +endif + +export_file = custom_target('libpq.exports', + kwargs: gen_export_kwargs, +) + +# port needs to be in include path due to pthread-win32.h +libpq_inc = include_directories('.', '../../port') +libpq_c_args = ['-DSO_MAJOR_VERSION=5'] + +# Not using both_libraries() here as +# 1) resource files should only be in the shared library +# 2) we want the .pc file to include a dependency to {pgport,common}_static for +# libpq_st, and {pgport,common}_shlib for libpq_sh +# +# We could try to avoid building the source files twice, but it probably adds +# more complexity than its worth (AIX doesn't support link_whole yet, reusing +# object files requires also linking to the library on windows or breaks +# precompiled headers). +libpq_st = static_library('libpq', + libpq_sources, + include_directories: [libpq_inc], + c_args: libpq_c_args, + c_pch: pch_postgres_fe_h, + dependencies: [frontend_stlib_code, libpq_deps], + kwargs: default_lib_args, +) + +libpq_so = shared_library('libpq', + libpq_sources + libpq_so_sources, + include_directories: [libpq_inc, postgres_inc], + c_args: libpq_c_args, + c_pch: pch_postgres_fe_h, + version: '5.' + pg_version_major.to_string(), + soversion: host_system != 'windows' ? '5' : '', + darwin_versions: ['5', '5.' + pg_version_major.to_string()], + dependencies: [frontend_shlib_code, libpq_deps], + link_depends: export_file, + link_args: export_fmt.format(export_file.full_path()), + kwargs: default_lib_args, +) + +libpq = declare_dependency( + link_with: [libpq_so], + include_directories: [include_directories('.')] +) + +pkgconfig.generate( + name: 'libpq', + description: 'PostgreSQL libpq library', + url: pg_url, + libraries: libpq, + libraries_private: [frontend_stlib_code, libpq_deps], +) + +install_headers( + 'libpq-fe.h', + 'libpq-events.h', +) + +install_headers( + 'libpq-int.h', + 'pqexpbuffer.h', + 'fe-auth-sasl.h', + install_dir: dir_include_internal, +) +install_data('pg_service.conf.sample', + install_dir: dir_data, +) + + +tests += { + 'name': 'libpq', + 'sd': meson.current_source_dir(), + 'bd': meson.current_build_dir(), + 'tap': { + 'tests': [ + 't/001_uri.pl', + 't/002_api.pl', + 't/003_load_balance_host_list.pl', + 't/004_load_balance_dns.pl', + ], + 'env': {'with_ssl': ssl_library}, + }, +} + +subdir('po', if_found: libintl) diff --git a/src/interfaces/libpq/nls.mk b/src/interfaces/libpq/nls.mk new file mode 100644 index 0000000..5959fa0 --- /dev/null +++ b/src/interfaces/libpq/nls.mk @@ -0,0 +1,27 @@ +# src/interfaces/libpq/nls.mk +CATALOG_NAME = libpq +GETTEXT_FILES = fe-auth.c \ + fe-auth-scram.c \ + fe-connect.c \ + fe-exec.c \ + fe-gssapi-common.c \ + fe-lobj.c \ + fe-misc.c \ + fe-protocol3.c \ + fe-secure.c \ + fe-secure-common.c \ + fe-secure-gssapi.c \ + fe-secure-openssl.c \ + win32.c \ + ../../port/thread.c +GETTEXT_TRIGGERS = libpq_append_conn_error:2 \ + libpq_append_error:2 \ + libpq_gettext \ + libpq_ngettext:1,2 \ + pqInternalNotice:2 +GETTEXT_FLAGS = libpq_append_conn_error:2:c-format \ + libpq_append_error:2:c-format \ + libpq_gettext:1:pass-c-format \ + libpq_ngettext:1:pass-c-format \ + libpq_ngettext:2:pass-c-format \ + pqInternalNotice:2:c-format diff --git a/src/interfaces/libpq/pg_service.conf.sample b/src/interfaces/libpq/pg_service.conf.sample new file mode 100644 index 0000000..5a1c083 --- /dev/null +++ b/src/interfaces/libpq/pg_service.conf.sample @@ -0,0 +1,17 @@ +# +# Connection configuration file +# +# A service is a set of named connection parameters. You may specify +# multiple services in this file. Each starts with a service name in +# brackets. Subsequent lines have connection configuration parameters of +# the pattern "param=value" or LDAP URLs starting with "ldap://" +# to look up such parameters. A sample configuration for postgres is +# included in this file. Lines beginning with '#' are comments. +# +# Copy this to your sysconf directory (typically /usr/local/pgsql/etc) and +# rename it pg_service.conf. +# +# +#[postgres] +#dbname=postgres +#user=postgres diff --git a/src/interfaces/libpq/po/LINGUAS b/src/interfaces/libpq/po/LINGUAS new file mode 100644 index 0000000..00f815d --- /dev/null +++ b/src/interfaces/libpq/po/LINGUAS @@ -0,0 +1 @@ +cs de el es fr he it ja ka ko pl pt_BR ru sv tr uk zh_CN zh_TW diff --git a/src/interfaces/libpq/po/cs.po b/src/interfaces/libpq/po/cs.po new file mode 100644 index 0000000..ff590c7 --- /dev/null +++ b/src/interfaces/libpq/po/cs.po @@ -0,0 +1,1334 @@ +# Czech translation of libpq messages +# +# pgtranslation Id: libpq.po,v 1.6 2011/09/08 18:23:05 petere Exp $ +# +# Karel Žák, 2001-2003, 2004. +# Zdeněk Kotala, 2009, 2011, 2012, 2013. +# Tomáš Vondra <tv@fuzzy.cz>, 2012, 2013. +msgid "" +msgstr "" +"Project-Id-Version: libpq-cs (PostgreSQL 9.3)\n" +"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" +"POT-Creation-Date: 2020-10-31 16:09+0000\n" +"PO-Revision-Date: 2020-10-31 21:45+0100\n" +"Last-Translator: Tomas Vondra <tv@fuzzy.cz>\n" +"Language-Team: Czech <info@cspug.cx>\n" +"Language: cs\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" +"X-Generator: Poedit 2.4.1\n" + +#: fe-auth-scram.c:212 +msgid "malformed SCRAM message (empty message)\n" +msgstr "poškozená SCRAM zpráva (prázdná zpráva)\n" + +#: fe-auth-scram.c:218 +msgid "malformed SCRAM message (length mismatch)\n" +msgstr "poškozená SCRAM zpráva (délka neodpovídá)\n" + +#: fe-auth-scram.c:265 +msgid "incorrect server signature\n" +msgstr "chybná signatura serveru\n" + +#: fe-auth-scram.c:274 +msgid "invalid SCRAM exchange state\n" +msgstr "chybný stav SCRAM výměny\n" + +#: fe-auth-scram.c:296 +#, c-format +msgid "malformed SCRAM message (attribute \"%c\" expected)\n" +msgstr "poškozená SCRAM zpráva (očekáván atribut \"%c\")\n" + +#: fe-auth-scram.c:305 +#, c-format +msgid "malformed SCRAM message (expected character \"=\" for attribute \"%c\")\n" +msgstr "poškozená SCRAM zpráva (očekáván znak \"=\" pro atribut \"%c\")\n" + +#: fe-auth-scram.c:346 +msgid "could not generate nonce\n" +msgstr "nelze vygenerovat nonce\n" + +#: fe-auth-scram.c:356 fe-auth-scram.c:431 fe-auth-scram.c:579 +#: fe-auth-scram.c:600 fe-auth-scram.c:626 fe-auth-scram.c:641 +#: fe-auth-scram.c:691 fe-auth-scram.c:725 fe-auth.c:289 fe-auth.c:359 +#: fe-auth.c:394 fe-auth.c:611 fe-auth.c:770 fe-auth.c:1129 fe-auth.c:1277 +#: fe-connect.c:892 fe-connect.c:1419 fe-connect.c:1595 fe-connect.c:2200 +#: fe-connect.c:2223 fe-connect.c:2952 fe-connect.c:4601 fe-connect.c:4857 +#: fe-connect.c:4976 fe-connect.c:5229 fe-connect.c:5309 fe-connect.c:5408 +#: fe-connect.c:5664 fe-connect.c:5693 fe-connect.c:5765 fe-connect.c:5789 +#: fe-connect.c:5807 fe-connect.c:5908 fe-connect.c:5917 fe-connect.c:6273 +#: fe-connect.c:6423 fe-exec.c:2747 fe-exec.c:3494 fe-exec.c:3659 +#: fe-gssapi-common.c:111 fe-lobj.c:895 fe-protocol2.c:1207 fe-protocol3.c:995 +#: fe-protocol3.c:1699 fe-secure-common.c:110 fe-secure-gssapi.c:504 +#: fe-secure-openssl.c:440 fe-secure-openssl.c:1091 +msgid "out of memory\n" +msgstr "nedostatek paměti\n" + +#: fe-auth-scram.c:364 +msgid "could not encode nonce\n" +msgstr "nelze zakódovat nonce\n" + +#: fe-auth-scram.c:563 +msgid "could not encode client proof\n" +msgstr "nelze zakódovat client proof\n" + +#: fe-auth-scram.c:618 +msgid "invalid SCRAM response (nonce mismatch)\n" +msgstr "chybná SCRAM odpověď (nonce neodpovídá)\n" + +#: fe-auth-scram.c:651 +msgid "malformed SCRAM message (invalid salt)\n" +msgstr "poškozená SCRAM zpráva (chybná salt hodnota)\n" + +#: fe-auth-scram.c:665 +msgid "malformed SCRAM message (invalid iteration count)\n" +msgstr "poškozená SCRAM zpráva (chybný počet iterací)\n" + +#: fe-auth-scram.c:671 +msgid "malformed SCRAM message (garbage at end of server-first-message)\n" +msgstr "poškozená SCRAM zpráva (smetí na konci server-first-message)\n" + +#: fe-auth-scram.c:702 +#, c-format +msgid "error received from server in SCRAM exchange: %s\n" +msgstr "server zaslal chybu v rámci SCRAM výměny: %s\n" + +#: fe-auth-scram.c:718 +msgid "malformed SCRAM message (garbage at end of server-final-message)\n" +msgstr "poškozená SCRAM zpráva (smetí na konci server-final-message)\n" + +#: fe-auth-scram.c:737 +msgid "malformed SCRAM message (invalid server signature)\n" +msgstr "poškozená SCRAM zpráva (chybná signatura serveru)\n" + +#: fe-auth.c:76 +#, c-format +msgid "out of memory allocating GSSAPI buffer (%d)\n" +msgstr "při alokaci GSSAPI bufferu došla paměť (%d)\n" + +#: fe-auth.c:131 +msgid "GSSAPI continuation error" +msgstr "Přetrvávající chyba GSSAPI" + +#: fe-auth.c:158 fe-auth.c:388 fe-gssapi-common.c:98 fe-secure-common.c:98 +msgid "host name must be specified\n" +msgstr "host musí být specifikován\n" + +#: fe-auth.c:165 +msgid "duplicate GSS authentication request\n" +msgstr "duplikátní GSS autentizační požadavek\n" + +#: fe-auth.c:230 +#, c-format +msgid "out of memory allocating SSPI buffer (%d)\n" +msgstr "při alokaci SSPI bufferu došla paměť (%d)\n" + +#: fe-auth.c:278 +msgid "SSPI continuation error" +msgstr "Přetrvávající chyba SSPI" + +#: fe-auth.c:349 +msgid "duplicate SSPI authentication request\n" +msgstr "duplicitní SSPI autentizační požadavek\n" + +#: fe-auth.c:374 +msgid "could not acquire SSPI credentials" +msgstr "nelze získat SSPI credentials" + +#: fe-auth.c:429 +msgid "channel binding required, but SSL not in use\n" +msgstr "channel binding vyžadováno, ale SSL není zapnuto\n" + +#: fe-auth.c:436 +msgid "duplicate SASL authentication request\n" +msgstr "duplicitní SASL autentizační požadavek\n" + +#: fe-auth.c:492 +msgid "channel binding is required, but client does not support it\n" +msgstr "channel binding je vyžadován, ale klient ho nepodporuje\n" + +#: fe-auth.c:509 +msgid "server offered SCRAM-SHA-256-PLUS authentication over a non-SSL connection\n" +msgstr "server nabídl SCRAM-SHA-256-PLUS authentizaci přes ne-SSL spojení\n" + +#: fe-auth.c:521 +msgid "none of the server's SASL authentication mechanisms are supported\n" +msgstr "žádný ze SASL authentizačních mechanismů serveru není podporován\n" + +#: fe-auth.c:529 +msgid "channel binding is required, but server did not offer an authentication method that supports channel binding\n" +msgstr "channel binding je vyžadováno, ale server nenabídl methodu autentizace které channel binding podporuje\n" + +#: fe-auth.c:635 +#, c-format +msgid "out of memory allocating SASL buffer (%d)\n" +msgstr "při alokaci SASL bufferu došla paměť (%d)\n" + +#: fe-auth.c:660 +msgid "AuthenticationSASLFinal received from server, but SASL authentication was not completed\n" +msgstr "AuthenticationSASLFinal obdržena od serveru, ale SASL authentizace nebyla dokončena\n" + +#: fe-auth.c:737 +msgid "SCM_CRED authentication method not supported\n" +msgstr "SCM_CRED metoda autentizace není podporována\n" + +#: fe-auth.c:836 +msgid "channel binding required, but server authenticated client without channel binding\n" +msgstr "channel binding vyžadováno, ale server authentizoval klienta bez channel binding\n" + +#: fe-auth.c:842 +msgid "channel binding required but not supported by server's authentication request\n" +msgstr "channel binding je vyžadován ale není podporován autentizační metodou serveru\n" + +#: fe-auth.c:875 +msgid "Kerberos 4 authentication not supported\n" +msgstr "Kerberos 4 autentizace není podporována\n" + +#: fe-auth.c:880 +msgid "Kerberos 5 authentication not supported\n" +msgstr "Kerberos 5 autentizace není podporována\n" + +#: fe-auth.c:951 +msgid "GSSAPI authentication not supported\n" +msgstr "GSSAPI autentizace není podporována\n" + +#: fe-auth.c:983 +msgid "SSPI authentication not supported\n" +msgstr "SSPI autentizace není podporována\n" + +#: fe-auth.c:991 +msgid "Crypt authentication not supported\n" +msgstr "Crypt autentizace není podporována\n" + +#: fe-auth.c:1057 +#, c-format +msgid "authentication method %u not supported\n" +msgstr "autentizační metoda %u není podporována\n" + +#: fe-auth.c:1104 +#, c-format +msgid "user name lookup failure: error code %lu\n" +msgstr "vyhledání uživatele selhalo: chybový kód %lu\n" + +#: fe-auth.c:1114 fe-connect.c:2834 +#, c-format +msgid "could not look up local user ID %d: %s\n" +msgstr "nelze vyhledat lokálního uživatele ID %d: %s\n" + +#: fe-auth.c:1119 fe-connect.c:2839 +#, c-format +msgid "local user with ID %d does not exist\n" +msgstr "lokální uživatel s ID %d neexistuje\n" + +#: fe-auth.c:1221 +msgid "unexpected shape of result set returned for SHOW\n" +msgstr "neočekávaná podoba výsledku pro SHOW\n" + +#: fe-auth.c:1230 +msgid "password_encryption value too long\n" +msgstr "hodnota password_encryption je příliš dlouhá\n" + +#: fe-auth.c:1270 +#, c-format +msgid "unrecognized password encryption algorithm \"%s\"\n" +msgstr "neznámý algoritmus pro šifrování hesla \"%s\"\n" + +#: fe-connect.c:1075 +#, c-format +msgid "could not match %d host names to %d hostaddr values\n" +msgstr "nelze napárovat %d jmen hostů na %d hostaddr hodnot\n" + +#: fe-connect.c:1156 +#, c-format +msgid "could not match %d port numbers to %d hosts\n" +msgstr "nelze napárovat %d čísel portů na %d hostů\n" + +#: fe-connect.c:1249 +#, c-format +#| msgid "invalid channel binding type\n" +msgid "invalid channel_binding value: \"%s\"\n" +msgstr "neplatná hodnota channel_binding: \"%s\"\n" + +#: fe-connect.c:1275 +#, c-format +msgid "invalid sslmode value: \"%s\"\n" +msgstr "neplatná hodnota sslmode: \"%s\"\n" + +#: fe-connect.c:1296 +#, c-format +msgid "sslmode value \"%s\" invalid when SSL support is not compiled in\n" +msgstr "hodnota sslmode \"%s\" je neplatná pokud není zakompilována podpora SSL\n" + +#: fe-connect.c:1317 +#, c-format +msgid "invalid ssl_min_protocol_version value: \"%s\"\n" +msgstr "neplatná hodnodta ssl_min_protocol_version: \"%s\"\n" + +#: fe-connect.c:1325 +#, c-format +#| msgid "invalid sslmode value: \"%s\"\n" +msgid "invalid ssl_max_protocol_version value: \"%s\"\n" +msgstr "neplatná hodnota ssl_max_protocol_version: \"%s\"\n" + +#: fe-connect.c:1342 +msgid "invalid SSL protocol version range\n" +msgstr "neplatný rozsah verzí SSL protokolu\n" + +#: fe-connect.c:1357 +#, c-format +msgid "invalid gssencmode value: \"%s\"\n" +msgstr "invalid gssencmode gssencmode: \"%s\"\n" + +#: fe-connect.c:1366 +#, c-format +msgid "gssencmode value \"%s\" invalid when GSSAPI support is not compiled in\n" +msgstr "gssencmode hodnota \"%s\" je neplatná při nezakompilované GSSAPI podpoře\n" + +#: fe-connect.c:1401 +#, c-format +msgid "invalid target_session_attrs value: \"%s\"\n" +msgstr "neplatná hodnota target_session_attrs: \"%s\"\n" + +#: fe-connect.c:1619 +#, c-format +msgid "could not set socket to TCP no delay mode: %s\n" +msgstr "nelze nastavit \"no delay\" mód TCP soketu: %s\n" + +#: fe-connect.c:1680 +#, c-format +msgid "" +"could not connect to server: %s\n" +"\tIs the server running locally and accepting\n" +"\tconnections on Unix domain socket \"%s\"?\n" +msgstr "" +"nelze navázat spojení se serverem: %s\n" +"\tJe spuštěn server lokálně a akceptuje\n" +"\tspojení pomocí Unix soketu \"%s\"?\n" + +#: fe-connect.c:1717 +#, c-format +msgid "" +"could not connect to server: %s\n" +"\tIs the server running on host \"%s\" (%s) and accepting\n" +"\tTCP/IP connections on port %s?\n" +msgstr "" +"nelze navázat spojení se serverem: %s\n" +"\tJe server na \"%s\" (%s) spuštěn a akceptuje\n" +"\tTCP/IP spojení na portu %s?\n" + +#: fe-connect.c:1725 +#, c-format +msgid "" +"could not connect to server: %s\n" +"\tIs the server running on host \"%s\" and accepting\n" +"\tTCP/IP connections on port %s?\n" +msgstr "" +"nelze navázat spojení se serverem: %s\n" +"\tJe server na \"%s\" spuštěn a akceptuje\n" +"\tTCP/IP spojení na portu %s?\n" + +#: fe-connect.c:1795 +#, c-format +msgid "invalid integer value \"%s\" for connection option \"%s\"\n" +msgstr "chybná integer hodnota \"%s\" pro volbu spojení \"%s\"\n" + +#: fe-connect.c:1825 fe-connect.c:1859 fe-connect.c:1894 fe-connect.c:1981 +#: fe-connect.c:2623 +#, c-format +msgid "setsockopt(%s) failed: %s\n" +msgstr "setsockopt(%s) selhalo: %s\n" + +#: fe-connect.c:1947 +#, c-format +msgid "WSAIoctl(SIO_KEEPALIVE_VALS) failed: %ui\n" +msgstr "WSAIoctl(SIO_KEEPALIVE_VALS) selhalo: %ui\n" + +#: fe-connect.c:2313 +msgid "invalid connection state, probably indicative of memory corruption\n" +msgstr "neplatný stav spojení, pravděpodobně způsobený poškozením paměti\n" + +#: fe-connect.c:2379 +#, c-format +msgid "invalid port number: \"%s\"\n" +msgstr "neplatné číslo portu: \"%s\"\n" + +#: fe-connect.c:2395 +#, c-format +msgid "could not translate host name \"%s\" to address: %s\n" +msgstr "nemohu přeložit jméno hostitele \"%s\" na adresu: %s\n" + +#: fe-connect.c:2408 +#, c-format +msgid "could not parse network address \"%s\": %s\n" +msgstr "nelze naparsovat síťovou adresu \"%s\": %s\n" + +#: fe-connect.c:2421 +#, c-format +msgid "Unix-domain socket path \"%s\" is too long (maximum %d bytes)\n" +msgstr "Cesta k unixovému \"%s\" je příliš dlouhá (maximum %d bytů)\n" + +#: fe-connect.c:2436 +#, c-format +msgid "could not translate Unix-domain socket path \"%s\" to address: %s\n" +msgstr "nemohu přeložit cestu Unix-domain soketu \"%s\" na adresu: %s\n" + +#: fe-connect.c:2560 +#, c-format +msgid "could not create socket: %s\n" +msgstr "nelze vytvořit soket: %s\n" + +#: fe-connect.c:2582 +#, c-format +msgid "could not set socket to nonblocking mode: %s\n" +msgstr "soket nelze nastavit do neblokujícího módu: %s\n" + +#: fe-connect.c:2592 +#, c-format +msgid "could not set socket to close-on-exec mode: %s\n" +msgstr "nelze nastavit soket do close-on-exec módu: %s\n" + +#: fe-connect.c:2610 +msgid "keepalives parameter must be an integer\n" +msgstr "parametr keepalives musí být celé číslo\n" + +#: fe-connect.c:2750 +#, c-format +msgid "could not get socket error status: %s\n" +msgstr "nelze obdržet chybový status soketu: %s\n" + +#: fe-connect.c:2778 +#, c-format +msgid "could not get client address from socket: %s\n" +msgstr "nelze získat adresu klienta ze soketu: %s\n" + +#: fe-connect.c:2820 +msgid "requirepeer parameter is not supported on this platform\n" +msgstr "parametr requirepeer není na této platformě podporován\n" + +#: fe-connect.c:2823 +#, c-format +msgid "could not get peer credentials: %s\n" +msgstr "nelze získat informace (credentials) protistrany: %s\n" + +#: fe-connect.c:2847 +#, c-format +msgid "requirepeer specifies \"%s\", but actual peer user name is \"%s\"\n" +msgstr "requirepeer obsahuje \"%s\", ale skutečné jméno peera je \"%s\"\n" + +#: fe-connect.c:2887 +#, c-format +msgid "could not send GSSAPI negotiation packet: %s\n" +msgstr "nelze zaslat GSSAPI negociační packet: %s\n" + +#: fe-connect.c:2899 +msgid "GSSAPI encryption required but was impossible (possibly no credential cache, no server support, or using a local socket)\n" +msgstr "GSSAPI šifrování je vyžadováno ale bylo nemožné (možná kvůli chybějící credential cache, podpoře na serveru, nebo používání lokálního socketu)\n" + +#: fe-connect.c:2926 +#, c-format +msgid "could not send SSL negotiation packet: %s\n" +msgstr "nelze poslat SSL \"negotiation paket\": %s\n" + +#: fe-connect.c:2965 +#, c-format +msgid "could not send startup packet: %s\n" +msgstr "nelze poslat počáteční paket: %s\n" + +#: fe-connect.c:3035 +msgid "server does not support SSL, but SSL was required\n" +msgstr "server nepodporuje SSL, leč SSL je vyžadováno\n" + +#: fe-connect.c:3061 +#, c-format +msgid "received invalid response to SSL negotiation: %c\n" +msgstr "přijata neplatná odpověď na SSL negotiation: %c\n" + +#: fe-connect.c:3151 +msgid "server doesn't support GSSAPI encryption, but it was required\n" +msgstr "server nepodporuje GSSAPI šifrování, to ale bylo vyžadováno\n" + +#: fe-connect.c:3162 +#, c-format +msgid "received invalid response to GSSAPI negotiation: %c\n" +msgstr "přijata neplatná odpověď na GSSAPI negotiation: %c\n" + +#: fe-connect.c:3229 fe-connect.c:3260 +#, c-format +msgid "expected authentication request from server, but received %c\n" +msgstr "očekáván byl autentizační dotaz ze serveru, ale přijat byl %c\n" + +#: fe-connect.c:3502 +msgid "unexpected message from server during startup\n" +msgstr "neočekávaná zpráva ze serveru během startu\n" + +#: fe-connect.c:3707 +#, c-format +msgid "could not make a writable connection to server \"%s:%s\"\n" +msgstr "nelze otevřít zapisovatelné spojení na server \"%s:%s\"\n" + +#: fe-connect.c:3753 +#, c-format +msgid "test \"SHOW transaction_read_only\" failed on server \"%s:%s\"\n" +msgstr "test \"SHOW transaction_read_only\" selhal na serveru \"%s:%s\"\n" + +#: fe-connect.c:3768 +#, c-format +msgid "invalid connection state %d, probably indicative of memory corruption\n" +msgstr "neplatný stav spojení %d, pravděpodobně způsobený poškozením paměti\n" + +#: fe-connect.c:4207 fe-connect.c:4267 +#, c-format +msgid "PGEventProc \"%s\" failed during PGEVT_CONNRESET event\n" +msgstr "PGEventProc \"%s\" selhalo během události PGEVT_CONNRESET\n" + +#: fe-connect.c:4614 +#, c-format +msgid "invalid LDAP URL \"%s\": scheme must be ldap://\n" +msgstr "naplatné LDAP URL \"%s\": schéma musí být ldap://\n" + +#: fe-connect.c:4629 +#, c-format +msgid "invalid LDAP URL \"%s\": missing distinguished name\n" +msgstr "neplatné LDAP URL \"%s\": chybí rozlišující jméno\n" + +#: fe-connect.c:4641 fe-connect.c:4696 +#, c-format +msgid "invalid LDAP URL \"%s\": must have exactly one attribute\n" +msgstr "neplatné LDAP URL \"%s\": musí mít právě jeden atribut\n" + +#: fe-connect.c:4652 fe-connect.c:4711 +#, c-format +msgid "invalid LDAP URL \"%s\": must have search scope (base/one/sub)\n" +msgstr "naplatné LDAP URL \"%s\": musí mít vyhledávací rozsah (base/one/sub)\n" + +#: fe-connect.c:4663 +#, c-format +msgid "invalid LDAP URL \"%s\": no filter\n" +msgstr "naplatné LDAP URL \"%s\": není filter\n" + +#: fe-connect.c:4684 +#, c-format +msgid "invalid LDAP URL \"%s\": invalid port number\n" +msgstr "naplatné LDAP URL \"%s\": neplatný číslo portu\n" + +#: fe-connect.c:4720 +msgid "could not create LDAP structure\n" +msgstr "nelze vytvořit LDAP strukturu\n" + +#: fe-connect.c:4796 +#, c-format +msgid "lookup on LDAP server failed: %s\n" +msgstr "vyhledávání na LDAP serveru selhalo: %s\n" + +#: fe-connect.c:4807 +msgid "more than one entry found on LDAP lookup\n" +msgstr "nalezen více jak jeden záznam při LDAP vyhledávání\n" + +#: fe-connect.c:4808 fe-connect.c:4820 +msgid "no entry found on LDAP lookup\n" +msgstr "nebyl nalezen žádný záznam při LDAP vyhledávání\n" + +#: fe-connect.c:4831 fe-connect.c:4844 +msgid "attribute has no values on LDAP lookup\n" +msgstr "atribut nemá žádnou hodnotu při LDAP vyhledávání\n" + +#: fe-connect.c:4896 fe-connect.c:4915 fe-connect.c:5447 +#, c-format +msgid "missing \"=\" after \"%s\" in connection info string\n" +msgstr "chybné \"=\" po \"%s\" v informačním řetězci spojení\n" + +#: fe-connect.c:4988 fe-connect.c:5632 fe-connect.c:6406 +#, c-format +msgid "invalid connection option \"%s\"\n" +msgstr "neplatný parametr spojení \"%s\"\n" + +#: fe-connect.c:5004 fe-connect.c:5496 +msgid "unterminated quoted string in connection info string\n" +msgstr "neukončený řetězec v uvozovkách v informačním řetězci spojení\n" + +#: fe-connect.c:5087 +#, c-format +msgid "definition of service \"%s\" not found\n" +msgstr "definice služby \"%s\" nenalezena\n" + +#: fe-connect.c:5110 +#, c-format +msgid "service file \"%s\" not found\n" +msgstr "soubor se seznamem služeb \"%s\" nebyl nalezen\n" + +#: fe-connect.c:5125 +#, c-format +msgid "line %d too long in service file \"%s\"\n" +msgstr "řádek %d v souboru se seznamem služeb \"%s\" je příliš dlouhý\n" + +#: fe-connect.c:5197 fe-connect.c:5241 +#, c-format +msgid "syntax error in service file \"%s\", line %d\n" +msgstr "syntaktická chyba v souboru se seznamu služeb \"%s\", řádek %d\n" + +#: fe-connect.c:5208 +#, c-format +msgid "nested service specifications not supported in service file \"%s\", line %d\n" +msgstr "vnořené specifikace služeb nejsou podporovány v service souboru \"%s\", řádek %d\n" + +#: fe-connect.c:5928 +#, c-format +msgid "invalid URI propagated to internal parser routine: \"%s\"\n" +msgstr "neplatné URI propagované do interní procedury parseru: \"%s\"\n" + +#: fe-connect.c:6005 +#, c-format +msgid "end of string reached when looking for matching \"]\" in IPv6 host address in URI: \"%s\"\n" +msgstr "při hledání odpovídajícího znaku \"]\" v IPv6 adrese hostitele byl dosažen konec řetězce URI: \"%s\"\n" + +#: fe-connect.c:6012 +#, c-format +msgid "IPv6 host address may not be empty in URI: \"%s\"\n" +msgstr "IPv6 adresa hostitele v URI nesmí být prázdná: \"%s\"\n" + +#: fe-connect.c:6027 +#, c-format +msgid "unexpected character \"%c\" at position %d in URI (expected \":\" or \"/\"): \"%s\"\n" +msgstr "neočekávaný znak \"%c\" na pozici %d v URI (očekáváno \":\" nebo \"/\"): \"%s\"\n" + +#: fe-connect.c:6156 +#, c-format +msgid "extra key/value separator \"=\" in URI query parameter: \"%s\"\n" +msgstr "přebytečný oddělovač klíče/hodnoty \"=\" v URI parametru dotazu: \"%s\"\n" + +#: fe-connect.c:6176 +#, c-format +msgid "missing key/value separator \"=\" in URI query parameter: \"%s\"\n" +msgstr "chybějící oddělovač klíče/hodnoty \"=\" v URI parametru dotazu: \"%s\"\n" + +#: fe-connect.c:6227 +#, c-format +msgid "invalid URI query parameter: \"%s\"\n" +msgstr "neplatný parametr v URI dotazu: \"%s\"\n" + +#: fe-connect.c:6301 +#, c-format +msgid "invalid percent-encoded token: \"%s\"\n" +msgstr "neplatný procenty-kódovaný token \"%s\"\n" + +#: fe-connect.c:6311 +#, c-format +msgid "forbidden value %%00 in percent-encoded value: \"%s\"\n" +msgstr "zakázaná hodnota %%00 v procenty-k´odované hodnotě: \"%s\"\n" + +#: fe-connect.c:6674 +msgid "connection pointer is NULL\n" +msgstr "pointer spojení je NULL\n" + +#: fe-connect.c:6970 +#, c-format +msgid "WARNING: password file \"%s\" is not a plain file\n" +msgstr "VAROVÁNÍ: soubor s hesly \"%s\" není prostý (plain) soubor\n" + +#: fe-connect.c:6979 +#, c-format +msgid "WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n" +msgstr "UPOZORNĚNÍ: Soubor s hesly \"%s\" má přístupová práva pro čtení pro skupinu nebo všechny uživatele; práva by měla být u=rw (0600)\n" + +#: fe-connect.c:7087 +#, c-format +msgid "password retrieved from file \"%s\"\n" +msgstr "heslo načteno ze souboru \"%s\"\n" + +#: fe-exec.c:444 fe-exec.c:2821 +#, c-format +msgid "row number %d is out of range 0..%d" +msgstr "číslo řádky %d je mimo rozsah 0..%d" + +#: fe-exec.c:505 fe-protocol2.c:497 fe-protocol2.c:532 fe-protocol2.c:1050 +#: fe-protocol3.c:206 fe-protocol3.c:233 fe-protocol3.c:250 fe-protocol3.c:330 +#: fe-protocol3.c:723 fe-protocol3.c:954 +msgid "out of memory" +msgstr "nedostatek paměti" + +#: fe-exec.c:506 fe-protocol2.c:1396 fe-protocol3.c:1907 +#, c-format +msgid "%s" +msgstr "%s" + +#: fe-exec.c:815 +msgid "write to server failed\n" +msgstr "zápis na server selhal\n" + +#: fe-exec.c:896 +msgid "NOTICE" +msgstr "POZNÁMKA" + +#: fe-exec.c:954 +msgid "PGresult cannot support more than INT_MAX tuples" +msgstr "PGresult nemůže podporovat více než INT_MAX řádek" + +#: fe-exec.c:966 +msgid "size_t overflow" +msgstr "size_t přetečení" + +#: fe-exec.c:1243 fe-exec.c:1301 fe-exec.c:1347 +msgid "command string is a null pointer\n" +msgstr "řetězec příkazu je prázdný ukazatel\n" + +#: fe-exec.c:1307 fe-exec.c:1353 fe-exec.c:1448 +msgid "number of parameters must be between 0 and 65535\n" +msgstr "počet parametrů musí být mezi 0 a 65535\n" + +#: fe-exec.c:1341 fe-exec.c:1442 +msgid "statement name is a null pointer\n" +msgstr "název výrazu je prázdný ukazatel\n" + +#: fe-exec.c:1361 fe-exec.c:1524 fe-exec.c:2233 fe-exec.c:2435 +msgid "function requires at least protocol version 3.0\n" +msgstr "funkce vyžaduje protokol alespoň 3.0 a vyšší\n" + +#: fe-exec.c:1479 +msgid "no connection to the server\n" +msgstr "není spojení se serverem\n" + +#: fe-exec.c:1486 +msgid "another command is already in progress\n" +msgstr "zpracovává se již jiný příkaz\n" + +#: fe-exec.c:1600 +msgid "length must be given for binary parameter\n" +msgstr "délka musí být specifikována pro binarní parametr\n" + +#: fe-exec.c:1863 +#, c-format +msgid "unexpected asyncStatus: %d\n" +msgstr "neočekávaný asyncStatus: %d\n" + +#: fe-exec.c:1883 +#, c-format +msgid "PGEventProc \"%s\" failed during PGEVT_RESULTCREATE event\n" +msgstr "PGEventProc \"%s\" selhala během události PGEVT_RESULTCREATE\n" + +#: fe-exec.c:2043 +msgid "COPY terminated by new PQexec" +msgstr "COPY bylo ukončeno novým PQexec" + +#: fe-exec.c:2051 +msgid "COPY IN state must be terminated first\n" +msgstr "COPY IN status musí být nejdříve ukončen\n" + +#: fe-exec.c:2071 +msgid "COPY OUT state must be terminated first\n" +msgstr "COPY OUT status musí být nejdříve ukončen\n" + +#: fe-exec.c:2079 +msgid "PQexec not allowed during COPY BOTH\n" +msgstr "PQexec není povoleno během COPY BOTH\n" + +#: fe-exec.c:2325 fe-exec.c:2392 fe-exec.c:2482 fe-protocol2.c:1353 +#: fe-protocol3.c:1838 +msgid "no COPY in progress\n" +msgstr "COPY se neprovádí\n" + +#: fe-exec.c:2672 +msgid "connection in wrong state\n" +msgstr "spojení je ve špatném stavu\n" + +#: fe-exec.c:2703 +msgid "invalid ExecStatusType code" +msgstr "neplatný ExecStatusType kód" + +#: fe-exec.c:2730 +msgid "PGresult is not an error result\n" +msgstr "PGresult není chybový výsledek\n" + +#: fe-exec.c:2805 fe-exec.c:2828 +#, c-format +msgid "column number %d is out of range 0..%d" +msgstr "číslo sloupce %d je mimo rozsah 0..%d" + +#: fe-exec.c:2843 +#, c-format +msgid "parameter number %d is out of range 0..%d" +msgstr "číslo parametru %d je mimo rozsah 0..%d" + +#: fe-exec.c:3153 +#, c-format +msgid "could not interpret result from server: %s" +msgstr "nelze interpretovat výsledek ze serveru: %s" + +#: fe-exec.c:3392 fe-exec.c:3476 +msgid "incomplete multibyte character\n" +msgstr "nekompletní multibyte znak\n" + +#: fe-gssapi-common.c:124 +msgid "GSSAPI name import error" +msgstr "chyba importu GSSAPI jména" + +#: fe-lobj.c:154 +msgid "cannot determine OID of function lo_truncate\n" +msgstr "nelze určit OID funkce lo_truncare\n" + +#: fe-lobj.c:170 +msgid "argument of lo_truncate exceeds integer range\n" +msgstr "argument pro lo_truncate přesahuje rozsah typu integer\n" + +#: fe-lobj.c:221 +msgid "cannot determine OID of function lo_truncate64\n" +msgstr "nelze určit OID funkce lo_truncare64\n" + +#: fe-lobj.c:279 +msgid "argument of lo_read exceeds integer range\n" +msgstr "agrument pro lo_read přesahuje rozsah typu integer\n" + +#: fe-lobj.c:334 +msgid "argument of lo_write exceeds integer range\n" +msgstr "agrument pro lo_write přesahuje rozsah typu integer\n" + +#: fe-lobj.c:425 +msgid "cannot determine OID of function lo_lseek64\n" +msgstr "nelze určit OID funkce lo_lseek64\n" + +#: fe-lobj.c:521 +msgid "cannot determine OID of function lo_create\n" +msgstr "nelze určit OID funkce lo_create\n" + +#: fe-lobj.c:600 +msgid "cannot determine OID of function lo_tell64\n" +msgstr "nelze určit OID funkce lo_tell64\n" + +#: fe-lobj.c:706 fe-lobj.c:815 +#, c-format +msgid "could not open file \"%s\": %s\n" +msgstr "nelze otevřít soubor \"%s\": %s\n" + +#: fe-lobj.c:761 +#, c-format +msgid "could not read from file \"%s\": %s\n" +msgstr "nelze číst ze souboru \"%s\": %s\n" + +#: fe-lobj.c:835 fe-lobj.c:859 +#, c-format +msgid "could not write to file \"%s\": %s\n" +msgstr "nelze zapsat do souboru \"%s\": %s\n" + +#: fe-lobj.c:946 +msgid "query to initialize large object functions did not return data\n" +msgstr "dotaz inicializující \"large object\" funkce nevrátil data\n" + +#: fe-lobj.c:995 +msgid "cannot determine OID of function lo_open\n" +msgstr "nelze určit OID funkce lo_open\n" + +#: fe-lobj.c:1002 +msgid "cannot determine OID of function lo_close\n" +msgstr "nelze určit OID funkce lo_close\n" + +#: fe-lobj.c:1009 +msgid "cannot determine OID of function lo_creat\n" +msgstr "nelze určit OID funkce lo_create\n" + +#: fe-lobj.c:1016 +msgid "cannot determine OID of function lo_unlink\n" +msgstr "nelze určit OID funkce lo_unlink\n" + +#: fe-lobj.c:1023 +msgid "cannot determine OID of function lo_lseek\n" +msgstr "nelze určit OID funkce lo_lseek\n" + +#: fe-lobj.c:1030 +msgid "cannot determine OID of function lo_tell\n" +msgstr "nelze určit OID funkce lo_tell\n" + +#: fe-lobj.c:1037 +msgid "cannot determine OID of function loread\n" +msgstr "nelze určit OID funkce loread\n" + +#: fe-lobj.c:1044 +msgid "cannot determine OID of function lowrite\n" +msgstr "nelze určit OID funkce lowrite\n" + +#: fe-misc.c:289 +#, c-format +msgid "integer of size %lu not supported by pqGetInt" +msgstr "pqGetInt nepodporuje integer velikosti %lu" + +#: fe-misc.c:325 +#, c-format +msgid "integer of size %lu not supported by pqPutInt" +msgstr "pqPutInt nepodporuje integer velikosti %lu" + +#: fe-misc.c:636 fe-misc.c:869 +msgid "connection not open\n" +msgstr "spojení není otevřeno\n" + +#: fe-misc.c:805 fe-secure-openssl.c:209 fe-secure-openssl.c:316 +#: fe-secure.c:267 fe-secure.c:383 +msgid "" +"server closed the connection unexpectedly\n" +"\tThis probably means the server terminated abnormally\n" +"\tbefore or while processing the request.\n" +msgstr "" +"server neočekávaně ukončil spojení\n" +"\tToto pravděpodobně znamená, že byl ukončen nestandardně\n" +"\tpřed nebo během vykonávání požadavku.\n" + +#: fe-misc.c:1063 +msgid "timeout expired\n" +msgstr "časový limit (timeout) uběhl\n" + +#: fe-misc.c:1108 +msgid "invalid socket\n" +msgstr "chybný socket\n" + +#: fe-misc.c:1131 +#, c-format +msgid "select() failed: %s\n" +msgstr "select() selhal: %s\n" + +#: fe-protocol2.c:87 +#, c-format +msgid "invalid setenv state %c, probably indicative of memory corruption\n" +msgstr "neplatný status spojení %c, pravděpodobně způsobený poškozením paměti\n" + +#: fe-protocol2.c:384 +#, c-format +msgid "invalid state %c, probably indicative of memory corruption\n" +msgstr "neplatný status %c, pravděpodobně způsobený poškozením paměti\n" + +#: fe-protocol2.c:473 fe-protocol3.c:183 +#, c-format +msgid "message type 0x%02x arrived from server while idle" +msgstr "zpráva typu 0x%02x přišla ze serveru během nečinnosti" + +#: fe-protocol2.c:523 +#, c-format +msgid "unexpected character %c following empty query response (\"I\" message)" +msgstr "neočekávaný znak %c následuje prázdnou odezvu dotazu(\"I\" zpráva)" + +#: fe-protocol2.c:589 +#, c-format +msgid "server sent data (\"D\" message) without prior row description (\"T\" message)" +msgstr "server odeslal data (\"D\" zpráva) bez předcházejícího popisu řádky (\"T\" zpráva)" + +#: fe-protocol2.c:607 +#, c-format +msgid "server sent binary data (\"B\" message) without prior row description (\"T\" message)" +msgstr "server odeslal binární data (\"B\" zpráva) bez předchozího popisu řádky (\"T\" zpráva)" + +#: fe-protocol2.c:626 fe-protocol3.c:408 +#, c-format +msgid "unexpected response from server; first received character was \"%c\"\n" +msgstr "neočekávaná odpověď serveru; předchozí znak byl \"%c\"\n" + +#: fe-protocol2.c:755 fe-protocol2.c:930 fe-protocol3.c:622 fe-protocol3.c:849 +msgid "out of memory for query result" +msgstr "nedostatek paměti pro výsledek dotazu" + +#: fe-protocol2.c:1408 +#, c-format +msgid "lost synchronization with server, resetting connection" +msgstr "ztráta synchronizace se serverem, resetuji spojení" + +#: fe-protocol2.c:1530 fe-protocol2.c:1562 fe-protocol3.c:2095 +#, c-format +msgid "protocol error: id=0x%x\n" +msgstr "chyba protokolu: id=0x%x\n" + +#: fe-protocol3.c:365 +msgid "server sent data (\"D\" message) without prior row description (\"T\" message)\n" +msgstr "server odeslal data (\"D\" zpráva) bez předchozího popisu řádky (\"T\" zpráva)\n" + +#: fe-protocol3.c:429 +#, c-format +msgid "message contents do not agree with length in message type \"%c\"\n" +msgstr "obsah zprávy nesouhlasí s délkou v typu zprávy \"%c\"\n" + +#: fe-protocol3.c:449 +#, c-format +msgid "lost synchronization with server: got message type \"%c\", length %d\n" +msgstr "ztracena synchronizace se serverem: obdržena zpráva typu \"%c\", délky %d\n" + +#: fe-protocol3.c:500 fe-protocol3.c:540 +msgid "insufficient data in \"T\" message" +msgstr "nedostatek dat v \"T\" zprávě" + +#: fe-protocol3.c:573 +msgid "extraneous data in \"T\" message" +msgstr "přebytečná data v \"T\" zprávě" + +#: fe-protocol3.c:686 +msgid "extraneous data in \"t\" message" +msgstr "přebytečná data v \"t\" zprávě" + +#: fe-protocol3.c:757 fe-protocol3.c:789 fe-protocol3.c:807 +msgid "insufficient data in \"D\" message" +msgstr "nedostatek dat v \"D\" zprávě" + +#: fe-protocol3.c:763 +msgid "unexpected field count in \"D\" message" +msgstr "neočekávaný počet položek v \"D\" zprávě" + +#: fe-protocol3.c:816 +msgid "extraneous data in \"D\" message" +msgstr "přebytečná data v \"D\" zprávě" + +#: fe-protocol3.c:1008 +msgid "no error message available\n" +msgstr "chybová zpráva není k dispozici\n" + +#. translator: %s represents a digit string +#: fe-protocol3.c:1056 fe-protocol3.c:1075 +#, c-format +msgid " at character %s" +msgstr " na znaku %s" + +#: fe-protocol3.c:1088 +#, c-format +msgid "DETAIL: %s\n" +msgstr "DETAIL: %s\n" + +#: fe-protocol3.c:1091 +#, c-format +msgid "HINT: %s\n" +msgstr "DOPORUČENÍ: %s\n" + +#: fe-protocol3.c:1094 +#, c-format +msgid "QUERY: %s\n" +msgstr "DOTAZ: %s\n" + +#: fe-protocol3.c:1101 +#, c-format +msgid "CONTEXT: %s\n" +msgstr "KONTEXT: %s\n" + +#: fe-protocol3.c:1110 +#, c-format +msgid "SCHEMA NAME: %s\n" +msgstr "NÁZEV SCHÉMATU: %s\n" + +#: fe-protocol3.c:1114 +#, c-format +msgid "TABLE NAME: %s\n" +msgstr "NÁZEV TABULKY: %s\n" + +#: fe-protocol3.c:1118 +#, c-format +msgid "COLUMN NAME: %s\n" +msgstr "NÁZEV SLOUPCE: %s\n" + +#: fe-protocol3.c:1122 +#, c-format +msgid "DATATYPE NAME: %s\n" +msgstr "NÁZEV DATOVÉHO TYPU: %s\n" + +#: fe-protocol3.c:1126 +#, c-format +msgid "CONSTRAINT NAME: %s\n" +msgstr "NÁZEV OMEZENÍ: %s\n" + +#: fe-protocol3.c:1138 +msgid "LOCATION: " +msgstr "UMÍSTĚNÍ: " + +#: fe-protocol3.c:1140 +#, c-format +msgid "%s, " +msgstr "%s, " + +#: fe-protocol3.c:1142 +#, c-format +msgid "%s:%s" +msgstr "%s:%s" + +#: fe-protocol3.c:1337 +#, c-format +msgid "LINE %d: " +msgstr "ŘÁDKA %d: " + +#: fe-protocol3.c:1732 +msgid "PQgetline: not doing text COPY OUT\n" +msgstr "PQgetline: not doing text COPY OUT\n" + +#: fe-secure-common.c:124 +msgid "SSL certificate's name contains embedded null\n" +msgstr "jméno SSL certifikátu obsahuje vloženou null hodnotu\n" + +#: fe-secure-common.c:171 +msgid "host name must be specified for a verified SSL connection\n" +msgstr "host musí být specifikován pro ověřené SSL spojení\n" + +#: fe-secure-common.c:196 +#, c-format +msgid "server certificate for \"%s\" does not match host name \"%s\"\n" +msgstr "serverový certifikát pro \"%s\" nesouhlasí s jménem serveru (host name) \"%s\"\n" + +#: fe-secure-common.c:202 +msgid "could not get server's host name from server certificate\n" +msgstr "ze serverového certifikátu nelze získat host name serveru\n" + +#: fe-secure-gssapi.c:201 +msgid "GSSAPI wrap error" +msgstr "GSSAPI wrap error" + +#: fe-secure-gssapi.c:209 +msgid "outgoing GSSAPI message would not use confidentiality\n" +msgstr "odchozí GSSAPI zpráva by nepoužívala důvěrnost (confidentiality)\n" + +#: fe-secure-gssapi.c:217 +#, c-format +msgid "client tried to send oversize GSSAPI packet (%zu > %zu)\n" +msgstr "klient se pokusil zaslat příliš velký GSSAPI packet (%zu > %zu)\n" + +#: fe-secure-gssapi.c:354 fe-secure-gssapi.c:596 +#, c-format +msgid "oversize GSSAPI packet sent by the server (%zu > %zu)\n" +msgstr "příliš velký GSSAPI packet zaslán serverem (%zu > %zu)\n" + +#: fe-secure-gssapi.c:393 +msgid "GSSAPI unwrap error" +msgstr "GSSAPI unwrap error" + +#: fe-secure-gssapi.c:403 +msgid "incoming GSSAPI message did not use confidentiality\n" +msgstr "příchozí GSSAPI zpráva nepoužívala důvěrnost (confidentiality)\n" + +#: fe-secure-gssapi.c:642 +msgid "could not initiate GSSAPI security context" +msgstr "nelze inicializovat GSSAPI bezpečnostní kontext" + +#: fe-secure-gssapi.c:673 +msgid "GSSAPI size check error" +msgstr "GSSAPI size check error" + +#: fe-secure-gssapi.c:684 +msgid "GSSAPI context establishment error" +msgstr "GSSAPI context establishment error" + +#: fe-secure-openssl.c:214 fe-secure-openssl.c:321 fe-secure-openssl.c:1291 +#, c-format +msgid "SSL SYSCALL error: %s\n" +msgstr "SSL SYSCALL chyba: %s\n" + +#: fe-secure-openssl.c:221 fe-secure-openssl.c:328 fe-secure-openssl.c:1295 +msgid "SSL SYSCALL error: EOF detected\n" +msgstr "SSL SYSCALL chyba: detekován EOF\n" + +#: fe-secure-openssl.c:232 fe-secure-openssl.c:339 fe-secure-openssl.c:1304 +#, c-format +msgid "SSL error: %s\n" +msgstr "SSL chyba: %s\n" + +#: fe-secure-openssl.c:247 fe-secure-openssl.c:354 +msgid "SSL connection has been closed unexpectedly\n" +msgstr "SSL spojení bylo neočekávaně ukončeno\n" + +#: fe-secure-openssl.c:253 fe-secure-openssl.c:360 fe-secure-openssl.c:1354 +#, c-format +msgid "unrecognized SSL error code: %d\n" +msgstr "neznámý chybový kód SSL: %d\n" + +#: fe-secure-openssl.c:400 +msgid "could not determine server certificate signature algorithm\n" +msgstr "nelze určit podepisovací algoritmus serverového certifikátu\n" + +#: fe-secure-openssl.c:421 +#, c-format +msgid "could not find digest for NID %s\n" +msgstr "nelze nalézt digest pro NID %s\n" + +#: fe-secure-openssl.c:431 +msgid "could not generate peer certificate hash\n" +msgstr "nelze vygenerovat hash peer cerfitikátu\n" + +#: fe-secure-openssl.c:488 +msgid "SSL certificate's name entry is missing\n" +msgstr "SSL certifikátu chybí položka name\n" + +#: fe-secure-openssl.c:815 +#, c-format +msgid "could not create SSL context: %s\n" +msgstr "nelze vytvořit SSL kontext: %s\n" + +#: fe-secure-openssl.c:854 +#, c-format +#| msgid "invalid integer value \"%s\" for connection option \"%s\"\n" +msgid "invalid value \"%s\" for minimum SSL protocol version\n" +msgstr "neplatná hodnota \"%s\" pro minimální verzi SSL protokolu\n" + +#: fe-secure-openssl.c:865 +#, c-format +#| msgid "could not establish SSL connection: %s\n" +msgid "could not set minimum SSL protocol version: %s\n" +msgstr "nelze nastavit minimální verzi SSL protokolu: %s\n" + +#: fe-secure-openssl.c:883 +#, c-format +msgid "invalid value \"%s\" for maximum SSL protocol version\n" +msgstr "neplatná hodnota \"%s\" pro maximální verzi SSL protokolu\n" + +#: fe-secure-openssl.c:894 +#, c-format +#| msgid "could not establish SSL connection: %s\n" +msgid "could not set maximum SSL protocol version: %s\n" +msgstr "nelze nastavit maximální verzi SSL protokolu: %s\n" + +#: fe-secure-openssl.c:930 +#, c-format +msgid "could not read root certificate file \"%s\": %s\n" +msgstr "nelze číst soubor s kořenovým certifikátem \"%s\": %s\n" + +#: fe-secure-openssl.c:974 +msgid "" +"could not get home directory to locate root certificate file\n" +"Either provide the file or change sslmode to disable server certificate verification.\n" +msgstr "" +"nelze určit domácí adresář pro nalezení souboru s kořenovým certifikátem\n" +"Buď poskytněte soubor nebo změňte ssl mód tak, aby neověřoval certifkát serveru.\n" + +#: fe-secure-openssl.c:978 +#, c-format +msgid "" +"root certificate file \"%s\" does not exist\n" +"Either provide the file or change sslmode to disable server certificate verification.\n" +msgstr "" +"soubor s kořenovým certifikátem \"%s\" neexistuje\n" +"poskytněnte soubor nebo změntě ssl mód tak, aby neověřoval certifkát serveru.\n" + +#: fe-secure-openssl.c:1009 +#, c-format +msgid "could not open certificate file \"%s\": %s\n" +msgstr "nelze otevřít soubor s certifikátem \"%s\": %s\n" + +#: fe-secure-openssl.c:1028 +#, c-format +msgid "could not read certificate file \"%s\": %s\n" +msgstr "nelze číst soubor s certifikátem \"%s\": %s\n" + +#: fe-secure-openssl.c:1053 +#, c-format +msgid "could not establish SSL connection: %s\n" +msgstr "nelze vytvořit SSL spojení: %s\n" + +#: fe-secure-openssl.c:1107 +#, c-format +msgid "could not load SSL engine \"%s\": %s\n" +msgstr "nelze nahrát SSL engine \"%s\": %s\n" + +#: fe-secure-openssl.c:1119 +#, c-format +msgid "could not initialize SSL engine \"%s\": %s\n" +msgstr "nelze inicializovat SSL engine \"%s\": %s\n" + +#: fe-secure-openssl.c:1135 +#, c-format +msgid "could not read private SSL key \"%s\" from engine \"%s\": %s\n" +msgstr "nelze číst soubor privátního klíče \"%s\" z enginu \"%s\": %s\n" + +#: fe-secure-openssl.c:1149 +#, c-format +msgid "could not load private SSL key \"%s\" from engine \"%s\": %s\n" +msgstr "nelze načíst soubor privátního klíče \"%s\" z enginu \"%s\": %s\n" + +#: fe-secure-openssl.c:1186 +#, c-format +msgid "certificate present, but not private key file \"%s\"\n" +msgstr "certifikát je přítomen, ale soubor privátního klíče ne \"%s\"\n" + +#: fe-secure-openssl.c:1194 +#, c-format +msgid "private key file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n" +msgstr "soubor s privátním klíčem \"%s\" má povolená přístupová práva pro skupinu nebo všechny uživatele; práva by měla být u=rw (0600) nebo přísnější\n" + +#: fe-secure-openssl.c:1219 +#, c-format +msgid "could not load private key file \"%s\": %s\n" +msgstr "nelze načíst soubor privátního klíče \"%s\": %s\n" + +#: fe-secure-openssl.c:1237 +#, c-format +msgid "certificate does not match private key file \"%s\": %s\n" +msgstr "certifikát nesouhlasí se souborem privátního klíče \"%s\": %s\n" + +#: fe-secure-openssl.c:1337 +#, c-format +msgid "This may indicate that the server does not support any SSL protocol version between %s and %s.\n" +msgstr "Toto může znamenat že server nepodporuje verzi SSL protokolu mezi %s a %s.\n" + +#: fe-secure-openssl.c:1373 +#, c-format +msgid "certificate could not be obtained: %s\n" +msgstr "certifikát nelze získat: %s\n" + +#: fe-secure-openssl.c:1462 +#, c-format +msgid "no SSL error reported" +msgstr "žádný chybový kód SSL nebyl hlášený" + +#: fe-secure-openssl.c:1471 +#, c-format +msgid "SSL error code %lu" +msgstr "SSL chybový kód %lu" + +#: fe-secure-openssl.c:1718 +#, c-format +msgid "WARNING: sslpassword truncated\n" +msgstr "WARNING: hodnota sslpassword oříznuta\n" + +#: fe-secure.c:275 +#, c-format +msgid "could not receive data from server: %s\n" +msgstr "nelze přijmout data ze serveru: %s\n" + +#: fe-secure.c:390 +#, c-format +msgid "could not send data to server: %s\n" +msgstr "nelze poslat data na server: %s\n" + +#: win32.c:314 +#, c-format +msgid "unrecognized socket error: 0x%08X/%d" +msgstr "neznámá chyba socketu: 0x%08X/%d" + +#~ msgid "empty channel binding data for channel binding type \"%s\"\n" +#~ msgstr "" +#~ "prázdná \"channel binding data\" pro channel binding typu \"%s\"\n" +#~ "\n" + +#~ msgid "could not set socket to blocking mode: %s\n" +#~ msgstr "nelze nastavit soket do blokujícího módu: %s\n" + +#~ msgid "Kerberos 5 authentication rejected: %*s\n" +#~ msgstr "Kerberos 5 autentizace odmítnuta: %*s\n" + +#~ msgid "setsockopt(TCP_KEEPIDLE) failed: %s\n" +#~ msgstr "setsockopt(TCP_KEEPIDLE) selhalo: %s\n" + +#~ msgid "setsockopt(TCP_KEEPALIVE) failed: %s\n" +#~ msgstr "setsockopt(TCP_KEEPALIVE) selhalo: %s\n" + +#~ msgid "setsockopt(TCP_KEEPINTVL) failed: %s\n" +#~ msgstr "setsockopt(TCP_KEEPINTVL) selhalo: %s\n" + +#~ msgid "setsockopt(SO_KEEPALIVE) failed: %s\n" +#~ msgstr "setsockopt(SO_KEEPALIVE) selhalo: %s\n" + +#~ msgid "could not get home directory to locate service definition file" +#~ msgstr "nelze získat domovský adresář pro nalezení kořenového certifikátu" + +#~ msgid "socket not open\n" +#~ msgstr "soket není otevřen\n" + +#~ msgid "unrecognized return value from row processor" +#~ msgstr "nerozpoznaná návratová hodnota z processoru řádek" + +#~ msgid "private key file \"%s\" changed during execution\n" +#~ msgstr "soubor privátního klíče \"%s\" byl za chodu změněn\n" + +#~ msgid "could not open private key file \"%s\": %s\n" +#~ msgstr "nelze otevřít soubor s privátním klíčem \"%s\": %s\n" + +#~ msgid "could not get home directory to locate client certificate files" +#~ msgstr "nelze získat domovský adresář pro nalezení klientského certifikátu" + +#~ msgid "SSL library does not support CRL certificates (file \"%s\")\n" +#~ msgstr "knihovna SSL nepodporuje CRL certifikáty (soubor \"%s\")\n" diff --git a/src/interfaces/libpq/po/de.po b/src/interfaces/libpq/po/de.po new file mode 100644 index 0000000..bdf67b5 --- /dev/null +++ b/src/interfaces/libpq/po/de.po @@ -0,0 +1,1471 @@ +# German message translation file for libpq +# Peter Eisentraut <peter@eisentraut.org>, 2001 - 2023. +# +# Use these quotes: »%s« +# +msgid "" +msgstr "" +"Project-Id-Version: PostgreSQL 16\n" +"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" +"POT-Creation-Date: 2023-06-23 12:40+0000\n" +"PO-Revision-Date: 2023-06-23 15:13+0200\n" +"Last-Translator: Peter Eisentraut <peter@eisentraut.org>\n" +"Language-Team: German <pgsql-translators@postgresql.org>\n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#: ../../port/thread.c:50 ../../port/thread.c:86 +#, c-format +msgid "could not look up local user ID %d: %s" +msgstr "konnte lokale Benutzer-ID %d nicht nachschlagen: %s" + +#: ../../port/thread.c:55 ../../port/thread.c:91 +#, c-format +msgid "local user with ID %d does not exist" +msgstr "lokaler Benutzer mit ID %d existiert nicht" + +#: fe-auth-scram.c:227 +#, c-format +msgid "malformed SCRAM message (empty message)" +msgstr "fehlerhafte SCRAM-Nachricht (leere Nachricht)" + +#: fe-auth-scram.c:232 +#, c-format +msgid "malformed SCRAM message (length mismatch)" +msgstr "fehlerhafte SCRAM-Nachricht (Länge stimmt nicht überein)" + +#: fe-auth-scram.c:275 +#, c-format +msgid "could not verify server signature: %s" +msgstr "konnte Serversignatur nicht überprüfen: %s" + +#: fe-auth-scram.c:281 +#, c-format +msgid "incorrect server signature" +msgstr "falsche Serversignatur" + +#: fe-auth-scram.c:290 +#, c-format +msgid "invalid SCRAM exchange state" +msgstr "ungültiger Zustand des SCRAM-Austauschs" + +#: fe-auth-scram.c:317 +#, c-format +msgid "malformed SCRAM message (attribute \"%c\" expected)" +msgstr "fehlerhafte SCRAM-Nachricht (Attribut »%c« erwartet)" + +#: fe-auth-scram.c:326 +#, c-format +msgid "malformed SCRAM message (expected character \"=\" for attribute \"%c\")" +msgstr "fehlerhafte SCRAM-Nachricht (Zeichen »=« für Attribut »%c« erwartet)" + +#: fe-auth-scram.c:366 +#, c-format +msgid "could not generate nonce" +msgstr "konnte Nonce nicht erzeugen" + +#: fe-auth-scram.c:375 fe-auth-scram.c:448 fe-auth-scram.c:600 +#: fe-auth-scram.c:620 fe-auth-scram.c:644 fe-auth-scram.c:658 +#: fe-auth-scram.c:704 fe-auth-scram.c:740 fe-auth-scram.c:914 fe-auth.c:295 +#: fe-auth.c:368 fe-auth.c:402 fe-auth.c:617 fe-auth.c:728 fe-auth.c:1209 +#: fe-auth.c:1374 fe-connect.c:925 fe-connect.c:1759 fe-connect.c:1921 +#: fe-connect.c:3291 fe-connect.c:4496 fe-connect.c:5161 fe-connect.c:5416 +#: fe-connect.c:5534 fe-connect.c:5781 fe-connect.c:5861 fe-connect.c:5959 +#: fe-connect.c:6210 fe-connect.c:6237 fe-connect.c:6313 fe-connect.c:6336 +#: fe-connect.c:6360 fe-connect.c:6395 fe-connect.c:6481 fe-connect.c:6489 +#: fe-connect.c:6846 fe-connect.c:6996 fe-exec.c:527 fe-exec.c:1321 +#: fe-exec.c:3111 fe-exec.c:4071 fe-exec.c:4235 fe-gssapi-common.c:109 +#: fe-lobj.c:870 fe-protocol3.c:204 fe-protocol3.c:228 fe-protocol3.c:256 +#: fe-protocol3.c:273 fe-protocol3.c:353 fe-protocol3.c:720 fe-protocol3.c:959 +#: fe-protocol3.c:1770 fe-protocol3.c:2170 fe-secure-common.c:110 +#: fe-secure-gssapi.c:500 fe-secure-openssl.c:434 fe-secure-openssl.c:1285 +#, c-format +msgid "out of memory" +msgstr "Speicher aufgebraucht" + +#: fe-auth-scram.c:382 +#, c-format +msgid "could not encode nonce" +msgstr "konnte Nonce nicht kodieren" + +#: fe-auth-scram.c:570 +#, c-format +msgid "could not calculate client proof: %s" +msgstr "konnte Client-Proof nicht berechnen: %s" + +#: fe-auth-scram.c:585 +#, c-format +msgid "could not encode client proof" +msgstr "konnte Client-Proof nicht kodieren" + +#: fe-auth-scram.c:637 +#, c-format +msgid "invalid SCRAM response (nonce mismatch)" +msgstr "ungültige SCRAM-Antwort (Nonce stimmt nicht überein)" + +#: fe-auth-scram.c:667 +#, c-format +msgid "malformed SCRAM message (invalid salt)" +msgstr "fehlerhafte SCRAM-Nachricht (ungültiges Salt)" + +#: fe-auth-scram.c:680 +#, c-format +msgid "malformed SCRAM message (invalid iteration count)" +msgstr "fehlerhafte SCRAM-Nachricht (ungültige Iterationszahl)" + +#: fe-auth-scram.c:685 +#, c-format +msgid "malformed SCRAM message (garbage at end of server-first-message)" +msgstr "fehlerhafte SCRAM-Nachricht (Müll am Ende der »server-first-message«)" + +#: fe-auth-scram.c:719 +#, c-format +msgid "error received from server in SCRAM exchange: %s" +msgstr "Fehler vom Server empfangen im SCRAM-Austausch: %s" + +#: fe-auth-scram.c:734 +#, c-format +msgid "malformed SCRAM message (garbage at end of server-final-message)" +msgstr "fehlerhafte SCRAM-Nachricht (Müll am Ende der »server-final-message«)" + +#: fe-auth-scram.c:751 +#, c-format +msgid "malformed SCRAM message (invalid server signature)" +msgstr "fehlerhafte SCRAM-Nachricht (ungültige Serversignatur)" + +#: fe-auth-scram.c:923 +msgid "could not generate random salt" +msgstr "konnte zufälliges Salt nicht erzeugen" + +#: fe-auth.c:76 +#, c-format +msgid "out of memory allocating GSSAPI buffer (%d)" +msgstr "Speicher aufgebraucht beim Anlegen des GSSAPI-Puffers (%d)" + +#: fe-auth.c:137 +msgid "GSSAPI continuation error" +msgstr "GSSAPI-Fortsetzungsfehler" + +#: fe-auth.c:167 fe-auth.c:396 fe-gssapi-common.c:97 fe-secure-common.c:99 +#: fe-secure-common.c:173 +#, c-format +msgid "host name must be specified" +msgstr "Hostname muss angegeben werden" + +#: fe-auth.c:173 +#, c-format +msgid "duplicate GSS authentication request" +msgstr "doppelte GSSAPI-Authentifizierungsanfrage" + +#: fe-auth.c:237 +#, c-format +msgid "out of memory allocating SSPI buffer (%d)" +msgstr "Speicher aufgebraucht beim Anlegen des SSPI-Puffers (%d)" + +#: fe-auth.c:284 +msgid "SSPI continuation error" +msgstr "SSPI-Fortsetzungsfehler" + +#: fe-auth.c:358 +#, c-format +msgid "duplicate SSPI authentication request" +msgstr "doppelte SSPI-Authentifizierungsanfrage" + +#: fe-auth.c:383 +msgid "could not acquire SSPI credentials" +msgstr "konnte SSPI-Credentials nicht erhalten" + +#: fe-auth.c:436 +#, c-format +msgid "channel binding required, but SSL not in use" +msgstr "Channel-Binding wurde verlangt, aber SSL wird nicht verwendet" + +#: fe-auth.c:442 +#, c-format +msgid "duplicate SASL authentication request" +msgstr "doppelte SASL-Authentifizierungsanfrage" + +#: fe-auth.c:500 +#, c-format +msgid "channel binding is required, but client does not support it" +msgstr "Channel-Binding wurde verlangt, aber der Client unterstützt es nicht" + +#: fe-auth.c:516 +#, c-format +msgid "server offered SCRAM-SHA-256-PLUS authentication over a non-SSL connection" +msgstr "Server hat Authentifizierung mit SCRAM-SHA-256-PLUS über eine Verbindung ohne SSL angeboten" + +#: fe-auth.c:530 +#, c-format +msgid "none of the server's SASL authentication mechanisms are supported" +msgstr "keine der SASL-Authentifizierungsmechanismen des Servers werden unterstützt" + +#: fe-auth.c:537 +#, c-format +msgid "channel binding is required, but server did not offer an authentication method that supports channel binding" +msgstr "Channel-Binding wurde verlangt, aber der Server hat keine Authentifizierungsmethode mit Channel-Binding angeboten" + +#: fe-auth.c:640 +#, c-format +msgid "out of memory allocating SASL buffer (%d)" +msgstr "Speicher aufgebraucht beim Anlegen des SASL-Puffers (%d)" + +#: fe-auth.c:664 +#, c-format +msgid "AuthenticationSASLFinal received from server, but SASL authentication was not completed" +msgstr "AuthenticationSASLFinal vom Server empfangen, aber SASL-Authentifizierung war noch nicht abgeschlossen" + +#: fe-auth.c:674 +#, c-format +msgid "no client response found after SASL exchange success" +msgstr "keine Client-Antwort gefunden nach Erfolg des SASL-Austauschs" + +#: fe-auth.c:737 fe-auth.c:744 fe-auth.c:1357 fe-auth.c:1368 +#, c-format +msgid "could not encrypt password: %s" +msgstr "konnte Passwort nicht verschlüsseln: %s" + +#: fe-auth.c:772 +msgid "server requested a cleartext password" +msgstr "Server hat ein Passwort im Klartext verlangt" + +#: fe-auth.c:774 +msgid "server requested a hashed password" +msgstr "Server hat ein gehashtes Passwort verlangt" + +#: fe-auth.c:777 +msgid "server requested GSSAPI authentication" +msgstr "Server hat GSSAPI-Authentifizierung verlangt" + +#: fe-auth.c:779 +msgid "server requested SSPI authentication" +msgstr "Server hat SSPI-Authentifizierung verlangt" + +#: fe-auth.c:783 +msgid "server requested SASL authentication" +msgstr "Server hat SASL-Authentifizierung verlangt" + +#: fe-auth.c:786 +msgid "server requested an unknown authentication type" +msgstr "Server hat einen unbekannten Authentifizierungstyp verlangt" + +#: fe-auth.c:819 +#, c-format +msgid "server did not request an SSL certificate" +msgstr "Server hat kein SSL-Zertifikat verlangt" + +#: fe-auth.c:824 +#, c-format +msgid "server accepted connection without a valid SSL certificate" +msgstr "Server hat Verbindung ohne gültiges SSL-Zertifikat angenommen" + +#: fe-auth.c:878 +msgid "server did not complete authentication" +msgstr "Server hat Authentifizierung nicht abgeschlossen" + +#: fe-auth.c:912 +#, c-format +msgid "authentication method requirement \"%s\" failed: %s" +msgstr "Authentifizierungsmethodenanforderung »%s« fehlgeschlagen: %s" + +#: fe-auth.c:935 +#, c-format +msgid "channel binding required, but server authenticated client without channel binding" +msgstr "Channel-Binding wurde verlangt, aber der Server hat den Client ohne Channel-Binding authentifiziert" + +#: fe-auth.c:940 +#, c-format +msgid "channel binding required but not supported by server's authentication request" +msgstr "Channel-Binding wurde verlangt aber von der Authentifizierungsanfrage des Servers nicht unterstützt" + +#: fe-auth.c:974 +#, c-format +msgid "Kerberos 4 authentication not supported" +msgstr "Authentifizierung mit Kerberos 4 nicht unterstützt" + +#: fe-auth.c:978 +#, c-format +msgid "Kerberos 5 authentication not supported" +msgstr "Authentifizierung mit Kerberos 5 nicht unterstützt" + +#: fe-auth.c:1048 +#, c-format +msgid "GSSAPI authentication not supported" +msgstr "Authentifizierung mit GSSAPI nicht unterstützt" + +#: fe-auth.c:1079 +#, c-format +msgid "SSPI authentication not supported" +msgstr "Authentifizierung mit SSPI nicht unterstützt" + +#: fe-auth.c:1086 +#, c-format +msgid "Crypt authentication not supported" +msgstr "Authentifizierung mit Crypt nicht unterstützt" + +#: fe-auth.c:1150 +#, c-format +msgid "authentication method %u not supported" +msgstr "Authentifizierungsmethode %u nicht unterstützt" + +#: fe-auth.c:1196 +#, c-format +msgid "user name lookup failure: error code %lu" +msgstr "Fehler beim Nachschlagen des Benutzernamens: Fehlercode %lu" + +#: fe-auth.c:1320 +#, c-format +msgid "unexpected shape of result set returned for SHOW" +msgstr "unerwartete Form der Ergebnismenge von SHOW" + +#: fe-auth.c:1328 +#, c-format +msgid "password_encryption value too long" +msgstr "Wert von password_encryption ist zu lang" + +#: fe-auth.c:1378 +#, c-format +msgid "unrecognized password encryption algorithm \"%s\"" +msgstr "unbekannter Passwortverschlüsselungsalgorithmus »%s«" + +#: fe-connect.c:1132 +#, c-format +msgid "could not match %d host names to %d hostaddr values" +msgstr "fehlerhafte Angabe: %d Hostnamen und %d hostaddr-Angaben" + +#: fe-connect.c:1212 +#, c-format +msgid "could not match %d port numbers to %d hosts" +msgstr "fehlerhafte Angabe: %d Portnummern und %d Hosts" + +#: fe-connect.c:1337 +#, c-format +msgid "negative require_auth method \"%s\" cannot be mixed with non-negative methods" +msgstr "negative require_auth-Methode »%s« kann nicht mit nicht-negativen Methoden vermischt werden" + +#: fe-connect.c:1350 +#, c-format +msgid "require_auth method \"%s\" cannot be mixed with negative methods" +msgstr "require_auth-Methode »%s« kann nicht mit negativen Methoden vermischt werden" + +#: fe-connect.c:1410 fe-connect.c:1461 fe-connect.c:1503 fe-connect.c:1559 +#: fe-connect.c:1567 fe-connect.c:1598 fe-connect.c:1644 fe-connect.c:1684 +#: fe-connect.c:1705 +#, c-format +msgid "invalid %s value: \"%s\"" +msgstr "ungültiger %s-Wert: »%s«" + +#: fe-connect.c:1443 +#, c-format +msgid "require_auth method \"%s\" is specified more than once" +msgstr "require_auth-Methode »%s« ist mehrmals angegeben" + +#: fe-connect.c:1484 fe-connect.c:1523 fe-connect.c:1606 +#, c-format +msgid "%s value \"%s\" invalid when SSL support is not compiled in" +msgstr "%s-Wert »%s« ist ungültig, wenn SSL-Unterstützung nicht einkompiliert worden ist" + +#: fe-connect.c:1546 +#, c-format +msgid "weak sslmode \"%s\" may not be used with sslrootcert=system (use \"verify-full\")" +msgstr "schwacher sslmode »%s« darf nicht mit sslrootcert=system verwendet werden (»verify-full« verwenden)" + +#: fe-connect.c:1584 +#, c-format +msgid "invalid SSL protocol version range" +msgstr "ungültiges SSL-Protokollsintervall" + +#: fe-connect.c:1621 +#, c-format +msgid "%s value \"%s\" is not supported (check OpenSSL version)" +msgstr "%s-Wert »%s« wird nicht unterstützt (OpenSSL-Version prüfen)" + +#: fe-connect.c:1651 +#, c-format +msgid "gssencmode value \"%s\" invalid when GSSAPI support is not compiled in" +msgstr "gssencmode-Wert »%s« ist ungültig, wenn GSSAPI-Unterstützung nicht einkompiliert worden ist" + +#: fe-connect.c:1944 +#, c-format +msgid "could not set socket to TCP no delay mode: %s" +msgstr "konnte Socket nicht auf TCP »No Delay«-Modus umstellen: %s" + +#: fe-connect.c:2003 +#, c-format +msgid "connection to server on socket \"%s\" failed: " +msgstr "Verbindung zum Server auf Socket »%s« fehlgeschlagen: " + +#: fe-connect.c:2029 +#, c-format +msgid "connection to server at \"%s\" (%s), port %s failed: " +msgstr "Verbindung zum Server auf »%s« (%s), Port %s fehlgeschlagen: " + +#: fe-connect.c:2034 +#, c-format +msgid "connection to server at \"%s\", port %s failed: " +msgstr "Verbindung zum Server auf »%s«, Port %s fehlgeschlagen: " + +#: fe-connect.c:2057 +#, c-format +msgid "\tIs the server running locally and accepting connections on that socket?" +msgstr "\tLäuft der Server lokal und akzeptiert er Verbindungen auf diesem Socket?" + +#: fe-connect.c:2059 +#, c-format +msgid "\tIs the server running on that host and accepting TCP/IP connections?" +msgstr "\tLäuft der Server auf diesem Host und akzeptiert er TCP/IP-Verbindungen?" + +#: fe-connect.c:2122 +#, c-format +msgid "invalid integer value \"%s\" for connection option \"%s\"" +msgstr "ungültiger Zahlenwert »%s« für Verbindungsoption »%s«" + +#: fe-connect.c:2151 fe-connect.c:2185 fe-connect.c:2220 fe-connect.c:2318 +#: fe-connect.c:2973 +#, c-format +msgid "%s(%s) failed: %s" +msgstr "%s(%s) fehlgeschlagen: %s" + +#: fe-connect.c:2284 +#, c-format +msgid "%s(%s) failed: error code %d" +msgstr "%s(%s) fehlgeschlagen: Fehlercode %d" + +#: fe-connect.c:2597 +#, c-format +msgid "invalid connection state, probably indicative of memory corruption" +msgstr "ungültiger Verbindungszustand, möglicherweise ein Speicherproblem" + +#: fe-connect.c:2676 +#, c-format +msgid "invalid port number: \"%s\"" +msgstr "ungültige Portnummer: »%s«" + +#: fe-connect.c:2690 +#, c-format +msgid "could not translate host name \"%s\" to address: %s" +msgstr "konnte Hostnamen »%s« nicht in Adresse übersetzen: %s" + +#: fe-connect.c:2702 +#, c-format +msgid "could not parse network address \"%s\": %s" +msgstr "konnte Netzwerkadresse »%s« nicht interpretieren: %s" + +#: fe-connect.c:2713 +#, c-format +msgid "Unix-domain socket path \"%s\" is too long (maximum %d bytes)" +msgstr "Unix-Domain-Socket-Pfad »%s« ist zu lang (maximal %d Bytes)" + +#: fe-connect.c:2727 +#, c-format +msgid "could not translate Unix-domain socket path \"%s\" to address: %s" +msgstr "konnte Unix-Domain-Socket-Pfad »%s« nicht in Adresse übersetzen: %s" + +#: fe-connect.c:2901 +#, c-format +msgid "could not create socket: %s" +msgstr "konnte Socket nicht erzeugen: %s" + +#: fe-connect.c:2932 +#, c-format +msgid "could not set socket to nonblocking mode: %s" +msgstr "konnte Socket nicht auf nicht-blockierenden Modus umstellen: %s" + +#: fe-connect.c:2943 +#, c-format +msgid "could not set socket to close-on-exec mode: %s" +msgstr "konnte Socket nicht auf »Close on exec«-Modus umstellen: %s" + +#: fe-connect.c:2961 +#, c-format +msgid "keepalives parameter must be an integer" +msgstr "Parameter »keepalives« muss eine ganze Zahl sein" + +#: fe-connect.c:3100 +#, c-format +msgid "could not get socket error status: %s" +msgstr "konnte Socket-Fehlerstatus nicht ermitteln: %s" + +#: fe-connect.c:3127 +#, c-format +msgid "could not get client address from socket: %s" +msgstr "konnte Client-Adresse vom Socket nicht ermitteln: %s" + +#: fe-connect.c:3165 +#, c-format +msgid "requirepeer parameter is not supported on this platform" +msgstr "Parameter »requirepeer« wird auf dieser Plattform nicht unterstützt" + +#: fe-connect.c:3167 +#, c-format +msgid "could not get peer credentials: %s" +msgstr "konnte Credentials von Gegenstelle nicht ermitteln: %s" + +#: fe-connect.c:3180 +#, c-format +msgid "requirepeer specifies \"%s\", but actual peer user name is \"%s\"" +msgstr "requirepeer gibt »%s« an, aber tatsächlicher Benutzername der Gegenstelle ist »%s«" + +#: fe-connect.c:3221 +#, c-format +msgid "could not send GSSAPI negotiation packet: %s" +msgstr "konnte Paket zur GSSAPI-Verhandlung nicht senden: %s" + +#: fe-connect.c:3233 +#, c-format +msgid "GSSAPI encryption required but was impossible (possibly no credential cache, no server support, or using a local socket)" +msgstr "GSSAPI-Verschlüsselung war gefordert aber war nicht möglich (möglicherweise kein Credential-Cache, keine Serverunterstützung oder lokales Socket wird verwendet)" + +#: fe-connect.c:3274 +#, c-format +msgid "could not send SSL negotiation packet: %s" +msgstr "konnte Paket zur SSL-Verhandlung nicht senden: %s" + +#: fe-connect.c:3303 +#, c-format +msgid "could not send startup packet: %s" +msgstr "konnte Startpaket nicht senden: %s" + +#: fe-connect.c:3378 +#, c-format +msgid "server does not support SSL, but SSL was required" +msgstr "Server unterstützt kein SSL, aber SSL wurde verlangt" + +#: fe-connect.c:3404 +#, c-format +msgid "received invalid response to SSL negotiation: %c" +msgstr "ungültige Antwort auf SSL-Verhandlungspaket empfangen: %c" + +#: fe-connect.c:3424 +#, c-format +msgid "received unencrypted data after SSL response" +msgstr "unverschlüsselte Daten nach SSL-Antwort empfangen" + +#: fe-connect.c:3504 +#, c-format +msgid "server doesn't support GSSAPI encryption, but it was required" +msgstr "Server unterstützt keine GSSAPI-Verschlüsselung, sie wurde aber verlangt" + +#: fe-connect.c:3515 +#, c-format +msgid "received invalid response to GSSAPI negotiation: %c" +msgstr "ungültige Antwort auf GSSAPI-Verhandlungspaket empfangen: %c" + +#: fe-connect.c:3533 +#, c-format +msgid "received unencrypted data after GSSAPI encryption response" +msgstr "unverschlüsselte Daten nach GSSAPI-Verschlüsselungsantwort empfangen" + +#: fe-connect.c:3598 +#, c-format +msgid "expected authentication request from server, but received %c" +msgstr "Authentifizierungsanfrage wurde vom Server erwartet, aber %c wurde empfangen" + +#: fe-connect.c:3625 fe-connect.c:3794 +#, c-format +msgid "received invalid authentication request" +msgstr "ungültige Authentifizierungsanforderung empfangen" + +#: fe-connect.c:3630 fe-connect.c:3779 +#, c-format +msgid "received invalid protocol negotiation message" +msgstr "ungültige Protokollverhandlungsnachricht empfangen" + +#: fe-connect.c:3648 fe-connect.c:3702 +#, c-format +msgid "received invalid error message" +msgstr "ungültige Fehlermeldung empfangen" + +#: fe-connect.c:3865 +#, c-format +msgid "unexpected message from server during startup" +msgstr "unerwartete Nachricht vom Server beim Start" + +#: fe-connect.c:3956 +#, c-format +msgid "session is read-only" +msgstr "Sitzung ist read-only" + +#: fe-connect.c:3958 +#, c-format +msgid "session is not read-only" +msgstr "Sitzung ist nicht read-only" + +#: fe-connect.c:4011 +#, c-format +msgid "server is in hot standby mode" +msgstr "Server ist im Hot-Standby-Modus" + +#: fe-connect.c:4013 +#, c-format +msgid "server is not in hot standby mode" +msgstr "Server ist nicht im Hot-Standby-Modus" + +#: fe-connect.c:4129 fe-connect.c:4179 +#, c-format +msgid "\"%s\" failed" +msgstr "»%s« fehlgeschlagen" + +#: fe-connect.c:4193 +#, c-format +msgid "invalid connection state %d, probably indicative of memory corruption" +msgstr "ungültiger Verbindungszustand %d, möglicherweise ein Speicherproblem" + +#: fe-connect.c:5174 +#, c-format +msgid "invalid LDAP URL \"%s\": scheme must be ldap://" +msgstr "ungültige LDAP-URL »%s«: Schema muss ldap:// sein" + +#: fe-connect.c:5189 +#, c-format +msgid "invalid LDAP URL \"%s\": missing distinguished name" +msgstr "ungültige LDAP-URL »%s«: Distinguished Name fehlt" + +#: fe-connect.c:5201 fe-connect.c:5259 +#, c-format +msgid "invalid LDAP URL \"%s\": must have exactly one attribute" +msgstr "ungültige LDAP-URL »%s«: muss genau ein Attribut haben" + +#: fe-connect.c:5213 fe-connect.c:5275 +#, c-format +msgid "invalid LDAP URL \"%s\": must have search scope (base/one/sub)" +msgstr "ungültige LDAP-URL »%s«: Suchbereich fehlt (base/one/sub)" + +#: fe-connect.c:5225 +#, c-format +msgid "invalid LDAP URL \"%s\": no filter" +msgstr "ungültige LDAP-URL »%s«: kein Filter" + +#: fe-connect.c:5247 +#, c-format +msgid "invalid LDAP URL \"%s\": invalid port number" +msgstr "ungültige LDAP-URL »%s«: ungültige Portnummer" + +#: fe-connect.c:5284 +#, c-format +msgid "could not create LDAP structure" +msgstr "konnte LDAP-Struktur nicht erzeugen" + +#: fe-connect.c:5359 +#, c-format +msgid "lookup on LDAP server failed: %s" +msgstr "Suche auf LDAP-Server fehlgeschlagen: %s" + +#: fe-connect.c:5369 +#, c-format +msgid "more than one entry found on LDAP lookup" +msgstr "LDAP-Suche ergab mehr als einen Eintrag" + +#: fe-connect.c:5371 fe-connect.c:5382 +#, c-format +msgid "no entry found on LDAP lookup" +msgstr "kein Eintrag gefunden bei LDAP-Suche" + +#: fe-connect.c:5392 fe-connect.c:5404 +#, c-format +msgid "attribute has no values on LDAP lookup" +msgstr "Attribut hat keine Werte bei LDAP-Suche" + +#: fe-connect.c:5455 fe-connect.c:5474 fe-connect.c:5998 +#, c-format +msgid "missing \"=\" after \"%s\" in connection info string" +msgstr "fehlendes »=« nach »%s« in der Zeichenkette der Verbindungsdaten" + +#: fe-connect.c:5545 fe-connect.c:6181 fe-connect.c:6979 +#, c-format +msgid "invalid connection option \"%s\"" +msgstr "ungültige Verbindungsoption »%s«" + +#: fe-connect.c:5560 fe-connect.c:6046 +#, c-format +msgid "unterminated quoted string in connection info string" +msgstr "fehlendes schließendes Anführungszeichen (\") in der Zeichenkette der Verbindungsdaten" + +#: fe-connect.c:5640 +#, c-format +msgid "definition of service \"%s\" not found" +msgstr "Definition von Service »%s« nicht gefunden" + +#: fe-connect.c:5666 +#, c-format +msgid "service file \"%s\" not found" +msgstr "Servicedatei »%s« nicht gefunden" + +#: fe-connect.c:5679 +#, c-format +msgid "line %d too long in service file \"%s\"" +msgstr "Zeile %d zu lang in Servicedatei »%s«" + +#: fe-connect.c:5750 fe-connect.c:5793 +#, c-format +msgid "syntax error in service file \"%s\", line %d" +msgstr "Syntaxfehler in Servicedatei »%s«, Zeile %d" + +#: fe-connect.c:5761 +#, c-format +msgid "nested service specifications not supported in service file \"%s\", line %d" +msgstr "geschachtelte »service«-Definitionen werden nicht unterstützt in Servicedatei »%s«, Zeile %d" + +#: fe-connect.c:6500 +#, c-format +msgid "invalid URI propagated to internal parser routine: \"%s\"" +msgstr "ungültige URI an interne Parserroutine weitergeleitet: »%s«" + +#: fe-connect.c:6577 +#, c-format +msgid "end of string reached when looking for matching \"]\" in IPv6 host address in URI: \"%s\"" +msgstr "Ende der Eingabezeichenkette gefunden beim Suchen nach passendem »]« in IPv6-Hostadresse in URI: »%s«" + +#: fe-connect.c:6584 +#, c-format +msgid "IPv6 host address may not be empty in URI: \"%s\"" +msgstr "IPv6-Hostadresse darf nicht leer sein in URI: »%s«" + +#: fe-connect.c:6599 +#, c-format +msgid "unexpected character \"%c\" at position %d in URI (expected \":\" or \"/\"): \"%s\"" +msgstr "unerwartetes Zeichen »%c« an Position %d in URI (»:« oder »/« erwartet): »%s«" + +#: fe-connect.c:6728 +#, c-format +msgid "extra key/value separator \"=\" in URI query parameter: \"%s\"" +msgstr "zusätzliches Schlüssel/Wert-Trennzeichen »=« in URI-Query-Parameter: »%s«" + +#: fe-connect.c:6748 +#, c-format +msgid "missing key/value separator \"=\" in URI query parameter: \"%s\"" +msgstr "fehlendes Schlüssel/Wert-Trennzeichen »=« in URI-Query-Parameter: »%s«" + +#: fe-connect.c:6800 +#, c-format +msgid "invalid URI query parameter: \"%s\"" +msgstr "ungültiger URI-Query-Parameter: »%s«" + +#: fe-connect.c:6874 +#, c-format +msgid "invalid percent-encoded token: \"%s\"" +msgstr "ungültiges Prozent-kodiertes Token: »%s«" + +#: fe-connect.c:6884 +#, c-format +msgid "forbidden value %%00 in percent-encoded value: \"%s\"" +msgstr "verbotener Wert %%00 in Prozent-kodiertem Wert: »%s«" + +#: fe-connect.c:7248 +msgid "connection pointer is NULL\n" +msgstr "Verbindung ist ein NULL-Zeiger\n" + +#: fe-connect.c:7256 fe-exec.c:710 fe-exec.c:970 fe-exec.c:3292 +#: fe-protocol3.c:974 fe-protocol3.c:1007 +msgid "out of memory\n" +msgstr "Speicher aufgebraucht\n" + +#: fe-connect.c:7547 +#, c-format +msgid "WARNING: password file \"%s\" is not a plain file\n" +msgstr "WARNUNG: Passwortdatei »%s« ist keine normale Datei\n" + +#: fe-connect.c:7556 +#, c-format +msgid "WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n" +msgstr "WARNUNG: Passwortdatei »%s« erlaubt Lesezugriff für Gruppe oder Andere; Rechte sollten u=rw (0600) oder weniger sein\n" + +#: fe-connect.c:7663 +#, c-format +msgid "password retrieved from file \"%s\"" +msgstr "Passwort wurde aus Datei »%s« gelesen" + +#: fe-exec.c:466 fe-exec.c:3366 +#, c-format +msgid "row number %d is out of range 0..%d" +msgstr "Zeilennummer %d ist außerhalb des zulässigen Bereichs 0..%d" + +#: fe-exec.c:528 fe-protocol3.c:1976 +#, c-format +msgid "%s" +msgstr "%s" + +#: fe-exec.c:831 +#, c-format +msgid "write to server failed" +msgstr "Schreiben zum Server fehlgeschlagen" + +#: fe-exec.c:869 +#, c-format +msgid "no error text available" +msgstr "kein Fehlertext verfügbar" + +#: fe-exec.c:958 +msgid "NOTICE" +msgstr "HINWEIS" + +#: fe-exec.c:1016 +msgid "PGresult cannot support more than INT_MAX tuples" +msgstr "PGresult kann nicht mehr als INT_MAX Tupel enthalten" + +#: fe-exec.c:1028 +msgid "size_t overflow" +msgstr "Überlauf von size_t" + +#: fe-exec.c:1444 fe-exec.c:1513 fe-exec.c:1559 +#, c-format +msgid "command string is a null pointer" +msgstr "Befehlszeichenkette ist ein NULL-Zeiger" + +#: fe-exec.c:1450 fe-exec.c:2888 +#, c-format +msgid "%s not allowed in pipeline mode" +msgstr "%s im Pipeline-Modus nicht erlaubt" + +#: fe-exec.c:1518 fe-exec.c:1564 fe-exec.c:1658 +#, c-format +msgid "number of parameters must be between 0 and %d" +msgstr "Anzahl der Parameter muss zwischen 0 und %d sein" + +#: fe-exec.c:1554 fe-exec.c:1653 +#, c-format +msgid "statement name is a null pointer" +msgstr "Anweisungsname ist ein NULL-Zeiger" + +#: fe-exec.c:1695 fe-exec.c:3220 +#, c-format +msgid "no connection to the server" +msgstr "keine Verbindung mit dem Server" + +#: fe-exec.c:1703 fe-exec.c:3228 +#, c-format +msgid "another command is already in progress" +msgstr "ein anderer Befehl ist bereits in Ausführung" + +#: fe-exec.c:1733 +#, c-format +msgid "cannot queue commands during COPY" +msgstr "während COPY können keine Befehle aufgereiht werden" + +#: fe-exec.c:1850 +#, c-format +msgid "length must be given for binary parameter" +msgstr "für binäre Parameter muss eine Länge angegeben werden" + +#: fe-exec.c:2171 +#, c-format +msgid "unexpected asyncStatus: %d" +msgstr "unerwarteter asyncStatus: %d" + +#: fe-exec.c:2327 +#, c-format +msgid "synchronous command execution functions are not allowed in pipeline mode" +msgstr "synchrone Befehlsausführungsfunktionen sind im Pipeline-Modus nicht erlaubt" + +#: fe-exec.c:2344 +msgid "COPY terminated by new PQexec" +msgstr "COPY von neuem PQexec beendet" + +#: fe-exec.c:2360 +#, c-format +msgid "PQexec not allowed during COPY BOTH" +msgstr "PQexec ist während COPY BOTH nicht erlaubt" + +#: fe-exec.c:2586 fe-exec.c:2641 fe-exec.c:2709 fe-protocol3.c:1907 +#, c-format +msgid "no COPY in progress" +msgstr "keine COPY in Ausführung" + +#: fe-exec.c:2895 +#, c-format +msgid "connection in wrong state" +msgstr "Verbindung im falschen Zustand" + +#: fe-exec.c:2938 +#, c-format +msgid "cannot enter pipeline mode, connection not idle" +msgstr "kann Pipeline-Modus nicht einschalten, Verbindung ist nicht inaktiv" + +#: fe-exec.c:2974 fe-exec.c:2995 +#, c-format +msgid "cannot exit pipeline mode with uncollected results" +msgstr "kann Pipeline-Modus nicht beenden, wegen nicht eingesammelter Ergebnisse" + +#: fe-exec.c:2978 +#, c-format +msgid "cannot exit pipeline mode while busy" +msgstr "kann Pipeline-Modus nicht beenden während die Verbindung beschäftigt ist" + +#: fe-exec.c:2989 +#, c-format +msgid "cannot exit pipeline mode while in COPY" +msgstr "kann Pipeline-Modus nicht beenden während COPY aktiv ist" + +#: fe-exec.c:3154 +#, c-format +msgid "cannot send pipeline when not in pipeline mode" +msgstr "Pipeline kann nicht gesendet werden, wenn der Pipeline-Modus aus ist" + +#: fe-exec.c:3255 +msgid "invalid ExecStatusType code" +msgstr "ungültiger ExecStatusType-Kode" + +#: fe-exec.c:3282 +msgid "PGresult is not an error result\n" +msgstr "PGresult ist kein Fehlerresultat\n" + +#: fe-exec.c:3350 fe-exec.c:3373 +#, c-format +msgid "column number %d is out of range 0..%d" +msgstr "Spaltennummer %d ist außerhalb des zulässigen Bereichs 0..%d" + +#: fe-exec.c:3388 +#, c-format +msgid "parameter number %d is out of range 0..%d" +msgstr "Parameternummer %d ist außerhalb des zulässigen Bereichs 0..%d" + +#: fe-exec.c:3699 +#, c-format +msgid "could not interpret result from server: %s" +msgstr "konnte Ergebnis vom Server nicht interpretieren: %s" + +#: fe-exec.c:3964 fe-exec.c:4054 +#, c-format +msgid "incomplete multibyte character" +msgstr "unvollständiges Mehrbyte-Zeichen" + +#: fe-gssapi-common.c:122 +msgid "GSSAPI name import error" +msgstr "GSSAPI-Namensimportfehler" + +#: fe-lobj.c:144 fe-lobj.c:207 fe-lobj.c:397 fe-lobj.c:487 fe-lobj.c:560 +#: fe-lobj.c:956 fe-lobj.c:963 fe-lobj.c:970 fe-lobj.c:977 fe-lobj.c:984 +#: fe-lobj.c:991 fe-lobj.c:998 fe-lobj.c:1005 +#, c-format +msgid "cannot determine OID of function %s" +msgstr "kann OID der Funktion %s nicht ermitteln" + +#: fe-lobj.c:160 +#, c-format +msgid "argument of lo_truncate exceeds integer range" +msgstr "Argument von lo_truncate überschreitet Bereich für ganze Zahlen" + +#: fe-lobj.c:262 +#, c-format +msgid "argument of lo_read exceeds integer range" +msgstr "Argument von lo_read überschreitet Bereich für ganze Zahlen" + +#: fe-lobj.c:313 +#, c-format +msgid "argument of lo_write exceeds integer range" +msgstr "Argument von lo_write überschreitet Bereich für ganze Zahlen" + +#: fe-lobj.c:669 fe-lobj.c:780 +#, c-format +msgid "could not open file \"%s\": %s" +msgstr "konnte Datei »%s« nicht öffnen: %s" + +#: fe-lobj.c:725 +#, c-format +msgid "could not read from file \"%s\": %s" +msgstr "konnte nicht aus Datei »%s« lesen: %s" + +#: fe-lobj.c:801 fe-lobj.c:824 +#, c-format +msgid "could not write to file \"%s\": %s" +msgstr "konnte nicht in Datei »%s« schreiben: %s" + +#: fe-lobj.c:908 +#, c-format +msgid "query to initialize large object functions did not return data" +msgstr "Abfrage zur Initialisierung der Large-Object-Funktionen ergab keine Daten" + +#: fe-misc.c:240 +#, c-format +msgid "integer of size %lu not supported by pqGetInt" +msgstr "Integer der Größe %lu wird von pqGetInt nicht unterstützt" + +#: fe-misc.c:273 +#, c-format +msgid "integer of size %lu not supported by pqPutInt" +msgstr "Integer der Größe %lu wird von pqPutInt nicht unterstützt" + +#: fe-misc.c:573 +#, c-format +msgid "connection not open" +msgstr "Verbindung nicht offen" + +#: fe-misc.c:751 fe-secure-openssl.c:215 fe-secure-openssl.c:315 +#: fe-secure.c:257 fe-secure.c:419 +#, c-format +msgid "" +"server closed the connection unexpectedly\n" +"\tThis probably means the server terminated abnormally\n" +"\tbefore or while processing the request." +msgstr "" +"Server beendete die Verbindung unerwartet\n" +"\tDas heißt wahrscheinlich, dass der Server abnormal beendete\n" +"\tbevor oder während die Anweisung bearbeitet wurde." + +#: fe-misc.c:818 +msgid "connection not open\n" +msgstr "Verbindung nicht offen\n" + +#: fe-misc.c:1003 +#, c-format +msgid "timeout expired" +msgstr "Timeout abgelaufen" + +#: fe-misc.c:1047 +#, c-format +msgid "invalid socket" +msgstr "ungültiges Socket" + +#: fe-misc.c:1069 +#, c-format +msgid "%s() failed: %s" +msgstr "%s() fehlgeschlagen: %s" + +#: fe-protocol3.c:182 +#, c-format +msgid "message type 0x%02x arrived from server while idle" +msgstr "Nachricht vom Typ 0x%02x kam vom Server im Ruhezustand" + +#: fe-protocol3.c:385 +#, c-format +msgid "server sent data (\"D\" message) without prior row description (\"T\" message)" +msgstr "Server sendete Daten (»D«-Nachricht) ohne vorherige Zeilenbeschreibung (»T«-Nachricht)" + +#: fe-protocol3.c:427 +#, c-format +msgid "unexpected response from server; first received character was \"%c\"" +msgstr "unerwartete Antwort vom Server; erstes empfangenes Zeichen war »%c«" + +#: fe-protocol3.c:450 +#, c-format +msgid "message contents do not agree with length in message type \"%c\"" +msgstr "Nachrichteninhalt stimmt nicht mit Länge in Nachrichtentyp »%c« überein" + +#: fe-protocol3.c:468 +#, c-format +msgid "lost synchronization with server: got message type \"%c\", length %d" +msgstr "Synchronisation mit Server verloren: Nachrichtentyp »%c« empfangen, Länge %d" + +#: fe-protocol3.c:520 fe-protocol3.c:560 +msgid "insufficient data in \"T\" message" +msgstr "nicht genug Daten in »T«-Nachricht" + +#: fe-protocol3.c:631 fe-protocol3.c:837 +msgid "out of memory for query result" +msgstr "Speicher für Anfrageergebnis aufgebraucht" + +#: fe-protocol3.c:700 +msgid "insufficient data in \"t\" message" +msgstr "nicht genug Daten in »t«-Nachricht" + +#: fe-protocol3.c:759 fe-protocol3.c:791 fe-protocol3.c:809 +msgid "insufficient data in \"D\" message" +msgstr "nicht genug Daten in »D«-Nachricht" + +#: fe-protocol3.c:765 +msgid "unexpected field count in \"D\" message" +msgstr "unerwartete Feldzahl in »D«-Nachricht" + +#: fe-protocol3.c:1020 +msgid "no error message available\n" +msgstr "keine Fehlermeldung verfügbar\n" + +#. translator: %s represents a digit string +#: fe-protocol3.c:1068 fe-protocol3.c:1087 +#, c-format +msgid " at character %s" +msgstr " bei Zeichen %s" + +#: fe-protocol3.c:1100 +#, c-format +msgid "DETAIL: %s\n" +msgstr "DETAIL: %s\n" + +#: fe-protocol3.c:1103 +#, c-format +msgid "HINT: %s\n" +msgstr "TIP: %s\n" + +#: fe-protocol3.c:1106 +#, c-format +msgid "QUERY: %s\n" +msgstr "ANFRAGE: %s\n" + +#: fe-protocol3.c:1113 +#, c-format +msgid "CONTEXT: %s\n" +msgstr "KONTEXT: %s\n" + +#: fe-protocol3.c:1122 +#, c-format +msgid "SCHEMA NAME: %s\n" +msgstr "SCHEMANAME: %s\n" + +#: fe-protocol3.c:1126 +#, c-format +msgid "TABLE NAME: %s\n" +msgstr "TABELLENNAME: %s\n" + +#: fe-protocol3.c:1130 +#, c-format +msgid "COLUMN NAME: %s\n" +msgstr "SPALTENNAME: %s\n" + +#: fe-protocol3.c:1134 +#, c-format +msgid "DATATYPE NAME: %s\n" +msgstr "DATENTYPNAME: %s\n" + +#: fe-protocol3.c:1138 +#, c-format +msgid "CONSTRAINT NAME: %s\n" +msgstr "CONSTRAINT-NAME: %s\n" + +#: fe-protocol3.c:1150 +msgid "LOCATION: " +msgstr "ORT: " + +#: fe-protocol3.c:1152 +#, c-format +msgid "%s, " +msgstr "%s, " + +#: fe-protocol3.c:1154 +#, c-format +msgid "%s:%s" +msgstr "%s:%s" + +#: fe-protocol3.c:1349 +#, c-format +msgid "LINE %d: " +msgstr "ZEILE %d: " + +#: fe-protocol3.c:1423 +#, c-format +msgid "protocol version not supported by server: client uses %u.%u, server supports up to %u.%u" +msgstr "Protokollversion nicht vom Server unterstützt: Client verwendet %u.%u, Server unterstützt bis %u.%u" + +#: fe-protocol3.c:1429 +#, c-format +msgid "protocol extension not supported by server: %s" +msgid_plural "protocol extensions not supported by server: %s" +msgstr[0] "Protokollerweiterung nicht vom Server unterstützt: %s" +msgstr[1] "Protokollerweiterungen nicht vom Server unterstützt: %s" + +#: fe-protocol3.c:1437 +#, c-format +msgid "invalid %s message" +msgstr "ungültige %s-Nachricht" + +#: fe-protocol3.c:1802 +#, c-format +msgid "PQgetline: not doing text COPY OUT" +msgstr "PQgetline: Text COPY OUT nicht ausgeführt" + +#: fe-protocol3.c:2176 +#, c-format +msgid "protocol error: no function result" +msgstr "Protokollfehler: kein Funktionsergebnis" + +#: fe-protocol3.c:2187 +#, c-format +msgid "protocol error: id=0x%x" +msgstr "Protokollfehler: id=0x%x" + +#: fe-secure-common.c:123 +#, c-format +msgid "SSL certificate's name contains embedded null" +msgstr "Name im SSL-Zertifikat enthält Null-Byte" + +#: fe-secure-common.c:228 +#, c-format +msgid "certificate contains IP address with invalid length %zu" +msgstr "Zertifikat enthält IP-Adresse mit ungültiger Länge %zu" + +#: fe-secure-common.c:237 +#, c-format +msgid "could not convert certificate's IP address to string: %s" +msgstr "konnte IP-Adresse des Zertifikats nicht in Zeichenkette umwandeln: %s" + +#: fe-secure-common.c:269 +#, c-format +msgid "host name must be specified for a verified SSL connection" +msgstr "Hostname muss angegeben werden für eine verifizierte SSL-Verbindung" + +#: fe-secure-common.c:286 +#, c-format +msgid "server certificate for \"%s\" (and %d other name) does not match host name \"%s\"" +msgid_plural "server certificate for \"%s\" (and %d other names) does not match host name \"%s\"" +msgstr[0] "Server-Zertifikat für »%s« (und %d anderen Namen) stimmt nicht mit dem Hostnamen »%s« überein" +msgstr[1] "Server-Zertifikat für »%s« (und %d andere Namen) stimmt nicht mit dem Hostnamen »%s« überein" + +#: fe-secure-common.c:294 +#, c-format +msgid "server certificate for \"%s\" does not match host name \"%s\"" +msgstr "Server-Zertifikat für »%s« stimmt nicht mit dem Hostnamen »%s« überein" + +#: fe-secure-common.c:299 +#, c-format +msgid "could not get server's host name from server certificate" +msgstr "konnte Hostnamen des Servers nicht aus dem Serverzertifikat ermitteln" + +#: fe-secure-gssapi.c:201 +msgid "GSSAPI wrap error" +msgstr "GSSAPI-Wrap-Fehler" + +#: fe-secure-gssapi.c:208 +#, c-format +msgid "outgoing GSSAPI message would not use confidentiality" +msgstr "ausgehende GSSAPI-Nachricht würde keine Vertraulichkeit verwenden" + +#: fe-secure-gssapi.c:215 +#, c-format +msgid "client tried to send oversize GSSAPI packet (%zu > %zu)" +msgstr "Client versuchte übergroßes GSSAPI-Paket zu senden (%zu > %zu)" + +#: fe-secure-gssapi.c:351 fe-secure-gssapi.c:593 +#, c-format +msgid "oversize GSSAPI packet sent by the server (%zu > %zu)" +msgstr "übergroßes GSSAPI-Paket vom Server gesendet (%zu > %zu)" + +#: fe-secure-gssapi.c:390 +msgid "GSSAPI unwrap error" +msgstr "GSSAPI-Unwrap-Fehler" + +#: fe-secure-gssapi.c:399 +#, c-format +msgid "incoming GSSAPI message did not use confidentiality" +msgstr "eingehende GSSAPI-Nachricht verwendete keine Vertraulichkeit" + +#: fe-secure-gssapi.c:656 +msgid "could not initiate GSSAPI security context" +msgstr "konnte GSSAPI-Sicherheitskontext nicht initiieren" + +#: fe-secure-gssapi.c:685 +msgid "GSSAPI size check error" +msgstr "GSSAPI-Fehler bei der Größenprüfung" + +#: fe-secure-gssapi.c:696 +msgid "GSSAPI context establishment error" +msgstr "GSSAPI-Fehler beim Einrichten des Kontexts" + +#: fe-secure-openssl.c:219 fe-secure-openssl.c:319 fe-secure-openssl.c:1531 +#, c-format +msgid "SSL SYSCALL error: %s" +msgstr "SSL-SYSCALL-Fehler: %s" + +#: fe-secure-openssl.c:225 fe-secure-openssl.c:325 fe-secure-openssl.c:1534 +#, c-format +msgid "SSL SYSCALL error: EOF detected" +msgstr "SSL-SYSCALL-Fehler: Dateiende entdeckt" + +#: fe-secure-openssl.c:235 fe-secure-openssl.c:335 fe-secure-openssl.c:1542 +#, c-format +msgid "SSL error: %s" +msgstr "SSL-Fehler: %s" + +#: fe-secure-openssl.c:249 fe-secure-openssl.c:349 +#, c-format +msgid "SSL connection has been closed unexpectedly" +msgstr "SSL-Verbindung wurde unerwartet geschlossen" + +#: fe-secure-openssl.c:254 fe-secure-openssl.c:354 fe-secure-openssl.c:1589 +#, c-format +msgid "unrecognized SSL error code: %d" +msgstr "unbekannter SSL-Fehlercode: %d" + +#: fe-secure-openssl.c:397 +#, c-format +msgid "could not determine server certificate signature algorithm" +msgstr "konnte Signaturalgorithmus des Serverzertifikats nicht ermitteln" + +#: fe-secure-openssl.c:417 +#, c-format +msgid "could not find digest for NID %s" +msgstr "konnte Digest für NID %s nicht finden" + +#: fe-secure-openssl.c:426 +#, c-format +msgid "could not generate peer certificate hash" +msgstr "konnte Hash des Zertifikats der Gegenstelle nicht erzeugen" + +#: fe-secure-openssl.c:509 +#, c-format +msgid "SSL certificate's name entry is missing" +msgstr "Namenseintrag fehlt im SSL-Zertifikat" + +#: fe-secure-openssl.c:543 +#, c-format +msgid "SSL certificate's address entry is missing" +msgstr "Adresseintrag fehlt im SSL-Zertifikat" + +#: fe-secure-openssl.c:960 +#, c-format +msgid "could not create SSL context: %s" +msgstr "konnte SSL-Kontext nicht erzeugen: %s" + +#: fe-secure-openssl.c:1002 +#, c-format +msgid "invalid value \"%s\" for minimum SSL protocol version" +msgstr "ungültiger Wert »%s« für minimale SSL-Protokollversion" + +#: fe-secure-openssl.c:1012 +#, c-format +msgid "could not set minimum SSL protocol version: %s" +msgstr "konnte minimale SSL-Protokollversion nicht setzen: %s" + +#: fe-secure-openssl.c:1028 +#, c-format +msgid "invalid value \"%s\" for maximum SSL protocol version" +msgstr "ungültiger Wert »%s« für maximale SSL-Protokollversion" + +#: fe-secure-openssl.c:1038 +#, c-format +msgid "could not set maximum SSL protocol version: %s" +msgstr "konnte maximale SSL-Protokollversion nicht setzen: %s" + +#: fe-secure-openssl.c:1076 +#, c-format +msgid "could not load system root certificate paths: %s" +msgstr "konnte System-Root-Zertifikat-Pfade nicht laden: %s" + +#: fe-secure-openssl.c:1093 +#, c-format +msgid "could not read root certificate file \"%s\": %s" +msgstr "konnte Root-Zertifikat-Datei »%s« nicht lesen: %s" + +#: fe-secure-openssl.c:1145 +#, c-format +msgid "" +"could not get home directory to locate root certificate file\n" +"Either provide the file, use the system's trusted roots with sslrootcert=system, or change sslmode to disable server certificate verification." +msgstr "" +"konnte Home-Verzeichnis nicht ermitteln, um Root-Zertifikat-Datei zu finden\n" +"Legen Sie entweder die Datei an, verwenden Sie die vertrauenswürdigen Roots des Systems mit sslrootcert=system, oder ändern Sie sslmode, um die Überprüfung der Serverzertifikate abzuschalten." + +#: fe-secure-openssl.c:1148 +#, c-format +msgid "" +"root certificate file \"%s\" does not exist\n" +"Either provide the file, use the system's trusted roots with sslrootcert=system, or change sslmode to disable server certificate verification." +msgstr "" +"Root-Zertifikat-Datei »%s« existiert nicht\n" +"Legen Sie entweder die Datei an, verwenden Sie die vertrauenswürdigen Roots des Systems mit sslrootcert=system, oder ändern Sie sslmode, um die Überprüfung der Serverzertifikate abzuschalten." + +#: fe-secure-openssl.c:1183 +#, c-format +msgid "could not open certificate file \"%s\": %s" +msgstr "konnte Zertifikatdatei »%s« nicht öffnen: %s" + +#: fe-secure-openssl.c:1201 +#, c-format +msgid "could not read certificate file \"%s\": %s" +msgstr "konnte Zertifikatdatei »%s« nicht lesen: %s" + +#: fe-secure-openssl.c:1225 +#, c-format +msgid "could not establish SSL connection: %s" +msgstr "konnte SSL-Verbindung nicht aufbauen: %s" + +#: fe-secure-openssl.c:1257 +#, c-format +msgid "could not set SSL Server Name Indication (SNI): %s" +msgstr "konnte SSL-Server-Name-Indication (SNI) nicht setzen: %s" + +#: fe-secure-openssl.c:1300 +#, c-format +msgid "could not load SSL engine \"%s\": %s" +msgstr "konnte SSL-Engine »%s« nicht laden: %s" + +#: fe-secure-openssl.c:1311 +#, c-format +msgid "could not initialize SSL engine \"%s\": %s" +msgstr "konnte SSL-Engine »%s« nicht initialisieren: %s" + +#: fe-secure-openssl.c:1326 +#, c-format +msgid "could not read private SSL key \"%s\" from engine \"%s\": %s" +msgstr "konnte privaten SSL-Schlüssel »%s« nicht von Engine »%s« lesen: %s" + +#: fe-secure-openssl.c:1339 +#, c-format +msgid "could not load private SSL key \"%s\" from engine \"%s\": %s" +msgstr "konnte privaten SSL-Schlüssel »%s« nicht von Engine »%s« laden: %s" + +#: fe-secure-openssl.c:1376 +#, c-format +msgid "certificate present, but not private key file \"%s\"" +msgstr "Zertifikat vorhanden, aber keine private Schlüsseldatei »%s«" + +#: fe-secure-openssl.c:1379 +#, c-format +msgid "could not stat private key file \"%s\": %m" +msgstr "konnte »stat« für private Schlüsseldatei »%s« nicht ausführen: %m" + +#: fe-secure-openssl.c:1387 +#, c-format +msgid "private key file \"%s\" is not a regular file" +msgstr "private Schlüsseldatei »%s« ist keine normale Datei" + +#: fe-secure-openssl.c:1420 +#, c-format +msgid "private key file \"%s\" has group or world access; file must have permissions u=rw (0600) or less if owned by the current user, or permissions u=rw,g=r (0640) or less if owned by root" +msgstr "private Schlüsseldatei »%s« erlaubt Lesezugriff für Gruppe oder Andere; Dateirechte müssen u=rw (0600) oder weniger sein, wenn der Eigentümer der aktuelle Benutzer ist, oder u=rw,g=r (0640) oder weniger, wenn der Eigentümer »root« ist" + +#: fe-secure-openssl.c:1444 +#, c-format +msgid "could not load private key file \"%s\": %s" +msgstr "konnte private Schlüsseldatei »%s« nicht laden: %s" + +#: fe-secure-openssl.c:1460 +#, c-format +msgid "certificate does not match private key file \"%s\": %s" +msgstr "Zertifikat passt nicht zur privaten Schlüsseldatei »%s«: %s" + +#: fe-secure-openssl.c:1528 +#, c-format +msgid "SSL error: certificate verify failed: %s" +msgstr "SSL-Fehler: Zertifikatsüberprüfung fehlgeschlagen: %s" + +#: fe-secure-openssl.c:1573 +#, c-format +msgid "This may indicate that the server does not support any SSL protocol version between %s and %s." +msgstr "Das zeigt möglicherweise an, dass der Server keine SSL-Protokollversion zwischen %s und %s unterstützt." + +#: fe-secure-openssl.c:1606 +#, c-format +msgid "certificate could not be obtained: %s" +msgstr "Zertifikat konnte nicht ermittelt werden: %s" + +#: fe-secure-openssl.c:1711 +#, c-format +msgid "no SSL error reported" +msgstr "kein SSL-Fehler berichtet" + +#: fe-secure-openssl.c:1720 +#, c-format +msgid "SSL error code %lu" +msgstr "SSL-Fehlercode %lu" + +#: fe-secure-openssl.c:1986 +#, c-format +msgid "WARNING: sslpassword truncated\n" +msgstr "WARNUNG: sslpassword abgeschnitten\n" + +#: fe-secure.c:263 +#, c-format +msgid "could not receive data from server: %s" +msgstr "konnte keine Daten vom Server empfangen: %s" + +#: fe-secure.c:434 +#, c-format +msgid "could not send data to server: %s" +msgstr "konnte keine Daten an den Server senden: %s" + +#: win32.c:310 +#, c-format +msgid "unrecognized socket error: 0x%08X/%d" +msgstr "unbekannter Socket-Fehler: 0x%08X/%d" diff --git a/src/interfaces/libpq/po/el.po b/src/interfaces/libpq/po/el.po new file mode 100644 index 0000000..d957fe8 --- /dev/null +++ b/src/interfaces/libpq/po/el.po @@ -0,0 +1,1587 @@ +# Greek message translation file for libpq +# Copyright (C) 2021 PostgreSQL Global Development Group +# This file is distributed under the same license as the libpq (PostgreSQL) package. +# Georgios Kokolatos <gkokolatos@pm.me>, 2021 +# +# +# +msgid "" +msgstr "" +"Project-Id-Version: libpq (PostgreSQL) 15\n" +"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" +"POT-Creation-Date: 2023-08-14 23:10+0000\n" +"PO-Revision-Date: 2023-08-15 11:46+0200\n" +"Last-Translator: Georgios Kokolatos <gkokolatos@pm.me>\n" +"Language-Team: \n" +"Language: el\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 3.3.2\n" + +#: ../../port/thread.c:50 ../../port/thread.c:86 +#, c-format +msgid "could not look up local user ID %d: %s" +msgstr "δεν ήταν δυνατή η αναζήτηση ID τοπικού χρήστη %d: %s" + +#: ../../port/thread.c:55 ../../port/thread.c:91 +#, c-format +msgid "local user with ID %d does not exist" +msgstr "δεν υπάρχει τοπικός χρήστης με ID %d" + +#: fe-auth-scram.c:227 +#, c-format +msgid "malformed SCRAM message (empty message)" +msgstr "κακοσχηματισμένο μήνυμα SCRAM (κενό μήνυμα)" + +#: fe-auth-scram.c:232 +#, c-format +msgid "malformed SCRAM message (length mismatch)" +msgstr "κακοσχηματισμένο μήνυμα SCRAM (αναντιστοιχία μήκους)" + +#: fe-auth-scram.c:275 +#, c-format +msgid "could not verify server signature: %s" +msgstr "δεν ήταν δυνατή πιστοποίηση της υπογραφής του διακομιστή: %s" + +#: fe-auth-scram.c:281 +#, c-format +msgid "incorrect server signature" +msgstr "λανθασμένη υπογραφή διακομιστή" + +#: fe-auth-scram.c:290 +#, c-format +msgid "invalid SCRAM exchange state" +msgstr "άκυρη κατάσταση ανταλλαγής SCRAM" + +#: fe-auth-scram.c:317 +#, c-format +msgid "malformed SCRAM message (attribute \"%c\" expected)" +msgstr "κακοσχηματισμένο μήνυμα SCRAM (αναμένεται χαρακτηριστικό «%c»)" + +#: fe-auth-scram.c:326 +#, c-format +msgid "malformed SCRAM message (expected character \"=\" for attribute \"%c\")" +msgstr "κακοσχηματισμένο μήνυμα SCRAM (αναμένεται χαρακτήρας «=» για το χαρακτηριστικό «%c»)" + +#: fe-auth-scram.c:366 +#, c-format +msgid "could not generate nonce" +msgstr "δεν δύναται να δημιουργήσει nonce" + +#: fe-auth-scram.c:375 fe-auth-scram.c:448 fe-auth-scram.c:600 +#: fe-auth-scram.c:620 fe-auth-scram.c:644 fe-auth-scram.c:658 +#: fe-auth-scram.c:704 fe-auth-scram.c:740 fe-auth-scram.c:914 fe-auth.c:296 +#: fe-auth.c:369 fe-auth.c:403 fe-auth.c:618 fe-auth.c:729 fe-auth.c:1210 +#: fe-auth.c:1375 fe-connect.c:925 fe-connect.c:1759 fe-connect.c:1921 +#: fe-connect.c:3291 fe-connect.c:4496 fe-connect.c:5161 fe-connect.c:5416 +#: fe-connect.c:5534 fe-connect.c:5781 fe-connect.c:5861 fe-connect.c:5959 +#: fe-connect.c:6210 fe-connect.c:6237 fe-connect.c:6313 fe-connect.c:6336 +#: fe-connect.c:6360 fe-connect.c:6395 fe-connect.c:6481 fe-connect.c:6489 +#: fe-connect.c:6846 fe-connect.c:6996 fe-exec.c:527 fe-exec.c:1321 +#: fe-exec.c:3111 fe-exec.c:4071 fe-exec.c:4235 fe-gssapi-common.c:109 +#: fe-lobj.c:870 fe-protocol3.c:204 fe-protocol3.c:228 fe-protocol3.c:256 +#: fe-protocol3.c:273 fe-protocol3.c:353 fe-protocol3.c:720 fe-protocol3.c:959 +#: fe-protocol3.c:1770 fe-protocol3.c:2170 fe-secure-common.c:110 +#: fe-secure-gssapi.c:500 fe-secure-openssl.c:434 fe-secure-openssl.c:1285 +#, c-format +msgid "out of memory" +msgstr "έλλειψη μνήμης" + +#: fe-auth-scram.c:382 +#, c-format +msgid "could not encode nonce" +msgstr "δεν δύναται να κωδικοποιήσει nonce" + +#: fe-auth-scram.c:570 +#, c-format +msgid "could not calculate client proof: %s" +msgstr "δεν μπόρεσε να υπολογίσει την απόδειξη του πελάτη: %s" + +#: fe-auth-scram.c:585 +#, c-format +msgid "could not encode client proof" +msgstr "δεν δύναται να κωδικοποιήσει την απόδειξη του πελάτη" + +#: fe-auth-scram.c:637 +#, c-format +msgid "invalid SCRAM response (nonce mismatch)" +msgstr "μη έγκυρη απόκριση SCRAM (ασυμφωνία nonce)" + +#: fe-auth-scram.c:667 +#, c-format +msgid "malformed SCRAM message (invalid salt)" +msgstr "κακοσχηματισμένο μήνυμα SCRAM (άκυρο salt)" + +#: fe-auth-scram.c:680 +#, c-format +msgid "malformed SCRAM message (invalid iteration count)" +msgstr "κακοσχηματισμένο μήνυμα SCRAM (άκυρη μέτρηση επαναλήψεων)" + +#: fe-auth-scram.c:685 +#, c-format +msgid "malformed SCRAM message (garbage at end of server-first-message)" +msgstr "κακοσχηματισμένο μήνυμα SCRAM (σκουπίδια στο τέλος του πρώτου-μηνύματος-διακομιστή)" + +#: fe-auth-scram.c:719 +#, c-format +msgid "error received from server in SCRAM exchange: %s" +msgstr "ελήφθει σφάλμα από τον διακομιστή κατά την ανταλλαγή SCRAM: %s" + +#: fe-auth-scram.c:734 +#, c-format +msgid "malformed SCRAM message (garbage at end of server-final-message)" +msgstr "κακοσχηματισμένο μήνυμα SCRAM (σκουπίδια στο τέλος του τελικού-μηνύματος-διακομιστή)" + +#: fe-auth-scram.c:751 +#, c-format +msgid "malformed SCRAM message (invalid server signature)" +msgstr "κακοσχηματισμένο μήνυμα SCRAM (άκυρη υπογραφή διακομιστή)" + +#: fe-auth-scram.c:923 +msgid "could not generate random salt" +msgstr "δεν δύναται να δημιουργήσει τυχαίο salt" + +#: fe-auth.c:77 +#, c-format +msgid "out of memory allocating GSSAPI buffer (%d)" +msgstr "η μνήμη δεν επαρκεί για την εκχώρηση της ενδιάμεσης μνήμης του GSSAPI (%d)" + +#: fe-auth.c:138 +msgid "GSSAPI continuation error" +msgstr "σφάλμα συνέχισης GSSAPI" + +#: fe-auth.c:168 fe-auth.c:397 fe-gssapi-common.c:97 fe-secure-common.c:99 +#: fe-secure-common.c:173 +#, c-format +msgid "host name must be specified" +msgstr "πρέπει να καθοριστεί το όνομα κεντρικού υπολογιστή" + +#: fe-auth.c:174 +#, c-format +msgid "duplicate GSS authentication request" +msgstr "διπλότυπη αίτηση ελέγχου ταυτότητας GSS" + +#: fe-auth.c:238 +#, c-format +msgid "out of memory allocating SSPI buffer (%d)" +msgstr "η μνήμη δεν επαρκεί για την εκχώρηση της ενδιάμεσης μνήμης του SSPI (%d)" + +#: fe-auth.c:285 +msgid "SSPI continuation error" +msgstr "σφάλμα συνέχισης SSPI" + +#: fe-auth.c:359 +#, c-format +msgid "duplicate SSPI authentication request" +msgstr "διπλότυπη αίτηση ελέγχου ταυτότητας SSPI" + +#: fe-auth.c:384 +msgid "could not acquire SSPI credentials" +msgstr "δεν δύναται η απόκτηση διαπιστευτηρίων SSPI" + +#: fe-auth.c:437 +#, c-format +msgid "channel binding required, but SSL not in use" +msgstr "απαιτείται σύνδεση καναλιού, αλλά δεν χρησιμοποιείται SSL" + +#: fe-auth.c:443 +#, c-format +msgid "duplicate SASL authentication request" +msgstr "διπλότυπη αίτηση ελέγχου ταυτότητας SASL" + +#: fe-auth.c:501 +#, c-format +msgid "channel binding is required, but client does not support it" +msgstr "απαιτείται σύνδεση καναλιού, αλλά ο πελάτης δεν την υποστηρίζει" + +#: fe-auth.c:517 +#, c-format +msgid "server offered SCRAM-SHA-256-PLUS authentication over a non-SSL connection" +msgstr "ο διακομιστής προσέφερε έλεγχο ταυτότητας SCRAM-SHA-256-PLUS μέσω σύνδεσης που δεν είναι SSL" + +#: fe-auth.c:531 +#, c-format +msgid "none of the server's SASL authentication mechanisms are supported" +msgstr "δεν υποστηρίζεται κανένας από τους μηχανισμούς ελέγχου ταυτότητας SASL του διακομιστή" + +#: fe-auth.c:538 +#, c-format +msgid "channel binding is required, but server did not offer an authentication method that supports channel binding" +msgstr "απαιτείται σύνδεση καναλιού, αλλά ο διακομιστής δεν προσέφερε καμία μέθοδο ελέγχου ταυτότητας που να υποστηρίζει σύνδεση καναλιού" + +#: fe-auth.c:641 +#, c-format +msgid "out of memory allocating SASL buffer (%d)" +msgstr "η μνήμη δεν επαρκεί για την εκχώρηση της ενδιάμεσης μνήμης του SASL (%d)" + +#: fe-auth.c:665 +#, c-format +msgid "AuthenticationSASLFinal received from server, but SASL authentication was not completed" +msgstr "παραλήφθηκε AuthenticationSASLFinal από το διακομιστή, αλλά ο έλεγχος ταυτότητας SASL δεν έχει ολοκληρωθεί" + +#: fe-auth.c:675 +#, c-format +msgid "no client response found after SASL exchange success" +msgstr "δεν βρέθηκε απάντηση πελάτη μετά την επιτυχία της ανταλλαγής SASL" + +#: fe-auth.c:738 fe-auth.c:745 fe-auth.c:1358 fe-auth.c:1369 +#, c-format +msgid "could not encrypt password: %s" +msgstr "δεν ήταν δυνατή η κρυπτογράφηση του κωδικού πρόσβασης : %s" + +#: fe-auth.c:773 +msgid "server requested a cleartext password" +msgstr "ο διακομιστής απαίτησε έναν κωδικό πρόσβασης καθαρού κειμένου" + +#: fe-auth.c:775 +msgid "server requested a hashed password" +msgstr "ο διακομιστής απαίτησε έναν κατακερματισμένο κωδικό πρόσβασης" + +#: fe-auth.c:778 +msgid "server requested GSSAPI authentication" +msgstr "ο διακομιστής απαίτησε έλεγχο ταυτότητας GSSAPI" + +#: fe-auth.c:780 +msgid "server requested SSPI authentication" +msgstr "ο διακομιστής απαίτησε έλεγχο ταυτότητας SSPI" + +#: fe-auth.c:784 +msgid "server requested SASL authentication" +msgstr "ο διακομιστής απαίτησε έλεγχο ταυτότητας SASL" + +#: fe-auth.c:787 +msgid "server requested an unknown authentication type" +msgstr "ο διακομιστής απαίτησε έναν άγνωστο τύπο ελέγχου ταυτότητας" + +#: fe-auth.c:820 +#, c-format +msgid "server did not request an SSL certificate" +msgstr "ο διακομιστής δεν απαίτησε πιστοποιητικό SSL" + +#: fe-auth.c:825 +#, c-format +msgid "server accepted connection without a valid SSL certificate" +msgstr "ο διακομιστής αποδέχθηκε σύνδεση χωρίς έγκυρο πιστοποιητικό SSL" + +#: fe-auth.c:879 +msgid "server did not complete authentication" +msgstr "ο διακομιστής δεν ολοκλήρωσε την πιστοποίηση" + +#: fe-auth.c:913 +#, c-format +msgid "authentication method requirement \"%s\" failed: %s" +msgstr "η απαιτούμενη μέθοδος πιστοποίησης «%s» απέτυχε: %s" + +#: fe-auth.c:936 +#, c-format +msgid "channel binding required, but server authenticated client without channel binding" +msgstr "απαιτείται σύνδεση καναλιού, αλλά ο διακομιστής πιστοποίησε τον πελάτη χωρίς σύνδεση καναλιού" + +#: fe-auth.c:941 +#, c-format +msgid "channel binding required but not supported by server's authentication request" +msgstr "απαιτείται σύνδεση καναλιού αλλά αυτή δεν υποστηρίζεται από την αίτηση ελέγχου ταυτότητας του διακομιστή" + +#: fe-auth.c:975 +#, c-format +msgid "Kerberos 4 authentication not supported" +msgstr "δεν υποστηρίζεται η μέθοδος πιστοποίησης Kerberos 4" + +#: fe-auth.c:979 +#, c-format +msgid "Kerberos 5 authentication not supported" +msgstr "δεν υποστηρίζεται η μέθοδος πιστοποίησης Kerberos 5" + +#: fe-auth.c:1049 +#, c-format +msgid "GSSAPI authentication not supported" +msgstr "δεν υποστηρίζεται η μέθοδος πιστοποίησης GSSAPI" + +#: fe-auth.c:1080 +#, c-format +msgid "SSPI authentication not supported" +msgstr "δεν υποστηρίζεται η μέθοδος πιστοποίησης SSPI" + +#: fe-auth.c:1087 +#, c-format +msgid "Crypt authentication not supported" +msgstr "δεν υποστηρίζεται η μέθοδος πιστοποίησης Crypt" + +#: fe-auth.c:1151 +#, c-format +msgid "authentication method %u not supported" +msgstr "δεν υποστηρίζεται η μέθοδος πιστοποίησης %u" + +#: fe-auth.c:1197 +#, c-format +msgid "user name lookup failure: error code %lu" +msgstr "αποτυχία αναζήτησης ονόματος χρήστη: κωδικός σφάλματος %lu" + +#: fe-auth.c:1321 +#, c-format +msgid "unexpected shape of result set returned for SHOW" +msgstr "μη αναμενόμενο σχήμα συνόλου αποτελεσμάτων που επιστράφηκε από την εντολή SHOW" + +#: fe-auth.c:1329 +#, c-format +msgid "password_encryption value too long" +msgstr "πολύ μακρυά τιμή password_encryption" + +#: fe-auth.c:1379 +#, c-format +msgid "unrecognized password encryption algorithm \"%s\"" +msgstr "μη αναγνωρίσιμος αλγόριθμος κρυπτογράφησης «%s» κωδικού πρόσβασης" + +#: fe-connect.c:1132 +#, c-format +msgid "could not match %d host names to %d hostaddr values" +msgstr "δεν μπόρεσε να ταιριάξει %d ονομασίες διακομιστών με %d τιμές hostaddr" + +#: fe-connect.c:1212 +#, c-format +msgid "could not match %d port numbers to %d hosts" +msgstr "δεν μπόρεσε να ταιριάξει %d αριθμούς θυρών με %d διακομιστές" + +#: fe-connect.c:1337 +#, c-format +msgid "negative require_auth method \"%s\" cannot be mixed with non-negative methods" +msgstr "η αρνητική μέθοδος require_auth «%s» δεν μπορεί να συνδυαστεί με μη αρνητικές μεθόδους" + +#: fe-connect.c:1350 +#, c-format +msgid "require_auth method \"%s\" cannot be mixed with negative methods" +msgstr "η μέθοδος require_auth «%s» δεν μπορεί να συνδυαστεί με αρνητικές μεθόδους" + +#: fe-connect.c:1410 fe-connect.c:1461 fe-connect.c:1503 fe-connect.c:1559 +#: fe-connect.c:1567 fe-connect.c:1598 fe-connect.c:1644 fe-connect.c:1684 +#: fe-connect.c:1705 +#, c-format +msgid "invalid %s value: \"%s\"" +msgstr "άκυρο %s τιμή: «%s»" + +#: fe-connect.c:1443 +#, c-format +msgid "require_auth method \"%s\" is specified more than once" +msgstr "η μέθοδος require_auth «%s» χρησιμοποιείται περισσότερες από μία φορές" + +#: fe-connect.c:1484 fe-connect.c:1523 fe-connect.c:1606 +#, c-format +msgid "%s value \"%s\" invalid when SSL support is not compiled in" +msgstr "%s τιμή «%s» είναι άκυρη όταν η υποστήριξη SSL δεν έχει μεταγλωττιστεί (compiled)" + +#: fe-connect.c:1546 +#, c-format +msgid "weak sslmode \"%s\" may not be used with sslrootcert=system (use \"verify-full\")" +msgstr "το αδύναμο sslmode «%s» δεν μπορεί να χρησιμοποιηθεί με sslrootcert=system (χρησιμοποιήστε το «verify-full»)" + +#: fe-connect.c:1584 +#, c-format +msgid "invalid SSL protocol version range" +msgstr "άκυρο εύρος εκδόσεων πρωτοκόλλου SSL" + +#: fe-connect.c:1621 +#, c-format +msgid "%s value \"%s\" is not supported (check OpenSSL version)" +msgstr "%s τιμή «%s» δεν υποστοιρίζεται (έλεγξε την έκδοση OpenSSL)" + +#: fe-connect.c:1651 +#, c-format +msgid "gssencmode value \"%s\" invalid when GSSAPI support is not compiled in" +msgstr "η τιμή SSLmode «%s» είναι άκυρη όταν η υποστήριξη GSSAPI δεν έχει μεταγλωττιστεί (compiled)" + +#: fe-connect.c:1944 +#, c-format +msgid "could not set socket to TCP no delay mode: %s" +msgstr "δεν μπόρεσε να ορίσει τον υποδοχέα σε λειτουργία TCP χωρίς καθυστέρηση: %s" + +#: fe-connect.c:2003 +#, c-format +msgid "connection to server on socket \"%s\" failed: " +msgstr "σύνδεση στον διακομιστή στην υποδοχή «%s» απέτυχε: " + +#: fe-connect.c:2029 +#, c-format +msgid "connection to server at \"%s\" (%s), port %s failed: " +msgstr "σύνδεση στον διακομιστή σε «%s» (%s), θύρα %s απέτυχε: " + +#: fe-connect.c:2034 +#, c-format +msgid "connection to server at \"%s\", port %s failed: " +msgstr "σύνδεση στον διακομιστή σε «%s», θύρα %s απέτυχε: " + +#: fe-connect.c:2057 +#, c-format +msgid "\tIs the server running locally and accepting connections on that socket?" +msgstr "\tΕκτελείται τοπικά ο διακομιστής και αποδέχεται συνδέσεις σε αυτή την υποδοχή;" + +#: fe-connect.c:2059 +#, c-format +msgid "\tIs the server running on that host and accepting TCP/IP connections?" +msgstr "\tΕκτελείται ο διακομιστής σε αυτόν τον κεντρικό υπολογιστή και αποδέχεται συνδέσεις TCP/IP;" + +#: fe-connect.c:2122 +#, c-format +msgid "invalid integer value \"%s\" for connection option \"%s\"" +msgstr "άκυρη τιμή ακεραίου »%s» για την επιλογή σύνδεσης «%s»" + +#: fe-connect.c:2151 fe-connect.c:2185 fe-connect.c:2220 fe-connect.c:2318 +#: fe-connect.c:2973 +#, c-format +msgid "%s(%s) failed: %s" +msgstr "%s(%s) απέτυχε: %s" + +#: fe-connect.c:2284 +#, c-format +msgid "%s(%s) failed: error code %d" +msgstr "%s(%s) απέτυχε: κωδικός σφάλματος %d" + +#: fe-connect.c:2597 +#, c-format +msgid "invalid connection state, probably indicative of memory corruption" +msgstr "μη έγκυρη κατάσταση σύνδεσης, πιθανώς ενδεικτική αλλοίωσης μνήμης" + +#: fe-connect.c:2676 +#, c-format +msgid "invalid port number: \"%s\"" +msgstr "μη έγκυρος αριθμός πύλης: «%s»" + +#: fe-connect.c:2690 +#, c-format +msgid "could not translate host name \"%s\" to address: %s" +msgstr "δεν ήταν δυνατή η μετάφραση του ονόματος κεντρικού υπολογιστή «%s» στη διεύθυνση: %s" + +#: fe-connect.c:2702 +#, c-format +msgid "could not parse network address \"%s\": %s" +msgstr "δεν ήταν δυνατή η ανάλυση της διεύθυνσης δικτύου «%s»: %s" + +#: fe-connect.c:2713 +#, c-format +msgid "Unix-domain socket path \"%s\" is too long (maximum %d bytes)" +msgstr "η διαδρομή υποδοχής τομέα Unix «%s» είναι πολύ μακρυά (μέγιστο %d bytes)" + +#: fe-connect.c:2727 +#, c-format +msgid "could not translate Unix-domain socket path \"%s\" to address: %s" +msgstr "δεν ήταν δυνατή η μετάφραση της διαδρομής υποδοχής πεδίου-Unix «%s» στη διεύθυνση: %s" + +#: fe-connect.c:2901 +#, c-format +msgid "could not create socket: %s" +msgstr "δεν ήταν δυνατή η δημιουργία υποδοχέα: %s" + +#: fe-connect.c:2932 +#, c-format +msgid "could not set socket to nonblocking mode: %s" +msgstr "δεν ήταν δυνατή η ρύθμιση της υποδοχής σε λειτουργία μη αποκλεισμού: %s" + +#: fe-connect.c:2943 +#, c-format +msgid "could not set socket to close-on-exec mode: %s" +msgstr "δεν ήταν δυνατή η ρύθμιση της υποδοχής σε λειτουργία close-on-exec: %s" + +#: fe-connect.c:2961 +#, c-format +msgid "keepalives parameter must be an integer" +msgstr "η παράμετρος keepalives πρέπει να είναι ακέραιος" + +#: fe-connect.c:3100 +#, c-format +msgid "could not get socket error status: %s" +msgstr "δεν ήταν δυνατή η απόκτηση κατάστασης σφάλματος της υποδοχής: %s" + +#: fe-connect.c:3127 +#, c-format +msgid "could not get client address from socket: %s" +msgstr "δεν ήταν δυνατή η απόκτηση διεύθυνσης πελάτη από την υποδοχή: %s" + +#: fe-connect.c:3165 +#, c-format +msgid "requirepeer parameter is not supported on this platform" +msgstr "η παράμετρος requirepeer δεν υποστηρίζεται από την παρούσα πλατφόρμα" + +#: fe-connect.c:3167 +#, c-format +msgid "could not get peer credentials: %s" +msgstr "δεν ήταν δυνατή η απόκτηση διαπιστευτηρίων από peer: %s" + +#: fe-connect.c:3180 +#, c-format +msgid "requirepeer specifies \"%s\", but actual peer user name is \"%s\"" +msgstr "το requirepeer καθορίζει «%s», αλλά το πραγματικό όνομα ομότιμου χρήστη είναι «%s»" + +#: fe-connect.c:3221 +#, c-format +msgid "could not send GSSAPI negotiation packet: %s" +msgstr "δεν ήταν δυνατή η αποστολή GSSAPI πακέτου διαπραγμάτευσης: %s" + +#: fe-connect.c:3233 +#, c-format +msgid "GSSAPI encryption required but was impossible (possibly no credential cache, no server support, or using a local socket)" +msgstr "GSSAPI κρυπτογράφηση απαιτείται αλλά ήταν αδύνατη (πιθανώς απουσία cache διαπιστευτηρίων, απουσία υποστήριξης διακομιστή, ή χρησιμοποιείται τοπική υποδοχή)" + +#: fe-connect.c:3274 +#, c-format +msgid "could not send SSL negotiation packet: %s" +msgstr "δεν ήταν δυνατή η αποστολή SSL πακέτου διαπραγμάτευσης: %s" + +#: fe-connect.c:3303 +#, c-format +msgid "could not send startup packet: %s" +msgstr "δεν ήταν δυνατή η αποστολή πακέτου εκκίνησης: %s" + +#: fe-connect.c:3378 +#, c-format +msgid "server does not support SSL, but SSL was required" +msgstr "ο διακομιστής δεν υποστηρίζει SSL, αλλά απαιτείται SSL" + +#: fe-connect.c:3404 +#, c-format +msgid "received invalid response to SSL negotiation: %c" +msgstr "έλαβε μη έγκυρη απάντηση κατά τη διαπραγμάτευση SSL: %c" + +#: fe-connect.c:3424 +#, c-format +msgid "received unencrypted data after SSL response" +msgstr "έλαβε μη κρυπτογραφημένα δεδομένα μετά την απάντηση SSL" + +#: fe-connect.c:3504 +#, c-format +msgid "server doesn't support GSSAPI encryption, but it was required" +msgstr "ο διακομιστής δεν υποστηρίζει κρυπτογράφηση GSSAPI, αλλά αυτή ήταν απαραίτητη" + +#: fe-connect.c:3515 +#, c-format +msgid "received invalid response to GSSAPI negotiation: %c" +msgstr "έλαβε μη έγκυρη απάντηση κατά τη διαπραγμάτευση GSSAPI: %c" + +#: fe-connect.c:3533 +#, c-format +msgid "received unencrypted data after GSSAPI encryption response" +msgstr "λήψη μη κρυπτογραφημένων δεδομένων μετά την απάντηση κρυπτογράφησης GSSAPI" + +#: fe-connect.c:3598 +#, c-format +msgid "expected authentication request from server, but received %c" +msgstr "ανέμενε αίτηση ελέγχου ταυτότητας από το διακομιστή, αλλά αντί αυτής ελήφθη %c" + +#: fe-connect.c:3625 fe-connect.c:3794 +#, c-format +msgid "received invalid authentication request" +msgstr "έλαβε μη έγκυρη αίτηση πιστοποίησης" + +#: fe-connect.c:3630 fe-connect.c:3779 +#, c-format +msgid "received invalid protocol negotiation message" +msgstr "έλαβε μη έγκυρο μήνυμα διαπραγμάτευσης πρωτοκόλλου" + +#: fe-connect.c:3648 fe-connect.c:3702 +#, c-format +msgid "received invalid error message" +msgstr "έλαβε άκυρο μήνυμα σφάλματος" + +#: fe-connect.c:3865 +#, c-format +msgid "unexpected message from server during startup" +msgstr "μη αναμενόμενο μήνυμα από το διακομιστή κατά την εκκίνηση" + +#: fe-connect.c:3956 +#, c-format +msgid "session is read-only" +msgstr "η περίοδος λειτουργίας είναι μόνο για ανάγνωση" + +#: fe-connect.c:3958 +#, c-format +msgid "session is not read-only" +msgstr "η περίοδος λειτουργίας δεν είναι μόνο για ανάγνωση" + +#: fe-connect.c:4011 +#, c-format +msgid "server is in hot standby mode" +msgstr "ο διακομιστής βρίσκεται σε hot κατάσταση αναμονής" + +#: fe-connect.c:4013 +#, c-format +msgid "server is not in hot standby mode" +msgstr "ο διακομιστής δεν βρίσκεται σε hot κατάσταση αναμονής" + +#: fe-connect.c:4129 fe-connect.c:4179 +#, c-format +msgid "\"%s\" failed" +msgstr "«%s» απέτυχε" + +#: fe-connect.c:4193 +#, c-format +msgid "invalid connection state %d, probably indicative of memory corruption" +msgstr "κατάσταση μη έγκυρης σύνδεσης %d, πιθανώς ενδεικτική αλλοίωσης της μνήμης" + +#: fe-connect.c:5174 +#, c-format +msgid "invalid LDAP URL \"%s\": scheme must be ldap://" +msgstr "άκυρη διεύθυνση URL LDAP «%s»: ο συνδυασμός πρέπει να είναι ldap://" + +#: fe-connect.c:5189 +#, c-format +msgid "invalid LDAP URL \"%s\": missing distinguished name" +msgstr "άκυρη διεύθυνση URL LDAP «%s»: λείπει το αποκλειστικό όνομα" + +#: fe-connect.c:5201 fe-connect.c:5259 +#, c-format +msgid "invalid LDAP URL \"%s\": must have exactly one attribute" +msgstr "άκυρη διεύθυνση URL LDAP «%s»: πρέπει να περιέχει ακριβώς ένα χαρακτηριστικό" + +#: fe-connect.c:5213 fe-connect.c:5275 +#, c-format +msgid "invalid LDAP URL \"%s\": must have search scope (base/one/sub)" +msgstr "άκυρη διεύθυνση URL LDAP «%s»: πρέπει να έχει εμβέλεια αναζήτησης (base/one/sub)" + +#: fe-connect.c:5225 +#, c-format +msgid "invalid LDAP URL \"%s\": no filter" +msgstr "άκυρη διεύθυνση URL LDAP «%s»: κανένα φίλτρο" + +#: fe-connect.c:5247 +#, c-format +msgid "invalid LDAP URL \"%s\": invalid port number" +msgstr "άκυρη διεύθυνση URL LDAP «%s»: άκυρος αριθμός θύρας" + +#: fe-connect.c:5284 +#, c-format +msgid "could not create LDAP structure" +msgstr "δεν ήταν δυνατή η δημιουργία δομής LDAP" + +#: fe-connect.c:5359 +#, c-format +msgid "lookup on LDAP server failed: %s" +msgstr "απέτυχε η αναζήτηση στον διακομιστή LDAP: %s" + +#: fe-connect.c:5369 +#, c-format +msgid "more than one entry found on LDAP lookup" +msgstr "βρέθηκαν περισσότερες από μία καταχωρήσεις στην αναζήτηση LDAP" + +#: fe-connect.c:5371 fe-connect.c:5382 +#, c-format +msgid "no entry found on LDAP lookup" +msgstr "δεν βρέθηκε καταχώρηση στην αναζήτηση LDAP" + +#: fe-connect.c:5392 fe-connect.c:5404 +#, c-format +msgid "attribute has no values on LDAP lookup" +msgstr "το χαρακτηριστικό δεν έχει τιμές στην αναζήτηση LDAP" + +#: fe-connect.c:5455 fe-connect.c:5474 fe-connect.c:5998 +#, c-format +msgid "missing \"=\" after \"%s\" in connection info string" +msgstr "λείπει το «=» μετά από «%s» στην συμβολοσειρά πληροφορίας σύνδεσης" + +#: fe-connect.c:5545 fe-connect.c:6181 fe-connect.c:6979 +#, c-format +msgid "invalid connection option \"%s\"" +msgstr "άκυρη επιλογή σύνδεσης «%s»" + +#: fe-connect.c:5560 fe-connect.c:6046 +#, c-format +msgid "unterminated quoted string in connection info string" +msgstr "ατερμάτιστη συμβολοσειρά με εισαγωγικά στην συμβολοσειρά πληροφορίας σύνδεσης" + +#: fe-connect.c:5640 +#, c-format +msgid "definition of service \"%s\" not found" +msgstr "δεν βρέθηκε ο ορισμός της υπηρεσίας «%s»" + +#: fe-connect.c:5666 +#, c-format +msgid "service file \"%s\" not found" +msgstr "δεν βρέθηκε αρχείο υπηρεσίας «%s»" + +#: fe-connect.c:5679 +#, c-format +msgid "line %d too long in service file \"%s\"" +msgstr "πολύ μακρυά γραμμή %d στο αρχείο υπηρεσίας «%s»" + +#: fe-connect.c:5750 fe-connect.c:5793 +#, c-format +msgid "syntax error in service file \"%s\", line %d" +msgstr "συντακτικό σφάλμα στο αρχείο υπηρεσίας «%s», γραμμή %d" + +#: fe-connect.c:5761 +#, c-format +msgid "nested service specifications not supported in service file \"%s\", line %d" +msgstr "οι ένθετες προδιαγραφές υπηρεσίας δεν υποστηρίζονται στο αρχείο υπηρεσίας «%s», γραμμή %d" + +#: fe-connect.c:6500 +#, c-format +msgid "invalid URI propagated to internal parser routine: \"%s\"" +msgstr "μη έγκυρο URI διαδόθηκε στη ρουτίνα εσωτερικής ανάλυσης: «%s»" + +#: fe-connect.c:6577 +#, c-format +msgid "end of string reached when looking for matching \"]\" in IPv6 host address in URI: \"%s\"" +msgstr "έφτασε στο τέλος της συμβολοσειράς κατά την αναζήτηση αντίστοιχου «]» στη διεύθυνση IPv6 κεντρικού υπολογιστή στο URI: «%s»" + +#: fe-connect.c:6584 +#, c-format +msgid "IPv6 host address may not be empty in URI: \"%s\"" +msgstr "η διεύθυνση IPv6 κεντρικού υπολογιστή δεν δύναται να είναι κενή στο URI: «%s»" + +#: fe-connect.c:6599 +#, c-format +msgid "unexpected character \"%c\" at position %d in URI (expected \":\" or \"/\"): \"%s\"" +msgstr "μη αναμενόμενος χαρακτήρας «%c» στη θέση %d του URI (αναμένεται «:» ή «/»): «%s»" + +#: fe-connect.c:6728 +#, c-format +msgid "extra key/value separator \"=\" in URI query parameter: \"%s\"" +msgstr "επιπλέον διαχωριστικό κλειδιού/τιμής «=» στην παράμετρο ερωτήματος URI: «%s»" + +#: fe-connect.c:6748 +#, c-format +msgid "missing key/value separator \"=\" in URI query parameter: \"%s\"" +msgstr "λείπει διαχωριστικό κλειδιού/τιμής «=» στην παράμετρο ερωτήματος URI: «%s»" + +#: fe-connect.c:6800 +#, c-format +msgid "invalid URI query parameter: \"%s\"" +msgstr "άκυρη παράμετρος ερωτήματος URI: «%s»" + +#: fe-connect.c:6874 +#, c-format +msgid "invalid percent-encoded token: \"%s\"" +msgstr "άκυρο διακριτικό με κωδικοποίηση ποσοστού: «%s»" + +#: fe-connect.c:6884 +#, c-format +msgid "forbidden value %%00 in percent-encoded value: \"%s\"" +msgstr "απαγορευμένη τιμή %%00 σε τιμή κωδικοποιημένου ποσοστού: «%s»" + +#: fe-connect.c:7248 +msgid "connection pointer is NULL\n" +msgstr "ο δείκτης σύνδεσης είναι NULL\n" + +#: fe-connect.c:7256 fe-exec.c:710 fe-exec.c:970 fe-exec.c:3292 +#: fe-protocol3.c:974 fe-protocol3.c:1007 +msgid "out of memory\n" +msgstr "έλλειψη μνήμης\n" + +#: fe-connect.c:7547 +#, c-format +msgid "WARNING: password file \"%s\" is not a plain file\n" +msgstr "ΠΡΟΕΙΔΟΠΟΙΗΣΗ: το αρχείο κωδικών πρόσβασης «%s» δεν είναι ένα απλό αρχείο\n" + +#: fe-connect.c:7556 +#, c-format +msgid "WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n" +msgstr "ΠΡΟΕΙΔΟΠΟΙΗΣΗ: το αρχείο κωδικού πρόσβασης «%s» έχει ομαδική ή παγκόσμια πρόσβαση· τα δικαιώματα πρέπει να είναι U=RW (0600) ή λιγότερα\n" + +#: fe-connect.c:7663 +#, c-format +msgid "password retrieved from file \"%s\"" +msgstr "ο κωδικός πρόσβασης ελήφθει από αρχείο «%s»" + +#: fe-exec.c:466 fe-exec.c:3366 +#, c-format +msgid "row number %d is out of range 0..%d" +msgstr "ο αριθμός σειράς %d βρίσκεται εκτός εύρους 0..%d" + +#: fe-exec.c:528 fe-protocol3.c:1976 +#, c-format +msgid "%s" +msgstr "%s" + +#: fe-exec.c:831 +#, c-format +msgid "write to server failed" +msgstr "απέτυχε η εγγραφή στον διακομιστή" + +#: fe-exec.c:869 +#, c-format +msgid "no error text available" +msgstr "κανένα μήνυμα σφάλματος διαθέσιμο" + +#: fe-exec.c:958 +msgid "NOTICE" +msgstr "NOTICE" + +#: fe-exec.c:1016 +msgid "PGresult cannot support more than INT_MAX tuples" +msgstr "το PGresult δεν μπορεί να υποστηρίξει περισσότερες πλείαδες από INT_MAX" + +#: fe-exec.c:1028 +msgid "size_t overflow" +msgstr "υπερχείλιση overflow" + +#: fe-exec.c:1444 fe-exec.c:1513 fe-exec.c:1559 +#, c-format +msgid "command string is a null pointer" +msgstr "η συμβολοσειρά εντολής είναι ένας κενός δείκτης" + +#: fe-exec.c:1450 fe-exec.c:2888 +#, c-format +msgid "%s not allowed in pipeline mode" +msgstr "%s δεν επιτρέπεται σε λειτουργία αγωγού" + +#: fe-exec.c:1518 fe-exec.c:1564 fe-exec.c:1658 +#, c-format +msgid "number of parameters must be between 0 and %d" +msgstr "ο αριθμός των παραμέτρων πρέπει να είναι μεταξύ 0 και %d" + +#: fe-exec.c:1554 fe-exec.c:1653 +#, c-format +msgid "statement name is a null pointer" +msgstr "η ονομασία της δήλωσης είναι ένας κενός δείκτης" + +#: fe-exec.c:1695 fe-exec.c:3220 +#, c-format +msgid "no connection to the server" +msgstr "καμία σύνδεση στον διακομιστή" + +#: fe-exec.c:1703 fe-exec.c:3228 +#, c-format +msgid "another command is already in progress" +msgstr "υπάρχει άλλη εντολή σε πρόοδο" + +#: fe-exec.c:1733 +#, c-format +msgid "cannot queue commands during COPY" +msgstr "δεν είναι δυνατή η ουρά εντολών κατά τη διάρκεια του COPY" + +#: fe-exec.c:1850 +#, c-format +msgid "length must be given for binary parameter" +msgstr "το μήκος πρέπει να περαστεί ως δυαδική παράμετρος" + +#: fe-exec.c:2171 +#, c-format +msgid "unexpected asyncStatus: %d" +msgstr "μη αναμενόμενο asyncStatus: %d" + +#: fe-exec.c:2327 +#, c-format +msgid "synchronous command execution functions are not allowed in pipeline mode" +msgstr "οι συναρτήσεις σύγχρονης εκτέλεσης εντολών δεν επιτρέπονται σε λειτουργία διοχέτευσης" + +#: fe-exec.c:2344 +msgid "COPY terminated by new PQexec" +msgstr "COPY τερματίστηκε από νέο PQexec" + +#: fe-exec.c:2360 +#, c-format +msgid "PQexec not allowed during COPY BOTH" +msgstr "PQexec δεν επιτρέπεται κατά τη διάρκεια COPY BOTH" + +#: fe-exec.c:2586 fe-exec.c:2641 fe-exec.c:2709 fe-protocol3.c:1907 +#, c-format +msgid "no COPY in progress" +msgstr "κανένα COPY σε εξέλιξη" + +#: fe-exec.c:2895 +#, c-format +msgid "connection in wrong state" +msgstr "σύνδεση σε λανθάνουσα κατάσταση" + +#: fe-exec.c:2938 +#, c-format +msgid "cannot enter pipeline mode, connection not idle" +msgstr "δεν ήταν δυνατή η είσοδος σε λειτουργία διοχέτευσης, σύνδεση μη αδρανή" + +#: fe-exec.c:2974 fe-exec.c:2995 +#, c-format +msgid "cannot exit pipeline mode with uncollected results" +msgstr "δεν είναι δυνατή η έξοδος από τη λειτουργία διοχέτευσης με μη λαμβανόμενα αποτελέσματα" + +#: fe-exec.c:2978 +#, c-format +msgid "cannot exit pipeline mode while busy" +msgstr "δεν είναι δυνατή η έξοδος από τη λειτουργία διοχέτευσης ενώ απασχολείται" + +#: fe-exec.c:2989 +#, c-format +msgid "cannot exit pipeline mode while in COPY" +msgstr "δεν μπορεί να εξέλθει από τη λειτουργία αγωγού ενώ βρίσκεται σε COPY" + +#: fe-exec.c:3154 +#, c-format +msgid "cannot send pipeline when not in pipeline mode" +msgstr "δεν είναι δυνατή η αποστολή διοχέτευσης όταν δεν βρίσκεται σε λειτουργία διοχέτευσης" + +#: fe-exec.c:3255 +msgid "invalid ExecStatusType code" +msgstr "άκυρος κωδικός ExecStatusType" + +#: fe-exec.c:3282 +msgid "PGresult is not an error result\n" +msgstr "PGresult δεν είναι ένα αποτέλεσμα σφάλματος\n" + +#: fe-exec.c:3350 fe-exec.c:3373 +#, c-format +msgid "column number %d is out of range 0..%d" +msgstr "αριθμός στήλης %d βρίσκεται εκτός εύρους 0..%d" + +#: fe-exec.c:3388 +#, c-format +msgid "parameter number %d is out of range 0..%d" +msgstr "αριθμός παραμέτρου %d βρίσκεται εκτός εύρους 0..%d" + +#: fe-exec.c:3699 +#, c-format +msgid "could not interpret result from server: %s" +msgstr "δεν μπόρεσε να ερμηνεύσει το αποτέλεσμα από τον διακομιστή: %s" + +#: fe-exec.c:3964 fe-exec.c:4054 +#, c-format +msgid "incomplete multibyte character" +msgstr "ελλιπής χαρακτήρας πολλαπλών byte" + +#: fe-gssapi-common.c:122 +msgid "GSSAPI name import error" +msgstr "σφάλμα εισαγωγής ονόματος GSSAPI" + +#: fe-lobj.c:144 fe-lobj.c:207 fe-lobj.c:397 fe-lobj.c:487 fe-lobj.c:560 +#: fe-lobj.c:956 fe-lobj.c:963 fe-lobj.c:970 fe-lobj.c:977 fe-lobj.c:984 +#: fe-lobj.c:991 fe-lobj.c:998 fe-lobj.c:1005 +#, c-format +msgid "cannot determine OID of function %s" +msgstr "δεν ήταν δυνατός ο προσδιορισμός του OID της συνάρτησης %s" + +#: fe-lobj.c:160 +#, c-format +msgid "argument of lo_truncate exceeds integer range" +msgstr "η παράμετρος του lo_truncate υπερβαίνει το εύρος ακέραιων" + +#: fe-lobj.c:262 +#, c-format +msgid "argument of lo_read exceeds integer range" +msgstr "η παράμετρος του lo_read υπερβαίνει το εύρος ακέραιων" + +#: fe-lobj.c:313 +#, c-format +msgid "argument of lo_write exceeds integer range" +msgstr "η παράμετρος του lo_write υπερβαίνει το εύρος ακέραιων" + +#: fe-lobj.c:669 fe-lobj.c:780 +#, c-format +msgid "could not open file \"%s\": %s" +msgstr "δεν ήταν δυνατό το άνοιγμα του αρχείου «%s»: %s" + +#: fe-lobj.c:725 +#, c-format +msgid "could not read from file \"%s\": %s" +msgstr "δεν ήταν δυνατή η ανάγνωση από το αρχείο «%s»: %s" + +#: fe-lobj.c:801 fe-lobj.c:824 +#, c-format +msgid "could not write to file \"%s\": %s" +msgstr "δεν ήταν δυνατή η εγγραφή στο αρχείο »%s»: %s" + +#: fe-lobj.c:908 +#, c-format +msgid "query to initialize large object functions did not return data" +msgstr "το ερώτημα αρχικοποίησης συναρτήσεων μεγάλων αντικειμένων δεν επέστρεψε δεδομένα" + +#: fe-misc.c:240 +#, c-format +msgid "integer of size %lu not supported by pqGetInt" +msgstr "ακέραιος μεγέθους %lu δεν υποστηρίζεται από pqGetInt" + +#: fe-misc.c:273 +#, c-format +msgid "integer of size %lu not supported by pqPutInt" +msgstr "ακέραιος μεγέθους %lu δεν υποστηρίζεται από pqPutInt" + +#: fe-misc.c:573 +#, c-format +msgid "connection not open" +msgstr "μη ανοικτή σύνδεση" + +#: fe-misc.c:751 fe-secure-openssl.c:215 fe-secure-openssl.c:315 +#: fe-secure.c:257 fe-secure.c:419 +#, c-format +msgid "" +"server closed the connection unexpectedly\n" +"\tThis probably means the server terminated abnormally\n" +"\tbefore or while processing the request." +msgstr "" +"ο διακομιστής έκλεισε απροσδόκητα τη σύνδεση\n" +"\tΑυτό πιθανώς σημαίνει ότι ο διακομιστής τερματίστηκε ασυνήθιστα\n" +"\tπριν ή κατά την επεξεργασία του αιτήματος." + +#: fe-misc.c:818 +msgid "connection not open\n" +msgstr "μη ανοικτή σύνδεση\n" + +#: fe-misc.c:1003 +#, c-format +msgid "timeout expired" +msgstr "έληξε το χρονικό όριο" + +#: fe-misc.c:1047 +#, c-format +msgid "invalid socket" +msgstr "άκυρος υποδοχέας" + +#: fe-misc.c:1069 +#, c-format +msgid "%s() failed: %s" +msgstr "%s() απέτυχε: %s" + +#: fe-protocol3.c:182 +#, c-format +msgid "message type 0x%02x arrived from server while idle" +msgstr "μήνυμα τύπου 0x%02x έφτασε από το διακομιστή ενώ αυτός ήταν αδρανής" + +#: fe-protocol3.c:385 +#, c-format +msgid "server sent data (\"D\" message) without prior row description (\"T\" message)" +msgstr "ο διακομιστής έστειλε δεδομένα («D» μήνυμα) χωρίς προηγούμενη περιγραφή γραμμής («T» μήνυμα)" + +#: fe-protocol3.c:427 +#, c-format +msgid "unexpected response from server; first received character was \"%c\"" +msgstr "μη αναμενόμενη απόκριση από το διακομιστή· πρώτος χαρακτήρας που ελήφθη ήταν «%c»" + +#: fe-protocol3.c:450 +#, c-format +msgid "message contents do not agree with length in message type \"%c\"" +msgstr "τα περιεχόμενα του μηνύματος δεν συμφωνούν με το μήκος του σε τύπο μηνύματος «%c»" + +#: fe-protocol3.c:468 +#, c-format +msgid "lost synchronization with server: got message type \"%c\", length %d" +msgstr "χάθηκε ο συγχρονισμός με το διακομιστή: ελήφθει τύπος μηνύματος «%c», μήκους %d" + +#: fe-protocol3.c:520 fe-protocol3.c:560 +msgid "insufficient data in \"T\" message" +msgstr "ανεπαρκή δεδομένα σε «T» μήνυμα" + +#: fe-protocol3.c:631 fe-protocol3.c:837 +msgid "out of memory for query result" +msgstr "έλλειψη μνήμης για το αποτέλεσμα ερωτήματος" + +#: fe-protocol3.c:700 +msgid "insufficient data in \"t\" message" +msgstr "ανεπαρκή δεδομένα σε «t» μήνυμα" + +#: fe-protocol3.c:759 fe-protocol3.c:791 fe-protocol3.c:809 +msgid "insufficient data in \"D\" message" +msgstr "ανεπαρκή δεδομένα σε «D» μήνυμα" + +#: fe-protocol3.c:765 +msgid "unexpected field count in \"D\" message" +msgstr "μη αναμενόμενο πλήθος πεδίων σε »D» μήνυμα" + +#: fe-protocol3.c:1020 +msgid "no error message available\n" +msgstr "κανένα μήνυμα σφάλματος διαθέσιμο\n" + +#. translator: %s represents a digit string +#: fe-protocol3.c:1068 fe-protocol3.c:1087 +#, c-format +msgid " at character %s" +msgstr " στο χαρακτήρα %s" + +#: fe-protocol3.c:1100 +#, c-format +msgid "DETAIL: %s\n" +msgstr "DETAIL: %s\n" + +#: fe-protocol3.c:1103 +#, c-format +msgid "HINT: %s\n" +msgstr "HINT: %s\n" + +#: fe-protocol3.c:1106 +#, c-format +msgid "QUERY: %s\n" +msgstr "ΕΡΩΤΗΜΑ: %s\n" + +#: fe-protocol3.c:1113 +#, c-format +msgid "CONTEXT: %s\n" +msgstr "CONTEXT: %s\n" + +#: fe-protocol3.c:1122 +#, c-format +msgid "SCHEMA NAME: %s\n" +msgstr "SCHEMA NAME: %s\n" + +#: fe-protocol3.c:1126 +#, c-format +msgid "TABLE NAME: %s\n" +msgstr "TABLE NAME: %s\n" + +#: fe-protocol3.c:1130 +#, c-format +msgid "COLUMN NAME: %s\n" +msgstr "COLUMN NAME: %s\n" + +#: fe-protocol3.c:1134 +#, c-format +msgid "DATATYPE NAME: %s\n" +msgstr "DATATYPE NAME: %s\n" + +#: fe-protocol3.c:1138 +#, c-format +msgid "CONSTRAINT NAME: %s\n" +msgstr "CONSTRAINT NAME: %s\n" + +#: fe-protocol3.c:1150 +msgid "LOCATION: " +msgstr "LOCATION: " + +#: fe-protocol3.c:1152 +#, c-format +msgid "%s, " +msgstr "%s, " + +#: fe-protocol3.c:1154 +#, c-format +msgid "%s:%s" +msgstr "%s: %s" + +#: fe-protocol3.c:1349 +#, c-format +msgid "LINE %d: " +msgstr "ΓΡΑΜΜΗ %d: " + +#: fe-protocol3.c:1423 +#, c-format +msgid "protocol version not supported by server: client uses %u.%u, server supports up to %u.%u" +msgstr "έκδοση πρωτοκόλλου που δεν υποστηρίζεται από τον διακομιστή: ο πελάτης χρησιμοποιεί %u.%u, ο διακομιστής υποστηρίζει έως και %u.%u" + +#: fe-protocol3.c:1429 +#, c-format +msgid "protocol extension not supported by server: %s" +msgid_plural "protocol extensions not supported by server: %s" +msgstr[0] "η επέκταση πρωτοκόλλου δεν υποστηρίζεται από τον διακομιστή: %s" +msgstr[1] "οι επεκτάσεις πρωτοκόλλου δεν υποστηρίζονται από τον διακομιστή: %s" + +#: fe-protocol3.c:1437 +#, c-format +msgid "invalid %s message" +msgstr "μη έγκυρη μήνυμα %s" + +#: fe-protocol3.c:1802 +#, c-format +msgid "PQgetline: not doing text COPY OUT" +msgstr "PQgetline: δεν κάνει το κείμενο COPY OUT" + +#: fe-protocol3.c:2176 +#, c-format +msgid "protocol error: no function result" +msgstr "σφάλμα πρωτοκόλλου: κανένα αποτέλεσμα συνάρτησης" + +#: fe-protocol3.c:2187 +#, c-format +msgid "protocol error: id=0x%x" +msgstr "σφάλμα πρωτοκόλλου: id=0x%x" + +#: fe-secure-common.c:123 +#, c-format +msgid "SSL certificate's name contains embedded null" +msgstr "το όνομα του πιστοποιητικού SSL περιέχει ενσωματωμένο null" + +#: fe-secure-common.c:228 +#, c-format +msgid "certificate contains IP address with invalid length %zu" +msgstr "το πιστοποιητικό περιέχει διεύθυνση IP με μη έγκυρο μήκος %zu" + +#: fe-secure-common.c:237 +#, c-format +msgid "could not convert certificate's IP address to string: %s" +msgstr "δεν μπόρεσε να μετατρέψει τη διεύθυνση IP του πιστοποιητικού σε συμβολοσειρά: %s" + +#: fe-secure-common.c:269 +#, c-format +msgid "host name must be specified for a verified SSL connection" +msgstr "το όνομα κεντρικού υπολογιστή πρέπει να έχει καθοριστεί για μια επαληθευμένη σύνδεση SSL" + +#: fe-secure-common.c:286 +#, c-format +msgid "server certificate for \"%s\" (and %d other name) does not match host name \"%s\"" +msgid_plural "server certificate for \"%s\" (and %d other names) does not match host name \"%s\"" +msgstr[0] "το πιστοποιητικό διακομιστή για το «%s» (όπως και %d άλλο όνομα) δεν ταιριάζει με το όνομα κεντρικού υπολογιστή «%s»" +msgstr[1] "το πιστοποιητικό διακομιστή για το «%s» (όπως και %d άλλα ονόματα) δεν ταιριάζει με το όνομα κεντρικού υπολογιστή «%s»" + +#: fe-secure-common.c:294 +#, c-format +msgid "server certificate for \"%s\" does not match host name \"%s\"" +msgstr "το πιστοποιητικό διακομιστή για το «%s» δεν ταιριάζει με το όνομα κεντρικού υπολογιστή «%s»" + +#: fe-secure-common.c:299 +#, c-format +msgid "could not get server's host name from server certificate" +msgstr "δεν ήταν δυνατή η απόκτηση του όνοματος κεντρικού υπολογιστή του διακομιστή από το πιστοποιητικό διακομιστή" + +#: fe-secure-gssapi.c:201 +msgid "GSSAPI wrap error" +msgstr "σφάλμα αναδίπλωσης GSSAPI" + +#: fe-secure-gssapi.c:208 +#, c-format +msgid "outgoing GSSAPI message would not use confidentiality" +msgstr "το εξερχόμενο μήνυμα GSSAPI δεν θα χρησιμοποιούσε εμπιστευτικότητα" + +#: fe-secure-gssapi.c:215 +#, c-format +msgid "client tried to send oversize GSSAPI packet (%zu > %zu)" +msgstr "ο πελάτης προσπάθησε να στείλει υπερμέγεθες πακέτο GSSAPI (%zu > %zu)" + +#: fe-secure-gssapi.c:351 fe-secure-gssapi.c:593 +#, c-format +msgid "oversize GSSAPI packet sent by the server (%zu > %zu)" +msgstr "ο διακομιστής έστειλε υπερμέγεθες πακέτο GSSAPI (%zu > %zu)" + +#: fe-secure-gssapi.c:390 +msgid "GSSAPI unwrap error" +msgstr "σφάλμα ξεδιπλώσης GSSAPI" + +#: fe-secure-gssapi.c:399 +#, c-format +msgid "incoming GSSAPI message did not use confidentiality" +msgstr "εισερχόμενο μήνυμα GSSAPI δεν χρησιμοποίησε εμπιστευτικότητα" + +#: fe-secure-gssapi.c:656 +msgid "could not initiate GSSAPI security context" +msgstr "δεν ήταν δυνατή η έναρξη περιεχομένου ασφαλείας GSSAPI" + +#: fe-secure-gssapi.c:685 +msgid "GSSAPI size check error" +msgstr "σφάλμα ελέγχου μεγέθους GSSAPI" + +#: fe-secure-gssapi.c:696 +msgid "GSSAPI context establishment error" +msgstr "σφάλμα δημιουργίας περιεχομένου GSSAPI" + +#: fe-secure-openssl.c:219 fe-secure-openssl.c:319 fe-secure-openssl.c:1531 +#, c-format +msgid "SSL SYSCALL error: %s" +msgstr "SSL SYSCALL σφάλμα: %s" + +#: fe-secure-openssl.c:225 fe-secure-openssl.c:325 fe-secure-openssl.c:1534 +#, c-format +msgid "SSL SYSCALL error: EOF detected" +msgstr "SSL SYSCALL σφάλμα: ανιχνεύτηκε EOF" + +#: fe-secure-openssl.c:235 fe-secure-openssl.c:335 fe-secure-openssl.c:1542 +#, c-format +msgid "SSL error: %s" +msgstr "SSL σφάλμα: %s" + +#: fe-secure-openssl.c:249 fe-secure-openssl.c:349 +#, c-format +msgid "SSL connection has been closed unexpectedly" +msgstr "η σύνδεση SSL έκλεισε απροσδόκητα" + +#: fe-secure-openssl.c:254 fe-secure-openssl.c:354 fe-secure-openssl.c:1589 +#, c-format +msgid "unrecognized SSL error code: %d" +msgstr "μη αναγνωρίσιμος κωδικός σφάλματος SSL: %d" + +#: fe-secure-openssl.c:397 +#, c-format +msgid "could not determine server certificate signature algorithm" +msgstr "δεν μπόρεσε να προσδιορίσει τον αλγόριθμο υπογραφής πιστοποιητικού διακομιστή" + +#: fe-secure-openssl.c:417 +#, c-format +msgid "could not find digest for NID %s" +msgstr "δεν μπόρεσε να βρεθεί σύνοψη (digest) για NID %s" + +#: fe-secure-openssl.c:426 +#, c-format +msgid "could not generate peer certificate hash" +msgstr "δεν ήταν δυνατή η δημιουργία ομότιμου πιστοποιητικού hash" + +#: fe-secure-openssl.c:509 +#, c-format +msgid "SSL certificate's name entry is missing" +msgstr "λείπει καταχώρηση ονόματος του πιστοποιητικού SSL" + +#: fe-secure-openssl.c:543 +#, c-format +msgid "SSL certificate's address entry is missing" +msgstr "λείπει καταχώρηση ονόματος του πιστοποιητικού SSL" + +#: fe-secure-openssl.c:960 +#, c-format +msgid "could not create SSL context: %s" +msgstr "δεν ήταν δυνατή η δημιουργία περιεχομένου SSL: %s" + +#: fe-secure-openssl.c:1002 +#, c-format +msgid "invalid value \"%s\" for minimum SSL protocol version" +msgstr "άκυρη τιμή «%s» για την ελάχιστη έκδοση πρωτοκόλλου SSL" + +#: fe-secure-openssl.c:1012 +#, c-format +msgid "could not set minimum SSL protocol version: %s" +msgstr "δεν ήταν δυνατό να ορίσει ελάχιστη έκδοση πρωτοκόλλου SSL: %s" + +#: fe-secure-openssl.c:1028 +#, c-format +msgid "invalid value \"%s\" for maximum SSL protocol version" +msgstr "άκυρη τιμή «%s» για μέγιστη έκδοση πρωτοκόλλου SSL" + +#: fe-secure-openssl.c:1038 +#, c-format +msgid "could not set maximum SSL protocol version: %s" +msgstr "δεν ήταν δυνατό να ορίσει μέγιστη έκδοση πρωτοκόλλου SSL: %s" + +#: fe-secure-openssl.c:1076 +#, c-format +msgid "could not load system root certificate paths: %s" +msgstr "δεν ήταν δυνατή η φόρτωση διαδρομών βασικών αρχείων πιστοποιητικών: %s" + +#: fe-secure-openssl.c:1093 +#, c-format +msgid "could not read root certificate file \"%s\": %s" +msgstr "δεν ήταν δυνατή η ανάγνωση βασικού αρχείου πιστοποιητικού «%s»: %s" + +#: fe-secure-openssl.c:1145 +#, c-format +msgid "" +"could not get home directory to locate root certificate file\n" +"Either provide the file, use the system's trusted roots with sslrootcert=system, or change sslmode to disable server certificate verification." +msgstr "" +"δεν ήταν δυνατή η δημιουργία του προσωπικού καταλόγου για τον εντοπισμό βασικού αρχείου πιστοποιητικού\n" +"Δώστε το αρχείο ή αλλάξτε το sslmode για να απενεργοποιήσετε την επαλήθευση πιστοποιητικού διακομιστή." + +#: fe-secure-openssl.c:1148 +#, c-format +msgid "" +"root certificate file \"%s\" does not exist\n" +"Either provide the file, use the system's trusted roots with sslrootcert=system, or change sslmode to disable server certificate verification." +msgstr "" +"βασικό αρχείο πιστοποιητικού «%s» δεν υπάρχει\n" +"Είτε παρουσιάστε το αρχείο, χρησιμοποιήστε τις επαληθευμένες roots του συστήματος με sslrootcert=system, ή αλλάξτε το sslmode για να απενεργοποιήσετε την επαλήθευση πιστοποιητικού διακομιστή." + +#: fe-secure-openssl.c:1183 +#, c-format +msgid "could not open certificate file \"%s\": %s" +msgstr "δεν ήταν δυνατό το άνοιγμα αρχείου πιστοποιητικού «%s»: %s" + +#: fe-secure-openssl.c:1201 +#, c-format +msgid "could not read certificate file \"%s\": %s" +msgstr "δεν ήταν δυνατή η ανάγνωση αρχείου πιστοποιητικού «%s»: %s" + +#: fe-secure-openssl.c:1225 +#, c-format +msgid "could not establish SSL connection: %s" +msgstr "δεν ήταν δυνατή η δημιουργία σύνδεσης SSL: %s" + +#: fe-secure-openssl.c:1257 +#, c-format +msgid "could not set SSL Server Name Indication (SNI): %s" +msgstr "δεν ήταν δυνατός ο ορισμός SSL Server Name Indication (SNI): %s" + +#: fe-secure-openssl.c:1300 +#, c-format +msgid "could not load SSL engine \"%s\": %s" +msgstr "δεν ήταν δυνατή η φόρτωση της μηχανής SSL «%s»: %s" + +#: fe-secure-openssl.c:1311 +#, c-format +msgid "could not initialize SSL engine \"%s\": %s" +msgstr "δεν ήταν δυνατή η εκκίνηση του κινητήρα SSL «%s»: %s" + +#: fe-secure-openssl.c:1326 +#, c-format +msgid "could not read private SSL key \"%s\" from engine \"%s\": %s" +msgstr "δεν ήταν δυνατή η ανάγνωση του ιδιωτικού κλειδιού SSL «%s» από την μηχανή «%s»: %s" + +#: fe-secure-openssl.c:1339 +#, c-format +msgid "could not load private SSL key \"%s\" from engine \"%s\": %s" +msgstr "δεν ήταν δυνατή η φόρτωση του ιδιωτικού κλειδιού SSL «%s» από την μηχανή «%s»: %s" + +#: fe-secure-openssl.c:1376 +#, c-format +msgid "certificate present, but not private key file \"%s\"" +msgstr "υπάρχει πιστοποιητικό, αλλά όχι αρχείο ιδιωτικού κλειδιού «%s»" + +#: fe-secure-openssl.c:1379 +#, c-format +msgid "could not stat private key file \"%s\": %m" +msgstr "δεν ήταν δυνατή η φόρτωση αρχείου ιδιωτικού κλειδιού «%s»: %m" + +#: fe-secure-openssl.c:1387 +#, c-format +msgid "private key file \"%s\" is not a regular file" +msgstr "το αρχείο ιδιωτικού κλειδιού «%s» δεν είναι κανονικό αρχείο" + +#: fe-secure-openssl.c:1420 +#, c-format +msgid "private key file \"%s\" has group or world access; file must have permissions u=rw (0600) or less if owned by the current user, or permissions u=rw,g=r (0640) or less if owned by root" +msgstr "το αρχείο ιδιωτικού κλειδιού «%s» έχει πρόσβαση σε ομάδα ή κόσμο- το αρχείο πρέπει να έχει δικαιώματα u=rw (0600) ή λιγότερα αν ανήκει στον τρέχοντα χρήστη, ή δικαιώματα u=rw,g=r (0640) ή λιγότερα αν ανήκει στον υπερχρήστη" + +#: fe-secure-openssl.c:1444 +#, c-format +msgid "could not load private key file \"%s\": %s" +msgstr "δεν ήταν δυνατή η φόρτωση αρχείου ιδιωτικού κλειδιού «%s»: %s" + +#: fe-secure-openssl.c:1460 +#, c-format +msgid "certificate does not match private key file \"%s\": %s" +msgstr "το πιστοποιητικό δεν ταιριάζει με το αρχείο ιδιωτικού κλειδιού «%s»: %s" + +#: fe-secure-openssl.c:1528 +#, c-format +msgid "SSL error: certificate verify failed: %s" +msgstr "SSL σφάλμα: η επαλήθευση πιστοποιητικού απέτυχε: %s" + +#: fe-secure-openssl.c:1573 +#, c-format +msgid "This may indicate that the server does not support any SSL protocol version between %s and %s." +msgstr "Αυτό μπορεί να υποδεικνύει ότι ο διακομιστής δεν υποστηρίζει καμία έκδοση πρωτοκόλλου SSL μεταξύ %s και %s." + +#: fe-secure-openssl.c:1606 +#, c-format +msgid "certificate could not be obtained: %s" +msgstr "δεν ήταν δυνατή η λήψη πιστοποιητικού: %s" + +#: fe-secure-openssl.c:1711 +#, c-format +msgid "no SSL error reported" +msgstr "δεν αναφέρθηκε κανένα σφάλμα SSL" + +#: fe-secure-openssl.c:1720 +#, c-format +msgid "SSL error code %lu" +msgstr "κωδικός σφάλματος SSL %lu" + +#: fe-secure-openssl.c:1986 +#, c-format +msgid "WARNING: sslpassword truncated\n" +msgstr "WARNING: περικομμένο sslpassword\n" + +#: fe-secure.c:263 +#, c-format +msgid "could not receive data from server: %s" +msgstr "δεν ήταν δυνατή η λήψη δεδομένων από το διακομιστή: %s" + +#: fe-secure.c:434 +#, c-format +msgid "could not send data to server: %s" +msgstr "δεν ήταν δυνατή η αποστολή δεδομένων στο διακομιστή: %s" + +#: win32.c:310 +#, c-format +msgid "unrecognized socket error: 0x%08X/%d" +msgstr "μη αναγνωρίσιμο σφάλμα υποδοχής: 0x%08X/%d" + +#~ msgid "COPY IN state must be terminated first\n" +#~ msgstr "" +#~ "πρέπει πρώτα να τερματιστεί η κατάσταση COPY IN\n" +#~ "\n" + +#~ msgid "COPY OUT state must be terminated first\n" +#~ msgstr "πρέπει πρώτα να τερματιστεί η κατάσταση COPY OUT\n" + +#~ msgid "PGEventProc \"%s\" failed during PGEVT_CONNRESET event\n" +#~ msgstr "PGEventProc «%s» απέτυχε κατά τη διάρκεια συμβάντος PGEVT_CONNRESET\n" + +#~ msgid "PGEventProc \"%s\" failed during PGEVT_RESULTCREATE event\n" +#~ msgstr "PGEventProc «%s» κατά τη διάρκεια συμβάντος PGEVT_RESULTCREATE\n" + +#~ msgid "SCM_CRED authentication method not supported\n" +#~ msgstr "δεν υποστηρίζεται η μέθοδος πιστοποίησης SCM_CRED\n" + +#~ msgid "WSAIoctl(SIO_KEEPALIVE_VALS) failed: %ui\n" +#~ msgstr "WSAIoctl(SIO_KEEPALIVE_VALS) απέτυχε: %ui\n" + +#~ msgid "cannot determine OID of function lo_creat\n" +#~ msgstr "δεν είναι δυνατός ο προσδιορισμός του OID της συνάρτησης lo_creat\n" + +#~ msgid "cannot determine OID of function lo_create\n" +#~ msgstr "δεν μπόρεσε να προσδιορίσει το OID της συνάρτησης lo_create\n" + +#~ msgid "cannot determine OID of function lo_lseek\n" +#~ msgstr "δεν είναι δυνατός ο προσδιορισμός του OID της συνάρτησης lo_lseek\n" + +#~ msgid "cannot determine OID of function lo_lseek64\n" +#~ msgstr "δεν μπόρεσε να προσδιορίσει το OID της συνάρτησης lo_lseek64\n" + +#~ msgid "cannot determine OID of function lo_open\n" +#~ msgstr "δεν είναι δυνατός ο προσδιορισμός του OID της συνάρτησης lo_open\n" + +#~ msgid "cannot determine OID of function lo_tell64\n" +#~ msgstr "δεν μπόρεσε να προσδιορίσει το OID της συνάρτησης lo_tell64\n" + +#~ msgid "cannot determine OID of function lo_truncate\n" +#~ msgstr "δεν μπόρεσε να προσδιορίσει το OID της συνάρτησης lo_truncate\n" + +#~ msgid "cannot determine OID of function lo_truncate64\n" +#~ msgstr "δεν μπόρεσε να προσδιορίσει το OID της συνάρτησης lo_truncate64\n" + +#~ msgid "cannot determine OID of function lo_unlink\n" +#~ msgstr "δεν είναι δυνατός ο προσδιορισμός του OID της συνάρτησης lo_unlink\n" + +#~ msgid "cannot determine OID of function loread\n" +#~ msgstr "δεν είναι δυνατός ο προσδιορισμός του OID της συνάρτησης loread\n" + +#~ msgid "cannot determine OID of function lowrite\n" +#~ msgstr "δεν είναι δυνατός ο προσδιορισμός του OID της συνάρτησης lowrite\n" + +#~ msgid "" +#~ "could not connect to server: %s\n" +#~ "\tIs the server running on host \"%s\" (%s) and accepting\n" +#~ "\tTCP/IP connections on port %s?\n" +#~ msgstr "" +#~ "δεν ήταν δυνατή η σύνδεση με το διακομιστή: %s\n" +#~ "\tΕκτελείται ο διακομιστής στον κεντρικό υπολογιστή »%s» (%s) και αποδέχεται\n" +#~ "\tσυνδέσεις TCP/IP στην θύρα %s;\n" + +#~ msgid "could not make a writable connection to server \"%s:%s\"\n" +#~ msgstr "δεν ήταν δυνατή η πραγματοποίηση εγγράψιμης σύνδεσης με το διακομιστή \"%s:%s\"\n" + +#~ msgid "function requires at least protocol version 3.0\n" +#~ msgstr "η συνάρτηση απαιτεί πρωτόκολλο ελάχιστης έκδοσης 3.0\n" + +#~ msgid "invalid channel_binding value: \"%s\"\n" +#~ msgstr "άκυρη τιμή channel_binding: «%s»\n" + +#~ msgid "invalid gssencmode value: \"%s\"\n" +#~ msgstr "άκυρη τιμή gssencmode: «%s»\n" + +#~ msgid "invalid setenv state %c, probably indicative of memory corruption\n" +#~ msgstr "μη έγκυρη κατάσταση %c setenv, πιθανώς ενδεικτική αλλοίωσης μνήμης\n" + +#~ msgid "invalid ssl_max_protocol_version value: \"%s\"\n" +#~ msgstr "άκυρη τιμή ssl_max_protocol_version: «%s»\n" + +#~ msgid "invalid ssl_min_protocol_version value: \"%s\"\n" +#~ msgstr "άκυρη τιμή ssl_min_protocol_version: «%s»\n" + +#~ msgid "invalid state %c, probably indicative of memory corruption\n" +#~ msgstr "μη έγκυρη κατάσταση %c, πιθανώς ενδεικτική αλλοίωσης μνήμης\n" + +#~ msgid "invalid target_session_attrs value: \"%s\"\n" +#~ msgstr "άκυρη τιμή target_session_attrs: «%s»\n" + +#~ msgid "lost synchronization with server, resetting connection" +#~ msgstr "χάθηκε ο συγχρονισμός με τον διακομιστή, επαναρυθμίζεται η σύνδεση" + +#~ msgid "select() failed: %s\n" +#~ msgstr "απέτυχε το select(): %s\n" + +#~ msgid "server sent binary data (\"B\" message) without prior row description (\"T\" message)" +#~ msgstr "ο διακομιστής έστειλε δυαδικά δεδομένα («B» μήνυμα) χωρίς προηγούμενη περιγραφή γραμμής («T» μήνυμα)" + +#~ msgid "server sent data (\"D\" message) without prior row description (\"T\" message)\n" +#~ msgstr "ο διακομιστής έστειλε δεδομένα («D» μήνυμα) χωρίς προηγούμενη περιγραφή γραμμής («T» μήνυμα)\n" + +#~ msgid "setsockopt(%s) failed: %s\n" +#~ msgstr "setsockopt(%s) απέτυχε: %s\n" + +#~ msgid "test \"SHOW transaction_read_only\" failed on server \"%s:%s\"\n" +#~ msgstr "το τεστ «SHOW transaction_read_only» απέτυχε στον διακομιστή «%s:%s»\n" + +#~ msgid "unexpected character %c following empty query response (\"I\" message)" +#~ msgstr "μη αναμενόμενος χαρακτήρας %c μετά από κενή απόκριση ερωτήματος («I» μήνυμα)" + +#~ msgid "user name lookup failure: error code %lu\n" +#~ msgstr "αποτυχία αναζήτησης ονόματος χρήστη: κωδικός σφάλματος %lu\n" diff --git a/src/interfaces/libpq/po/es.po b/src/interfaces/libpq/po/es.po new file mode 100644 index 0000000..98349a8 --- /dev/null +++ b/src/interfaces/libpq/po/es.po @@ -0,0 +1,1477 @@ +# Spanish message translation file for libpq 2013-08-30 12:42-0400\n" +# +# Copyright (c) 2002-2021, PostgreSQL Global Development Group +# This file is distributed under the same license as the PostgreSQL package. +# +# Karim <karim@mribti.com>, 2002. +# Alvaro Herrera <alvherre@alvh.no-ip.org>, 2003-2013 +# Mario González <gonzalemario@gmail.com>, 2005 +# Carlos Chapi <carloswaldo@babelruins.org>, 2017, 2021 +# +msgid "" +msgstr "" +"Project-Id-Version: libpq (PostgreSQL) 16\n" +"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" +"POT-Creation-Date: 2023-10-03 07:10+0000\n" +"PO-Revision-Date: 2023-10-06 13:28+0200\n" +"Last-Translator: Carlos Chapi <carloswaldo@babelruins.org>\n" +"Language-Team: PgSQL-es-Ayuda <pgsql-es-ayuda@lists.postgresql.org>\n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: BlackCAT 1.1\n" + +#: ../../port/thread.c:50 ../../port/thread.c:86 +#, c-format +msgid "could not look up local user ID %d: %s" +msgstr "no se pudo buscar el usuario local de ID %d: %s" + +#: ../../port/thread.c:55 ../../port/thread.c:91 +#, c-format +msgid "local user with ID %d does not exist" +msgstr "no existe un usuario local con ID %d" + +#: fe-auth-scram.c:227 +#, c-format +msgid "malformed SCRAM message (empty message)" +msgstr "mensaje SCRAM mal formado (mensaje vacío)" + +#: fe-auth-scram.c:232 +#, c-format +msgid "malformed SCRAM message (length mismatch)" +msgstr "mensaje SCRAM mal formado (longitud no coincide)" + +#: fe-auth-scram.c:275 +#, c-format +msgid "could not verify server signature: %s" +msgstr "no se pudo verificar la signatura del servidor: %s" + +#: fe-auth-scram.c:281 +#, c-format +msgid "incorrect server signature" +msgstr "signatura de servidor incorrecta" + +#: fe-auth-scram.c:290 +#, c-format +msgid "invalid SCRAM exchange state" +msgstr "estado de intercambio SCRAM no es válido" + +#: fe-auth-scram.c:317 +#, c-format +msgid "malformed SCRAM message (attribute \"%c\" expected)" +msgstr "mensaje SCRAM mal formado (se esperaba atributo «%c»)" + +#: fe-auth-scram.c:326 +#, c-format +msgid "malformed SCRAM message (expected character \"=\" for attribute \"%c\")" +msgstr "mensaje SCRAM mal formado (se esperaba el carácter «=» para el atributo «%c»)" + +#: fe-auth-scram.c:366 +#, c-format +msgid "could not generate nonce" +msgstr "no se pudo generar nonce" + +#: fe-auth-scram.c:375 fe-auth-scram.c:448 fe-auth-scram.c:600 +#: fe-auth-scram.c:620 fe-auth-scram.c:644 fe-auth-scram.c:658 +#: fe-auth-scram.c:704 fe-auth-scram.c:740 fe-auth-scram.c:914 fe-auth.c:296 +#: fe-auth.c:369 fe-auth.c:403 fe-auth.c:618 fe-auth.c:729 fe-auth.c:1210 +#: fe-auth.c:1375 fe-connect.c:925 fe-connect.c:1759 fe-connect.c:1921 +#: fe-connect.c:3291 fe-connect.c:4496 fe-connect.c:5161 fe-connect.c:5416 +#: fe-connect.c:5534 fe-connect.c:5781 fe-connect.c:5861 fe-connect.c:5959 +#: fe-connect.c:6210 fe-connect.c:6237 fe-connect.c:6313 fe-connect.c:6336 +#: fe-connect.c:6360 fe-connect.c:6395 fe-connect.c:6481 fe-connect.c:6489 +#: fe-connect.c:6846 fe-connect.c:6996 fe-exec.c:527 fe-exec.c:1321 +#: fe-exec.c:3111 fe-exec.c:4071 fe-exec.c:4235 fe-gssapi-common.c:109 +#: fe-lobj.c:870 fe-protocol3.c:204 fe-protocol3.c:228 fe-protocol3.c:256 +#: fe-protocol3.c:273 fe-protocol3.c:353 fe-protocol3.c:720 fe-protocol3.c:959 +#: fe-protocol3.c:1770 fe-protocol3.c:2170 fe-secure-common.c:110 +#: fe-secure-gssapi.c:500 fe-secure-openssl.c:434 fe-secure-openssl.c:1285 +#, c-format +msgid "out of memory" +msgstr "memoria agotada" + +#: fe-auth-scram.c:382 +#, c-format +msgid "could not encode nonce" +msgstr "no se pudo codificar nonce" + +#: fe-auth-scram.c:570 +#, c-format +msgid "could not calculate client proof: %s" +msgstr "no se pudo calcular la prueba del cliente: %s" + +#: fe-auth-scram.c:585 +#, c-format +msgid "could not encode client proof" +msgstr "no se pudo codificar la prueba del cliente" + +#: fe-auth-scram.c:637 +#, c-format +msgid "invalid SCRAM response (nonce mismatch)" +msgstr "respuesta SCRAM no es válida (nonce no coincide)" + +#: fe-auth-scram.c:667 +#, c-format +msgid "malformed SCRAM message (invalid salt)" +msgstr "mensaje SCRAM mal formado (sal no válida)" + +#: fe-auth-scram.c:680 +#, c-format +msgid "malformed SCRAM message (invalid iteration count)" +msgstr "mensaje SCRAM mal formado (el conteo de iteración no es válido)" + +#: fe-auth-scram.c:685 +#, c-format +msgid "malformed SCRAM message (garbage at end of server-first-message)" +msgstr "mensaje SCRAM mal formado (se encontró basura al final de server-first-message)" + +#: fe-auth-scram.c:719 +#, c-format +msgid "error received from server in SCRAM exchange: %s" +msgstr "se recibió un error desde el servidor durante el intercambio SCRAM: %s" + +#: fe-auth-scram.c:734 +#, c-format +msgid "malformed SCRAM message (garbage at end of server-final-message)" +msgstr "mensaje SCRAM mal formado (se encontró basura al final de server-final-message)" + +#: fe-auth-scram.c:751 +#, c-format +msgid "malformed SCRAM message (invalid server signature)" +msgstr "mensaje SCRAM mal formado (la signatura del servidor no es válida)" + +#: fe-auth-scram.c:923 +msgid "could not generate random salt" +msgstr "no se pudo generar una sal aleatoria" + +#: fe-auth.c:77 +#, c-format +msgid "out of memory allocating GSSAPI buffer (%d)" +msgstr "memoria agotada creando el búfer GSSAPI (%d)" + +#: fe-auth.c:138 +msgid "GSSAPI continuation error" +msgstr "error en continuación de GSSAPI" + +#: fe-auth.c:168 fe-auth.c:397 fe-gssapi-common.c:97 fe-secure-common.c:99 +#: fe-secure-common.c:173 +#, c-format +msgid "host name must be specified" +msgstr "el nombre de servidor debe ser especificado" + +#: fe-auth.c:174 +#, c-format +msgid "duplicate GSS authentication request" +msgstr "petición de autentificación GSS duplicada" + +#: fe-auth.c:238 +#, c-format +msgid "out of memory allocating SSPI buffer (%d)" +msgstr "memoria agotada creando el búfer SSPI (%d)" + +#: fe-auth.c:285 +msgid "SSPI continuation error" +msgstr "error en continuación de SSPI" + +#: fe-auth.c:359 +#, c-format +msgid "duplicate SSPI authentication request" +msgstr "petición de autentificación SSPI duplicada" + +#: fe-auth.c:384 +msgid "could not acquire SSPI credentials" +msgstr "no se pudo obtener las credenciales SSPI" + +#: fe-auth.c:437 +#, c-format +msgid "channel binding required, but SSL not in use" +msgstr "se requiere enlazado de canal (channel binding), pero no se está usando SSL" + +#: fe-auth.c:443 +#, c-format +msgid "duplicate SASL authentication request" +msgstr "petición de autentificación SASL duplicada" + +#: fe-auth.c:501 +#, c-format +msgid "channel binding is required, but client does not support it" +msgstr "se requiere enlazado de canal (channel binding), pero no está soportado en el cliente" + +#: fe-auth.c:517 +#, c-format +msgid "server offered SCRAM-SHA-256-PLUS authentication over a non-SSL connection" +msgstr "el servidor ofreció autenticación SCRAM-SHA-256-PLUS sobre una conexión no-SSL" + +#: fe-auth.c:531 +#, c-format +msgid "none of the server's SASL authentication mechanisms are supported" +msgstr "ningún método de autentificación SASL del servidor está soportado" + +#: fe-auth.c:538 +#, c-format +msgid "channel binding is required, but server did not offer an authentication method that supports channel binding" +msgstr "se requiere enlazado de canal (channel binding), pero el servidor no ofrece un método de autenticación que lo soporte" + +#: fe-auth.c:641 +#, c-format +msgid "out of memory allocating SASL buffer (%d)" +msgstr "memoria agotada creando el búfer SASL (%d)" + +#: fe-auth.c:665 +#, c-format +msgid "AuthenticationSASLFinal received from server, but SASL authentication was not completed" +msgstr "Se recibió AuthenticationSASLFinal desde el servidor, pero la autentificación SASL no se completó" + +#: fe-auth.c:675 +#, c-format +msgid "no client response found after SASL exchange success" +msgstr "no se encontró respuesta del cliente luego del intercambio SASL exitoso" + +#: fe-auth.c:738 fe-auth.c:745 fe-auth.c:1358 fe-auth.c:1369 +#, c-format +msgid "could not encrypt password: %s" +msgstr "no se pudo cifrar contraseña: %s" + +#: fe-auth.c:773 +msgid "server requested a cleartext password" +msgstr "el servidor solicitó una contraseña en texto claro" + +#: fe-auth.c:775 +msgid "server requested a hashed password" +msgstr "el servidor solicitó una contraseña cifrada" + +#: fe-auth.c:778 +msgid "server requested GSSAPI authentication" +msgstr "el servidor solicitó autentificación GSSAPI" + +#: fe-auth.c:780 +msgid "server requested SSPI authentication" +msgstr "el servidor solicitó autentificación SSPI" + +#: fe-auth.c:784 +msgid "server requested SASL authentication" +msgstr "el servidor solicitó autentificación SASL" + +#: fe-auth.c:787 +msgid "server requested an unknown authentication type" +msgstr "múltiples valores especificados para el tipo de autentificación" + +#: fe-auth.c:820 +#, c-format +msgid "server did not request an SSL certificate" +msgstr "el servidor no solicitó un certificado SSL" + +#: fe-auth.c:825 +#, c-format +msgid "server accepted connection without a valid SSL certificate" +msgstr "el servidor aceptó la conexión sin un certificado SSL válido" + +#: fe-auth.c:879 +msgid "server did not complete authentication" +msgstr "el servidor no completó la autentificación" + +#: fe-auth.c:913 +#, c-format +msgid "authentication method requirement \"%s\" failed: %s" +msgstr "el método de autentificación «%s» requerido falló: %s" + +#: fe-auth.c:936 +#, c-format +msgid "channel binding required, but server authenticated client without channel binding" +msgstr "se requiere enlazado de canal (channel binding), pero el servidor autenticó al cliente sin enlazado de canal" + +#: fe-auth.c:941 +#, c-format +msgid "channel binding required but not supported by server's authentication request" +msgstr "se requiere enlazado de canal (channel binding), pero no es compatible con la solicitud de autenticación del servidor" + +#: fe-auth.c:975 +#, c-format +msgid "Kerberos 4 authentication not supported" +msgstr "el método de autentificación Kerberos 4 no está soportado" + +#: fe-auth.c:979 +#, c-format +msgid "Kerberos 5 authentication not supported" +msgstr "el método de autentificación Kerberos 5 no está soportado" + +#: fe-auth.c:1049 +#, c-format +msgid "GSSAPI authentication not supported" +msgstr "el método de autentificación GSSAPI no está soportado" + +#: fe-auth.c:1080 +#, c-format +msgid "SSPI authentication not supported" +msgstr "el método de autentificación SSPI no está soportado" + +#: fe-auth.c:1087 +#, c-format +msgid "Crypt authentication not supported" +msgstr "el método de autentificación Crypt no está soportado" + +#: fe-auth.c:1151 +#, c-format +msgid "authentication method %u not supported" +msgstr "el método de autentificación %u no está soportado" + +#: fe-auth.c:1197 +#, c-format +msgid "user name lookup failure: error code %lu" +msgstr "fallo en la búsqueda de nombre de usuario: código de error %lu" + +#: fe-auth.c:1321 +#, c-format +msgid "unexpected shape of result set returned for SHOW" +msgstr "SHOW retornó un conjunto de resultados con estructura inesperada" + +#: fe-auth.c:1329 +#, c-format +msgid "password_encryption value too long" +msgstr "el valor para password_encryption es demasiado largo" + +#: fe-auth.c:1379 +#, c-format +msgid "unrecognized password encryption algorithm \"%s\"" +msgstr "algoritmo para cifrado de contraseña «%s» desconocido" + +#: fe-connect.c:1132 +#, c-format +msgid "could not match %d host names to %d hostaddr values" +msgstr "no se pudo emparejar %d nombres de host a %d direcciones de host" + +#: fe-connect.c:1212 +#, c-format +msgid "could not match %d port numbers to %d hosts" +msgstr "no se pudo emparejar %d números de puertos a %d hosts" + +#: fe-connect.c:1337 +#, c-format +msgid "negative require_auth method \"%s\" cannot be mixed with non-negative methods" +msgstr "el método require_auth negativo «%s» no puede ser mezclado con métodos no-negativos" + +#: fe-connect.c:1350 +#, c-format +msgid "require_auth method \"%s\" cannot be mixed with negative methods" +msgstr "el método require_auth «%s» no puede ser mezclado con métodos negativos" + +#: fe-connect.c:1410 fe-connect.c:1461 fe-connect.c:1503 fe-connect.c:1559 +#: fe-connect.c:1567 fe-connect.c:1598 fe-connect.c:1644 fe-connect.c:1684 +#: fe-connect.c:1705 +#, c-format +msgid "invalid %s value: \"%s\"" +msgstr "valor %s no válido: «%s»" + +#: fe-connect.c:1443 +#, c-format +msgid "require_auth method \"%s\" is specified more than once" +msgstr "el método “require_auth” «%s» se especifica más de una vez" + +#: fe-connect.c:1484 fe-connect.c:1523 fe-connect.c:1606 +#, c-format +msgid "%s value \"%s\" invalid when SSL support is not compiled in" +msgstr "el valor «%2$s» de %1$s no es válido cuando el soporte SSL no está compilado" + +#: fe-connect.c:1546 +#, c-format +msgid "weak sslmode \"%s\" may not be used with sslrootcert=system (use \"verify-full\")" +msgstr "el sslmode débil «%s» no puede ser usado con sslrootcert=system (use «verify-full»)" + +#: fe-connect.c:1584 +#, c-format +msgid "invalid SSL protocol version range" +msgstr "rango de versión de protocolo SSL no válido " + +#: fe-connect.c:1621 +#, c-format +msgid "%s value \"%s\" is not supported (check OpenSSL version)" +msgstr "el valor «%2$s» de %1$s no está soportado (verifique la versión de OpenSSL)" + +#: fe-connect.c:1651 +#, c-format +msgid "gssencmode value \"%s\" invalid when GSSAPI support is not compiled in" +msgstr "el valor gssencmode «%s» no es válido cuando no se ha compilado con soporte GSSAPI" + +#: fe-connect.c:1944 +#, c-format +msgid "could not set socket to TCP no delay mode: %s" +msgstr "no se pudo establecer el socket en modo TCP sin retardo: %s" + +#: fe-connect.c:2003 +#, c-format +msgid "connection to server on socket \"%s\" failed: " +msgstr "falló la conexión al servidor en el socket «%s»: " + +#: fe-connect.c:2029 +#, c-format +msgid "connection to server at \"%s\" (%s), port %s failed: " +msgstr "falló la conexión al servidor en «%s» (%s), puerto %s: " + +#: fe-connect.c:2034 +#, c-format +msgid "connection to server at \"%s\", port %s failed: " +msgstr "falló la conexión al servidor en «%s», puerto %s: " + +#: fe-connect.c:2057 +#, c-format +msgid "\tIs the server running locally and accepting connections on that socket?" +msgstr "\t¿Está el servidor en ejecución localmente y aceptando conexiones en ese socket?" + +#: fe-connect.c:2059 +#, c-format +msgid "\tIs the server running on that host and accepting TCP/IP connections?" +msgstr "\t¿Está el servidor en ejecución en ese host y aceptando conexiones TCP/IP?" + +#: fe-connect.c:2122 +#, c-format +msgid "invalid integer value \"%s\" for connection option \"%s\"" +msgstr "valor entero «%s» no válido para la opción de conexión «%s»" + +#: fe-connect.c:2151 fe-connect.c:2185 fe-connect.c:2220 fe-connect.c:2318 +#: fe-connect.c:2973 +#, c-format +msgid "%s(%s) failed: %s" +msgstr "%s(%s) falló: %s" + +#: fe-connect.c:2284 +#, c-format +msgid "%s(%s) failed: error code %d" +msgstr "%s(%s) falló: código de error %d" + +#: fe-connect.c:2597 +#, c-format +msgid "invalid connection state, probably indicative of memory corruption" +msgstr "el estado de conexión no es válido, probablemente por corrupción de memoria" + +#: fe-connect.c:2676 +#, c-format +msgid "invalid port number: \"%s\"" +msgstr "número de puerto no válido: «%s»" + +#: fe-connect.c:2690 +#, c-format +msgid "could not translate host name \"%s\" to address: %s" +msgstr "no se pudo traducir el nombre «%s» a una dirección: %s" + +#: fe-connect.c:2702 +#, c-format +msgid "could not parse network address \"%s\": %s" +msgstr "no se pudo interpretar la dirección de red «%s»: %s" + +#: fe-connect.c:2713 +#, c-format +msgid "Unix-domain socket path \"%s\" is too long (maximum %d bytes)" +msgstr "la ruta al socket de dominio Unix «%s» es demasiado larga (máximo %d bytes)" + +#: fe-connect.c:2727 +#, c-format +msgid "could not translate Unix-domain socket path \"%s\" to address: %s" +msgstr "no se pudo traducir la ruta del socket Unix «%s» a una dirección: %s" + +#: fe-connect.c:2901 +#, c-format +msgid "could not create socket: %s" +msgstr "no se pudo crear el socket: %s" + +#: fe-connect.c:2932 +#, c-format +msgid "could not set socket to nonblocking mode: %s" +msgstr "no se pudo establecer el socket en modo no bloqueante: %s" + +#: fe-connect.c:2943 +#, c-format +msgid "could not set socket to close-on-exec mode: %s" +msgstr "no se pudo poner el socket en modo close-on-exec: %s" + +#: fe-connect.c:2961 +#, c-format +msgid "keepalives parameter must be an integer" +msgstr "el parámetro de keepalives debe ser un entero" + +#: fe-connect.c:3100 +#, c-format +msgid "could not get socket error status: %s" +msgstr "no se pudo determinar el estado de error del socket: %s" + +#: fe-connect.c:3127 +#, c-format +msgid "could not get client address from socket: %s" +msgstr "no se pudo obtener la dirección del cliente desde el socket: %s" + +#: fe-connect.c:3165 +#, c-format +msgid "requirepeer parameter is not supported on this platform" +msgstr "el parámetro requirepeer no está soportado en esta plataforma" + +#: fe-connect.c:3167 +#, c-format +msgid "could not get peer credentials: %s" +msgstr "no se pudo obtener credenciales de la contraparte: %s" + +#: fe-connect.c:3180 +#, c-format +msgid "requirepeer specifies \"%s\", but actual peer user name is \"%s\"" +msgstr "requirepeer especifica «%s», pero el nombre de usuario de la contraparte es «%s»" + +#: fe-connect.c:3221 +#, c-format +msgid "could not send GSSAPI negotiation packet: %s" +msgstr "no se pudo enviar el paquete de negociación GSSAPI: %s" + +#: fe-connect.c:3233 +#, c-format +msgid "GSSAPI encryption required but was impossible (possibly no credential cache, no server support, or using a local socket)" +msgstr "cifrado GSSAPI requerido, pero fue imposible (posiblemente no hay cache de credenciales, no hay soporte de servidor, o se está usando un socket local)" + +#: fe-connect.c:3274 +#, c-format +msgid "could not send SSL negotiation packet: %s" +msgstr "no se pudo enviar el paquete de negociación SSL: %s" + +#: fe-connect.c:3303 +#, c-format +msgid "could not send startup packet: %s" +msgstr "no se pudo enviar el paquete de inicio: %s" + +#: fe-connect.c:3378 +#, c-format +msgid "server does not support SSL, but SSL was required" +msgstr "el servidor no soporta SSL, pero SSL es requerida" + +#: fe-connect.c:3404 +#, c-format +msgid "received invalid response to SSL negotiation: %c" +msgstr "se ha recibido una respuesta no válida en la negociación SSL: %c" + +#: fe-connect.c:3424 +#, c-format +msgid "received unencrypted data after SSL response" +msgstr "se recibieron datos no cifrados después de la respuesta SSL" + +#: fe-connect.c:3504 +#, c-format +msgid "server doesn't support GSSAPI encryption, but it was required" +msgstr "el servidor no soporta cifrado GSSAPI, pero es requerida" + +#: fe-connect.c:3515 +#, c-format +msgid "received invalid response to GSSAPI negotiation: %c" +msgstr "se ha recibido una respuesta no válida en la negociación GSSAPI: %c" + +#: fe-connect.c:3533 +#, c-format +msgid "received unencrypted data after GSSAPI encryption response" +msgstr "se recibieron datos no cifrados después de la respuesta de cifrado GSSAPI" + +#: fe-connect.c:3598 +#, c-format +msgid "expected authentication request from server, but received %c" +msgstr "se esperaba una petición de autentificación desde el servidor, pero se ha recibido %c" + +#: fe-connect.c:3625 fe-connect.c:3794 +#, c-format +msgid "received invalid authentication request" +msgstr "se recibió una solicitud de autentificación no válida" + +#: fe-connect.c:3630 fe-connect.c:3779 +#, c-format +msgid "received invalid protocol negotiation message" +msgstr "se recibió un mensaje de negociación de protocolo no válido" + +#: fe-connect.c:3648 fe-connect.c:3702 +#, c-format +msgid "received invalid error message" +msgstr "se recibió un mensaje de error no válido" + +#: fe-connect.c:3865 +#, c-format +msgid "unexpected message from server during startup" +msgstr "se ha recibido un mensaje inesperado del servidor durante el inicio" + +#: fe-connect.c:3956 +#, c-format +msgid "session is read-only" +msgstr "la sesión es de solo lectura" + +#: fe-connect.c:3958 +#, c-format +msgid "session is not read-only" +msgstr "la sesión no es de solo lectura" + +#: fe-connect.c:4011 +#, c-format +msgid "server is in hot standby mode" +msgstr "el servidor está en modo hot standby" + +#: fe-connect.c:4013 +#, c-format +msgid "server is not in hot standby mode" +msgstr "el servidor no está en modo hot standby" + +#: fe-connect.c:4129 fe-connect.c:4179 +#, c-format +msgid "\"%s\" failed" +msgstr "«%s» falló" + +#: fe-connect.c:4193 +#, c-format +msgid "invalid connection state %d, probably indicative of memory corruption" +msgstr "estado de conexión no válido %d, probablemente por corrupción de memoria" + +#: fe-connect.c:5174 +#, c-format +msgid "invalid LDAP URL \"%s\": scheme must be ldap://" +msgstr "URL LDAP no válida «%s»: el esquema debe ser ldap://" + +#: fe-connect.c:5189 +#, c-format +msgid "invalid LDAP URL \"%s\": missing distinguished name" +msgstr "URL LDAP no válida «%s»: distinguished name faltante" + +#: fe-connect.c:5201 fe-connect.c:5259 +#, c-format +msgid "invalid LDAP URL \"%s\": must have exactly one attribute" +msgstr "URL LDAP no válida «%s»: debe tener exactamente un atributo" + +#: fe-connect.c:5213 fe-connect.c:5275 +#, c-format +msgid "invalid LDAP URL \"%s\": must have search scope (base/one/sub)" +msgstr "URL LDAP no válida «%s»: debe tener ámbito de búsqueda (base/one/sub)" + +#: fe-connect.c:5225 +#, c-format +msgid "invalid LDAP URL \"%s\": no filter" +msgstr "URL LDAP no válida «%s»: no tiene filtro" + +#: fe-connect.c:5247 +#, c-format +msgid "invalid LDAP URL \"%s\": invalid port number" +msgstr "URL LDAP no válida «%s»: número de puerto no válido" + +#: fe-connect.c:5284 +#, c-format +msgid "could not create LDAP structure" +msgstr "no se pudo crear estructura LDAP" + +#: fe-connect.c:5359 +#, c-format +msgid "lookup on LDAP server failed: %s" +msgstr "búsqueda en servidor LDAP falló: %s" + +#: fe-connect.c:5369 +#, c-format +msgid "more than one entry found on LDAP lookup" +msgstr "se encontro más de una entrada en búsqueda LDAP" + +#: fe-connect.c:5371 fe-connect.c:5382 +#, c-format +msgid "no entry found on LDAP lookup" +msgstr "no se encontró ninguna entrada en búsqueda LDAP" + +#: fe-connect.c:5392 fe-connect.c:5404 +#, c-format +msgid "attribute has no values on LDAP lookup" +msgstr "la búsqueda LDAP entregó atributo sin valores" + +#: fe-connect.c:5455 fe-connect.c:5474 fe-connect.c:5998 +#, c-format +msgid "missing \"=\" after \"%s\" in connection info string" +msgstr "falta «=» después de «%s» en la cadena de información de la conexión" + +#: fe-connect.c:5545 fe-connect.c:6181 fe-connect.c:6979 +#, c-format +msgid "invalid connection option \"%s\"" +msgstr "opción de conexión no válida «%s»" + +#: fe-connect.c:5560 fe-connect.c:6046 +#, c-format +msgid "unterminated quoted string in connection info string" +msgstr "cadena de caracteres entre comillas sin terminar en la cadena de información de conexión" + +#: fe-connect.c:5640 +#, c-format +msgid "definition of service \"%s\" not found" +msgstr "la definición de servicio «%s» no fue encontrada" + +#: fe-connect.c:5666 +#, c-format +msgid "service file \"%s\" not found" +msgstr "el archivo de servicio «%s» no fue encontrado" + +#: fe-connect.c:5679 +#, c-format +msgid "line %d too long in service file \"%s\"" +msgstr "la línea %d es demasiado larga en archivo de servicio «%s»" + +#: fe-connect.c:5750 fe-connect.c:5793 +#, c-format +msgid "syntax error in service file \"%s\", line %d" +msgstr "error de sintaxis en archivo de servicio «%s», línea %d" + +#: fe-connect.c:5761 +#, c-format +msgid "nested service specifications not supported in service file \"%s\", line %d" +msgstr "especificaciones de servicio anidadas no soportadas en archivo de servicio «%s», línea %d" + +#: fe-connect.c:6500 +#, c-format +msgid "invalid URI propagated to internal parser routine: \"%s\"" +msgstr "URI no válida propagada a rutina interna de procesamiento: «%s»" + +#: fe-connect.c:6577 +#, c-format +msgid "end of string reached when looking for matching \"]\" in IPv6 host address in URI: \"%s\"" +msgstr "se encontró el fin de la cadena mientras se buscaba el «]» correspondiente en dirección IPv6 en URI: «%s»" + +#: fe-connect.c:6584 +#, c-format +msgid "IPv6 host address may not be empty in URI: \"%s\"" +msgstr "la dirección IPv6 no puede ser vacía en la URI: «%s»" + +#: fe-connect.c:6599 +#, c-format +msgid "unexpected character \"%c\" at position %d in URI (expected \":\" or \"/\"): \"%s\"" +msgstr "carácter «%c» inesperado en la posición %d en URI (se esperaba «:» o «/»): «%s»" + +#: fe-connect.c:6728 +#, c-format +msgid "extra key/value separator \"=\" in URI query parameter: \"%s\"" +msgstr "separador llave/valor «=» extra en parámetro de la URI: «%s»" + +#: fe-connect.c:6748 +#, c-format +msgid "missing key/value separator \"=\" in URI query parameter: \"%s\"" +msgstr "separador llave/valor «=» faltante en parámetro de la URI: «%s»" + +#: fe-connect.c:6800 +#, c-format +msgid "invalid URI query parameter: \"%s\"" +msgstr "parámetro de URI no válido: «%s»" + +#: fe-connect.c:6874 +#, c-format +msgid "invalid percent-encoded token: \"%s\"" +msgstr "elemento escapado con %% no válido: «%s»" + +#: fe-connect.c:6884 +#, c-format +msgid "forbidden value %%00 in percent-encoded value: \"%s\"" +msgstr "valor no permitido %%00 en valor escapado con %%: «%s»" + +#: fe-connect.c:7248 +msgid "connection pointer is NULL\n" +msgstr "el puntero de conexión es NULL\n" + +#: fe-connect.c:7256 fe-exec.c:710 fe-exec.c:970 fe-exec.c:3292 +#: fe-protocol3.c:974 fe-protocol3.c:1007 +msgid "out of memory\n" +msgstr "memoria agotada\n" + +#: fe-connect.c:7547 +#, c-format +msgid "WARNING: password file \"%s\" is not a plain file\n" +msgstr "ADVERTENCIA: El archivo de claves «%s» no es un archivo plano\n" + +#: fe-connect.c:7556 +#, c-format +msgid "WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n" +msgstr "ADVERTENCIA: El archivo de claves «%s» tiene permiso de lectura para el grupo u otros; los permisos deberían ser u=rw (0600) o menos\n" + +#: fe-connect.c:7663 +#, c-format +msgid "password retrieved from file \"%s\"" +msgstr "contraseña obtenida desde el archivo «%s»" + +#: fe-exec.c:466 fe-exec.c:3366 +#, c-format +msgid "row number %d is out of range 0..%d" +msgstr "el número de fila %d está fuera del rango 0..%d" + +#: fe-exec.c:528 fe-protocol3.c:1976 +#, c-format +msgid "%s" +msgstr "%s" + +#: fe-exec.c:831 +#, c-format +msgid "write to server failed" +msgstr "falló escritura al servidor" + +#: fe-exec.c:869 +#, c-format +msgid "no error text available" +msgstr "no hay mensaje de error disponible" + +#: fe-exec.c:958 +msgid "NOTICE" +msgstr "AVISO" + +#: fe-exec.c:1016 +msgid "PGresult cannot support more than INT_MAX tuples" +msgstr "PGresult no puede soportar un número de tuplas mayor que INT_MAX" + +#: fe-exec.c:1028 +msgid "size_t overflow" +msgstr "desbordamiento de size_t" + +#: fe-exec.c:1444 fe-exec.c:1513 fe-exec.c:1559 +#, c-format +msgid "command string is a null pointer" +msgstr "la cadena de orden es un puntero nulo" + +#: fe-exec.c:1450 fe-exec.c:2888 +#, c-format +msgid "%s not allowed in pipeline mode" +msgstr "no se permite %s en modo pipeline" + +#: fe-exec.c:1518 fe-exec.c:1564 fe-exec.c:1658 +#, c-format +msgid "number of parameters must be between 0 and %d" +msgstr "el número de parámetros debe estar entre 0 y %d" + +#: fe-exec.c:1554 fe-exec.c:1653 +#, c-format +msgid "statement name is a null pointer" +msgstr "el nombre de sentencia es un puntero nulo" + +#: fe-exec.c:1695 fe-exec.c:3220 +#, c-format +msgid "no connection to the server" +msgstr "no hay conexión con el servidor" + +#: fe-exec.c:1703 fe-exec.c:3228 +#, c-format +msgid "another command is already in progress" +msgstr "hay otra orden en ejecución" + +#: fe-exec.c:1733 +#, c-format +msgid "cannot queue commands during COPY" +msgstr "no se puede agregar órdenes a la cola mientras se hace COPY" + +#: fe-exec.c:1850 +#, c-format +msgid "length must be given for binary parameter" +msgstr "el largo debe ser especificado para un parámetro binario" + +#: fe-exec.c:2171 +#, c-format +msgid "unexpected asyncStatus: %d" +msgstr "asyncStatus no esperado: %d" + +#: fe-exec.c:2327 +#, c-format +msgid "synchronous command execution functions are not allowed in pipeline mode" +msgstr "no se permiten funciones que ejecuten órdenes sincrónicas en modo pipeline" + +#: fe-exec.c:2344 +msgid "COPY terminated by new PQexec" +msgstr "COPY terminado por un nuevo PQexec" + +#: fe-exec.c:2360 +#, c-format +msgid "PQexec not allowed during COPY BOTH" +msgstr "PQexec no está permitido durante COPY BOTH" + +#: fe-exec.c:2586 fe-exec.c:2641 fe-exec.c:2709 fe-protocol3.c:1907 +#, c-format +msgid "no COPY in progress" +msgstr "no hay COPY alguno en ejecución" + +#: fe-exec.c:2895 +#, c-format +msgid "connection in wrong state" +msgstr "la conexión está en un estado incorrecto" + +#: fe-exec.c:2938 +#, c-format +msgid "cannot enter pipeline mode, connection not idle" +msgstr "no se puede entrar en modo pipeline, la conexión no está inactiva" + +#: fe-exec.c:2974 fe-exec.c:2995 +#, c-format +msgid "cannot exit pipeline mode with uncollected results" +msgstr "no se puede salir de modo pipeline al tener resultados sin recolectar" + +#: fe-exec.c:2978 +#, c-format +msgid "cannot exit pipeline mode while busy" +msgstr "no se puede salir de modo pipeline mientras haya actividad" + +#: fe-exec.c:2989 +#, c-format +msgid "cannot exit pipeline mode while in COPY" +msgstr "no se puede salir de modo pipeline mientras se está en COPY" + +#: fe-exec.c:3154 +#, c-format +msgid "cannot send pipeline when not in pipeline mode" +msgstr "no se puede enviar pipeline cuando no se está en modo pipeline" + +#: fe-exec.c:3255 +msgid "invalid ExecStatusType code" +msgstr "el código de ExecStatusType no es válido" + +#: fe-exec.c:3282 +msgid "PGresult is not an error result\n" +msgstr "PGresult no es un resultado de error\n" + +#: fe-exec.c:3350 fe-exec.c:3373 +#, c-format +msgid "column number %d is out of range 0..%d" +msgstr "el número de columna %d está fuera del rango 0..%d" + +#: fe-exec.c:3388 +#, c-format +msgid "parameter number %d is out of range 0..%d" +msgstr "el número de parámetro %d está fuera del rango 0..%d" + +#: fe-exec.c:3699 +#, c-format +msgid "could not interpret result from server: %s" +msgstr "no se pudo interpretar el resultado del servidor: %s" + +#: fe-exec.c:3964 fe-exec.c:4054 +#, c-format +msgid "incomplete multibyte character" +msgstr "carácter multibyte incompleto" + +#: fe-gssapi-common.c:122 +msgid "GSSAPI name import error" +msgstr "error de importación de nombre de GSSAPI" + +#: fe-lobj.c:144 fe-lobj.c:207 fe-lobj.c:397 fe-lobj.c:487 fe-lobj.c:560 +#: fe-lobj.c:956 fe-lobj.c:963 fe-lobj.c:970 fe-lobj.c:977 fe-lobj.c:984 +#: fe-lobj.c:991 fe-lobj.c:998 fe-lobj.c:1005 +#, c-format +msgid "cannot determine OID of function %s" +msgstr "no se puede determinar el OID de la función %s" + +#: fe-lobj.c:160 +#, c-format +msgid "argument of lo_truncate exceeds integer range" +msgstr "el argumento de lo_truncate excede el rango de enteros" + +#: fe-lobj.c:262 +#, c-format +msgid "argument of lo_read exceeds integer range" +msgstr "el argumento de lo_read excede el rango de enteros" + +#: fe-lobj.c:313 +#, c-format +msgid "argument of lo_write exceeds integer range" +msgstr "el argumento de lo_write excede el rango de enteros" + +#: fe-lobj.c:669 fe-lobj.c:780 +#, c-format +msgid "could not open file \"%s\": %s" +msgstr "no se pudo abrir el archivo «%s»: %s" + +#: fe-lobj.c:725 +#, c-format +msgid "could not read from file \"%s\": %s" +msgstr "no se pudo leer el archivo «%s»: %s" + +#: fe-lobj.c:801 fe-lobj.c:824 +#, c-format +msgid "could not write to file \"%s\": %s" +msgstr "no se pudo escribir a archivo «%s»: %s" + +#: fe-lobj.c:908 +#, c-format +msgid "query to initialize large object functions did not return data" +msgstr "la consulta para inicializar las funciones de objetos grandes no devuelve datos" + +#: fe-misc.c:240 +#, c-format +msgid "integer of size %lu not supported by pqGetInt" +msgstr "el entero de tamaño %lu no está soportado por pqGetInt" + +#: fe-misc.c:273 +#, c-format +msgid "integer of size %lu not supported by pqPutInt" +msgstr "el entero de tamaño %lu no está soportado por pqPutInt" + +#: fe-misc.c:573 +#, c-format +msgid "connection not open" +msgstr "la conexión no está abierta" + +#: fe-misc.c:751 fe-secure-openssl.c:215 fe-secure-openssl.c:315 +#: fe-secure.c:257 fe-secure.c:419 +#, c-format +msgid "" +"server closed the connection unexpectedly\n" +"\tThis probably means the server terminated abnormally\n" +"\tbefore or while processing the request." +msgstr "" +"el servidor ha cerrado la conexión inesperadamente\n" +"\tProbablemente se debe a que el servidor terminó de manera anormal\n" +"\tantes o durante el procesamiento de la petición." + +#: fe-misc.c:818 +msgid "connection not open\n" +msgstr "la conexión no está abierta\n" + +#: fe-misc.c:1003 +#, c-format +msgid "timeout expired" +msgstr "tiempo de espera agotado" + +#: fe-misc.c:1047 +#, c-format +msgid "invalid socket" +msgstr "socket no válido" + +#: fe-misc.c:1069 +#, c-format +msgid "%s() failed: %s" +msgstr "%s() falló: %s" + +#: fe-protocol3.c:182 +#, c-format +msgid "message type 0x%02x arrived from server while idle" +msgstr "un mensaje de tipo 0x%02x llegó del servidor estando inactivo" + +#: fe-protocol3.c:385 +#, c-format +msgid "server sent data (\"D\" message) without prior row description (\"T\" message)" +msgstr "el servidor envió datos (mensaje «D») sin precederlos con una descripción de fila (mensaje «T»)" + +#: fe-protocol3.c:427 +#, c-format +msgid "unexpected response from server; first received character was \"%c\"" +msgstr "se ha recibido una respuesta inesperada del servidor; el primer carácter recibido fue «%c»" + +#: fe-protocol3.c:450 +#, c-format +msgid "message contents do not agree with length in message type \"%c\"" +msgstr "el contenido del mensaje no concuerda con el largo, en el mensaje tipo «%c»" + +#: fe-protocol3.c:468 +#, c-format +msgid "lost synchronization with server: got message type \"%c\", length %d" +msgstr "se perdió la sincronía con el servidor: se recibió un mensaje de tipo «%c», largo %d" + +#: fe-protocol3.c:520 fe-protocol3.c:560 +msgid "insufficient data in \"T\" message" +msgstr "datos insuficientes en el mensaje «T»" + +#: fe-protocol3.c:631 fe-protocol3.c:837 +msgid "out of memory for query result" +msgstr "no hay suficiente memoria para el resultado de la consulta" + +#: fe-protocol3.c:700 +msgid "insufficient data in \"t\" message" +msgstr "datos insuficientes en el mensaje «t»" + +#: fe-protocol3.c:759 fe-protocol3.c:791 fe-protocol3.c:809 +msgid "insufficient data in \"D\" message" +msgstr "datos insuficientes en el mensaje «D»" + +#: fe-protocol3.c:765 +msgid "unexpected field count in \"D\" message" +msgstr "cantidad de campos inesperada en mensaje «D»" + +#: fe-protocol3.c:1020 +msgid "no error message available\n" +msgstr "no hay mensaje de error disponible\n" + +#. translator: %s represents a digit string +#: fe-protocol3.c:1068 fe-protocol3.c:1087 +#, c-format +msgid " at character %s" +msgstr " en el carácter %s" + +#: fe-protocol3.c:1100 +#, c-format +msgid "DETAIL: %s\n" +msgstr "DETALLE: %s\n" + +#: fe-protocol3.c:1103 +#, c-format +msgid "HINT: %s\n" +msgstr "SUGERENCIA: %s\n" + +#: fe-protocol3.c:1106 +#, c-format +msgid "QUERY: %s\n" +msgstr "CONSULTA: %s\n" + +#: fe-protocol3.c:1113 +#, c-format +msgid "CONTEXT: %s\n" +msgstr "CONTEXTO: %s\n" + +#: fe-protocol3.c:1122 +#, c-format +msgid "SCHEMA NAME: %s\n" +msgstr "NOMBRE DE ESQUEMA: %s\n" + +#: fe-protocol3.c:1126 +#, c-format +msgid "TABLE NAME: %s\n" +msgstr "NOMBRE DE TABLA: %s\n" + +#: fe-protocol3.c:1130 +#, c-format +msgid "COLUMN NAME: %s\n" +msgstr "NOMBRE DE COLUMNA: %s\n" + +#: fe-protocol3.c:1134 +#, c-format +msgid "DATATYPE NAME: %s\n" +msgstr "NOMBRE TIPO DE DATO: %s\n" + +#: fe-protocol3.c:1138 +#, c-format +msgid "CONSTRAINT NAME: %s\n" +msgstr "NOMBRE DE RESTRICCIÓN: %s\n" + +#: fe-protocol3.c:1150 +msgid "LOCATION: " +msgstr "UBICACIÓN: " + +#: fe-protocol3.c:1152 +#, c-format +msgid "%s, " +msgstr "%s, " + +#: fe-protocol3.c:1154 +#, c-format +msgid "%s:%s" +msgstr "%s:%s" + +#: fe-protocol3.c:1349 +#, c-format +msgid "LINE %d: " +msgstr "LÍNEA %d: " + +#: fe-protocol3.c:1423 +#, c-format +msgid "protocol version not supported by server: client uses %u.%u, server supports up to %u.%u" +msgstr "versión de protocolo no soportada por el servidor: cliente usa %u.%u, servidor soporta hasta %u.%u" + +#: fe-protocol3.c:1429 +#, c-format +msgid "protocol extension not supported by server: %s" +msgid_plural "protocol extensions not supported by server: %s" +msgstr[0] "extensión del protocolo no soportada por el servidor: %s" +msgstr[1] "extensiones del protocolo no soportadas por el servidor: %s" + +#: fe-protocol3.c:1437 +#, c-format +msgid "invalid %s message" +msgstr "mensaje %s no válido" + +#: fe-protocol3.c:1802 +#, c-format +msgid "PQgetline: not doing text COPY OUT" +msgstr "PQgetline: no se está haciendo COPY OUT de texto" + +#: fe-protocol3.c:2176 +#, c-format +msgid "protocol error: no function result" +msgstr "error de protocolo: no hay resultado de función" + +#: fe-protocol3.c:2187 +#, c-format +msgid "protocol error: id=0x%x" +msgstr "error de protocolo: id=0x%x" + +#: fe-secure-common.c:123 +#, c-format +msgid "SSL certificate's name contains embedded null" +msgstr "el elemento de nombre en el certificado SSL contiene un carácter null" + +#: fe-secure-common.c:228 +#, c-format +msgid "certificate contains IP address with invalid length %zu" +msgstr "el certificado contiene una dirección IP con largo %zu no válido" + +#: fe-secure-common.c:237 +#, c-format +msgid "could not convert certificate's IP address to string: %s" +msgstr "no se pudo convertir la dirección IP del certificado a cadena: %s" + +#: fe-secure-common.c:269 +#, c-format +msgid "host name must be specified for a verified SSL connection" +msgstr "el nombre de servidor debe ser especificado para una conexión SSL verificada" + +#: fe-secure-common.c:286 +#, c-format +msgid "server certificate for \"%s\" (and %d other name) does not match host name \"%s\"" +msgid_plural "server certificate for \"%s\" (and %d other names) does not match host name \"%s\"" +msgstr[0] "el certificado de servidor para «%s» (y %d otro nombre) no coincide con el nombre de servidor «%s»" +msgstr[1] "el certificado de servidor para «%s» (y %d otros nombres) no coincide con el nombre de servidor «%s»" + +#: fe-secure-common.c:294 +#, c-format +msgid "server certificate for \"%s\" does not match host name \"%s\"" +msgstr "el certificado de servidor para «%s» no coincide con el nombre de servidor «%s»" + +#: fe-secure-common.c:299 +#, c-format +msgid "could not get server's host name from server certificate" +msgstr "no se pudo obtener el nombre de servidor desde el certificado del servidor" + +#: fe-secure-gssapi.c:201 +msgid "GSSAPI wrap error" +msgstr "error de «wrap» de GSSAPI" + +#: fe-secure-gssapi.c:208 +#, c-format +msgid "outgoing GSSAPI message would not use confidentiality" +msgstr "mensaje saliente GSSAPI no proveería confidencialidad" + +#: fe-secure-gssapi.c:215 +#, c-format +msgid "client tried to send oversize GSSAPI packet (%zu > %zu)" +msgstr "el cliente intentó enviar un paquete GSSAPI demasiado grande (%zu > %zu)" + +#: fe-secure-gssapi.c:351 fe-secure-gssapi.c:593 +#, c-format +msgid "oversize GSSAPI packet sent by the server (%zu > %zu)" +msgstr "paquete GSSAPI demasiado grande enviado por el servidor (%zu > %zu)" + +#: fe-secure-gssapi.c:390 +msgid "GSSAPI unwrap error" +msgstr "error de «unwrap» de GSSAPI" + +#: fe-secure-gssapi.c:399 +#, c-format +msgid "incoming GSSAPI message did not use confidentiality" +msgstr "mensaje GSSAPI entrante no usó confidencialidad" + +#: fe-secure-gssapi.c:656 +msgid "could not initiate GSSAPI security context" +msgstr "no se pudo iniciar un contexto de seguridad GSSAPI" + +#: fe-secure-gssapi.c:685 +msgid "GSSAPI size check error" +msgstr "error de verificación de tamaño GSSAPI" + +#: fe-secure-gssapi.c:696 +msgid "GSSAPI context establishment error" +msgstr "error de establecimiento de contexto de GSSAPI" + +#: fe-secure-openssl.c:219 fe-secure-openssl.c:319 fe-secure-openssl.c:1531 +#, c-format +msgid "SSL SYSCALL error: %s" +msgstr "ERROR en llamada SSL: %s" + +#: fe-secure-openssl.c:225 fe-secure-openssl.c:325 fe-secure-openssl.c:1534 +#, c-format +msgid "SSL SYSCALL error: EOF detected" +msgstr "ERROR en llamada SSL: detectado fin de archivo" + +#: fe-secure-openssl.c:235 fe-secure-openssl.c:335 fe-secure-openssl.c:1542 +#, c-format +msgid "SSL error: %s" +msgstr "error de SSL: %s" + +#: fe-secure-openssl.c:249 fe-secure-openssl.c:349 +#, c-format +msgid "SSL connection has been closed unexpectedly" +msgstr "la conexión SSL se ha cerrado inesperadamente" + +#: fe-secure-openssl.c:254 fe-secure-openssl.c:354 fe-secure-openssl.c:1589 +#, c-format +msgid "unrecognized SSL error code: %d" +msgstr "código de error SSL no reconocido: %d" + +#: fe-secure-openssl.c:397 +#, c-format +msgid "could not determine server certificate signature algorithm" +msgstr "no se pudo determinar el algoritmo de firma del certificado del servidor" + +#: fe-secure-openssl.c:417 +#, c-format +msgid "could not find digest for NID %s" +msgstr "no se pudo encontrar «digest» para el NID %s" + +#: fe-secure-openssl.c:426 +#, c-format +msgid "could not generate peer certificate hash" +msgstr "no se pudo generar hash de certificado de la contraparte" + +#: fe-secure-openssl.c:509 +#, c-format +msgid "SSL certificate's name entry is missing" +msgstr "falta el elemento de nombre en el certificado SSL" + +#: fe-secure-openssl.c:543 +#, c-format +msgid "SSL certificate's address entry is missing" +msgstr "falta el elemento de dirección en el certificado SSL" + +#: fe-secure-openssl.c:960 +#, c-format +msgid "could not create SSL context: %s" +msgstr "no se pudo crear un contexto SSL: %s" + +#: fe-secure-openssl.c:1002 +#, c-format +msgid "invalid value \"%s\" for minimum SSL protocol version" +msgstr "valor entero «%s» no válido para la versión mínima del protocolo SSL" + +#: fe-secure-openssl.c:1012 +#, c-format +msgid "could not set minimum SSL protocol version: %s" +msgstr "no se pudo definir la versión mínima de protocolo SSL: %s" + +#: fe-secure-openssl.c:1028 +#, c-format +msgid "invalid value \"%s\" for maximum SSL protocol version" +msgstr "valor entero «%s» no válido para la versión máxima del protocolo SSL" + +#: fe-secure-openssl.c:1038 +#, c-format +msgid "could not set maximum SSL protocol version: %s" +msgstr "no se pudo definir la versión máxima de protocolo SSL: %s" + +#: fe-secure-openssl.c:1076 +#, c-format +msgid "could not load system root certificate paths: %s" +msgstr "no se pudo cargar las rutas de los certificados raíz del sistema: %s" + +#: fe-secure-openssl.c:1093 +#, c-format +msgid "could not read root certificate file \"%s\": %s" +msgstr "no se pudo leer la lista de certificado raíz «%s»: %s" + +#: fe-secure-openssl.c:1145 +#, c-format +msgid "" +"could not get home directory to locate root certificate file\n" +"Either provide the file, use the system's trusted roots with sslrootcert=system, or change sslmode to disable server certificate verification." +msgstr "" +"no se pudo obtener el directorio «home» para ubicar el archivo del certificado raíz\n" +"Debe ya sea entregar este archivo, usar las raíces confiadas por el sistema con sslrootcert=system, o bien cambiar sslmode para inhabilitarla verificación de certificados del servidor." + +#: fe-secure-openssl.c:1148 +#, c-format +msgid "" +"root certificate file \"%s\" does not exist\n" +"Either provide the file, use the system's trusted roots with sslrootcert=system, or change sslmode to disable server certificate verification." +msgstr "" +"el archivo de certificado raíz «%s» no existe\n" +"Debe ya sea entregar este archivo, usar las raíces confiadas por el sistema con sslrootcert=system, o bien cambiar sslmode para inhabilitar la verificación de certificados del servidor." + +#: fe-secure-openssl.c:1183 +#, c-format +msgid "could not open certificate file \"%s\": %s" +msgstr "no se pudo abrir el archivo de certificado «%s»: %s" + +#: fe-secure-openssl.c:1201 +#, c-format +msgid "could not read certificate file \"%s\": %s" +msgstr "no se pudo leer el archivo de certificado «%s»: %s" + +#: fe-secure-openssl.c:1225 +#, c-format +msgid "could not establish SSL connection: %s" +msgstr "no se pudo establecer conexión SSL: %s" + +#: fe-secure-openssl.c:1257 +#, c-format +msgid "could not set SSL Server Name Indication (SNI): %s" +msgstr "no se pudo establecer el Indicador de Nombre del Servidor (SNI) de SSL: %s" + +#: fe-secure-openssl.c:1300 +#, c-format +msgid "could not load SSL engine \"%s\": %s" +msgstr "no se pudo cargar el motor SSL «%s»: %s" + +#: fe-secure-openssl.c:1311 +#, c-format +msgid "could not initialize SSL engine \"%s\": %s" +msgstr "no se pudo inicializar el motor SSL «%s»: %s" + +#: fe-secure-openssl.c:1326 +#, c-format +msgid "could not read private SSL key \"%s\" from engine \"%s\": %s" +msgstr "no se pudo leer el archivo de la llave privada SSL «%s» desde el motor «%s»: %s" + +#: fe-secure-openssl.c:1339 +#, c-format +msgid "could not load private SSL key \"%s\" from engine \"%s\": %s" +msgstr "no se pudo leer la llave privada SSL «%s» desde el motor «%s»: %s" + +#: fe-secure-openssl.c:1376 +#, c-format +msgid "certificate present, but not private key file \"%s\"" +msgstr "el certificado está presente, pero no la llave privada «%s»" + +#: fe-secure-openssl.c:1379 +#, c-format +msgid "could not stat private key file \"%s\": %m" +msgstr "no se pudo hacer stat del archivo de la llave privada «%s»: %m" + +#: fe-secure-openssl.c:1387 +#, c-format +msgid "private key file \"%s\" is not a regular file" +msgstr "el archivo de llave privada «%s» no es un archivo regular" + +#: fe-secure-openssl.c:1420 +#, c-format +msgid "private key file \"%s\" has group or world access; file must have permissions u=rw (0600) or less if owned by the current user, or permissions u=rw,g=r (0640) or less if owned by root" +msgstr "el archivo de llave privada «%s» tiene acceso de grupo o para todos; debe tener permisos u=rw (0600) o menos si es de propiedad del usuario de base de datos, o permisos u=rw,g=r (0640) o menos si es de root" + +#: fe-secure-openssl.c:1444 +#, c-format +msgid "could not load private key file \"%s\": %s" +msgstr "no se pudo cargar el archivo de la llave privada «%s»: %s" + +#: fe-secure-openssl.c:1460 +#, c-format +msgid "certificate does not match private key file \"%s\": %s" +msgstr "el certificado no coincide con la llave privada «%s»: %s" + +#: fe-secure-openssl.c:1528 +#, c-format +msgid "SSL error: certificate verify failed: %s" +msgstr "error SSL: falló la verificación de certificado: %s" + +#: fe-secure-openssl.c:1573 +#, c-format +msgid "This may indicate that the server does not support any SSL protocol version between %s and %s." +msgstr "Esto puede indicar que el servidor no soporta ninguna versión del protocolo SSL entre %s y %s." + +#: fe-secure-openssl.c:1606 +#, c-format +msgid "certificate could not be obtained: %s" +msgstr "el certificado no pudo ser obtenido: %s" + +#: fe-secure-openssl.c:1711 +#, c-format +msgid "no SSL error reported" +msgstr "código de error SSL no reportado" + +#: fe-secure-openssl.c:1720 +#, c-format +msgid "SSL error code %lu" +msgstr "código de error SSL %lu" + +#: fe-secure-openssl.c:1986 +#, c-format +msgid "WARNING: sslpassword truncated\n" +msgstr "ADVERTENCIA: sslpassword truncada\n" + +#: fe-secure.c:263 +#, c-format +msgid "could not receive data from server: %s" +msgstr "no se pudo recibir datos del servidor: %s" + +#: fe-secure.c:434 +#, c-format +msgid "could not send data to server: %s" +msgstr "no se pudo enviar datos al servidor: %s" + +#: win32.c:310 +#, c-format +msgid "unrecognized socket error: 0x%08X/%d" +msgstr "código de error de socket no reconocido: 0x%08X/%d" diff --git a/src/interfaces/libpq/po/fr.po b/src/interfaces/libpq/po/fr.po new file mode 100644 index 0000000..8c94d72 --- /dev/null +++ b/src/interfaces/libpq/po/fr.po @@ -0,0 +1,1752 @@ +# LANGUAGE message translation file for libpq +# Copyright (C) 2004-2022 PostgreSQL Global Development Group +# This file is distributed under the same license as the libpq (PostgreSQL) package. +# +# Use these quotes: « %s » +# +# Guillaume Lelarge <guillaume@lelarge.info>, 2004-2009. +# Stéphane Schildknecht <stephane.schildknecht@dalibo.com>, 2009. +# Guillaume Lelarge <guillaume@lelarge.info>, 2010-2009. +# +msgid "" +msgstr "" +"Project-Id-Version: PostgreSQL 15\n" +"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" +"POT-Creation-Date: 2023-07-29 09:10+0000\n" +"PO-Revision-Date: 2023-07-30 08:42+0200\n" +"Last-Translator: Guillaume Lelarge <guillaume@lelarge.info>\n" +"Language-Team: French <guillaume@lelarge.info>\n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Generator: Poedit 3.3.2\n" + +#: ../../port/thread.c:50 ../../port/thread.c:86 +#, c-format +msgid "could not look up local user ID %d: %s" +msgstr "n'a pas pu rechercher l'identifiant de l'utilisateur local %d : %s" + +#: ../../port/thread.c:55 ../../port/thread.c:91 +#, c-format +msgid "local user with ID %d does not exist" +msgstr "l'utilisateur local dont l'identifiant est %d n'existe pas" + +#: fe-auth-scram.c:227 +#, c-format +msgid "malformed SCRAM message (empty message)" +msgstr "message SCRAM malformé (message vide)" + +#: fe-auth-scram.c:232 +#, c-format +msgid "malformed SCRAM message (length mismatch)" +msgstr "message SCRAM malformé (pas de correspondance sur la longueur)" + +#: fe-auth-scram.c:275 +#, c-format +msgid "could not verify server signature: %s" +msgstr "n'a pas pu vérifier la signature du serveur : %s" + +#: fe-auth-scram.c:281 +#, c-format +msgid "incorrect server signature" +msgstr "signature invalide du serveur" + +#: fe-auth-scram.c:290 +#, c-format +msgid "invalid SCRAM exchange state" +msgstr "état d'échange SCRAM invalide" + +#: fe-auth-scram.c:317 +#, c-format +msgid "malformed SCRAM message (attribute \"%c\" expected)" +msgstr "message SCRAM malformé (attribut « %c » attendu)" + +#: fe-auth-scram.c:326 +#, c-format +msgid "malformed SCRAM message (expected character \"=\" for attribute \"%c\")" +msgstr "message SCRAM malformé (caractère « = » attendu pour l'attribut « %c »)" + +#: fe-auth-scram.c:366 +#, c-format +msgid "could not generate nonce" +msgstr "n'a pas pu générer le nonce" + +#: fe-auth-scram.c:375 fe-auth-scram.c:448 fe-auth-scram.c:600 +#: fe-auth-scram.c:620 fe-auth-scram.c:644 fe-auth-scram.c:658 +#: fe-auth-scram.c:704 fe-auth-scram.c:740 fe-auth-scram.c:914 fe-auth.c:296 +#: fe-auth.c:369 fe-auth.c:403 fe-auth.c:618 fe-auth.c:729 fe-auth.c:1210 +#: fe-auth.c:1375 fe-connect.c:925 fe-connect.c:1759 fe-connect.c:1921 +#: fe-connect.c:3291 fe-connect.c:4496 fe-connect.c:5161 fe-connect.c:5416 +#: fe-connect.c:5534 fe-connect.c:5781 fe-connect.c:5861 fe-connect.c:5959 +#: fe-connect.c:6210 fe-connect.c:6237 fe-connect.c:6313 fe-connect.c:6336 +#: fe-connect.c:6360 fe-connect.c:6395 fe-connect.c:6481 fe-connect.c:6489 +#: fe-connect.c:6846 fe-connect.c:6996 fe-exec.c:527 fe-exec.c:1321 +#: fe-exec.c:3111 fe-exec.c:4071 fe-exec.c:4235 fe-gssapi-common.c:109 +#: fe-lobj.c:870 fe-protocol3.c:204 fe-protocol3.c:228 fe-protocol3.c:256 +#: fe-protocol3.c:273 fe-protocol3.c:353 fe-protocol3.c:720 fe-protocol3.c:959 +#: fe-protocol3.c:1770 fe-protocol3.c:2170 fe-secure-common.c:110 +#: fe-secure-gssapi.c:500 fe-secure-openssl.c:434 fe-secure-openssl.c:1285 +#, c-format +msgid "out of memory" +msgstr "mémoire épuisée" + +#: fe-auth-scram.c:382 +#, c-format +msgid "could not encode nonce" +msgstr "n'a pas pu encoder le nonce" + +#: fe-auth-scram.c:570 +#, c-format +msgid "could not calculate client proof: %s" +msgstr "n'a pas pu calculer la preuve du client : %s" + +#: fe-auth-scram.c:585 +#, c-format +msgid "could not encode client proof" +msgstr "n'a pas pu encoder la preuve du client" + +#: fe-auth-scram.c:637 +#, c-format +msgid "invalid SCRAM response (nonce mismatch)" +msgstr "réponse SCRAM invalide (pas de correspondance sur nonce)" + +#: fe-auth-scram.c:667 +#, c-format +msgid "malformed SCRAM message (invalid salt)" +msgstr "message SCRAM malformé (sel invalide)" + +#: fe-auth-scram.c:680 +#, c-format +msgid "malformed SCRAM message (invalid iteration count)" +msgstr "message SCRAM malformé (décompte d'itération invalide)" + +#: fe-auth-scram.c:685 +#, c-format +msgid "malformed SCRAM message (garbage at end of server-first-message)" +msgstr "message SCRAM malformé (problème à la fin du server-first-message)" + +#: fe-auth-scram.c:719 +#, c-format +msgid "error received from server in SCRAM exchange: %s" +msgstr "réception d'une erreur du serveur dans l'échange SCRAM : %s" + +#: fe-auth-scram.c:734 +#, c-format +msgid "malformed SCRAM message (garbage at end of server-final-message)" +msgstr "message SCRAM malformé (problème à la fin du server-final-message)" + +#: fe-auth-scram.c:751 +#, c-format +msgid "malformed SCRAM message (invalid server signature)" +msgstr "message SCRAM malformé (signature serveur invalide)" + +#: fe-auth-scram.c:923 +msgid "could not generate random salt" +msgstr "n'a pas pu générer le sel aléatoire" + +#: fe-auth.c:77 +#, c-format +msgid "out of memory allocating GSSAPI buffer (%d)" +msgstr "mémoire épuisée lors de l'allocation du tampon GSSAPI (%d)" + +#: fe-auth.c:138 +msgid "GSSAPI continuation error" +msgstr "erreur de suite GSSAPI" + +#: fe-auth.c:168 fe-auth.c:397 fe-gssapi-common.c:97 fe-secure-common.c:99 +#: fe-secure-common.c:173 +#, c-format +msgid "host name must be specified" +msgstr "le nom d'hôte doit être précisé" + +#: fe-auth.c:174 +#, c-format +msgid "duplicate GSS authentication request" +msgstr "requête d'authentification GSS dupliquée" + +#: fe-auth.c:238 +#, c-format +msgid "out of memory allocating SSPI buffer (%d)" +msgstr "mémoire épuisée lors de l'allocation du tampon SSPI (%d)" + +#: fe-auth.c:285 +msgid "SSPI continuation error" +msgstr "erreur de suite SSPI" + +#: fe-auth.c:359 +#, c-format +msgid "duplicate SSPI authentication request" +msgstr "requête d'authentification SSPI dupliquée" + +#: fe-auth.c:384 +msgid "could not acquire SSPI credentials" +msgstr "n'a pas pu obtenir les pièces d'identité SSPI" + +#: fe-auth.c:437 +#, c-format +msgid "channel binding required, but SSL not in use" +msgstr "lien de canal requis, mais SSL non utilisé" + +#: fe-auth.c:443 +#, c-format +msgid "duplicate SASL authentication request" +msgstr "requête d'authentification SASL dupliquée" + +#: fe-auth.c:501 +#, c-format +msgid "channel binding is required, but client does not support it" +msgstr "le lien de canal SCRAM est requis mais le client ne supporte par cette option" + +#: fe-auth.c:517 +#, c-format +msgid "server offered SCRAM-SHA-256-PLUS authentication over a non-SSL connection" +msgstr "le serveur a proposé une authentification SCRAM-SHA-256-PLUS sur une connexion non SSL" + +#: fe-auth.c:531 +#, c-format +msgid "none of the server's SASL authentication mechanisms are supported" +msgstr "aucun des mécanismes d'authentification SASL du serveur n'est supporté" + +#: fe-auth.c:538 +#, c-format +msgid "channel binding is required, but server did not offer an authentication method that supports channel binding" +msgstr "Lien de canal requis, mais le serveur ne propose pas de méthode d'authentification le supportant" + +#: fe-auth.c:641 +#, c-format +msgid "out of memory allocating SASL buffer (%d)" +msgstr "mémoire épuisée lors de l'allocation du tampon SASL (%d)" + +#: fe-auth.c:665 +#, c-format +msgid "AuthenticationSASLFinal received from server, but SASL authentication was not completed" +msgstr "AuthenticationSASLFinal reçu du serveur mais l'authentification SASL n'a pas été terminée" + +#: fe-auth.c:675 +#, c-format +msgid "no client response found after SASL exchange success" +msgstr "aucune réponse client trouvée après le succès de l'échange SASL" + +#: fe-auth.c:738 fe-auth.c:745 fe-auth.c:1358 fe-auth.c:1369 +#, c-format +msgid "could not encrypt password: %s" +msgstr "n'a pas pu chiffré le mot de passe : %s" + +#: fe-auth.c:773 +msgid "server requested a cleartext password" +msgstr "le serveur a demandé un mot de passe en clair" + +#: fe-auth.c:775 +msgid "server requested a hashed password" +msgstr "le serveur a demandé un mot de passe haché" + +#: fe-auth.c:778 +msgid "server requested GSSAPI authentication" +msgstr "le serveur a demandé l'authentification GSSAPI" + +#: fe-auth.c:780 +msgid "server requested SSPI authentication" +msgstr "le serveur a demandé l'authentification SSPI" + +#: fe-auth.c:784 +msgid "server requested SASL authentication" +msgstr "le serveur a demandé l'authentification SASL" + +#: fe-auth.c:787 +msgid "server requested an unknown authentication type" +msgstr "le serveur a demandé un type d'authentification inconnu" + +#: fe-auth.c:820 +#, c-format +msgid "server did not request an SSL certificate" +msgstr "le serveur n'a pas réclamé de certificat SSL" + +#: fe-auth.c:825 +#, c-format +msgid "server accepted connection without a valid SSL certificate" +msgstr "le serveur a accepté la connexion sans certificat SSL valide" + +#: fe-auth.c:879 +msgid "server did not complete authentication" +msgstr "le serveur n'a pas terminé l'authentification" + +#: fe-auth.c:913 +#, c-format +msgid "authentication method requirement \"%s\" failed: %s" +msgstr "la demande de la méthode d'authentification « %s » a échoué : %s" + +#: fe-auth.c:936 +#, c-format +msgid "channel binding required, but server authenticated client without channel binding" +msgstr "lien de canal requis, mais le serveur a authentifié le client sans lien de canal" + +#: fe-auth.c:941 +#, c-format +msgid "channel binding required but not supported by server's authentication request" +msgstr "lien de canal requis, mais non supporté par la requête d'authentification du serveur" + +#: fe-auth.c:975 +#, c-format +msgid "Kerberos 4 authentication not supported" +msgstr "authentification Kerberos 4 non supportée" + +#: fe-auth.c:979 +#, c-format +msgid "Kerberos 5 authentication not supported" +msgstr "authentification Kerberos 5 non supportée" + +#: fe-auth.c:1049 +#, c-format +msgid "GSSAPI authentication not supported" +msgstr "authentification GSSAPI non supportée" + +#: fe-auth.c:1080 +#, c-format +msgid "SSPI authentication not supported" +msgstr "authentification SSPI non supportée" + +#: fe-auth.c:1087 +#, c-format +msgid "Crypt authentication not supported" +msgstr "authentification crypt non supportée" + +#: fe-auth.c:1151 +#, c-format +msgid "authentication method %u not supported" +msgstr "méthode d'authentification %u non supportée" + +#: fe-auth.c:1197 +#, c-format +msgid "user name lookup failure: error code %lu" +msgstr "échec de la recherche du nom d'utilisateur : code d'erreur %lu" + +#: fe-auth.c:1321 +#, c-format +msgid "unexpected shape of result set returned for SHOW" +msgstr "forme du résultat inattendu pour SHOW" + +#: fe-auth.c:1329 +#, c-format +msgid "password_encryption value too long" +msgstr "la valeur de password_encryption est trop longue" + +#: fe-auth.c:1379 +#, c-format +msgid "unrecognized password encryption algorithm \"%s\"" +msgstr "algorithme de chiffrement du mot de passe « %s » non reconnu" + +#: fe-connect.c:1132 +#, c-format +msgid "could not match %d host names to %d hostaddr values" +msgstr "n'a pas pu faire correspondre les %d noms d'hôte aux %d valeurs hostaddr" + +#: fe-connect.c:1212 +#, c-format +msgid "could not match %d port numbers to %d hosts" +msgstr "n'a pas pu faire correspondre les %d numéros de port aux %d hôtes" + +#: fe-connect.c:1337 +#, c-format +msgid "negative require_auth method \"%s\" cannot be mixed with non-negative methods" +msgstr "la méthode négative require_auth « %s » ne peut pas être mélangée avec des méthodes non négatives" + +#: fe-connect.c:1350 +#, c-format +msgid "require_auth method \"%s\" cannot be mixed with negative methods" +msgstr "la méthode require_auth « %s » ne peut pas être mélangée avec des méthodes négatives" + +#: fe-connect.c:1410 fe-connect.c:1461 fe-connect.c:1503 fe-connect.c:1559 +#: fe-connect.c:1567 fe-connect.c:1598 fe-connect.c:1644 fe-connect.c:1684 +#: fe-connect.c:1705 +#, c-format +msgid "invalid %s value: \"%s\"" +msgstr "valeur %s invalide : « %s »" + +#: fe-connect.c:1443 +#, c-format +msgid "require_auth method \"%s\" is specified more than once" +msgstr "require_auth method \"%s\" est spécifié plus d'une fois" + +#: fe-connect.c:1484 fe-connect.c:1523 fe-connect.c:1606 +#, c-format +msgid "%s value \"%s\" invalid when SSL support is not compiled in" +msgstr "valeur %s « %s » invalide si le support SSL n'est pas compilé" + +#: fe-connect.c:1546 +#, c-format +msgid "weak sslmode \"%s\" may not be used with sslrootcert=system (use \"verify-full\")" +msgstr "le sslmode fiable « %s » pourrait ne pas être utilisé avec sslrootcert=system (utilisez \"verify-full\")" + +#: fe-connect.c:1584 +#, c-format +msgid "invalid SSL protocol version range" +msgstr "intervalle de version invalide pour le protocole SSL" + +#: fe-connect.c:1621 +#, c-format +msgid "%s value \"%s\" is not supported (check OpenSSL version)" +msgstr "%s la valeur « %s » n'est pas supportée (vérifiez la version d'OpenSSL)" + +#: fe-connect.c:1651 +#, c-format +msgid "gssencmode value \"%s\" invalid when GSSAPI support is not compiled in" +msgstr "valeur gssencmode « %s » invalide si le support GSSAPI n'est pas compilé" + +#: fe-connect.c:1944 +#, c-format +msgid "could not set socket to TCP no delay mode: %s" +msgstr "n'a pas pu activer le mode TCP sans délai pour la socket : %s" + +#: fe-connect.c:2003 +#, c-format +msgid "connection to server on socket \"%s\" failed: " +msgstr "la connexion au serveur sur le socket « %s » a échoué : " + +#: fe-connect.c:2029 +#, c-format +msgid "connection to server at \"%s\" (%s), port %s failed: " +msgstr "la connexion au serveur sur « %s » (%s), port %s a échoué : " + +#: fe-connect.c:2034 +#, c-format +msgid "connection to server at \"%s\", port %s failed: " +msgstr "la connexion au serveur sur « %s », port %s a échoué : " + +#: fe-connect.c:2057 +#, c-format +msgid "\tIs the server running locally and accepting connections on that socket?" +msgstr "\tLe serveur est-il actif localement et accepte-t-il les connexions sur ce socket ?" + +#: fe-connect.c:2059 +#, c-format +msgid "\tIs the server running on that host and accepting TCP/IP connections?" +msgstr "\tLe serveur est-il actif sur cet hôte et accepte-t-il les connexions ?" + +#: fe-connect.c:2122 +#, c-format +msgid "invalid integer value \"%s\" for connection option \"%s\"" +msgstr "valeur entière « %s » invalide pour l'option de connexion « %s »" + +#: fe-connect.c:2151 fe-connect.c:2185 fe-connect.c:2220 fe-connect.c:2318 +#: fe-connect.c:2973 +#, c-format +msgid "%s(%s) failed: %s" +msgstr "échec de %s(%s) : %s" + +#: fe-connect.c:2284 +#, c-format +msgid "%s(%s) failed: error code %d" +msgstr "échec de %s(%s) : code d'erreur %d" + +#: fe-connect.c:2597 +#, c-format +msgid "invalid connection state, probably indicative of memory corruption" +msgstr "état de connexion invalide, indique probablement une corruption de mémoire" + +#: fe-connect.c:2676 +#, c-format +msgid "invalid port number: \"%s\"" +msgstr "numéro de port invalide : « %s »" + +#: fe-connect.c:2690 +#, c-format +msgid "could not translate host name \"%s\" to address: %s" +msgstr "n'a pas pu traduire le nom d'hôte « %s » en adresse : %s" + +#: fe-connect.c:2702 +#, c-format +msgid "could not parse network address \"%s\": %s" +msgstr "n'a pas pu analyser l'adresse réseau « %s » : %s" + +#: fe-connect.c:2713 +#, c-format +msgid "Unix-domain socket path \"%s\" is too long (maximum %d bytes)" +msgstr "Le chemin du socket de domaine Unix, « %s », est trop (maximum %d octets)" + +#: fe-connect.c:2727 +#, c-format +msgid "could not translate Unix-domain socket path \"%s\" to address: %s" +msgstr "n'a pas pu traduire le chemin de la socket du domaine Unix « %s » en adresse : %s" + +#: fe-connect.c:2901 +#, c-format +msgid "could not create socket: %s" +msgstr "n'a pas pu créer la socket : %s" + +#: fe-connect.c:2932 +#, c-format +msgid "could not set socket to nonblocking mode: %s" +msgstr "n'a pas pu activer le mode non-bloquant pour la socket : %s" + +#: fe-connect.c:2943 +#, c-format +msgid "could not set socket to close-on-exec mode: %s" +msgstr "n'a pas pu paramétrer la socket en mode close-on-exec : %s" + +#: fe-connect.c:2961 +#, c-format +msgid "keepalives parameter must be an integer" +msgstr "le paramètre keepalives doit être un entier" + +#: fe-connect.c:3100 +#, c-format +msgid "could not get socket error status: %s" +msgstr "n'a pas pu déterminer le statut d'erreur de la socket : %s" + +#: fe-connect.c:3127 +#, c-format +msgid "could not get client address from socket: %s" +msgstr "n'a pas pu obtenir l'adresse du client depuis la socket : %s" + +#: fe-connect.c:3165 +#, c-format +msgid "requirepeer parameter is not supported on this platform" +msgstr "le paramètre requirepeer n'est pas supporté sur cette plateforme" + +#: fe-connect.c:3167 +#, c-format +msgid "could not get peer credentials: %s" +msgstr "n'a pas pu obtenir l'authentification de l'autre : %s" + +#: fe-connect.c:3180 +#, c-format +msgid "requirepeer specifies \"%s\", but actual peer user name is \"%s\"" +msgstr "requirepeer indique « %s » mais le nom de l'utilisateur réel est « %s »" + +#: fe-connect.c:3221 +#, c-format +msgid "could not send GSSAPI negotiation packet: %s" +msgstr "n'a pas pu transmettre le paquet de négociation GSSAPI : %s" + +#: fe-connect.c:3233 +#, c-format +msgid "GSSAPI encryption required but was impossible (possibly no credential cache, no server support, or using a local socket)" +msgstr "le chiffrage avec GSSAPI était requis, mais impossible (potentiellement pas de cache, de support serveur ou de socket local)" + +#: fe-connect.c:3274 +#, c-format +msgid "could not send SSL negotiation packet: %s" +msgstr "n'a pas pu transmettre le paquet de négociation SSL : %s" + +#: fe-connect.c:3303 +#, c-format +msgid "could not send startup packet: %s" +msgstr "n'a pas pu transmettre le paquet de démarrage : %s" + +#: fe-connect.c:3378 +#, c-format +msgid "server does not support SSL, but SSL was required" +msgstr "le serveur ne supporte pas SSL alors que SSL était réclamé" + +#: fe-connect.c:3404 +#, c-format +msgid "received invalid response to SSL negotiation: %c" +msgstr "a reçu une réponse invalide à la négociation SSL : %c" + +#: fe-connect.c:3424 +#, c-format +msgid "received unencrypted data after SSL response" +msgstr "a reçu des données non chiffrées après la réponse SSL" + +#: fe-connect.c:3504 +#, c-format +msgid "server doesn't support GSSAPI encryption, but it was required" +msgstr "le serveur ne supporte pas le chiffrage GSSAPI alors qu'il était réclamé" + +#: fe-connect.c:3515 +#, c-format +msgid "received invalid response to GSSAPI negotiation: %c" +msgstr "a reçu une réponse invalide à la négociation GSSAPI : %c" + +#: fe-connect.c:3533 +#, c-format +msgid "received unencrypted data after GSSAPI encryption response" +msgstr "a reçu des données non chiffrées après la réponse de chiffrement GSSAPI" + +#: fe-connect.c:3598 +#, c-format +msgid "expected authentication request from server, but received %c" +msgstr "attendait une requête d'authentification du serveur, mais a reçu %c" + +#: fe-connect.c:3625 fe-connect.c:3794 +#, c-format +msgid "received invalid authentication request" +msgstr "méthode d'authentification invalide reçue" + +#: fe-connect.c:3630 fe-connect.c:3779 +#, c-format +msgid "received invalid protocol negotiation message" +msgstr "a reçu un message invalide pour la négociation du protocole" + +#: fe-connect.c:3648 fe-connect.c:3702 +#, c-format +msgid "received invalid error message" +msgstr "a reçu un message d'erreur invalide" + +#: fe-connect.c:3865 +#, c-format +msgid "unexpected message from server during startup" +msgstr "message inattendu du serveur lors du démarrage" + +#: fe-connect.c:3956 +#, c-format +msgid "session is read-only" +msgstr "la session est en lecture seule" + +#: fe-connect.c:3958 +#, c-format +msgid "session is not read-only" +msgstr "la session n'est pas en lecture seule" + +#: fe-connect.c:4011 +#, c-format +msgid "server is in hot standby mode" +msgstr "le serveur est dans le mode hot standby" + +#: fe-connect.c:4013 +#, c-format +msgid "server is not in hot standby mode" +msgstr "le serveur n'est pas dans le mode hot standby" + +#: fe-connect.c:4129 fe-connect.c:4179 +#, c-format +msgid "\"%s\" failed" +msgstr "échec de « %s »" + +#: fe-connect.c:4193 +#, c-format +msgid "invalid connection state %d, probably indicative of memory corruption" +msgstr "état de connexion invalide (%d), indiquant probablement une corruption de mémoire" + +#: fe-connect.c:5174 +#, c-format +msgid "invalid LDAP URL \"%s\": scheme must be ldap://" +msgstr "URL LDAP « %s » invalide : le schéma doit être ldap://" + +#: fe-connect.c:5189 +#, c-format +msgid "invalid LDAP URL \"%s\": missing distinguished name" +msgstr "URL LDAP « %s » invalide : le « distinguished name » manque" + +#: fe-connect.c:5201 fe-connect.c:5259 +#, c-format +msgid "invalid LDAP URL \"%s\": must have exactly one attribute" +msgstr "URL LDAP « %s » invalide : doit avoir exactement un attribut" + +#: fe-connect.c:5213 fe-connect.c:5275 +#, c-format +msgid "invalid LDAP URL \"%s\": must have search scope (base/one/sub)" +msgstr "URL LDAP « %s » invalide : doit avoir une échelle de recherche (base/un/sous)" + +#: fe-connect.c:5225 +#, c-format +msgid "invalid LDAP URL \"%s\": no filter" +msgstr "URL LDAP « %s » invalide : aucun filtre" + +#: fe-connect.c:5247 +#, c-format +msgid "invalid LDAP URL \"%s\": invalid port number" +msgstr "URL LDAP « %s » invalide : numéro de port invalide" + +#: fe-connect.c:5284 +#, c-format +msgid "could not create LDAP structure" +msgstr "n'a pas pu créer la structure LDAP" + +#: fe-connect.c:5359 +#, c-format +msgid "lookup on LDAP server failed: %s" +msgstr "échec de la recherche sur le serveur LDAP : %s" + +#: fe-connect.c:5369 +#, c-format +msgid "more than one entry found on LDAP lookup" +msgstr "plusieurs entrées trouvées pendant la recherche LDAP" + +#: fe-connect.c:5371 fe-connect.c:5382 +#, c-format +msgid "no entry found on LDAP lookup" +msgstr "aucune entrée trouvée pendant la recherche LDAP" + +#: fe-connect.c:5392 fe-connect.c:5404 +#, c-format +msgid "attribute has no values on LDAP lookup" +msgstr "l'attribut n'a pas de valeur après la recherche LDAP" + +#: fe-connect.c:5455 fe-connect.c:5474 fe-connect.c:5998 +#, c-format +msgid "missing \"=\" after \"%s\" in connection info string" +msgstr "« = » manquant après « %s » dans la chaîne des paramètres de connexion" + +#: fe-connect.c:5545 fe-connect.c:6181 fe-connect.c:6979 +#, c-format +msgid "invalid connection option \"%s\"" +msgstr "option de connexion « %s » invalide" + +#: fe-connect.c:5560 fe-connect.c:6046 +#, c-format +msgid "unterminated quoted string in connection info string" +msgstr "guillemets non refermés dans la chaîne des paramètres de connexion" + +#: fe-connect.c:5640 +#, c-format +msgid "definition of service \"%s\" not found" +msgstr "définition du service « %s » introuvable" + +#: fe-connect.c:5666 +#, c-format +msgid "service file \"%s\" not found" +msgstr "fichier de service « %s » introuvable" + +#: fe-connect.c:5679 +#, c-format +msgid "line %d too long in service file \"%s\"" +msgstr "ligne %d trop longue dans le fichier service « %s »" + +#: fe-connect.c:5750 fe-connect.c:5793 +#, c-format +msgid "syntax error in service file \"%s\", line %d" +msgstr "erreur de syntaxe dans le fichier service « %s », ligne %d" + +#: fe-connect.c:5761 +#, c-format +msgid "nested service specifications not supported in service file \"%s\", line %d" +msgstr "spécifications imbriquées de service non supportées dans le fichier service « %s », ligne %d" + +#: fe-connect.c:6500 +#, c-format +msgid "invalid URI propagated to internal parser routine: \"%s\"" +msgstr "URI invalide propagée à la routine d'analyse interne : « %s »" + +#: fe-connect.c:6577 +#, c-format +msgid "end of string reached when looking for matching \"]\" in IPv6 host address in URI: \"%s\"" +msgstr "" +"fin de chaîne atteinte lors de la recherche du « ] » correspondant dans\n" +"l'adresse IPv6 de l'hôte indiquée dans l'URI : « %s »" + +#: fe-connect.c:6584 +#, c-format +msgid "IPv6 host address may not be empty in URI: \"%s\"" +msgstr "l'adresse IPv6 de l'hôte ne peut pas être vide dans l'URI : « %s »" + +#: fe-connect.c:6599 +#, c-format +msgid "unexpected character \"%c\" at position %d in URI (expected \":\" or \"/\"): \"%s\"" +msgstr "caractère « %c » inattendu à la position %d de l'URI (caractère « : » ou « / » attendu) : « %s »" + +#: fe-connect.c:6728 +#, c-format +msgid "extra key/value separator \"=\" in URI query parameter: \"%s\"" +msgstr "séparateur « = » de clé/valeur en trop dans le paramètre de requête URI : « %s »" + +#: fe-connect.c:6748 +#, c-format +msgid "missing key/value separator \"=\" in URI query parameter: \"%s\"" +msgstr "séparateur « = » de clé/valeur manquant dans le paramètre de requête URI : « %s »" + +#: fe-connect.c:6800 +#, c-format +msgid "invalid URI query parameter: \"%s\"" +msgstr "paramètre de la requête URI invalide : « %s »" + +#: fe-connect.c:6874 +#, c-format +msgid "invalid percent-encoded token: \"%s\"" +msgstr "jeton encodé en pourcentage invalide : « %s »" + +#: fe-connect.c:6884 +#, c-format +msgid "forbidden value %%00 in percent-encoded value: \"%s\"" +msgstr "valeur %%00 interdite dans la valeur codée en pourcentage : « %s »" + +#: fe-connect.c:7248 +msgid "connection pointer is NULL\n" +msgstr "le pointeur de connexion est NULL\n" + +#: fe-connect.c:7256 fe-exec.c:710 fe-exec.c:970 fe-exec.c:3292 +#: fe-protocol3.c:974 fe-protocol3.c:1007 +msgid "out of memory\n" +msgstr "mémoire épuisée\n" + +#: fe-connect.c:7547 +#, c-format +msgid "WARNING: password file \"%s\" is not a plain file\n" +msgstr "ATTENTION : le fichier de mots de passe « %s » n'est pas un fichier texte\n" + +#: fe-connect.c:7556 +#, c-format +msgid "WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n" +msgstr "" +"ATTENTION : le fichier de mots de passe « %s » a des droits d'accès en\n" +"lecture pour le groupe ou universel ; les droits devraient être u=rw (0600)\n" +"ou inférieur\n" + +#: fe-connect.c:7663 +#, c-format +msgid "password retrieved from file \"%s\"" +msgstr "mot de passe récupéré dans le fichier « %s »" + +#: fe-exec.c:466 fe-exec.c:3366 +#, c-format +msgid "row number %d is out of range 0..%d" +msgstr "le numéro de ligne %d est en dehors des limites 0..%d" + +#: fe-exec.c:528 fe-protocol3.c:1976 +#, c-format +msgid "%s" +msgstr "%s" + +#: fe-exec.c:831 +#, c-format +msgid "write to server failed" +msgstr "échec en écriture vers le serveur" + +#: fe-exec.c:869 +#, c-format +msgid "no error text available" +msgstr "aucun texte d'erreur disponible" + +#: fe-exec.c:958 +msgid "NOTICE" +msgstr "NOTICE" + +#: fe-exec.c:1016 +msgid "PGresult cannot support more than INT_MAX tuples" +msgstr "PGresult ne supporte pas plus de INT_MAX lignes" + +#: fe-exec.c:1028 +msgid "size_t overflow" +msgstr "saturation de size_t" + +#: fe-exec.c:1444 fe-exec.c:1513 fe-exec.c:1559 +#, c-format +msgid "command string is a null pointer" +msgstr "la chaîne de commande est un pointeur nul" + +#: fe-exec.c:1450 fe-exec.c:2888 +#, c-format +msgid "%s not allowed in pipeline mode" +msgstr "%s non autorisé dans le mode pipeline" + +#: fe-exec.c:1518 fe-exec.c:1564 fe-exec.c:1658 +#, c-format +msgid "number of parameters must be between 0 and %d" +msgstr "le nombre de paramètres doit être compris entre 0 et %d" + +#: fe-exec.c:1554 fe-exec.c:1653 +#, c-format +msgid "statement name is a null pointer" +msgstr "le nom de l'instruction est un pointeur nul" + +#: fe-exec.c:1695 fe-exec.c:3220 +#, c-format +msgid "no connection to the server" +msgstr "aucune connexion au serveur" + +#: fe-exec.c:1703 fe-exec.c:3228 +#, c-format +msgid "another command is already in progress" +msgstr "une autre commande est déjà en cours" + +#: fe-exec.c:1733 +#, c-format +msgid "cannot queue commands during COPY" +msgstr "ne peut pas mettre en queue les commandes lors du COPY" + +#: fe-exec.c:1850 +#, c-format +msgid "length must be given for binary parameter" +msgstr "la longueur doit être indiquée pour les paramètres binaires" + +#: fe-exec.c:2171 +#, c-format +msgid "unexpected asyncStatus: %d" +msgstr "asyncStatus inattendu : %d" + +#: fe-exec.c:2327 +#, c-format +msgid "synchronous command execution functions are not allowed in pipeline mode" +msgstr "les fonctions d'exécution de commande synchrone ne sont pas autorisées en mode pipeline" + +#: fe-exec.c:2344 +msgid "COPY terminated by new PQexec" +msgstr "COPY terminé par un nouveau PQexec" + +#: fe-exec.c:2360 +#, c-format +msgid "PQexec not allowed during COPY BOTH" +msgstr "PQexec non autorisé pendant COPY BOTH" + +#: fe-exec.c:2586 fe-exec.c:2641 fe-exec.c:2709 fe-protocol3.c:1907 +#, c-format +msgid "no COPY in progress" +msgstr "aucun COPY en cours" + +#: fe-exec.c:2895 +#, c-format +msgid "connection in wrong state" +msgstr "connexion dans un état erroné" + +#: fe-exec.c:2938 +#, c-format +msgid "cannot enter pipeline mode, connection not idle" +msgstr "ne peut pas entrer dans le mode pipeline, connexion active" + +#: fe-exec.c:2974 fe-exec.c:2995 +#, c-format +msgid "cannot exit pipeline mode with uncollected results" +msgstr "ne peut pas sortir du mode pipeline avec des résultats non récupérés" + +#: fe-exec.c:2978 +#, c-format +msgid "cannot exit pipeline mode while busy" +msgstr "ne peut pas sortir du mode pipeline alors qu'il est occupé" + +#: fe-exec.c:2989 +#, c-format +msgid "cannot exit pipeline mode while in COPY" +msgstr "ne peut pas sortir du mode pipeline pendant un COPY" + +#: fe-exec.c:3154 +#, c-format +msgid "cannot send pipeline when not in pipeline mode" +msgstr "ne peut pas envoyer le pipeline lorsqu'il n'est pas en mode pipeline" + +#: fe-exec.c:3255 +msgid "invalid ExecStatusType code" +msgstr "code ExecStatusType invalide" + +#: fe-exec.c:3282 +msgid "PGresult is not an error result\n" +msgstr "PGresult n'est pas un résultat d'erreur\n" + +#: fe-exec.c:3350 fe-exec.c:3373 +#, c-format +msgid "column number %d is out of range 0..%d" +msgstr "le numéro de colonne %d est en dehors des limites 0..%d" + +#: fe-exec.c:3388 +#, c-format +msgid "parameter number %d is out of range 0..%d" +msgstr "le numéro de paramètre %d est en dehors des limites 0..%d" + +#: fe-exec.c:3699 +#, c-format +msgid "could not interpret result from server: %s" +msgstr "n'a pas pu interpréter la réponse du serveur : %s" + +#: fe-exec.c:3964 fe-exec.c:4054 +#, c-format +msgid "incomplete multibyte character" +msgstr "caractère multi-octet incomplet" + +#: fe-gssapi-common.c:122 +msgid "GSSAPI name import error" +msgstr "erreur d'import du nom GSSAPI" + +#: fe-lobj.c:144 fe-lobj.c:207 fe-lobj.c:397 fe-lobj.c:487 fe-lobj.c:560 +#: fe-lobj.c:956 fe-lobj.c:963 fe-lobj.c:970 fe-lobj.c:977 fe-lobj.c:984 +#: fe-lobj.c:991 fe-lobj.c:998 fe-lobj.c:1005 +#, c-format +msgid "cannot determine OID of function %s" +msgstr "ne peut pas déterminer l'OID de la fonction %s" + +#: fe-lobj.c:160 +#, c-format +msgid "argument of lo_truncate exceeds integer range" +msgstr "l'argument de lo_truncate dépasse l'échelle des entiers" + +#: fe-lobj.c:262 +#, c-format +msgid "argument of lo_read exceeds integer range" +msgstr "l'argument de lo_read dépasse l'échelle des entiers" + +#: fe-lobj.c:313 +#, c-format +msgid "argument of lo_write exceeds integer range" +msgstr "l'argument de lo_write dépasse l'échelle des entiers" + +#: fe-lobj.c:669 fe-lobj.c:780 +#, c-format +msgid "could not open file \"%s\": %s" +msgstr "n'a pas pu ouvrir le fichier « %s » : %s" + +#: fe-lobj.c:725 +#, c-format +msgid "could not read from file \"%s\": %s" +msgstr "n'a pas pu lire le fichier « %s » : %s" + +#: fe-lobj.c:801 fe-lobj.c:824 +#, c-format +msgid "could not write to file \"%s\": %s" +msgstr "n'a pas pu écrire dans le fichier « %s » : %s" + +#: fe-lobj.c:908 +#, c-format +msgid "query to initialize large object functions did not return data" +msgstr "la requête d'initialisation des fonctions pour « Larges Objects » ne renvoie pas de données" + +#: fe-misc.c:240 +#, c-format +msgid "integer of size %lu not supported by pqGetInt" +msgstr "entier de taille %lu non supporté par pqGetInt" + +#: fe-misc.c:273 +#, c-format +msgid "integer of size %lu not supported by pqPutInt" +msgstr "entier de taille %lu non supporté par pqPutInt" + +#: fe-misc.c:573 +#, c-format +msgid "connection not open" +msgstr "la connexion n'est pas active" + +#: fe-misc.c:751 fe-secure-openssl.c:215 fe-secure-openssl.c:315 +#: fe-secure.c:257 fe-secure.c:419 +#, c-format +msgid "" +"server closed the connection unexpectedly\n" +"\tThis probably means the server terminated abnormally\n" +"\tbefore or while processing the request." +msgstr "" +"la connexion au serveur a été coupée de façon inattendue\n" +"\tLe serveur s'est peut-être arrêté anormalement avant ou durant le\n" +"\ttraitement de la requête." + +#: fe-misc.c:818 +msgid "connection not open\n" +msgstr "la connexion n'est pas active\n" + +#: fe-misc.c:1003 +#, c-format +msgid "timeout expired" +msgstr "le délai est dépassé" + +#: fe-misc.c:1047 +#, c-format +msgid "invalid socket" +msgstr "socket invalide" + +#: fe-misc.c:1069 +#, c-format +msgid "%s() failed: %s" +msgstr "échec de %s() : %s" + +#: fe-protocol3.c:182 +#, c-format +msgid "message type 0x%02x arrived from server while idle" +msgstr "le message de type 0x%02x est arrivé alors que le serveur était en attente" + +#: fe-protocol3.c:385 +#, c-format +msgid "server sent data (\"D\" message) without prior row description (\"T\" message)" +msgstr "" +"le serveur a envoyé des données (message « D ») sans description préalable\n" +"de la ligne (message « T »)" + +#: fe-protocol3.c:427 +#, c-format +msgid "unexpected response from server; first received character was \"%c\"" +msgstr "réponse inattendue du serveur, le premier caractère reçu étant « %c »" + +#: fe-protocol3.c:450 +#, c-format +msgid "message contents do not agree with length in message type \"%c\"" +msgstr "le contenu du message ne correspond pas avec la longueur du type de message « %c »" + +#: fe-protocol3.c:468 +#, c-format +msgid "lost synchronization with server: got message type \"%c\", length %d" +msgstr "synchronisation perdue avec le serveur : a reçu le type de message « %c », longueur %d" + +#: fe-protocol3.c:520 fe-protocol3.c:560 +msgid "insufficient data in \"T\" message" +msgstr "données insuffisantes dans le message « T »" + +#: fe-protocol3.c:631 fe-protocol3.c:837 +msgid "out of memory for query result" +msgstr "mémoire épuisée pour le résultat de la requête" + +#: fe-protocol3.c:700 +msgid "insufficient data in \"t\" message" +msgstr "données insuffisantes dans le message « t »" + +#: fe-protocol3.c:759 fe-protocol3.c:791 fe-protocol3.c:809 +msgid "insufficient data in \"D\" message" +msgstr "données insuffisantes dans le message « D »" + +#: fe-protocol3.c:765 +msgid "unexpected field count in \"D\" message" +msgstr "nombre de champs inattendu dans le message « D »" + +#: fe-protocol3.c:1020 +msgid "no error message available\n" +msgstr "aucun message d'erreur disponible\n" + +#. translator: %s represents a digit string +#: fe-protocol3.c:1068 fe-protocol3.c:1087 +#, c-format +msgid " at character %s" +msgstr " au caractère %s" + +#: fe-protocol3.c:1100 +#, c-format +msgid "DETAIL: %s\n" +msgstr "DÉTAIL : %s\n" + +#: fe-protocol3.c:1103 +#, c-format +msgid "HINT: %s\n" +msgstr "ASTUCE : %s\n" + +#: fe-protocol3.c:1106 +#, c-format +msgid "QUERY: %s\n" +msgstr "REQUÊTE : %s\n" + +#: fe-protocol3.c:1113 +#, c-format +msgid "CONTEXT: %s\n" +msgstr "CONTEXTE : %s\n" + +#: fe-protocol3.c:1122 +#, c-format +msgid "SCHEMA NAME: %s\n" +msgstr "NOM DE SCHÉMA : %s\n" + +#: fe-protocol3.c:1126 +#, c-format +msgid "TABLE NAME: %s\n" +msgstr "NOM DE TABLE : %s\n" + +#: fe-protocol3.c:1130 +#, c-format +msgid "COLUMN NAME: %s\n" +msgstr "NOM DE COLONNE : %s\n" + +#: fe-protocol3.c:1134 +#, c-format +msgid "DATATYPE NAME: %s\n" +msgstr "NOM DU TYPE DE DONNÉES : %s\n" + +#: fe-protocol3.c:1138 +#, c-format +msgid "CONSTRAINT NAME: %s\n" +msgstr "NOM DE CONTRAINTE : %s\n" + +#: fe-protocol3.c:1150 +msgid "LOCATION: " +msgstr "EMPLACEMENT : " + +#: fe-protocol3.c:1152 +#, c-format +msgid "%s, " +msgstr "%s, " + +#: fe-protocol3.c:1154 +#, c-format +msgid "%s:%s" +msgstr "%s : %s" + +#: fe-protocol3.c:1349 +#, c-format +msgid "LINE %d: " +msgstr "LIGNE %d : " + +#: fe-protocol3.c:1423 +#, c-format +msgid "protocol version not supported by server: client uses %u.%u, server supports up to %u.%u" +msgstr "version du protocole non supportée par le serveur : le client utilise %u.%u, le serveur supporte jusqu'à %u.%u" + +#: fe-protocol3.c:1429 +#, c-format +msgid "protocol extension not supported by server: %s" +msgid_plural "protocol extensions not supported by server: %s" +msgstr[0] "extension du protocole non supportée par le serveur : %s" +msgstr[1] "extensions du protocole non supportées par le serveur : %s" + +#: fe-protocol3.c:1437 +#, c-format +msgid "invalid %s message" +msgstr "message %s invalide" + +#: fe-protocol3.c:1802 +#, c-format +msgid "PQgetline: not doing text COPY OUT" +msgstr "PQgetline : ne va pas réaliser un COPY OUT au format texte" + +#: fe-protocol3.c:2176 +#, c-format +msgid "protocol error: no function result" +msgstr "erreur de protocole : aucun résultat de fonction" + +#: fe-protocol3.c:2187 +#, c-format +msgid "protocol error: id=0x%x" +msgstr "erreur de protocole : id=0x%x" + +#: fe-secure-common.c:123 +#, c-format +msgid "SSL certificate's name contains embedded null" +msgstr "le nom du certificat SSL contient des NULL" + +#: fe-secure-common.c:228 +#, c-format +msgid "certificate contains IP address with invalid length %zu" +msgstr "le certificat contient une adresse IP de longueur invalide %zu" + +#: fe-secure-common.c:237 +#, c-format +msgid "could not convert certificate's IP address to string: %s" +msgstr "n'a pas pu convertir l'adresse IP du certificat en chaîne de caractères : %s" + +#: fe-secure-common.c:269 +#, c-format +msgid "host name must be specified for a verified SSL connection" +msgstr "le nom d'hôte doit être précisé pour une connexion SSL vérifiée" + +#: fe-secure-common.c:286 +#, c-format +msgid "server certificate for \"%s\" (and %d other name) does not match host name \"%s\"" +msgid_plural "server certificate for \"%s\" (and %d other names) does not match host name \"%s\"" +msgstr[0] "le certificat serveur pour « %s » (et %d autre nom) ne correspond pas au nom d'hôte « %s »" +msgstr[1] "le certificat serveur pour « %s » (et %d autres noms) ne correspond pas au nom d'hôte « %s »" + +#: fe-secure-common.c:294 +#, c-format +msgid "server certificate for \"%s\" does not match host name \"%s\"" +msgstr "le certificat serveur pour « %s » ne correspond pas au nom d'hôte « %s »" + +#: fe-secure-common.c:299 +#, c-format +msgid "could not get server's host name from server certificate" +msgstr "n'a pas pu récupérer le nom d'hôte du serveur à partir du certificat serveur" + +#: fe-secure-gssapi.c:201 +msgid "GSSAPI wrap error" +msgstr "erreur d'emballage GSSAPI" + +#: fe-secure-gssapi.c:208 +#, c-format +msgid "outgoing GSSAPI message would not use confidentiality" +msgstr "le message sortant GSSAPI n'utiliserait pas la confidentialité" + +#: fe-secure-gssapi.c:215 +#, c-format +msgid "client tried to send oversize GSSAPI packet (%zu > %zu)" +msgstr "le client a essayé d'envoyer un paquet GSSAPI trop gros (%zu > %zu)" + +#: fe-secure-gssapi.c:351 fe-secure-gssapi.c:593 +#, c-format +msgid "oversize GSSAPI packet sent by the server (%zu > %zu)" +msgstr "paquet GSSAPI trop gros envoyé par le serveur (%zu > %zu)" + +#: fe-secure-gssapi.c:390 +msgid "GSSAPI unwrap error" +msgstr "erreur de dépaquetage GSSAPI" + +#: fe-secure-gssapi.c:399 +#, c-format +msgid "incoming GSSAPI message did not use confidentiality" +msgstr "le message entrant GSSAPI n'a pas utilisé la confidentialité" + +#: fe-secure-gssapi.c:656 +msgid "could not initiate GSSAPI security context" +msgstr "n'a pas pu initier le contexte de sécurité GSSAPI" + +#: fe-secure-gssapi.c:685 +msgid "GSSAPI size check error" +msgstr "erreur de vérification de la taille GSSAPI" + +#: fe-secure-gssapi.c:696 +msgid "GSSAPI context establishment error" +msgstr "erreur d'établissement du contexte GSSAPI" + +#: fe-secure-openssl.c:219 fe-secure-openssl.c:319 fe-secure-openssl.c:1531 +#, c-format +msgid "SSL SYSCALL error: %s" +msgstr "erreur SYSCALL SSL : %s" + +#: fe-secure-openssl.c:225 fe-secure-openssl.c:325 fe-secure-openssl.c:1534 +#, c-format +msgid "SSL SYSCALL error: EOF detected" +msgstr "erreur SYSCALL SSL : EOF détecté" + +#: fe-secure-openssl.c:235 fe-secure-openssl.c:335 fe-secure-openssl.c:1542 +#, c-format +msgid "SSL error: %s" +msgstr "erreur SSL : %s" + +#: fe-secure-openssl.c:249 fe-secure-openssl.c:349 +#, c-format +msgid "SSL connection has been closed unexpectedly" +msgstr "la connexion SSL a été fermée de façon inattendu" + +#: fe-secure-openssl.c:254 fe-secure-openssl.c:354 fe-secure-openssl.c:1589 +#, c-format +msgid "unrecognized SSL error code: %d" +msgstr "code d'erreur SSL inconnu : %d" + +#: fe-secure-openssl.c:397 +#, c-format +msgid "could not determine server certificate signature algorithm" +msgstr "n'a pas pu déterminer l'algorithme de signature du certificat serveur" + +#: fe-secure-openssl.c:417 +#, c-format +msgid "could not find digest for NID %s" +msgstr "n'a pas pu trouver l'entrée pour le NID %s" + +#: fe-secure-openssl.c:426 +#, c-format +msgid "could not generate peer certificate hash" +msgstr "n'a pas pu générer le hachage du certificat peer" + +#: fe-secure-openssl.c:509 +#, c-format +msgid "SSL certificate's name entry is missing" +msgstr "l'entrée du nom du certificat SSL est manquante" + +#: fe-secure-openssl.c:543 +#, c-format +msgid "SSL certificate's address entry is missing" +msgstr "l'entrée d'adresse du certificat SSL est manquante" + +#: fe-secure-openssl.c:960 +#, c-format +msgid "could not create SSL context: %s" +msgstr "n'a pas pu créer le contexte SSL : %s" + +#: fe-secure-openssl.c:1002 +#, c-format +msgid "invalid value \"%s\" for minimum SSL protocol version" +msgstr "valeur « %s » invalide pour la version minimale du protocole SSL" + +#: fe-secure-openssl.c:1012 +#, c-format +msgid "could not set minimum SSL protocol version: %s" +msgstr "n'a pas pu configurer la version minimale de protocole SSL : %s" + +#: fe-secure-openssl.c:1028 +#, c-format +msgid "invalid value \"%s\" for maximum SSL protocol version" +msgstr "valeur « %s » invalide pour la version maximale du protocole SSL" + +#: fe-secure-openssl.c:1038 +#, c-format +msgid "could not set maximum SSL protocol version: %s" +msgstr "n'a pas pu configurer la version maximale de protocole SSL : %s" + +#: fe-secure-openssl.c:1076 +#, c-format +msgid "could not load system root certificate paths: %s" +msgstr "n'a pas pu charger les chemins du certificat racine système : %s" + +#: fe-secure-openssl.c:1093 +#, c-format +msgid "could not read root certificate file \"%s\": %s" +msgstr "n'a pas pu lire le certificat racine « %s » : %s" + +#: fe-secure-openssl.c:1145 +#, c-format +msgid "" +"could not get home directory to locate root certificate file\n" +"Either provide the file, use the system's trusted roots with sslrootcert=system, or change sslmode to disable server certificate verification." +msgstr "" +"n'a pas pu obtenir le répertoire personnel pour situer le fichier de certificat racine.\n" +"Fournissez le fichier, utilisez les racines de confiance du système avec sslrootcert=system, ou modifiez sslmode pour désactiver la vérification du certificat par le serveur." + +#: fe-secure-openssl.c:1148 +#, c-format +msgid "" +"root certificate file \"%s\" does not exist\n" +"Either provide the file, use the system's trusted roots with sslrootcert=system, or change sslmode to disable server certificate verification." +msgstr "" +"le fichier de certificat racine « %s » n'existe pas.\n" +"Fournissez le fichier, utilisez les racines de confiance du système avec sslrootcert=system, ou modifiez sslmode pour désactiver la vérification du certificat par le serveur." + +#: fe-secure-openssl.c:1183 +#, c-format +msgid "could not open certificate file \"%s\": %s" +msgstr "n'a pas pu ouvrir le certificat « %s » : %s" + +#: fe-secure-openssl.c:1201 +#, c-format +msgid "could not read certificate file \"%s\": %s" +msgstr "n'a pas pu lire le certificat « %s » : %s" + +#: fe-secure-openssl.c:1225 +#, c-format +msgid "could not establish SSL connection: %s" +msgstr "n'a pas pu établir la connexion SSL : %s" + +#: fe-secure-openssl.c:1257 +#, c-format +msgid "could not set SSL Server Name Indication (SNI): %s" +msgstr "n'a pas pu configurer le SSL Server Name Indication (SNI) : %s" + +#: fe-secure-openssl.c:1300 +#, c-format +msgid "could not load SSL engine \"%s\": %s" +msgstr "n'a pas pu charger le moteur SSL « %s » : %s" + +#: fe-secure-openssl.c:1311 +#, c-format +msgid "could not initialize SSL engine \"%s\": %s" +msgstr "n'a pas pu initialiser le moteur SSL « %s » : %s" + +#: fe-secure-openssl.c:1326 +#, c-format +msgid "could not read private SSL key \"%s\" from engine \"%s\": %s" +msgstr "n'a pas pu lire la clé privée SSL « %s » à partir du moteur « %s » : %s" + +#: fe-secure-openssl.c:1339 +#, c-format +msgid "could not load private SSL key \"%s\" from engine \"%s\": %s" +msgstr "n'a pas pu charger la clé privée SSL « %s » à partir du moteur « %s » : %s" + +#: fe-secure-openssl.c:1376 +#, c-format +msgid "certificate present, but not private key file \"%s\"" +msgstr "le certificat est présent, mais la clé privée « %s » est absente" + +#: fe-secure-openssl.c:1379 +#, c-format +msgid "could not stat private key file \"%s\": %m" +msgstr "n'a pas pu interroger le fichier de clé privée « %s » : %m" + +#: fe-secure-openssl.c:1387 +#, c-format +msgid "private key file \"%s\" is not a regular file" +msgstr "le fichier de clé privée « %s » n'est pas un fichier" + +#: fe-secure-openssl.c:1420 +#, c-format +msgid "private key file \"%s\" has group or world access; file must have permissions u=rw (0600) or less if owned by the current user, or permissions u=rw,g=r (0640) or less if owned by root" +msgstr "le fichier de clé privée « %s » a des droits d'accès pour le groupe ou le monde ; le fichier doit avoir les droits u=rw (0600) ou moins si le propriétaire est l'utilisateur courant, ou les droits u=rw,g=r (0640) ou moins si le propriétaire est root" + +#: fe-secure-openssl.c:1444 +#, c-format +msgid "could not load private key file \"%s\": %s" +msgstr "n'a pas pu charger le fichier de clé privée « %s » : %s" + +#: fe-secure-openssl.c:1460 +#, c-format +msgid "certificate does not match private key file \"%s\": %s" +msgstr "le certificat ne correspond pas à la clé privée « %s » : %s" + +#: fe-secure-openssl.c:1528 +#, c-format +msgid "SSL error: certificate verify failed: %s" +msgstr "erreur SSL : échec de la vérification du certificat : %s" + +#: fe-secure-openssl.c:1573 +#, c-format +msgid "This may indicate that the server does not support any SSL protocol version between %s and %s." +msgstr "Ceci pourrait indiquer que le serveur ne supporte aucune des versions du protocole SSL entre %s et %s." + +#: fe-secure-openssl.c:1606 +#, c-format +msgid "certificate could not be obtained: %s" +msgstr "le certificat n'a pas pu être obtenu : %s" + +#: fe-secure-openssl.c:1711 +#, c-format +msgid "no SSL error reported" +msgstr "aucune erreur SSL reportée" + +#: fe-secure-openssl.c:1720 +#, c-format +msgid "SSL error code %lu" +msgstr "code d'erreur SSL %lu" + +#: fe-secure-openssl.c:1986 +#, c-format +msgid "WARNING: sslpassword truncated\n" +msgstr "ATTENTION : sslpassword tronqué\n" + +#: fe-secure.c:263 +#, c-format +msgid "could not receive data from server: %s" +msgstr "n'a pas pu recevoir des données depuis le serveur : %s" + +#: fe-secure.c:434 +#, c-format +msgid "could not send data to server: %s" +msgstr "n'a pas pu transmettre les données au serveur : %s" + +#: win32.c:310 +#, c-format +msgid "unrecognized socket error: 0x%08X/%d" +msgstr "erreur de socket non reconnue : 0x%08X/%d" + +#~ msgid "\"SELECT pg_is_in_recovery()\" failed\n" +#~ msgstr "\"SELECT pg_is_in_recovery()\" a échoué\n" + +#~ msgid "\"SHOW transaction_read_only\" failed\n" +#~ msgstr "\"SHOW transaction_read_only\" a échoué\n" + +#, c-format +#~ msgid "%s(%s) failed: error code %d\n" +#~ msgstr "échec de %s(%s) : code d'erreur %d\n" + +#~ msgid "COPY IN state must be terminated first\n" +#~ msgstr "l'état COPY IN doit d'abord être terminé\n" + +#~ msgid "COPY OUT state must be terminated first\n" +#~ msgstr "l'état COPY OUT doit d'abord être terminé\n" + +#~ msgid "Kerberos 5 authentication rejected: %*s\n" +#~ msgstr "authentification Kerberos 5 rejetée : %*s\n" + +#, c-format +#~ msgid "PGEventProc \"%s\" failed during PGEVT_CONNRESET event\n" +#~ msgstr "échec de PGEventProc « %s » lors de l'événement PGEVT_CONNRESET\n" + +#, c-format +#~ msgid "PGEventProc \"%s\" failed during PGEVT_RESULTCREATE event\n" +#~ msgstr "échec de PGEventProc « %s » lors de l'événement PGEVT_RESULTCREATE\n" + +#~ msgid "SCM_CRED authentication method not supported\n" +#~ msgstr "authentification SCM_CRED non supportée\n" + +#, c-format +#~ msgid "SSL error: %s\n" +#~ msgstr "erreur SSL : %s\n" + +#~ msgid "SSL library does not support CRL certificates (file \"%s\")\n" +#~ msgstr "la bibliothèque SSL ne supporte pas les certificats CRL (fichier « %s »)\n" + +#, c-format +#~ msgid "Unix-domain socket path \"%s\" is too long (maximum %d bytes)\n" +#~ msgstr "Le chemin du socket de domaine Unix, « %s », est trop (maximum %d octets)\n" + +#~ msgid "WARNING: line %d too long in password file \"%s\"\n" +#~ msgstr "ATTENTION : ligne %d trop longue dans le fichier de mots de passe « %s »\n" + +#~ msgid "WSAIoctl(SIO_KEEPALIVE_VALS) failed: %d\n" +#~ msgstr "échec de WSAIoctl(SIO_KEEPALIVE_VALS) : %d\n" + +#~ msgid "cannot determine OID of function lo_creat\n" +#~ msgstr "ne peut pas déterminer l'OID de la fonction lo_creat\n" + +#~ msgid "cannot determine OID of function lo_create\n" +#~ msgstr "ne peut pas déterminer l'OID de la fonction lo_create\n" + +#~ msgid "cannot determine OID of function lo_lseek\n" +#~ msgstr "ne peut pas déterminer l'OID de la fonction lo_lseek\n" + +#~ msgid "cannot determine OID of function lo_lseek64\n" +#~ msgstr "ne peut pas déterminer l'OID de la fonction lo_lseek64\n" + +#~ msgid "cannot determine OID of function lo_open\n" +#~ msgstr "ne peut pas déterminer l'OID de la fonction lo_open\n" + +#~ msgid "cannot determine OID of function lo_tell64\n" +#~ msgstr "ne peut pas déterminer l'OID de la fonction lo_tell64\n" + +#~ msgid "cannot determine OID of function lo_truncate\n" +#~ msgstr "ne peut pas déterminer l'OID de la fonction lo_truncate\n" + +#~ msgid "cannot determine OID of function lo_truncate64\n" +#~ msgstr "ne peut pas déterminer l'OID de la fonction lo_truncate64\n" + +#~ msgid "cannot determine OID of function lo_unlink\n" +#~ msgstr "ne peut pas déterminer l'OID de la fonction lo_unlink\n" + +#~ msgid "cannot determine OID of function loread\n" +#~ msgstr "ne peut pas déterminer l'OID de la fonction loread\n" + +#~ msgid "cannot determine OID of function lowrite\n" +#~ msgstr "ne peut pas déterminer l'OID de la fonction lowrite\n" + +#~ msgid "could not acquire mutex: %s\n" +#~ msgstr "n'a pas pu acquérir le mutex : %s\n" + +#~ msgid "" +#~ "could not connect to server: %s\n" +#~ "\tIs the server running on host \"%s\" (%s) and accepting\n" +#~ "\tTCP/IP connections on port %s?\n" +#~ msgstr "" +#~ "n'a pas pu se connecter au serveur : %s\n" +#~ "\tLe serveur est-il actif sur l'hôte « %s » (%s)\n" +#~ "\tet accepte-t-il les connexionsTCP/IP sur le port %s ?\n" + +#, c-format +#~ msgid "could not create SSL context: %s\n" +#~ msgstr "n'a pas pu créer le contexte SSL : %s\n" + +#~ msgid "could not get home directory to locate client certificate files\n" +#~ msgstr "" +#~ "n'a pas pu récupérer le répertoire personnel pour trouver les certificats\n" +#~ "du client\n" + +#~ msgid "could not get home directory to locate password file\n" +#~ msgstr "" +#~ "n'a pas pu obtenir le répertoire personnel pour trouver le fichier de\n" +#~ "mot de passe\n" + +#~ msgid "could not get home directory to locate service definition file" +#~ msgstr "" +#~ "n'a pas pu obtenir le répertoire personnel pour trouver le certificat de\n" +#~ "définition du service" + +#, c-format +#~ msgid "could not load private key file \"%s\": %s\n" +#~ msgstr "n'a pas pu charger le fichier de clé privée « %s » : %s\n" + +#~ msgid "could not make a writable connection to server \"%s:%s\"\n" +#~ msgstr "n'a pas pu réaliser une connexion en écriture au serveur « %s » : %s\n" + +#, c-format +#~ msgid "could not open file \"%s\": %s\n" +#~ msgstr "n'a pas pu ouvrir le fichier « %s » : %s\n" + +#~ msgid "could not open private key file \"%s\": %s\n" +#~ msgstr "n'a pas pu ouvrir le fichier de clé privée « %s » : %s\n" + +#~ msgid "could not read private key file \"%s\": %s\n" +#~ msgstr "n'a pas pu lire la clé privée « %s » : %s\n" + +#~ msgid "could not restore nonblocking mode on socket: %s\n" +#~ msgstr "n'a pas pu rétablir le mode non-bloquant pour la socket : %s\n" + +#~ msgid "could not set maximum version of SSL protocol: %s\n" +#~ msgstr "n'a pas pu mettre en place la version maximale du protocole SSL : %s\n" + +#~ msgid "could not set minimum version of SSL protocol: %s\n" +#~ msgstr "n'a pas pu mettre en place la version minimale du protocole SSL : %s\n" + +#~ msgid "could not set socket to blocking mode: %s\n" +#~ msgstr "n'a pas pu activer le mode bloquant pour la socket : %s\n" + +#~ msgid "extraneous data in \"D\" message" +#~ msgstr "données supplémentaires dans le message « D »" + +#~ msgid "extraneous data in \"T\" message" +#~ msgstr "données supplémentaires dans le message « T »" + +#~ msgid "extraneous data in \"t\" message" +#~ msgstr "données supplémentaires dans le message « t »" + +#~ msgid "failed to generate nonce\n" +#~ msgstr "échec pour la génération de nonce\n" + +#~ msgid "failed to generate random salt" +#~ msgstr "a échoué à générer le sel aléatoire" + +#~ msgid "function requires at least protocol version 3.0\n" +#~ msgstr "la fonction nécessite au minimum le protocole 3.0\n" + +#~ msgid "incoming GSSAPI message did not use confidentiality\n" +#~ msgstr "le message entrant GSSAPI n'a pas utilisé pas la confidentialité\n" + +#~ msgid "invalid appname state %d, probably indicative of memory corruption\n" +#~ msgstr "état appname %d invalide, indiquant probablement une corruption de la mémoire\n" + +#~ msgid "invalid channel_binding value: \"%s\"\n" +#~ msgstr "valeur de channel_binding invalide : « %s »\n" + +#~ msgid "invalid gssencmode value: \"%s\"\n" +#~ msgstr "valeur gssencmode invalide : « %s »\n" + +#~ msgid "invalid setenv state %c, probably indicative of memory corruption\n" +#~ msgstr "état setenv %c invalide, indiquant probablement une corruption de la mémoire\n" + +#~ msgid "invalid ssl_max_protocol_version value: \"%s\"\n" +#~ msgstr "valeur ssl_max_protocol_version invalide : « %s »\n" + +#~ msgid "invalid ssl_min_protocol_version value: \"%s\"\n" +#~ msgstr "valeur ssl_min_protocol_version invalide : « %s »\n" + +#~ msgid "invalid state %c, probably indicative of memory corruption\n" +#~ msgstr "état %c invalide, indiquant probablement une corruption de la mémoire\n" + +#~ msgid "invalid target_session_attrs value: \"%s\"\n" +#~ msgstr "valeur target_session_attrs invalide : « %s »\n" + +#, c-format +#~ msgid "local user with ID %d does not exist\n" +#~ msgstr "l'utilisateur local dont l'identifiant est %d n'existe pas\n" + +#~ msgid "lost synchronization with server, resetting connection" +#~ msgstr "synchronisation perdue avec le serveur, réinitialisation de la connexion" + +#~ msgid "no GSSAPI support; cannot require GSSAPI\n" +#~ msgstr "pas de support de GSSAPI : ne peut pas nécessiter GSSAPI\n" + +#~ msgid "outgoing GSSAPI message would not use confidentiality\n" +#~ msgstr "le message sortant GSSAPI n'utiliserait pas la confidentialité\n" + +#~ msgid "private key file \"%s\" changed during execution\n" +#~ msgstr "la clé privée « %s » a été modifiée durant l'exécution\n" + +#, c-format +#~ msgid "private key file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n" +#~ msgstr "" +#~ "le fichier de la clé privée « %s » a des droits d'accès en lecture\n" +#~ "pour le groupe ou universel ; les droits devraient être u=rw (0600)\n" +#~ "ou inférieur\n" + +#, c-format +#~ msgid "private key file \"%s\" is not a regular file\n" +#~ msgstr "le fichier de clé privée « %s » n'est pas un fichier standard\n" + +#, c-format +#~ msgid "private key file \"%s\" must be owned by the current user or root\n" +#~ msgstr "le fichier de clé privée « %s » doit avoir comme propriétaire l'utilisateur courant ou root\n" + +#~ msgid "select() failed: %s\n" +#~ msgstr "échec de select() : %s\n" + +#~ msgid "server sent binary data (\"B\" message) without prior row description (\"T\" message)" +#~ msgstr "" +#~ "le serveur a envoyé des données binaires (message « B ») sans description\n" +#~ "préalable de la ligne (message « T »)" + +#~ msgid "server sent data (\"D\" message) without prior row description (\"T\" message)\n" +#~ msgstr "" +#~ "le serveur a envoyé des données (message « D ») sans description préalable\n" +#~ "de la ligne (message « T »)\n" + +#~ msgid "setsockopt(%s) failed: %s\n" +#~ msgstr "setsockopt(%s) a échoué : %s\n" + +#~ msgid "setsockopt(SO_KEEPALIVE) failed: %s\n" +#~ msgstr "setsockopt(SO_KEEPALIVE) a échoué : %s\n" + +#~ msgid "setsockopt(TCP_KEEPALIVE) failed: %s\n" +#~ msgstr "setsockopt(TCP_KEEPALIVE) a échoué : %s\n" + +#~ msgid "setsockopt(TCP_KEEPIDLE) failed: %s\n" +#~ msgstr "setsockopt(TCP_KEEPIDLE) a échoué : %s\n" + +#~ msgid "setsockopt(TCP_KEEPINTVL) failed: %s\n" +#~ msgstr "setsockopt(TCP_KEEPINTVL) a échoué : %s\n" + +#~ msgid "socket not open\n" +#~ msgstr "socket non ouvert\n" + +#~ msgid "unexpected character %c following empty query response (\"I\" message)" +#~ msgstr "" +#~ "caractère %c inattendu à la suite d'une réponse de requête vide (message\n" +#~ "« I »)" + +#, c-format +#~ msgid "unrecognized SSL error code: %d\n" +#~ msgstr "code d'erreur SSL inconnu : %d\n" + +#~ msgid "unrecognized return value from row processor" +#~ msgstr "valeur de retour du traitement de la ligne non reconnue" + +#, c-format +#~ msgid "user name lookup failure: error code %lu\n" +#~ msgstr "échec de la recherche du nom d'utilisateur : code d'erreur %lu\n" + +#~ msgid "verified SSL connections are only supported when connecting to a host name\n" +#~ msgstr "" +#~ "les connexions SSL vérifiées ne sont supportées que lors de la connexion\n" +#~ "à un alias hôte\n" diff --git a/src/interfaces/libpq/po/he.po b/src/interfaces/libpq/po/he.po new file mode 100644 index 0000000..2b26f60 --- /dev/null +++ b/src/interfaces/libpq/po/he.po @@ -0,0 +1,1087 @@ +# Hebrew message translation file for libpq +# Copyright (C) 2017 PostgreSQL Global Development Group +# This file is distributed under the same license as the PostgreSQL package. +# Michael Goldberg <mic.goldbrg@gmail.com>, 2017. +# +msgid "" +msgstr "" +"Project-Id-Version: libpq (PostgreSQL) 10\n" +"Report-Msgid-Bugs-To: pgsql-bugs@postgresql.org\n" +"POT-Creation-Date: 2017-05-16 18:18+0300\n" +"PO-Revision-Date: 2017-05-16 22:35+0300\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 2.0.2\n" +"Last-Translator: Michael Goldberg <mic.goldbrg@gmail.com>, 2017.\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"Language: he_IL\n" + +#: fe-auth.c:122 +#, c-format +msgid "out of memory allocating GSSAPI buffer (%d)\n" +msgstr "אין די זיכרון בהקצאת מאגר GSSAPI (%d)\n" + +#: fe-auth.c:172 +msgid "GSSAPI continuation error" +msgstr "שגיאה המשך GSSAPI" + +#: fe-auth.c:202 fe-auth.c:451 +msgid "host name must be specified\n" +msgstr "יש לציין שם מחשב מארח\n" + +#: fe-auth.c:209 +msgid "duplicate GSS authentication request\n" +msgstr "בקשת אימות GSS כפולה\n" + +#: fe-auth.c:222 fe-auth.c:357 fe-auth.c:422 fe-auth.c:457 fe-auth.c:599 +#: fe-auth.c:758 fe-auth.c:1070 fe-auth.c:1217 fe-connect.c:712 +#: fe-connect.c:1091 fe-connect.c:1267 fe-connect.c:1803 fe-connect.c:2331 +#: fe-connect.c:3932 fe-connect.c:4184 fe-connect.c:4303 fe-connect.c:4543 +#: fe-connect.c:4623 fe-connect.c:4722 fe-connect.c:4978 fe-connect.c:5007 +#: fe-connect.c:5079 fe-connect.c:5103 fe-connect.c:5121 fe-connect.c:5222 +#: fe-connect.c:5231 fe-connect.c:5587 fe-connect.c:5737 fe-exec.c:2651 +#: fe-exec.c:3398 fe-exec.c:3563 fe-lobj.c:896 fe-protocol2.c:1206 +#: fe-protocol3.c:992 fe-protocol3.c:1678 fe-secure-openssl.c:514 +#: fe-secure-openssl.c:1137 +msgid "out of memory\n" +msgstr "אין זיכרון פנוי\n" + +#: fe-auth.c:235 +msgid "GSSAPI name import error" +msgstr "שגיאת ייבוא שם GSSAPI" + +#: fe-auth.c:298 +#, c-format +msgid "out of memory allocating SSPI buffer (%d)\n" +msgstr "אין די זיכרון בהקצאת מאגר GSSAPI (%d)\n" + +#: fe-auth.c:346 +msgid "SSPI continuation error" +msgstr "שגיאה המשך SSPI" + +#: fe-auth.c:437 +msgid "could not acquire SSPI credentials" +msgstr "לא יכלו לרכוש אישורים SSPI" + +#: fe-auth.c:490 +msgid "duplicate SASL authentication request\n" +msgstr "בקשת אימות GSS כפולה\n" + +#: fe-auth.c:550 +msgid "none of the server's SASL authentication mechanisms are supported\n" +msgstr "אף אחד מנגנון אימות SASL של השרת אשר נתמך\n" + +#: fe-auth.c:623 +#, c-format +msgid "out of memory allocating SASL buffer (%d)\n" +msgstr "אין די זיכרון בהקצאת מאגר GSSAPI (%d)\n" + +#: fe-auth.c:648 +msgid "" +"AuthenticationSASLFinal received from server, but SASL authentication was " +"not completed\n" +msgstr "מהשרת התקבל AuthenticationSASLFinal, אבל אימות SASL לא הושלם\n" + +#: fe-auth.c:725 +msgid "SCM_CRED authentication method not supported\n" +msgstr "שיטת האימות SCM_CRED אינה נתמכת\n" + +#: fe-auth.c:816 +msgid "Kerberos 4 authentication not supported\n" +msgstr "אימות Kerberos 4 אינו נתמך\n" + +#: fe-auth.c:821 +msgid "Kerberos 5 authentication not supported\n" +msgstr "אימות Kerberos 5 אינו נתמך\n" + +#: fe-auth.c:892 +msgid "GSSAPI authentication not supported\n" +msgstr "אימות GSSAPI אינו נתמך\n" + +#: fe-auth.c:924 +msgid "SSPI authentication not supported\n" +msgstr "אימות SSPI אינו נתמך\n" + +#: fe-auth.c:932 +msgid "Crypt authentication not supported\n" +msgstr "אימות Crypt אינו נתמך\n" + +#: fe-auth.c:998 +#, c-format +msgid "authentication method %u not supported\n" +msgstr "שיטת האימות %u אינה נתמכת\n" + +#: fe-auth.c:1045 +#, c-format +msgid "user name lookup failure: error code %lu\n" +msgstr "כישלון בדיקה עבור שם המשתמש: קוד שגיאה %lu\n" + +#: fe-auth.c:1055 fe-connect.c:2258 +#, c-format +msgid "could not look up local user ID %d: %s\n" +msgstr "לא יכול לחפש משתמש מקומי עם מזהה %d: %s\n" + +#: fe-auth.c:1060 fe-connect.c:2263 +#, c-format +msgid "local user with ID %d does not exist\n" +msgstr "משתמש מקומי עם המזהה %d לא קיים\n" + +#: fe-auth.c:1162 +msgid "unexpected shape of result set returned for SHOW\n" +msgstr "צורה בלתי צפויה של תוצאה שהוגדרה עבור SHOW\n" + +#: fe-auth.c:1171 +msgid "password_encryption value too long\n" +msgstr "ערך password_encryption ארוך מדי\n" + +#: fe-auth.c:1211 +msgid "unknown password encryption algorithm\n" +msgstr "אלגוריתם הצפנת סיסמה לא ידוע\n" + +#: fe-connect.c:914 +#, c-format +msgid "could not match %d port numbers to %d hosts\n" +msgstr "לא היתה אפשרות להתאים את %d מספרי הפורטים ל %d למארחים\n" + +#: fe-connect.c:966 +msgid "could not get home directory to locate password file\n" +msgstr "לא ניתן לקבל את ספריית הבית על מנת לאתר את קובץ הסיסמאות\n" + +#: fe-connect.c:1017 +#, c-format +msgid "invalid sslmode value: \"%s\"\n" +msgstr "ערך sslmode לא חוקי: \"%s\"\n" + +#: fe-connect.c:1038 +#, c-format +msgid "sslmode value \"%s\" invalid when SSL support is not compiled in\n" +msgstr "ערך sslmode אינו חוקי \"%s\" כאשר תמיכת SSL אינה מקובצת\n" + +#: fe-connect.c:1073 +#, c-format +msgid "invalid target_session_attrs value: \"%s\"\n" +msgstr "ערך target_session_attrs לא חוקי: \"%s\"\n" + +#: fe-connect.c:1291 +#, c-format +msgid "could not set socket to TCP no delay mode: %s\n" +msgstr "לא היתה אפשרות להגדיר שקע למצב TCP ללא השהיה: %s\n" + +#: fe-connect.c:1321 +#, c-format +msgid "" +"could not connect to server: %s\n" +"\tIs the server running locally and accepting\n" +"\tconnections on Unix domain socket \"%s\"?\n" +msgstr "" +"לא היתה אפשרות להתחבר לשרת: %s\n" +"האם השרת פועל באופן מקומי ומקבל\n" +"חיבורים בתחום Unix שקע \"%s\"?\n" + +#: fe-connect.c:1376 +#, c-format +msgid "" +"could not connect to server: %s\n" +"\tIs the server running on host \"%s\" (%s) and accepting\n" +"\tTCP/IP connections on port %s?\n" +msgstr "" +"לא היתה אפשרות להתחבר לשרת: %s\n" +"הto השרת פועל במחשב מארח \"%s\" (%s) ומקבל\n" +"חיבורי TCP/IP בפורט %s?\n" + +#: fe-connect.c:1385 +#, c-format +msgid "" +"could not connect to server: %s\n" +"\tIs the server running on host \"%s\" and accepting\n" +"\tTCP/IP connections on port %s?\n" +msgstr "" +"לא היתה אפשרות להתחבר לשרת: %s\n" +"האם השרת פועל במחשב מארח \"%s\" ומקבל\n" +"חיבורי TCP/IP בפורט %s?\n" + +#: fe-connect.c:1436 +#, c-format +msgid "setsockopt(TCP_KEEPIDLE) failed: %s\n" +msgstr "נכשל setsockopt(TCP_KEEPIDLE): %s\n" + +#: fe-connect.c:1449 +#, c-format +msgid "setsockopt(TCP_KEEPALIVE) failed: %s\n" +msgstr "נכשל setsockopt(TCP_KEEPALIVE): %s\n" + +#: fe-connect.c:1481 +#, c-format +msgid "setsockopt(TCP_KEEPINTVL) failed: %s\n" +msgstr "נכשל setsockopt(TCP_KEEPCNT): %s\n" + +#: fe-connect.c:1513 +#, c-format +msgid "setsockopt(TCP_KEEPCNT) failed: %s\n" +msgstr "נכשל setsockopt(TCP_KEEPCNT): %s\n" + +#: fe-connect.c:1561 +#, c-format +msgid "WSAIoctl(SIO_KEEPALIVE_VALS) failed: %ui\n" +msgstr "נכשל WSAIoctl(SIO_KEEPALIVE_VALS): %ui\n" + +#: fe-connect.c:1619 +#, c-format +msgid "invalid port number: \"%s\"\n" +msgstr "מספר פורט לא חוקי: \"%s\"\n" + +#: fe-connect.c:1643 +#, c-format +msgid "Unix-domain socket path \"%s\" is too long (maximum %d bytes)\n" +msgstr "נתיב שקע Unix-תחום \"%s\" ארוך מדי (מקסימום %d בתים)\n" + +#: fe-connect.c:1661 +#, c-format +msgid "could not translate host name \"%s\" to address: %s\n" +msgstr "לא היתה אפשרות לתרגם את שם המארח \"%s\" לכתובת: %s\n" + +#: fe-connect.c:1665 +#, c-format +msgid "could not translate Unix-domain socket path \"%s\" to address: %s\n" +msgstr "לא היתה אפשרות לתרגם את נתיב שקע Unix-תחןם \"%s\" לכתובת: %s\n" + +#: fe-connect.c:1909 +msgid "invalid connection state, probably indicative of memory corruption\n" +msgstr "מצב חיבור לא חוקי, מה שמעיד כנראה על שחיתות בזיכרון\n" + +#: fe-connect.c:1966 +#, c-format +msgid "could not create socket: %s\n" +msgstr "לא היתה אפשרות ליצור שקע: %s\n" + +#: fe-connect.c:1988 +#, c-format +msgid "could not set socket to nonblocking mode: %s\n" +msgstr "לא היתה אפשרות להגדיר שקע למצב nonblocking: %s\n" + +#: fe-connect.c:1999 +#, c-format +msgid "could not set socket to close-on-exec mode: %s\n" +msgstr "לא היתה אפשרות להגדיר שקע למצב close-on-exec: %s\n" + +#: fe-connect.c:2018 +msgid "keepalives parameter must be an integer\n" +msgstr "פרמטר keepalives חייב להיות מספר שלם\n" + +#: fe-connect.c:2031 +#, c-format +msgid "setsockopt(SO_KEEPALIVE) failed: %s\n" +msgstr "נכשל setsockopt(TCP_KEEPALIVE): %s\n" + +#: fe-connect.c:2168 +#, c-format +msgid "could not get socket error status: %s\n" +msgstr "לא היתה אפשרות לקבל את מצב שגיאה של שקע: %s\n" + +#: fe-connect.c:2203 +#, c-format +msgid "could not get client address from socket: %s\n" +msgstr "לא היתה אפשרות לקבל כתובת הלקוח משקע: %s\n" + +#: fe-connect.c:2245 +msgid "requirepeer parameter is not supported on this platform\n" +msgstr "פרמטר requirepeer אינו נתמך בפלטפורמה זו\n" + +#: fe-connect.c:2248 +#, c-format +msgid "could not get peer credentials: %s\n" +msgstr "לא היתה אפשרות לקבל את האישורים של peer: %s\n" + +#: fe-connect.c:2271 +#, c-format +msgid "requirepeer specifies \"%s\", but actual peer user name is \"%s\"\n" +msgstr "ציון requirepeer \"%s\", אבל בפועל שם המשתמש של peer הוא \"%s\"\n" + +#: fe-connect.c:2305 +#, c-format +msgid "could not send SSL negotiation packet: %s\n" +msgstr "לא יכול לשלוח מנות SSL משא ומתן: %s\n" + +#: fe-connect.c:2344 +#, c-format +msgid "could not send startup packet: %s\n" +msgstr "לא היתה אפשרות לשלוח את מנת הפעלה: %s\n" + +#: fe-connect.c:2414 +msgid "server does not support SSL, but SSL was required\n" +msgstr "השרת אינו תומך ב- SSL, אבל SSL היה נדרש\n" + +#: fe-connect.c:2440 +#, c-format +msgid "received invalid response to SSL negotiation: %c\n" +msgstr "נתקבלה תגובה לא חוקית ממשא ומתן של SSL: %c\n" + +#: fe-connect.c:2516 fe-connect.c:2549 +#, c-format +msgid "expected authentication request from server, but received %c\n" +msgstr "צפויה בקשת אימות משרת, אבל התקבל %c\n" + +#: fe-connect.c:2778 +msgid "unexpected message from server during startup\n" +msgstr "הודעה לא צפויה משרת במהלך אתחול\n" + +#: fe-connect.c:2982 +#, c-format +msgid "could not make a writable connection to server \"%s:%s\"\n" +msgstr "לא יכול ליצור חיבור לכתיבה לשרת \"%s: %s\"\n" + +#: fe-connect.c:3024 +#, c-format +msgid "test \"show transaction_read_only\" failed on \"%s:%s\"\n" +msgstr "בדיקה \"הצג transaction_read_only\" נכשלה ב- \"%s: %s\"\n" + +#: fe-connect.c:3046 +#, c-format +msgid "invalid connection state %d, probably indicative of memory corruption\n" +msgstr "מצב החיבור לא חוקי %d, כנראה מעיד על נזק לזיכרון\n" + +#: fe-connect.c:3538 fe-connect.c:3598 +#, c-format +msgid "PGEventProc \"%s\" failed during PGEVT_CONNRESET event\n" +msgstr "נכשל PGEventProc \"%s\" במהלך האירוע PGEVT_CONNRESET\n" + +#: fe-connect.c:3945 +#, c-format +msgid "invalid LDAP URL \"%s\": scheme must be ldap://\n" +msgstr "כתובת URL של LDAP לא חוקי \"%s\": חייב סכימת ldap://\n" + +#: fe-connect.c:3960 +#, c-format +msgid "invalid LDAP URL \"%s\": missing distinguished name\n" +msgstr "כתובת URL של LDAP לא חוקי \"%s\": חסר שם ייחודי\n" + +#: fe-connect.c:3971 fe-connect.c:4024 +#, c-format +msgid "invalid LDAP URL \"%s\": must have exactly one attribute\n" +msgstr "כתובת URL של LDAP לא חוקי \"%s\": חייב תכונה אחת בדיוק\n" + +#: fe-connect.c:3981 fe-connect.c:4038 +#, c-format +msgid "invalid LDAP URL \"%s\": must have search scope (base/one/sub)\n" +msgstr "כתובת URL של LDAP לא חוקי \"%s\": חייב טווח החיפוש (base/one/sub)\n" + +#: fe-connect.c:3992 +#, c-format +msgid "invalid LDAP URL \"%s\": no filter\n" +msgstr "כתובת URL של LDAP לא חוקי \"%s\": אין פילטר\n" + +#: fe-connect.c:4013 +#, c-format +msgid "invalid LDAP URL \"%s\": invalid port number\n" +msgstr "כתובת URL של LDAP לא חוקי \"%s\": מספר פורט לא חוקי\n" + +#: fe-connect.c:4047 +msgid "could not create LDAP structure\n" +msgstr "לא היתה אפשרות ליצור את המבנה של LDAP\n" + +#: fe-connect.c:4123 +#, c-format +msgid "lookup on LDAP server failed: %s\n" +msgstr "בדיקת מידע בשרת LDAP נכשלה: %s\n" + +#: fe-connect.c:4134 +msgid "more than one entry found on LDAP lookup\n" +msgstr "יותר מאחד ערך נמצא בבדיקה של LDAP\n" + +#: fe-connect.c:4135 fe-connect.c:4147 +msgid "no entry found on LDAP lookup\n" +msgstr "לא נמצאו ערכים בבדיקה של LDAP\n" + +#: fe-connect.c:4158 fe-connect.c:4171 +msgid "attribute has no values on LDAP lookup\n" +msgstr "לתכונה אין ערכים בחיפוש LDAP\n" + +#: fe-connect.c:4223 fe-connect.c:4242 fe-connect.c:4761 +#, c-format +msgid "missing \"=\" after \"%s\" in connection info string\n" +msgstr "לא נמצא \"=\" לאחר \"%s\" במחרוזת החיבור פרטי\n" + +#: fe-connect.c:4315 fe-connect.c:4946 fe-connect.c:5720 +#, c-format +msgid "invalid connection option \"%s\"\n" +msgstr "אפשרות חיבור לא חוקי \"%s\"\n" + +#: fe-connect.c:4331 fe-connect.c:4810 +msgid "unterminated quoted string in connection info string\n" +msgstr "מחרוזת ללא סגירה מצוטטת במחרוזת פרטי חיבור\n" + +#: fe-connect.c:4371 +msgid "could not get home directory to locate service definition file" +msgstr "לא ניתן לגשת לספריית הבית כדי לאתר קובץ הגדרת שירות" + +#: fe-connect.c:4404 +#, c-format +msgid "definition of service \"%s\" not found\n" +msgstr "ההגדרה של שירות '%s' לא נמצא\n" + +#: fe-connect.c:4427 +#, c-format +msgid "service file \"%s\" not found\n" +msgstr "קובץ שירות '%s' לא נמצא\n" + +#: fe-connect.c:4440 +#, c-format +msgid "line %d too long in service file \"%s\"\n" +msgstr "שורה %d יותר מדי ארוכה בקובץ שירות \"%s\"\n" + +#: fe-connect.c:4511 fe-connect.c:4555 +#, c-format +msgid "syntax error in service file \"%s\", line %d\n" +msgstr "שגיאת תחביר בקובץ השירות \"%s\", שורה %d\n" + +#: fe-connect.c:4522 +#, c-format +msgid "" +"nested service specifications not supported in service file \"%s\", line %d\n" +msgstr "מפרטי שירות מקוננים אינם נתמכים בקובץ השירות \"%s\", שורה %d\n" + +#: fe-connect.c:5242 +#, c-format +msgid "invalid URI propagated to internal parser routine: \"%s\"\n" +msgstr "לשגרת מנתח פנימי מופץ URI לא חוקי: \"%s\"\n" + +#: fe-connect.c:5319 +#, c-format +msgid "" +"end of string reached when looking for matching \"]\" in IPv6 host address " +"in URI: \"%s\"\n" +msgstr "" +"הגעה לסיום מחרוזת בזמן חיפוש התאמת ל \"]\" ב- IPv6 כתובות של ארח ב- URI: \"%s" +"\"\n" + +#: fe-connect.c:5326 +#, c-format +msgid "IPv6 host address may not be empty in URI: \"%s\"\n" +msgstr "כתובת מחשב מארח של IPv6 אינו יכול להיות ריק ב- URI: \"%s\"\n" + +#: fe-connect.c:5341 +#, c-format +msgid "" +"unexpected character \"%c\" at position %d in URI (expected \":\" or \"/\"): " +"\"%s\"\n" +msgstr "תו לא צפוי '%c' במיקום %d ב- URI (צפוי \":\" או \"/\"): \"%s\"\n" + +#: fe-connect.c:5470 +#, c-format +msgid "extra key/value separator \"=\" in URI query parameter: \"%s\"\n" +msgstr "מפריד מפתח/ערך נוסף \"=\" פרמטר שאילתה של URI: \"%s\"\n" + +#: fe-connect.c:5490 +#, c-format +msgid "missing key/value separator \"=\" in URI query parameter: \"%s\"\n" +msgstr "חסר מפריד מפתח/ערך \"=\" בפרמטר שאילתה של URI: \"%s\"\n" + +#: fe-connect.c:5541 +#, c-format +msgid "invalid URI query parameter: \"%s\"\n" +msgstr "פרמטר שאילתה של URI לא חוקי: \"%s\"\n" + +#: fe-connect.c:5615 +#, c-format +msgid "invalid percent-encoded token: \"%s\"\n" +msgstr "אסימן אשר מקודד באחוזים לא חוקי: \"%s\"\n" + +#: fe-connect.c:5625 +#, c-format +msgid "forbidden value %%00 in percent-encoded value: \"%s\"\n" +msgstr "ערך אסור %%00 בערך מקודד באחוזים: \"%s\"\n" + +#: fe-connect.c:5970 +msgid "connection pointer is NULL\n" +msgstr "החיבור מצביע הוא NULL\n" + +#: fe-connect.c:6268 +#, c-format +msgid "WARNING: password file \"%s\" is not a plain file\n" +msgstr "אזהרה: קובץ הסיסמאות '%s' אינו קובץ רגיל\n" + +#: fe-connect.c:6277 +#, c-format +msgid "" +"WARNING: password file \"%s\" has group or world access; permissions should " +"be u=rw (0600) or less\n" +msgstr "" +"אזהרה: לקובץ הסיסמאות \"%s\" יש גישה קבוצתית או העולם; הרשאות צריך להיות " +"u=rw (0600) או פחות\n" + +#: fe-connect.c:6369 +#, c-format +msgid "password retrieved from file \"%s\"\n" +msgstr "הסיסמה שאוחזרו מקובץ \"%s\"\n" + +#: fe-exec.c:826 +msgid "NOTICE" +msgstr "הודעות" + +#: fe-exec.c:1141 fe-exec.c:1199 fe-exec.c:1245 +msgid "command string is a null pointer\n" +msgstr "מחרוזת הפקודה הוא מצביע null\n" + +#: fe-exec.c:1205 fe-exec.c:1251 fe-exec.c:1346 +msgid "number of parameters must be between 0 and 65535\n" +msgstr "מספר פרמטרים חייב להיות בין 0 ל- 65535\\\n" + +#: fe-exec.c:1239 fe-exec.c:1340 +msgid "statement name is a null pointer\n" +msgstr "שם המשפט הוא מצביע ריק\n" + +#: fe-exec.c:1259 fe-exec.c:1422 fe-exec.c:2140 fe-exec.c:2339 +msgid "function requires at least protocol version 3.0\n" +msgstr "פונקציה דורשת לפחות פרוטוקול גירסה 3.0\n" + +#: fe-exec.c:1377 +msgid "no connection to the server\n" +msgstr "אין חיבור לשרת\n" + +#: fe-exec.c:1384 +msgid "another command is already in progress\n" +msgstr "פקודה אחרת כבר נמצאת בביצוע\n" + +#: fe-exec.c:1498 +msgid "length must be given for binary parameter\n" +msgstr "אורך חייב להינתן עבור פרמטר בינארי\n" + +#: fe-exec.c:1770 +#, c-format +msgid "unexpected asyncStatus: %d\n" +msgstr "בלתי צפוי asyncStatus: %d\n" + +#: fe-exec.c:1790 +#, c-format +msgid "PGEventProc \"%s\" failed during PGEVT_RESULTCREATE event\n" +msgstr "נכשל PGEventProc \"%s\" במהלך האירוע PGEVT_RESULTCREATE\n" + +#: fe-exec.c:1950 +msgid "COPY terminated by new PQexec" +msgstr "תהליך COPY הופסק על-ידי PQexec חדש" + +#: fe-exec.c:1958 +msgid "COPY IN state must be terminated first\n" +msgstr "מצב COPY IN חייב להפסק קודם\n" + +#: fe-exec.c:1978 +msgid "COPY OUT state must be terminated first\n" +msgstr "מצב COPY OUT חייב להפסק קודם\n" + +#: fe-exec.c:1986 +msgid "PQexec not allowed during COPY BOTH\n" +msgstr "אינו מותר PQexec במהלך COPY BOTH\n" + +#: fe-exec.c:2229 fe-exec.c:2296 fe-exec.c:2386 fe-protocol2.c:1352 +#: fe-protocol3.c:1817 +msgid "no COPY in progress\n" +msgstr "אין COPY בביצוע\n" + +#: fe-exec.c:2576 +msgid "connection in wrong state\n" +msgstr "החיבור במצב הלא נכון\n" + +#: fe-exec.c:2607 +msgid "invalid ExecStatusType code" +msgstr "קוד ExecStatusTyp לא תקין" + +#: fe-exec.c:2634 +msgid "PGresult is not an error result\n" +msgstr "ערך PGresult אינו תוצאת שגיאה\n" + +#: fe-exec.c:2709 fe-exec.c:2732 +#, c-format +msgid "column number %d is out of range 0..%d" +msgstr "מספר העמודה %d נמצא מחוץ לטווח 0..%d" + +#: fe-exec.c:2725 +#, c-format +msgid "row number %d is out of range 0..%d" +msgstr "מספר שורה %d נמצא מחוץ לטווח 0..%d" + +#: fe-exec.c:2747 +#, c-format +msgid "parameter number %d is out of range 0..%d" +msgstr "פרמטר מספר %d נמצא מחוץ לטווח 0..%d" + +#: fe-exec.c:3057 +#, c-format +msgid "could not interpret result from server: %s" +msgstr "לא יכלה לפרש את התוצאה מן שרת: %s" + +#: fe-exec.c:3296 fe-exec.c:3380 +msgid "incomplete multibyte character\n" +msgstr "תווים מרובי-בתים לא שלמים\n" + +#: fe-lobj.c:155 +msgid "cannot determine OID of function lo_truncate\n" +msgstr "אין אפשרות לקבוע את OID של פונקציה lo_truncate\n" + +#: fe-lobj.c:171 +msgid "argument of lo_truncate exceeds integer range\n" +msgstr "הארגומנט ל lo_truncate עולה על טווח מספר שלם\n" + +#: fe-lobj.c:222 +msgid "cannot determine OID of function lo_truncate64\n" +msgstr "אין אפשרות לקבוע את OID של פונקציה lo_truncate64\n" + +#: fe-lobj.c:280 +msgid "argument of lo_read exceeds integer range\n" +msgstr "הארגומנט ל lo_read עולה על טווח מספר שלם\n" + +#: fe-lobj.c:335 +msgid "argument of lo_write exceeds integer range\n" +msgstr "הארגומנט ל lo_write עולה על טווח מספר שלם\n" + +#: fe-lobj.c:426 +msgid "cannot determine OID of function lo_lseek64\n" +msgstr "אין אפשרות לקבוע את OID של פונקציה lo_lseek64\n" + +#: fe-lobj.c:522 +msgid "cannot determine OID of function lo_create\n" +msgstr "אין אפשרות לקבוע את OID של פונקציה lo_create\n" + +#: fe-lobj.c:601 +msgid "cannot determine OID of function lo_tell64\n" +msgstr "אין אפשרות לקבוע את OID של פונקציה lo_tell64\n" + +#: fe-lobj.c:707 fe-lobj.c:816 +#, c-format +msgid "could not open file \"%s\": %s\n" +msgstr "לא ניתן לפתוח קובץ \"%s\": %s\n" + +#: fe-lobj.c:762 +#, c-format +msgid "could not read from file \"%s\": %s\n" +msgstr "לא היתה אפשרות לקרוא מתוך הקובץ \"%s\": %s\n" + +#: fe-lobj.c:836 fe-lobj.c:860 +#, c-format +msgid "could not write to file \"%s\": %s\n" +msgstr "לא ניתן לכתוב את הקובץ \"%s\": %s\n" + +#: fe-lobj.c:947 +msgid "query to initialize large object functions did not return data\n" +msgstr "שאילתת לאתחל פונקציות של אובייקט גדול לא החזירה נתונים\n" + +#: fe-lobj.c:996 +msgid "cannot determine OID of function lo_open\n" +msgstr "אין אפשרות לקבוע את OID של פונקציה lo_open\n" + +#: fe-lobj.c:1003 +msgid "cannot determine OID of function lo_close\n" +msgstr "אין אפשרות לקבוע את OID של פונקציה lo_close\n" + +#: fe-lobj.c:1010 +msgid "cannot determine OID of function lo_creat\n" +msgstr "אין אפשרות לקבוע את OID של פונקציה lo_creat\n" + +#: fe-lobj.c:1017 +msgid "cannot determine OID of function lo_unlink\n" +msgstr "אין אפשרות לקבוע את OID של פונקציה lo_unlink\n" + +#: fe-lobj.c:1024 +msgid "cannot determine OID of function lo_lseek\n" +msgstr "אין אפשרות לקבוע את OID של פונקציה lo_lseek\n" + +#: fe-lobj.c:1031 +msgid "cannot determine OID of function lo_tell\n" +msgstr "אין אפשרות לקבוע את OID של פונקציה lo_tell\n" + +#: fe-lobj.c:1038 +msgid "cannot determine OID of function loread\n" +msgstr "אין אפשרות לקבוע את OID של פונקציה loread\n" + +#: fe-lobj.c:1045 +msgid "cannot determine OID of function lowrite\n" +msgstr "אין אפשרות לקבוע את OID של פונקציה lowrite\n" + +#: fe-misc.c:292 +#, c-format +msgid "integer of size %lu not supported by pqGetInt" +msgstr "מספר שלם בגודל %lu אינו נתמך על ידי pqGetInt" + +#: fe-misc.c:328 +#, c-format +msgid "integer of size %lu not supported by pqPutInt" +msgstr "מספר שלם בגודל %lu אינו נתמך על ידי pqPutInt" + +#: fe-misc.c:639 fe-misc.c:840 +msgid "connection not open\n" +msgstr "חיבור לא פתוח\n" + +#: fe-misc.c:809 fe-secure-openssl.c:229 fe-secure-openssl.c:338 +#: fe-secure.c:253 fe-secure.c:362 +msgid "" +"server closed the connection unexpectedly\n" +"\tThis probably means the server terminated abnormally\n" +"\tbefore or while processing the request.\n" +msgstr "" +"שרת סגר את החיבור שבאופן בלתי צפוי\n" +"זה כנראה אומר שהשרת נכבה בצורה חריגה\n" +"לפני או בעת עיבוד הבקשה.\n" + +#: fe-misc.c:1013 +msgid "timeout expired\n" +msgstr "פג הזמן הקצוב\n" + +#: fe-misc.c:1058 +msgid "invalid socket\n" +msgstr "שקע לא חוקי\n" + +#: fe-misc.c:1081 +#, c-format +msgid "select() failed: %s\n" +msgstr "נכשל select(): %s\n" + +#: fe-protocol2.c:91 +#, c-format +msgid "invalid setenv state %c, probably indicative of memory corruption\n" +msgstr "מצב setenv לא תקין %c, כנראה מעידה על נזק לזיכרון\n" + +#: fe-protocol2.c:390 +#, c-format +msgid "invalid state %c, probably indicative of memory corruption\n" +msgstr "מצב לא תקין %c, כנראה מעידה על נזק לזיכרון\n" + +#: fe-protocol2.c:479 fe-protocol3.c:186 +#, c-format +msgid "message type 0x%02x arrived from server while idle" +msgstr "סוג ההודעה 0x%02x הגיעו משרת בזמן חוסר פעילות" + +#: fe-protocol2.c:503 fe-protocol2.c:538 fe-protocol2.c:1049 fe-protocol3.c:209 +#: fe-protocol3.c:236 fe-protocol3.c:253 fe-protocol3.c:333 fe-protocol3.c:728 +#: fe-protocol3.c:951 +msgid "out of memory" +msgstr "אין זיכרון פנוי" + +#: fe-protocol2.c:529 +#, c-format +msgid "unexpected character %c following empty query response (\"I\" message)" +msgstr "תו לא צפוי %c בעקבות תגובת שאילתה ריקה (הודעת \"I\")" + +#: fe-protocol2.c:595 +#, c-format +msgid "" +"server sent data (\"D\" message) without prior row description (\"T\" " +"message)" +msgstr "השרת שלח נתונים (\"D\" הודעה) ללא תיאור השורה מוקדמת (הודעה \"T\")" + +#: fe-protocol2.c:613 +#, c-format +msgid "" +"server sent binary data (\"B\" message) without prior row description (\"T\" " +"message)" +msgstr "" +"השרת שלח נתונים בינאריים (הודעה \"B\") ללא תיאור השורה מוקדמת (הודעה \"T\")" + +#: fe-protocol2.c:633 fe-protocol3.c:412 +#, c-format +msgid "unexpected response from server; first received character was \"%c\"\n" +msgstr "תגובה לא צפויה משרת; התו הראשון שהתקבל היה '%c'\n" + +#: fe-protocol2.c:762 fe-protocol2.c:937 fe-protocol3.c:627 fe-protocol3.c:854 +msgid "out of memory for query result" +msgstr "אין די זיכרון עבור תוצאת שאילתה" + +#: fe-protocol2.c:1395 fe-protocol3.c:1886 +#, c-format +msgid "%s" +msgstr "%s" + +#: fe-protocol2.c:1407 +#, c-format +msgid "lost synchronization with server, resetting connection" +msgstr "אבד סינכרון עם שרת, איפוס החיבור" + +#: fe-protocol2.c:1541 fe-protocol2.c:1573 fe-protocol3.c:2089 +#, c-format +msgid "protocol error: id=0x%x\n" +msgstr "שגיאת פרוטוקול: id=0x%x\n" + +#: fe-protocol3.c:368 +msgid "" +"server sent data (\"D\" message) without prior row description (\"T\" " +"message)\n" +msgstr "השרת שלח נתונים (\"D\" הודעה) ללא תיאור השורה מוקדמת (הודעה \"T\")\n" + +#: fe-protocol3.c:433 +#, c-format +msgid "message contents do not agree with length in message type \"%c\"\n" +msgstr "תוכן ההודעה לא תואם את האורך בסוג ההודעה '%c'\n" + +#: fe-protocol3.c:454 +#, c-format +msgid "lost synchronization with server: got message type \"%c\", length %d\n" +msgstr "אבד סינכרון עם שרת: יש סוג ההודעה \"%c\", אורך %d\n" + +#: fe-protocol3.c:505 fe-protocol3.c:545 +msgid "insufficient data in \"T\" message" +msgstr "אין מספיק נתונים בהודעת \"T\"" + +#: fe-protocol3.c:578 +msgid "extraneous data in \"T\" message" +msgstr "נתונים חיצוניים בהודעה \"T\"." + +#: fe-protocol3.c:691 +msgid "extraneous data in \"t\" message" +msgstr "נתונים חיצוניים בהודעה \"t\"" + +#: fe-protocol3.c:762 fe-protocol3.c:794 fe-protocol3.c:812 +msgid "insufficient data in \"D\" message" +msgstr "אין מספיק נתונים בהודעת \"D\"" + +#: fe-protocol3.c:768 +msgid "unexpected field count in \"D\" message" +msgstr "תוצאת ספירת שדות בלתי צפויה בהודעה \"D\"" + +#: fe-protocol3.c:821 +msgid "extraneous data in \"D\" message" +msgstr "נתונים חיצוניים בהודעה \"D\"" + +#: fe-protocol3.c:1005 +msgid "no error message available\n" +msgstr "הודעת שגיאה לא זמינה\n" + +#. translator: %s represents a digit string +#: fe-protocol3.c:1035 fe-protocol3.c:1054 +#, c-format +msgid " at character %s" +msgstr " בתו %s" + +#: fe-protocol3.c:1067 +#, c-format +msgid "DETAIL: %s\n" +msgstr "פירוט: %s\n" + +#: fe-protocol3.c:1070 +#, c-format +msgid "HINT: %s\n" +msgstr "רמז: %s\n" + +#: fe-protocol3.c:1073 +#, c-format +msgid "QUERY: %s\n" +msgstr "שאילתה: %s\n" + +#: fe-protocol3.c:1080 +#, c-format +msgid "CONTEXT: %s\n" +msgstr "ההקשר: %s\n" + +#: fe-protocol3.c:1089 +#, c-format +msgid "SCHEMA NAME: %s\n" +msgstr "שם הסכימה: %s\n" + +#: fe-protocol3.c:1093 +#, c-format +msgid "TABLE NAME: %s\n" +msgstr "שם הטבלה: %s\n" + +#: fe-protocol3.c:1097 +#, c-format +msgid "COLUMN NAME: %s\n" +msgstr "שם עמודה: %s\n" + +#: fe-protocol3.c:1101 +#, c-format +msgid "DATATYPE NAME: %s\n" +msgstr "שם סוג נתונים: %s\n" + +#: fe-protocol3.c:1105 +#, c-format +msgid "CONSTRAINT NAME: %s\n" +msgstr "שם לאילוץ: %s\n" + +#: fe-protocol3.c:1117 +msgid "LOCATION: " +msgstr "מיקום: " + +#: fe-protocol3.c:1119 +#, c-format +msgid "%s, " +msgstr "%s, " + +#: fe-protocol3.c:1121 +#, c-format +msgid "%s:%s" +msgstr "%s:%s" + +#: fe-protocol3.c:1316 +#, c-format +msgid "LINE %d: " +msgstr "השורה %d: " + +#: fe-protocol3.c:1711 +msgid "PQgetline: not doing text COPY OUT\n" +msgstr "תכנית PQgetline: לא עושה טקסט COPY OUT.\n" + +#: fe-secure-openssl.c:234 fe-secure-openssl.c:343 fe-secure-openssl.c:1321 +#, c-format +msgid "SSL SYSCALL error: %s\n" +msgstr "שגיאה SSL SYSCALL: %s\n" + +#: fe-secure-openssl.c:241 fe-secure-openssl.c:350 fe-secure-openssl.c:1325 +msgid "SSL SYSCALL error: EOF detected\n" +msgstr "שגיאת SSL SYSCALL: EOF זוהה\n" + +#: fe-secure-openssl.c:252 fe-secure-openssl.c:361 fe-secure-openssl.c:1334 +#, c-format +msgid "SSL error: %s\n" +msgstr "שגיאת SSL: %s\n" + +#: fe-secure-openssl.c:267 fe-secure-openssl.c:376 +msgid "SSL connection has been closed unexpectedly\n" +msgstr "חיבור SSL נסגר באופן בלתי צפוי\n" + +#: fe-secure-openssl.c:273 fe-secure-openssl.c:382 fe-secure-openssl.c:1343 +#, c-format +msgid "unrecognized SSL error code: %d\n" +msgstr "קוד שגיאת SSL לא מזוהה: %d\n" + +#: fe-secure-openssl.c:494 +msgid "SSL certificate's name entry is missing\n" +msgstr "שם תעודת SSL חסר\n" + +#: fe-secure-openssl.c:528 +msgid "SSL certificate's name contains embedded null\n" +msgstr "שם תעודת SSL מכיל ערך null מוטבע\n" + +#: fe-secure-openssl.c:580 +msgid "host name must be specified for a verified SSL connection\n" +msgstr "יש לציין שם המארח עבור חיבור SSL מאומת\n" + +#: fe-secure-openssl.c:680 +#, c-format +msgid "server certificate for \"%s\" does not match host name \"%s\"\n" +msgstr "תעודת השרת עבור '%s' אינה תואמת עם שם מארח \"%s\"\n" + +#: fe-secure-openssl.c:686 +msgid "could not get server's host name from server certificate\n" +msgstr "לא היתה אפשרות לקבל שם המארח של השרת מתעודת השרת\n" + +#: fe-secure-openssl.c:928 +#, c-format +msgid "could not create SSL context: %s\n" +msgstr "לא היתה אפשרות ליצור את הקשר SSL: %s\n" + +#: fe-secure-openssl.c:965 +#, c-format +msgid "could not read root certificate file \"%s\": %s\n" +msgstr "לא היתה אפשרות לקרוא את קובץ תעודת הבסיס \"%s\": %s\n" + +#: fe-secure-openssl.c:993 +#, c-format +msgid "SSL library does not support CRL certificates (file \"%s\")\n" +msgstr "ספריית SSL אינה תומכת בתעודות CRL (הקובץ \"%s\")\n" + +#: fe-secure-openssl.c:1021 +msgid "" +"could not get home directory to locate root certificate file\n" +"Either provide the file or change sslmode to disable server certificate " +"verification.\n" +msgstr "" +"לא ניתן לגשת לספריית הבית כדי לאתר קובץ תעודת הבסיס\n" +"או תספק את הקובץ או תשנה את sslmode כדי לבטל את אימות תעודת שרת.\n" + +#: fe-secure-openssl.c:1025 +#, c-format +msgid "" +"root certificate file \"%s\" does not exist\n" +"Either provide the file or change sslmode to disable server certificate " +"verification.\n" +msgstr "" +"קובץ תעודת הבסיס '%s' אינו קיים\n" +"או תספק את הקובץ או תשנה את sslmode כדי לבטל את אימות תעודת שרת.\n" + +#: fe-secure-openssl.c:1056 +#, c-format +msgid "could not open certificate file \"%s\": %s\n" +msgstr "לא היתה אפשרות לפתוח את קובץ התעודה \"%s\": %s\n" + +#: fe-secure-openssl.c:1075 +#, c-format +msgid "could not read certificate file \"%s\": %s\n" +msgstr "לא היתה אפשרות לקרוא את קובץ התעודה \"%s\": %s\n" + +#: fe-secure-openssl.c:1099 +#, c-format +msgid "could not establish SSL connection: %s\n" +msgstr "לא היתה אפשרות ליצור חיבור SSL: %s\n" + +#: fe-secure-openssl.c:1153 +#, c-format +msgid "could not load SSL engine \"%s\": %s\n" +msgstr "אין אפשרות לטעון את מנוע SSL \"%s\": %s\n" + +#: fe-secure-openssl.c:1165 +#, c-format +msgid "could not initialize SSL engine \"%s\": %s\n" +msgstr "לא היתה אפשרות לאתחל את מנוע SSL \"%s\": %s\n" + +#: fe-secure-openssl.c:1181 +#, c-format +msgid "could not read private SSL key \"%s\" from engine \"%s\": %s\n" +msgstr "לא היתה אפשרות לקרוא מפתח פרטי SSL \"%s\" מהמנוע \"%s\": %s\n" + +#: fe-secure-openssl.c:1195 +#, c-format +msgid "could not load private SSL key \"%s\" from engine \"%s\": %s\n" +msgstr "לא היתה אפשרות לטעון מפתח פרטי SSL \"%s\" מהמנוע \"%s\": %s\n" + +#: fe-secure-openssl.c:1232 +#, c-format +msgid "certificate present, but not private key file \"%s\"\n" +msgstr "התעודה קיימת, אבל לא קובץ של המפתח הפרטי \"%s\"\n" + +#: fe-secure-openssl.c:1240 +#, c-format +msgid "" +"private key file \"%s\" has group or world access; permissions should be " +"u=rw (0600) or less\n" +msgstr "" +"לקובץ המפתח פהרטי \"%s\" יש גישה קבוצתית או העולם; הרשאות צריך להיות u = rw " +"(0600) או פחות\n" + +#: fe-secure-openssl.c:1251 +#, c-format +msgid "could not load private key file \"%s\": %s\n" +msgstr "אין אפשרות לטעון את קובץ המפתח הפרטי \"%s\": %s\n" + +#: fe-secure-openssl.c:1265 +#, c-format +msgid "certificate does not match private key file \"%s\": %s\n" +msgstr "התעודה אינה תואמת קובץ המפתח הפרטי \"%s\": %s\n" + +#: fe-secure-openssl.c:1364 +#, c-format +msgid "certificate could not be obtained: %s\n" +msgstr "לא היתה אפשרות להשיג את התעודה: %s\n" + +#: fe-secure-openssl.c:1456 +#, c-format +msgid "no SSL error reported" +msgstr "אין דיווח על שגיאת SSL" + +#: fe-secure-openssl.c:1465 +#, c-format +msgid "SSL error code %lu" +msgstr "קוד שגיאת SSL %lu" + +#: fe-secure.c:261 +#, c-format +msgid "could not receive data from server: %s\n" +msgstr "לא יכול לקבל נתונים משרת: %s\n" + +#: fe-secure.c:369 +#, c-format +msgid "could not send data to server: %s\n" +msgstr "לא היתה אפשרות לשלוח נתונים לשרת: %s\n" + +#: win32.c:317 +#, c-format +msgid "unrecognized socket error: 0x%08X/%d" +msgstr "שגיאת שקע לא מזוהה: 0x%08X/%d" diff --git a/src/interfaces/libpq/po/it.po b/src/interfaces/libpq/po/it.po new file mode 100644 index 0000000..737f35b --- /dev/null +++ b/src/interfaces/libpq/po/it.po @@ -0,0 +1,1148 @@ +# +# libpq.po +# Italian message translation file for libpq +# +# For development and bug report please use: +# https://github.com/dvarrazzo/postgresql-it +# +# Copyright (C) 2012-2017 PostgreSQL Global Development Group +# Copyright (C) 2010, Associazione Culturale ITPUG +# +# Daniele Varrazzo <daniele.varrazzo@gmail.com>, 2012-2017 +# Maurizio Totti <maurizio.totti@gmail.com>, 2010 +# Fabrizio Mazzoni <veramente@libero.it>, 2003. +# Gaetano Mendola <mendola@bigfoot.com>, 2003. +# +# This file is distributed under the same license as the PostgreSQL package. +# +msgid "" +msgstr "" +"Project-Id-Version: libpq (PostgreSQL) 11\n" +"Report-Msgid-Bugs-To: pgsql-bugs@postgresql.org\n" +"POT-Creation-Date: 2018-10-08 14:08+0000\n" +"PO-Revision-Date: 2018-10-08 21:59+0100\n" +"Last-Translator: Daniele Varrazzo <daniele.varrazzo@gmail.com>\n" +"Language-Team: https://github.com/dvarrazzo/postgresql-it\n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Poedit-SourceCharset: UTF-8\n" +"X-Generator: Poedit 2.0.6\n" + +#: fe-auth-scram.c:189 +msgid "malformed SCRAM message (empty message)\n" +msgstr "messaggio SCRAM malformato (messaggio vuoto)\n" + +#: fe-auth-scram.c:195 +msgid "malformed SCRAM message (length mismatch)\n" +msgstr "messaggio SCRAM malformato (lunghezza errata)\n" + +#: fe-auth-scram.c:244 +msgid "incorrect server signature\n" +msgstr "firma del server non corretta\n" + +#: fe-auth-scram.c:253 +msgid "invalid SCRAM exchange state\n" +msgstr "stato di scambio SCRAM non valido\n" + +#: fe-auth-scram.c:276 +#, c-format +msgid "malformed SCRAM message (attribute \"%c\" expected)\n" +msgstr "messaggio SCRAM malformato (atteso attributo \"%c\")\n" + +#: fe-auth-scram.c:285 +#, c-format +msgid "malformed SCRAM message (expected character \"=\" for attribute \"%c\")\n" +msgstr "messaggio SCRAM malformato (atteso carattere \"=\" per l'attributo \"%c\")\n" + +#: fe-auth-scram.c:326 +msgid "could not generate nonce\n" +msgstr "generazione del nonce fallita\n" + +#: fe-auth-scram.c:334 fe-auth-scram.c:401 fe-auth-scram.c:523 +#: fe-auth-scram.c:543 fe-auth-scram.c:569 fe-auth-scram.c:583 +#: fe-auth-scram.c:625 fe-auth.c:227 fe-auth.c:362 fe-auth.c:432 fe-auth.c:467 +#: fe-auth.c:643 fe-auth.c:802 fe-auth.c:1114 fe-auth.c:1262 fe-connect.c:835 +#: fe-connect.c:1264 fe-connect.c:1440 fe-connect.c:1922 fe-connect.c:1945 +#: fe-connect.c:2606 fe-connect.c:4152 fe-connect.c:4404 fe-connect.c:4523 +#: fe-connect.c:4773 fe-connect.c:4853 fe-connect.c:4952 fe-connect.c:5208 +#: fe-connect.c:5237 fe-connect.c:5309 fe-connect.c:5333 fe-connect.c:5351 +#: fe-connect.c:5452 fe-connect.c:5461 fe-connect.c:5817 fe-connect.c:5967 +#: fe-exec.c:2702 fe-exec.c:3449 fe-exec.c:3614 fe-lobj.c:895 +#: fe-protocol2.c:1213 fe-protocol3.c:999 fe-protocol3.c:1685 +#: fe-secure-common.c:110 fe-secure-openssl.c:438 fe-secure-openssl.c:1025 +msgid "out of memory\n" +msgstr "memoria esaurita\n" + +#: fe-auth-scram.c:561 +msgid "invalid SCRAM response (nonce mismatch)\n" +msgstr "risposta SCRAM non valida (il nonce non combacia)\n" + +#: fe-auth-scram.c:600 +msgid "malformed SCRAM message (invalid iteration count)\n" +msgstr "messaggio SCRAM malformato (numero di iterazione non valido)\n" + +#: fe-auth-scram.c:606 +msgid "malformed SCRAM message (garbage at end of server-first-message)\n" +msgstr "messaggio SCRAM malformato (dati non riconosciuti dopo il primo messaggio del server)\n" + +#: fe-auth-scram.c:636 +#, c-format +msgid "error received from server in SCRAM exchange: %s\n" +msgstr "errore ricevuto dal server durante lo scambio SCRAM: %s\n" + +#: fe-auth-scram.c:652 +msgid "malformed SCRAM message (garbage at end of server-final-message)\n" +msgstr "messaggio SCRAM malformato (dati non riconosciuti dopo il messaggio finale del server)\n" + +#: fe-auth-scram.c:660 +msgid "malformed SCRAM message (invalid server signature)\n" +msgstr "messaggio SCRAM malformato (firma del server non valida)\n" + +#: fe-auth.c:122 +#, c-format +msgid "out of memory allocating GSSAPI buffer (%d)\n" +msgstr "memoria esaurita nell'allocazione del buffer GSSAPI (%d)\n" + +# DV: non ne sono convinto +#: fe-auth.c:177 +msgid "GSSAPI continuation error" +msgstr "GSSAPI errore di continuazione" + +#: fe-auth.c:207 fe-auth.c:461 fe-secure-common.c:98 +msgid "host name must be specified\n" +msgstr "il nome dell'host deve essere specificato\n" + +#: fe-auth.c:214 +msgid "duplicate GSS authentication request\n" +msgstr "richiesta di autenticazione GSS duplicata\n" + +# non è che mi torni tanto così +#: fe-auth.c:240 +msgid "GSSAPI name import error" +msgstr "errore di importazione del nome GSSAPI" + +#: fe-auth.c:303 +#, c-format +msgid "out of memory allocating SSPI buffer (%d)\n" +msgstr "memoria esaurita nell'allocazione del buffer SSPI (%d)\n" + +#: fe-auth.c:351 +msgid "SSPI continuation error" +msgstr "SSPI errore di continuazione" + +#: fe-auth.c:422 +msgid "duplicate SSPI authentication request\n" +msgstr "richiesta di autenticazione SSPI duplicata\n" + +#: fe-auth.c:447 +msgid "could not acquire SSPI credentials" +msgstr "non è stato possibile ottenere le credenziali SSPI" + +#: fe-auth.c:501 +msgid "duplicate SASL authentication request\n" +msgstr "doppia richiesta di autenticazione SASL\n" + +#: fe-auth.c:549 +msgid "server offered SCRAM-SHA-256-PLUS authentication over a non-SSL connection\n" +msgstr "il server ha offerto autenticazione SCRAM-SHA-256-PLUS su una connessione non SSL\n" + +#: fe-auth.c:561 +msgid "none of the server's SASL authentication mechanisms are supported\n" +msgstr "nessuno dei meccanismi di autenticazione SASL del server è supportato\n" + +#: fe-auth.c:667 +#, c-format +msgid "out of memory allocating SASL buffer (%d)\n" +msgstr "memoria esaurita nell'allocazione del buffer SASL (%d)\n" + +#: fe-auth.c:692 +msgid "AuthenticationSASLFinal received from server, but SASL authentication was not completed\n" +msgstr "ricevuto AuthenticationSASLFinal dal server, ma l'autenticazione SASL non è stata completata\n" + +#: fe-auth.c:769 +msgid "SCM_CRED authentication method not supported\n" +msgstr "il metodo di autenticazione SCM_CRED non è supportato\n" + +#: fe-auth.c:860 +msgid "Kerberos 4 authentication not supported\n" +msgstr "l'autenticazione Kerberos 4 non è supportata\n" + +#: fe-auth.c:865 +msgid "Kerberos 5 authentication not supported\n" +msgstr "l'autenticazione Kerberos 5 non è supportata\n" + +#: fe-auth.c:936 +msgid "GSSAPI authentication not supported\n" +msgstr "l'autenticazione GSSAPI non è supportata\n" + +#: fe-auth.c:968 +msgid "SSPI authentication not supported\n" +msgstr "l'autenticazione SSPI non è supportata\n" + +#: fe-auth.c:976 +msgid "Crypt authentication not supported\n" +msgstr "l'autenticazione Crypt non è supportata\n" + +#: fe-auth.c:1042 +#, c-format +msgid "authentication method %u not supported\n" +msgstr "l'autenticazione %u non è supportata\n" + +#: fe-auth.c:1089 +#, c-format +msgid "user name lookup failure: error code %lu\n" +msgstr "ricerca del nome utente fallita: codice di errore %lu\n" + +#: fe-auth.c:1099 fe-connect.c:2533 +#, c-format +msgid "could not look up local user ID %d: %s\n" +msgstr "ricerca dell'ID utente locale %d non riuscita: %s\n" + +#: fe-auth.c:1104 fe-connect.c:2538 +#, c-format +msgid "local user with ID %d does not exist\n" +msgstr "l'utente locale con ID %d non esiste\n" + +#: fe-auth.c:1206 +msgid "unexpected shape of result set returned for SHOW\n" +msgstr "il risultato restituito da SHOW ha una forma imprevista\n" + +#: fe-auth.c:1215 +msgid "password_encryption value too long\n" +msgstr "valore di password_encryption troppo lungo\n" + +#: fe-auth.c:1255 +#, c-format +msgid "unrecognized password encryption algorithm \"%s\"\n" +msgstr "algoritmo di criptaggio della password \"%s\" sconosciuto\n" + +#: fe-connect.c:1018 +#, c-format +msgid "could not match %d host names to %d hostaddr values\n" +msgstr "non è possibile far combaciare %d nomi host con %d valori hostaddr\n" + +#: fe-connect.c:1094 +#, c-format +msgid "could not match %d port numbers to %d hosts\n" +msgstr "non è possibile far combaciare %d numeri di porta con %d host\n" + +#: fe-connect.c:1190 +#, c-format +msgid "invalid sslmode value: \"%s\"\n" +msgstr "valore sslmode errato: \"%s\"\n" + +#: fe-connect.c:1211 +#, c-format +msgid "sslmode value \"%s\" invalid when SSL support is not compiled in\n" +msgstr "valore sslmode \"%s\" non valido quando il supporto SSL non è compilato\n" + +#: fe-connect.c:1246 +#, c-format +msgid "invalid target_session_attrs value: \"%s\"\n" +msgstr "valore per target_session_attrs non valido: \"%s\"\n" + +#: fe-connect.c:1464 +#, c-format +msgid "could not set socket to TCP no delay mode: %s\n" +msgstr "impostazione del socket in modalità TCP no delay fallita: %s\n" + +#: fe-connect.c:1494 +#, c-format +msgid "" +"could not connect to server: %s\n" +"\tIs the server running locally and accepting\n" +"\tconnections on Unix domain socket \"%s\"?\n" +msgstr "" +"connessione al server fallita: %s\n" +"\tVerifica che il server locale sia in funzione e che\n" +"\taccetti connessioni sul socket di dominio Unix \"%s\"\n" + +#: fe-connect.c:1552 +#, c-format +msgid "" +"could not connect to server: %s\n" +"\tIs the server running on host \"%s\" (%s) and accepting\n" +"\tTCP/IP connections on port %s?\n" +msgstr "" +"connessione al server fallita: %s\n" +"\tVerifica che il server all'indirizzo \"%s\" (%s) sia in funzione\n" +"\te che accetti connessioni TCP/IP sulla porta %s\n" + +#: fe-connect.c:1561 +#, c-format +msgid "" +"could not connect to server: %s\n" +"\tIs the server running on host \"%s\" and accepting\n" +"\tTCP/IP connections on port %s?\n" +msgstr "" +"connessione al server fallita: %s\n" +"\tVerifica che il server all'indirizzo \"%s\" sia in funzione\n" +"\te che accetti connessioni TCP/IP sulla porta %s\n" + +#: fe-connect.c:1612 fe-connect.c:1644 fe-connect.c:1677 fe-connect.c:2325 +#, c-format +msgid "setsockopt(%s) failed: %s\n" +msgstr "setsockopt(%s) fallita: %s\n" + +#: fe-connect.c:1726 +#, c-format +msgid "WSAIoctl(SIO_KEEPALIVE_VALS) failed: %ui\n" +msgstr "chiamata WSAIoctl(SIO_KEEPALIVE_VALS) fallito: %ui\n" + +#: fe-connect.c:2035 +msgid "invalid connection state, probably indicative of memory corruption\n" +msgstr "stato della connessione non valido, probabilmente indica una corruzione della memoria\n" + +#: fe-connect.c:2101 +#, c-format +msgid "invalid port number: \"%s\"\n" +msgstr "numero di porta non valido: \"%s\"\n" + +#: fe-connect.c:2117 +#, c-format +msgid "could not translate host name \"%s\" to address: %s\n" +msgstr "conversione del nome host \"%s\" in indirizzo fallita: %s\n" + +#: fe-connect.c:2130 +#, c-format +msgid "could not parse network address \"%s\": %s\n" +msgstr "interpretazione dell'indirizzo di rete \"%s\" fallita: %s\n" + +#: fe-connect.c:2143 +#, c-format +msgid "Unix-domain socket path \"%s\" is too long (maximum %d bytes)\n" +msgstr "Il percorso del socket di dominio unix \"%s\" è troppo lungo (massimo %d byte)\n" + +#: fe-connect.c:2158 +#, c-format +msgid "could not translate Unix-domain socket path \"%s\" to address: %s\n" +msgstr "conversione del percorso del socket di dominio Unix \"%s\" in indirizzo fallita: %s\n" + +#: fe-connect.c:2262 +#, c-format +msgid "could not create socket: %s\n" +msgstr "creazione del socket fallita: %s\n" + +#: fe-connect.c:2284 +#, c-format +msgid "could not set socket to nonblocking mode: %s\n" +msgstr "impostazione del socket in modalità non bloccante fallita: %s\n" + +#: fe-connect.c:2294 +#, c-format +msgid "could not set socket to close-on-exec mode: %s\n" +msgstr "impostazione del socket in modalità close-on-exec fallita: %s\n" + +#: fe-connect.c:2312 +msgid "keepalives parameter must be an integer\n" +msgstr "il parametro keepalives dev'essere un intero\n" + +#: fe-connect.c:2450 +#, c-format +msgid "could not get socket error status: %s\n" +msgstr "lettura dello stato di errore del socket fallita: %s\n" + +#: fe-connect.c:2478 +#, c-format +msgid "could not get client address from socket: %s\n" +msgstr "non è stato possibile ottenere l'indirizzo del client dal socket: %s\n" + +#: fe-connect.c:2520 +msgid "requirepeer parameter is not supported on this platform\n" +msgstr "il parametro requirepeer non è supportato su questa piattaforma\n" + +#: fe-connect.c:2523 +#, c-format +msgid "could not get peer credentials: %s\n" +msgstr "non è stato possibile ottenere le credenziali del peer: %s\n" + +#: fe-connect.c:2546 +#, c-format +msgid "requirepeer specifies \"%s\", but actual peer user name is \"%s\"\n" +msgstr "requirepeer specifica \"%s\", ma il vero nome utente del peer è \"%s\"\n" + +#: fe-connect.c:2580 +#, c-format +msgid "could not send SSL negotiation packet: %s\n" +msgstr "invio del pacchetto di negoziazione SSL fallito: %s\n" + +#: fe-connect.c:2619 +#, c-format +msgid "could not send startup packet: %s\n" +msgstr "invio del pacchetto di avvio fallito: %s\n" + +#: fe-connect.c:2689 +msgid "server does not support SSL, but SSL was required\n" +msgstr "il server non supporta SSL, ma SSL è stato richiesto\n" + +#: fe-connect.c:2715 +#, c-format +msgid "received invalid response to SSL negotiation: %c\n" +msgstr "ricevuta risposta errata alla negoziazione SSL: %c\n" + +#: fe-connect.c:2792 fe-connect.c:2825 +#, c-format +msgid "expected authentication request from server, but received %c\n" +msgstr "prevista richiesta di autenticazione dal server, ma è stato ricevuto %c\n" + +#: fe-connect.c:3052 +msgid "unexpected message from server during startup\n" +msgstr "messaggio imprevisto dal server durante l'avvio\n" + +#: fe-connect.c:3282 +#, c-format +msgid "could not make a writable connection to server \"%s:%s\"\n" +msgstr "errore nello stabilire una connessione scrivibile col server \"%s:%s\"\n" + +#: fe-connect.c:3328 +#, c-format +msgid "test \"SHOW transaction_read_only\" failed on server \"%s:%s\"\n" +msgstr "test \"SHOW transaction_read_only\" fallito sul server \"%s:%s\"\n" + +#: fe-connect.c:3343 +#, c-format +msgid "invalid connection state %d, probably indicative of memory corruption\n" +msgstr "stato connessione errato %d, probabilmente indica una corruzione di memoria\n" + +#: fe-connect.c:3758 fe-connect.c:3818 +#, c-format +msgid "PGEventProc \"%s\" failed during PGEVT_CONNRESET event\n" +msgstr "PGEventProc \"%s\" fallito durante l'evento PGEVT_CONNRESET\n" + +#: fe-connect.c:4165 +#, c-format +msgid "invalid LDAP URL \"%s\": scheme must be ldap://\n" +msgstr "URL LDAP \"%s\" non corretta: lo schema deve essere ldap://\n" + +#: fe-connect.c:4180 +#, c-format +msgid "invalid LDAP URL \"%s\": missing distinguished name\n" +msgstr "URL LDAP \"%s\" non corretta: distinguished name non trovato\n" + +#: fe-connect.c:4191 fe-connect.c:4244 +#, c-format +msgid "invalid LDAP URL \"%s\": must have exactly one attribute\n" +msgstr "URL LDAP \"%s\" non corretta: deve avere esattamente un attributo\n" + +#: fe-connect.c:4201 fe-connect.c:4258 +#, c-format +msgid "invalid LDAP URL \"%s\": must have search scope (base/one/sub)\n" +msgstr "URL LDAP \"%s\" non corretta: deve essere specificato la portata della ricerca (base/one/sub)\n" + +#: fe-connect.c:4212 +#, c-format +msgid "invalid LDAP URL \"%s\": no filter\n" +msgstr "URL LDAP \"%s\" non corretta: filtro non specificato\n" + +#: fe-connect.c:4233 +#, c-format +msgid "invalid LDAP URL \"%s\": invalid port number\n" +msgstr "URL LDAP \"%s\" non corretta: numero di porta non valido\n" + +#: fe-connect.c:4267 +msgid "could not create LDAP structure\n" +msgstr "creazione della struttura dati LDAP fallita\n" + +#: fe-connect.c:4343 +#, c-format +msgid "lookup on LDAP server failed: %s\n" +msgstr "ricerca del server LDAP fallita: %s\n" + +#: fe-connect.c:4354 +msgid "more than one entry found on LDAP lookup\n" +msgstr "trovata più di una voce nella ricerca LDAP\n" + +#: fe-connect.c:4355 fe-connect.c:4367 +msgid "no entry found on LDAP lookup\n" +msgstr "nessun elemento trovato per la ricerca LDAP\n" + +#: fe-connect.c:4378 fe-connect.c:4391 +msgid "attribute has no values on LDAP lookup\n" +msgstr "l'attributo non ha valori nella ricerca LDAP\n" + +#: fe-connect.c:4443 fe-connect.c:4462 fe-connect.c:4991 +#, c-format +msgid "missing \"=\" after \"%s\" in connection info string\n" +msgstr "manca \"=\" dopo \"%s\" nella stringa di connessione\n" + +#: fe-connect.c:4535 fe-connect.c:5176 fe-connect.c:5950 +#, c-format +msgid "invalid connection option \"%s\"\n" +msgstr "opzione di connessione errata \"%s\"\n" + +#: fe-connect.c:4551 fe-connect.c:5040 +msgid "unterminated quoted string in connection info string\n" +msgstr "stringa tra virgolette non terminata nella stringa di connessione\n" + +#: fe-connect.c:4634 +#, c-format +msgid "definition of service \"%s\" not found\n" +msgstr "il file di definizione di servizio \"%s\" non è stato trovato\n" + +#: fe-connect.c:4657 +#, c-format +msgid "service file \"%s\" not found\n" +msgstr "il file di servizio \"%s\" non è stato trovato\n" + +#: fe-connect.c:4670 +#, c-format +msgid "line %d too long in service file \"%s\"\n" +msgstr "la riga %d nel file di servizio \"%s\" è troppo lunga\n" + +#: fe-connect.c:4741 fe-connect.c:4785 +#, c-format +msgid "syntax error in service file \"%s\", line %d\n" +msgstr "errore di sintassi del file di servizio \"%s\", alla riga %d\n" + +#: fe-connect.c:4752 +#, c-format +msgid "nested service specifications not supported in service file \"%s\", line %d\n" +msgstr "specifiche di servizio annidate non supportate nel file di servizio \"%s\", linea %d\n" + +#: fe-connect.c:5472 +#, c-format +msgid "invalid URI propagated to internal parser routine: \"%s\"\n" +msgstr "URI invalida propagata alla routine di parsing interna: \"%s\"\n" + +#: fe-connect.c:5549 +#, c-format +msgid "end of string reached when looking for matching \"]\" in IPv6 host address in URI: \"%s\"\n" +msgstr "fine stringa raggiunta cercando un \"]\" corrispondente nell'indirizzo host IPv6 nella URI: \"%s\"\n" + +#: fe-connect.c:5556 +#, c-format +msgid "IPv6 host address may not be empty in URI: \"%s\"\n" +msgstr "l'indirizzo host IPv6 non dev'essere assente nella URI: \"%s\"\n" + +#: fe-connect.c:5571 +#, c-format +msgid "unexpected character \"%c\" at position %d in URI (expected \":\" or \"/\"): \"%s\"\n" +msgstr "carattere inatteso \"%c\" in posizione %d nella uri URI (atteso \":\" oppure \"/\"): \"%s\"\n" + +#: fe-connect.c:5700 +#, c-format +msgid "extra key/value separator \"=\" in URI query parameter: \"%s\"\n" +msgstr "separatore chiave/valore \"=\" in eccesso nei parametri della URI: \"%s\"\n" + +#: fe-connect.c:5720 +#, c-format +msgid "missing key/value separator \"=\" in URI query parameter: \"%s\"\n" +msgstr "separatore chiave/valore \"=\" mancante nei parametri della URI: \"%s\"\n" + +#: fe-connect.c:5771 +#, c-format +msgid "invalid URI query parameter: \"%s\"\n" +msgstr "parametro URI non valido: \"%s\"\n" + +#: fe-connect.c:5845 +#, c-format +msgid "invalid percent-encoded token: \"%s\"\n" +msgstr "simbolo percent-encoded non valido \"%s\"\n" + +#: fe-connect.c:5855 +#, c-format +msgid "forbidden value %%00 in percent-encoded value: \"%s\"\n" +msgstr "valore non ammesso %%00 nel valore percent-encoded: \"%s\"\n" + +#: fe-connect.c:6201 +msgid "connection pointer is NULL\n" +msgstr "il puntatore della connessione è NULL\n" + +#: fe-connect.c:6499 +#, c-format +msgid "WARNING: password file \"%s\" is not a plain file\n" +msgstr "ATTENZIONE: il file delle password \"%s\" non è un file regolare\n" + +#: fe-connect.c:6508 +#, c-format +msgid "WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n" +msgstr "" +"ATTENZIONE: Il file delle password %s ha privilegi di accesso in lettura e scrittura per tutti;\n" +"i permessi dovrebbero essere u=rw (0600) o inferiori\n" + +#: fe-connect.c:6602 +#, c-format +msgid "password retrieved from file \"%s\"\n" +msgstr "password ottenuta dal file \"%s\"\n" + +#: fe-exec.c:437 fe-exec.c:2776 +#, c-format +msgid "row number %d is out of range 0..%d" +msgstr "la riga numero %d non è compreso tra 0 e %d" + +#: fe-exec.c:498 fe-protocol2.c:502 fe-protocol2.c:537 fe-protocol2.c:1056 +#: fe-protocol3.c:208 fe-protocol3.c:235 fe-protocol3.c:252 fe-protocol3.c:332 +#: fe-protocol3.c:727 fe-protocol3.c:958 +msgid "out of memory" +msgstr "memoria esaurita" + +#: fe-exec.c:499 fe-protocol2.c:1402 fe-protocol3.c:1893 +#, c-format +msgid "%s" +msgstr "%s" + +#: fe-exec.c:847 +msgid "NOTICE" +msgstr "NOTIFICA" + +#: fe-exec.c:905 +msgid "PGresult cannot support more than INT_MAX tuples" +msgstr "PGresult non può supportare più di INT_MAX tuple" + +#: fe-exec.c:917 +msgid "size_t overflow" +msgstr "overflow size_t" + +#: fe-exec.c:1192 fe-exec.c:1250 fe-exec.c:1296 +msgid "command string is a null pointer\n" +msgstr "il testo del comando è un puntatore nullo\n" + +#: fe-exec.c:1256 fe-exec.c:1302 fe-exec.c:1397 +msgid "number of parameters must be between 0 and 65535\n" +msgstr "il numero di parametri deve essere tra 0 e 65535\n" + +#: fe-exec.c:1290 fe-exec.c:1391 +msgid "statement name is a null pointer\n" +msgstr "il nome dell'istruzione è un puntatore nullo\n" + +#: fe-exec.c:1310 fe-exec.c:1473 fe-exec.c:2191 fe-exec.c:2390 +msgid "function requires at least protocol version 3.0\n" +msgstr "la funzione richiede almeno il protocollo versione 3.0\n" + +#: fe-exec.c:1428 +msgid "no connection to the server\n" +msgstr "nessuna connessione al server\n" + +#: fe-exec.c:1435 +msgid "another command is already in progress\n" +msgstr "un altro comando è in esecuzione\n" + +#: fe-exec.c:1549 +msgid "length must be given for binary parameter\n" +msgstr "la lunghezza deve essere fornita per i parametri binari\n" + +#: fe-exec.c:1821 +#, c-format +msgid "unexpected asyncStatus: %d\n" +msgstr "asyncStatus imprevisto: %d\n" + +#: fe-exec.c:1841 +#, c-format +msgid "PGEventProc \"%s\" failed during PGEVT_RESULTCREATE event\n" +msgstr "PGEventProc \"%s\" fallito durante l'evento PGEVT_RESULTCREATE\n" + +#: fe-exec.c:2001 +msgid "COPY terminated by new PQexec" +msgstr "COPY terminato da una nuova PQexec" + +#: fe-exec.c:2009 +msgid "COPY IN state must be terminated first\n" +msgstr "lo stato COPY IN deve prima essere terminato\n" + +#: fe-exec.c:2029 +msgid "COPY OUT state must be terminated first\n" +msgstr "lo stato COPY OUT deve prima essere terminato\n" + +# NON SONO ASSOLUTAMENTE CONVINTO! +#: fe-exec.c:2037 +msgid "PQexec not allowed during COPY BOTH\n" +msgstr "PQexec not consentito durante COPY BOTH\n" + +#: fe-exec.c:2280 fe-exec.c:2347 fe-exec.c:2437 fe-protocol2.c:1359 +#: fe-protocol3.c:1824 +msgid "no COPY in progress\n" +msgstr "nessun comando COPY in corso\n" + +#: fe-exec.c:2627 +msgid "connection in wrong state\n" +msgstr "la connessione è in uno stato errato\n" + +#: fe-exec.c:2658 +msgid "invalid ExecStatusType code" +msgstr "codice ExecStatusType errato" + +#: fe-exec.c:2685 +msgid "PGresult is not an error result\n" +msgstr "PGresult non è un risultato di errore\n" + +#: fe-exec.c:2760 fe-exec.c:2783 +#, c-format +msgid "column number %d is out of range 0..%d" +msgstr "la colonna numero %d non è compreso tra 0 e %d" + +#: fe-exec.c:2798 +#, c-format +msgid "parameter number %d is out of range 0..%d" +msgstr "il parametro numero %d non è compreso tra 0 e %d" + +#: fe-exec.c:3108 +#, c-format +msgid "could not interpret result from server: %s" +msgstr "errore nell'interpretazione del risultato dal server: %s" + +#: fe-exec.c:3347 fe-exec.c:3431 +msgid "incomplete multibyte character\n" +msgstr "carattere multibyte incompleto\n" + +#: fe-lobj.c:154 +msgid "cannot determine OID of function lo_truncate\n" +msgstr "non è possibile determinare l'OID della funzione lo_truncate\n" + +#: fe-lobj.c:170 +msgid "argument of lo_truncate exceeds integer range\n" +msgstr "l'argomento di lo_truncate supera l'intervallo degli interi\n" + +#: fe-lobj.c:221 +msgid "cannot determine OID of function lo_truncate64\n" +msgstr "non è possibile determinare l'OID della funzione lo_truncate64\n" + +#: fe-lobj.c:279 +msgid "argument of lo_read exceeds integer range\n" +msgstr "l'argomento di lo_read supera l'intervallo degli interi\n" + +#: fe-lobj.c:334 +msgid "argument of lo_write exceeds integer range\n" +msgstr "l'argomento di lo_write supera l'intervallo degli interi\n" + +#: fe-lobj.c:425 +msgid "cannot determine OID of function lo_lseek64\n" +msgstr "non è possibile determinare l'OID della funzione lo_seek64\n" + +#: fe-lobj.c:521 +msgid "cannot determine OID of function lo_create\n" +msgstr "non è possibile determinare l'OID della funzione lo_create\n" + +#: fe-lobj.c:600 +msgid "cannot determine OID of function lo_tell64\n" +msgstr "non è possibile determinare l'OID della funzione lo_tell64\n" + +#: fe-lobj.c:706 fe-lobj.c:815 +#, c-format +msgid "could not open file \"%s\": %s\n" +msgstr "apertura del file \"%s\" fallita: %s\n" + +#: fe-lobj.c:761 +#, c-format +msgid "could not read from file \"%s\": %s\n" +msgstr "lettura dal file \"%s\" fallita: %s\n" + +#: fe-lobj.c:835 fe-lobj.c:859 +#, c-format +msgid "could not write to file \"%s\": %s\n" +msgstr "scrittura nel file \"%s\" fallita: %s\n" + +#: fe-lobj.c:946 +msgid "query to initialize large object functions did not return data\n" +msgstr "la query per inizializzare le funzioni large object non hanno restituito dati\n" + +#: fe-lobj.c:995 +msgid "cannot determine OID of function lo_open\n" +msgstr "non è possibile determinare l'OID della funzione lo_open\n" + +#: fe-lobj.c:1002 +msgid "cannot determine OID of function lo_close\n" +msgstr "non è possibile determinare l'OID della funzione lo_close\n" + +#: fe-lobj.c:1009 +msgid "cannot determine OID of function lo_creat\n" +msgstr "non è possibile determinare l'OID della funzione lo_create\n" + +#: fe-lobj.c:1016 +msgid "cannot determine OID of function lo_unlink\n" +msgstr "non è possibile determinare l'OID della funzione lo_unlink\n" + +#: fe-lobj.c:1023 +msgid "cannot determine OID of function lo_lseek\n" +msgstr "non è possibile determinare l'OID della funzione lo_seek\n" + +#: fe-lobj.c:1030 +msgid "cannot determine OID of function lo_tell\n" +msgstr "non è possibile determinare l'OID della funzione lo_tell\n" + +#: fe-lobj.c:1037 +msgid "cannot determine OID of function loread\n" +msgstr "non è possibile determinare l'OID della funzione loread\n" + +#: fe-lobj.c:1044 +msgid "cannot determine OID of function lowrite\n" +msgstr "non è possibile determinare l'OID della funzione lowrite\n" + +#: fe-misc.c:290 +#, c-format +msgid "integer of size %lu not supported by pqGetInt" +msgstr "intero di dimensione %lu non supportato da pqGetInt" + +#: fe-misc.c:326 +#, c-format +msgid "integer of size %lu not supported by pqPutInt" +msgstr "intero di dimensione %lu non supportato da pqPutInt" + +#: fe-misc.c:637 fe-misc.c:838 +msgid "connection not open\n" +msgstr "connessione non aperta\n" + +#: fe-misc.c:807 fe-secure-openssl.c:206 fe-secure-openssl.c:314 +#: fe-secure.c:261 fe-secure.c:371 +msgid "" +"server closed the connection unexpectedly\n" +"\tThis probably means the server terminated abnormally\n" +"\tbefore or while processing the request.\n" +msgstr "" +"il server ha chiuso la connessione inaspettatamente\n" +"\tQuesto probabilmente indica che il server ha terminato in modo anormale\n" +"\tprima o durante l'elaborazione della richiesta.\n" + +#: fe-misc.c:1009 +msgid "timeout expired\n" +msgstr "timeout scaduto\n" + +#: fe-misc.c:1054 +msgid "invalid socket\n" +msgstr "socket non valido\n" + +#: fe-misc.c:1077 +#, c-format +msgid "select() failed: %s\n" +msgstr "select() fallita: %s\n" + +#: fe-protocol2.c:90 +#, c-format +msgid "invalid setenv state %c, probably indicative of memory corruption\n" +msgstr "stato %c di setenv non valido, probabilmente indica una corruzione di memoria\n" + +#: fe-protocol2.c:389 +#, c-format +msgid "invalid state %c, probably indicative of memory corruption\n" +msgstr "stato %c non valido, probabilmente indica una corruzione di memoria\n" + +#: fe-protocol2.c:478 fe-protocol3.c:185 +#, c-format +msgid "message type 0x%02x arrived from server while idle" +msgstr "messaggio tipo 0x%02x arrivato dal server mentre era inattivo" + +#: fe-protocol2.c:528 +#, c-format +msgid "unexpected character %c following empty query response (\"I\" message)" +msgstr "carattere %c non previsto a seguito di una risposta vuota ad una query (messaggio \"I\")" + +#: fe-protocol2.c:594 +#, c-format +msgid "server sent data (\"D\" message) without prior row description (\"T\" message)" +msgstr "il server ha spedito dati (messaggio di tipo \"D\") senza prima il descrittore di riga (messaggio di tipo \"T\")" + +#: fe-protocol2.c:612 +#, c-format +msgid "server sent binary data (\"B\" message) without prior row description (\"T\" message)" +msgstr "il server ha spedito dati binari (messaggio di tipo \"B\") senza prima il descrittore di riga (messaggio di tipo \"T\")" + +#: fe-protocol2.c:632 fe-protocol3.c:411 +#, c-format +msgid "unexpected response from server; first received character was \"%c\"\n" +msgstr "risposta inattesa dal server; il primo carattere ricevuto era \"%c\"\n" + +#: fe-protocol2.c:761 fe-protocol2.c:936 fe-protocol3.c:626 fe-protocol3.c:853 +msgid "out of memory for query result" +msgstr "memoria esaurita per il risultato della query" + +#: fe-protocol2.c:1414 +#, c-format +msgid "lost synchronization with server, resetting connection" +msgstr "persa la sincronizzazione con il server, sto resettando la connessione" + +#: fe-protocol2.c:1548 fe-protocol2.c:1580 fe-protocol3.c:2096 +#, c-format +msgid "protocol error: id=0x%x\n" +msgstr "errore di protocollo: id=0x%x\n" + +#: fe-protocol3.c:367 +msgid "server sent data (\"D\" message) without prior row description (\"T\" message)\n" +msgstr "il server ha spedito dati (messaggio di tipo \"D\") senza prima il descrittore di riga (messaggio di tipo \"T\")\n" + +#: fe-protocol3.c:432 +#, c-format +msgid "message contents do not agree with length in message type \"%c\"\n" +msgstr "i contenuti del messaggio non sono in accordo con la lunghezza del tipo di messaggio \"%c\"\n" + +#: fe-protocol3.c:453 +#, c-format +msgid "lost synchronization with server: got message type \"%c\", length %d\n" +msgstr "persa la sincronizzazione con il server: ricevuto il tipo di messaggio \"%c\" di lunghezza %d\n" + +#: fe-protocol3.c:504 fe-protocol3.c:544 +msgid "insufficient data in \"T\" message" +msgstr "dati insufficienti nel messaggio di tipo \"T\"" + +#: fe-protocol3.c:577 +msgid "extraneous data in \"T\" message" +msgstr "dati estranei nel messaggio di tipo \"T\"" + +#: fe-protocol3.c:690 +msgid "extraneous data in \"t\" message" +msgstr "dati estranei nel messaggio di tipo \"t\"" + +#: fe-protocol3.c:761 fe-protocol3.c:793 fe-protocol3.c:811 +msgid "insufficient data in \"D\" message" +msgstr "dati insufficienti nel messaggio di tipo \"D\"" + +#: fe-protocol3.c:767 +msgid "unexpected field count in \"D\" message" +msgstr "numero dei campi non previsto nel messaggio di tipo \"D\"" + +#: fe-protocol3.c:820 +msgid "extraneous data in \"D\" message" +msgstr "dati estranei nel messaggio di tipo \"D\"" + +#: fe-protocol3.c:1012 +msgid "no error message available\n" +msgstr "nessun messaggio di errore disponibile\n" + +#. translator: %s represents a digit string +#: fe-protocol3.c:1042 fe-protocol3.c:1061 +#, c-format +msgid " at character %s" +msgstr " al carattere %s" + +#: fe-protocol3.c:1074 +#, c-format +msgid "DETAIL: %s\n" +msgstr "DETTAGLI: %s\n" + +#: fe-protocol3.c:1077 +#, c-format +msgid "HINT: %s\n" +msgstr "NOTA: %s\n" + +#: fe-protocol3.c:1080 +#, c-format +msgid "QUERY: %s\n" +msgstr "QUERY: %s\n" + +#: fe-protocol3.c:1087 +#, c-format +msgid "CONTEXT: %s\n" +msgstr "CONTESTO: %s\n" + +#: fe-protocol3.c:1096 +#, c-format +msgid "SCHEMA NAME: %s\n" +msgstr "NOME SCHEMA: %s\n" + +#: fe-protocol3.c:1100 +#, c-format +msgid "TABLE NAME: %s\n" +msgstr "NOME TABELLA: %s\n" + +#: fe-protocol3.c:1104 +#, c-format +msgid "COLUMN NAME: %s\n" +msgstr "NOME COLONNA: %s\n" + +#: fe-protocol3.c:1108 +#, c-format +msgid "DATATYPE NAME: %s\n" +msgstr "NOME TIPO DATI: %s\n" + +#: fe-protocol3.c:1112 +#, c-format +msgid "CONSTRAINT NAME: %s\n" +msgstr "NOME VINCOLO: %s\n" + +#: fe-protocol3.c:1124 +msgid "LOCATION: " +msgstr "POSIZIONE: " + +#: fe-protocol3.c:1126 +#, c-format +msgid "%s, " +msgstr "%s, " + +#: fe-protocol3.c:1128 +#, c-format +msgid "%s:%s" +msgstr "%s:%s" + +#: fe-protocol3.c:1323 +#, c-format +msgid "LINE %d: " +msgstr "RIGA %d: " + +#: fe-protocol3.c:1718 +msgid "PQgetline: not doing text COPY OUT\n" +msgstr "PQgetline: COPY OUT testuale ignorato\n" + +#: fe-secure-common.c:124 +msgid "SSL certificate's name contains embedded null\n" +msgstr "Il nome del certificato SSL contiene null\n" + +#: fe-secure-common.c:171 +msgid "host name must be specified for a verified SSL connection\n" +msgstr "il nome dell'host dev'essere specificato per una connessione SSL verificata\n" + +#: fe-secure-common.c:196 +#, c-format +msgid "server certificate for \"%s\" does not match host name \"%s\"\n" +msgstr "il certificato per il server \"%s\" non combacia col nome host \"%s\"\n" + +#: fe-secure-common.c:202 +msgid "could not get server's host name from server certificate\n" +msgstr "impossibile ottenere il nome dell'host del server dal certificato del server\n" + +#: fe-secure-openssl.c:211 fe-secure-openssl.c:319 fe-secure-openssl.c:1219 +#, c-format +msgid "SSL SYSCALL error: %s\n" +msgstr "errore SSL SYSCALL: %s\n" + +#: fe-secure-openssl.c:218 fe-secure-openssl.c:326 fe-secure-openssl.c:1223 +msgid "SSL SYSCALL error: EOF detected\n" +msgstr "errore SSL SYSCALL: rilevato EOF\n" + +#: fe-secure-openssl.c:229 fe-secure-openssl.c:337 fe-secure-openssl.c:1232 +#, c-format +msgid "SSL error: %s\n" +msgstr "errore SSL: %s\n" + +#: fe-secure-openssl.c:244 fe-secure-openssl.c:352 +msgid "SSL connection has been closed unexpectedly\n" +msgstr "la connessione SSL è stata chiusa inaspettatamente\n" + +#: fe-secure-openssl.c:250 fe-secure-openssl.c:358 fe-secure-openssl.c:1241 +#, c-format +msgid "unrecognized SSL error code: %d\n" +msgstr "codice di errore SSL sconosciuto: %d\n" + +#: fe-secure-openssl.c:398 +msgid "could not determine server certificate signature algorithm\n" +msgstr "impossibile determinare l'algoritmo di firma del certificato del server\n" + +#: fe-secure-openssl.c:419 +#, c-format +msgid "could not find digest for NID %s\n" +msgstr "impossibile trovare il digest per il NID %s\n" + +#: fe-secure-openssl.c:429 +msgid "could not generate peer certificate hash\n" +msgstr "impossibile generare l'hash del certificato del peer\n" + +#: fe-secure-openssl.c:486 +msgid "SSL certificate's name entry is missing\n" +msgstr "manca il nome del certificato SSL\n" + +#: fe-secure-openssl.c:815 +#, c-format +msgid "could not create SSL context: %s\n" +msgstr "creazione del contesto SSL fallita: %s\n" + +#: fe-secure-openssl.c:852 +#, c-format +msgid "could not read root certificate file \"%s\": %s\n" +msgstr "lettura del file di certificato radice \"%s\" fallita: %s\n" + +#: fe-secure-openssl.c:880 +#, c-format +msgid "SSL library does not support CRL certificates (file \"%s\")\n" +msgstr "la libreria SSL non supporta i certificati di tipo CRL (file \"%s\")\n" + +#: fe-secure-openssl.c:908 +msgid "" +"could not get home directory to locate root certificate file\n" +"Either provide the file or change sslmode to disable server certificate verification.\n" +msgstr "" +"directory utente non trovata per la locazione del file di certificato radice\n" +"Per favore fornisci il file oppure cambia sslmode per disabilitare la verifica del certificato del server.\n" + +#: fe-secure-openssl.c:912 +#, c-format +msgid "" +"root certificate file \"%s\" does not exist\n" +"Either provide the file or change sslmode to disable server certificate verification.\n" +msgstr "" +"il file \"%s\" del certificato radice non esiste\n" +"Per favore fornisci il file oppure cambia sslmode per disabilitare la verifica del certificato del server.\n" + +#: fe-secure-openssl.c:943 +#, c-format +msgid "could not open certificate file \"%s\": %s\n" +msgstr "apertura del file di certificato \"%s\" fallita: %s\n" + +#: fe-secure-openssl.c:962 +#, c-format +msgid "could not read certificate file \"%s\": %s\n" +msgstr "lettura del file di certificato \"%s\" fallita: %s\n" + +#: fe-secure-openssl.c:987 +#, c-format +msgid "could not establish SSL connection: %s\n" +msgstr "non è stato possibile stabilire una connessione SSL: %s\n" + +#: fe-secure-openssl.c:1041 +#, c-format +msgid "could not load SSL engine \"%s\": %s\n" +msgstr "caricamento del motore SSL \"%s\" fallito: %s\n" + +#: fe-secure-openssl.c:1053 +#, c-format +msgid "could not initialize SSL engine \"%s\": %s\n" +msgstr "inizializzazione del motore SSL \"%s\" fallita: %s\n" + +#: fe-secure-openssl.c:1069 +#, c-format +msgid "could not read private SSL key \"%s\" from engine \"%s\": %s\n" +msgstr "lettura del file della chiave privata SSL \"%s\" dal motore \"%s\" fallita: %s\n" + +#: fe-secure-openssl.c:1083 +#, c-format +msgid "could not load private SSL key \"%s\" from engine \"%s\": %s\n" +msgstr "caricamento della chiave privata SSL \"%s\" dal motore \"%s\" fallito: %s\n" + +#: fe-secure-openssl.c:1120 +#, c-format +msgid "certificate present, but not private key file \"%s\"\n" +msgstr "certificato trovato, ma non la chiave privata \"%s\"\n" + +#: fe-secure-openssl.c:1128 +#, c-format +msgid "private key file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n" +msgstr "Il file della chiave privata \"%s\" ha privilegi di accesso in lettura e scrittura per tutti; i permessi dovrebbero essere u=rw (0600) o inferiori\n" + +#: fe-secure-openssl.c:1139 +#, c-format +msgid "could not load private key file \"%s\": %s\n" +msgstr "caricamento del file della chiave privata \"%s\" fallito: %s\n" + +#: fe-secure-openssl.c:1153 +#, c-format +msgid "certificate does not match private key file \"%s\": %s\n" +msgstr "il certificato non corrisponde con il file della chiave privata \"%s\": %s\n" + +#: fe-secure-openssl.c:1262 +#, c-format +msgid "certificate could not be obtained: %s\n" +msgstr "non è stato possibile possibile ottenere il certificato: %s\n" + +#: fe-secure-openssl.c:1351 +#, c-format +msgid "no SSL error reported" +msgstr "nessun errore SSL riportato" + +#: fe-secure-openssl.c:1360 +#, c-format +msgid "SSL error code %lu" +msgstr "codice di errore SSL: %lu" + +#: fe-secure.c:269 +#, c-format +msgid "could not receive data from server: %s\n" +msgstr "ricezione dati dal server fallita: %s\n" + +#: fe-secure.c:378 +#, c-format +msgid "could not send data to server: %s\n" +msgstr "invio dati al server fallito: %s\n" + +#: win32.c:317 +#, c-format +msgid "unrecognized socket error: 0x%08X/%d" +msgstr "errore socket sconosciuto: 0x%08X/%d" diff --git a/src/interfaces/libpq/po/ja.po b/src/interfaces/libpq/po/ja.po new file mode 100644 index 0000000..af252b1 --- /dev/null +++ b/src/interfaces/libpq/po/ja.po @@ -0,0 +1,1472 @@ +# libpq.po +# Japanese message translation file for libpq +# +# Copyright (C) 2011-2022 PostgreSQL Global Development Group +# +# This file is distributed under the same license as the PostgreSQL package. +# +msgid "" +msgstr "" +"Project-Id-Version: libpq (PostgreSQL 16)\n" +"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" +"POT-Creation-Date: 2023-06-19 09:32+0900\n" +"PO-Revision-Date: 2023-08-23 07:41+0900\n" +"Last-Translator: Kyotaro Horiguchi <horikyota.ntt@gmail.com>\n" +"Language-Team: Japan PostgreSQL Users Group <jpug-doc@ml.postgresql.jp>\n" +"Language: ja\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Poedit 1.8.13\n" + +#: ../../port/thread.c:50 ../../port/thread.c:86 +#, c-format +msgid "could not look up local user ID %d: %s" +msgstr "ローカルユーザーID %dの参照に失敗しました: %s" + +#: ../../port/thread.c:55 ../../port/thread.c:91 +#, c-format +msgid "local user with ID %d does not exist" +msgstr "ID %d を持つローカルユーザーは存在しません" + +#: fe-auth-scram.c:227 +#, c-format +msgid "malformed SCRAM message (empty message)" +msgstr "SCRAMメッセージのフォーマット異常 (空のメッセージ)" + +#: fe-auth-scram.c:232 +#, c-format +msgid "malformed SCRAM message (length mismatch)" +msgstr "SCRAMメッセージのフォーマット異常 (長さの不整合)" + +#: fe-auth-scram.c:275 +#, c-format +msgid "could not verify server signature: %s" +msgstr "サーバー署名を検証できませんでした: %s" + +#: fe-auth-scram.c:281 +#, c-format +msgid "incorrect server signature" +msgstr "正しくないサーバー署名" + +#: fe-auth-scram.c:290 +#, c-format +msgid "invalid SCRAM exchange state" +msgstr "不正なSCRAM交換状態" + +#: fe-auth-scram.c:317 +#, c-format +msgid "malformed SCRAM message (attribute \"%c\" expected)" +msgstr "SCRAMメッセージのフォーマット異常 (属性 \"%c\" が必要)" + +#: fe-auth-scram.c:326 +#, c-format +msgid "malformed SCRAM message (expected character \"=\" for attribute \"%c\")" +msgstr "SCRAMメッセージのフォーマット異常 (属性 \"%c\" に文字 \"=\" が必要)" + +#: fe-auth-scram.c:366 +#, c-format +msgid "could not generate nonce" +msgstr "nonce を生成できませんでした" + +#: fe-auth-scram.c:375 fe-auth-scram.c:448 fe-auth-scram.c:600 +#: fe-auth-scram.c:620 fe-auth-scram.c:644 fe-auth-scram.c:658 +#: fe-auth-scram.c:704 fe-auth-scram.c:740 fe-auth-scram.c:914 fe-auth.c:295 +#: fe-auth.c:368 fe-auth.c:402 fe-auth.c:617 fe-auth.c:728 fe-auth.c:1209 +#: fe-auth.c:1374 fe-connect.c:925 fe-connect.c:1759 fe-connect.c:1921 +#: fe-connect.c:3291 fe-connect.c:4496 fe-connect.c:5161 fe-connect.c:5416 +#: fe-connect.c:5534 fe-connect.c:5781 fe-connect.c:5861 fe-connect.c:5959 +#: fe-connect.c:6210 fe-connect.c:6237 fe-connect.c:6313 fe-connect.c:6336 +#: fe-connect.c:6360 fe-connect.c:6395 fe-connect.c:6481 fe-connect.c:6489 +#: fe-connect.c:6846 fe-connect.c:6996 fe-exec.c:527 fe-exec.c:1321 +#: fe-exec.c:3111 fe-exec.c:4071 fe-exec.c:4235 fe-gssapi-common.c:109 +#: fe-lobj.c:870 fe-protocol3.c:204 fe-protocol3.c:228 fe-protocol3.c:256 +#: fe-protocol3.c:273 fe-protocol3.c:353 fe-protocol3.c:720 fe-protocol3.c:959 +#: fe-protocol3.c:1770 fe-protocol3.c:2170 fe-secure-common.c:110 +#: fe-secure-gssapi.c:500 fe-secure-openssl.c:434 fe-secure-openssl.c:1285 +#, c-format +msgid "out of memory" +msgstr "メモリ不足です" + +#: fe-auth-scram.c:382 +#, c-format +msgid "could not encode nonce" +msgstr "nonceをエンコードできませんでした" + +#: fe-auth-scram.c:570 +#, c-format +msgid "could not calculate client proof: %s" +msgstr "クライアント証明の算出に失敗しました: %s" + +#: fe-auth-scram.c:585 +#, c-format +msgid "could not encode client proof" +msgstr "クライアントの証明のエンコードに失敗しました" + +#: fe-auth-scram.c:637 +#, c-format +msgid "invalid SCRAM response (nonce mismatch)" +msgstr "不正なSCRAM応答 (nonce の不一致)" + +#: fe-auth-scram.c:667 +#, c-format +msgid "malformed SCRAM message (invalid salt)" +msgstr "SCRAMメッセージのフォーマット異常 (不正なソルト)" + +#: fe-auth-scram.c:680 +#, c-format +msgid "malformed SCRAM message (invalid iteration count)" +msgstr "SCRAMメッセージのフォーマット異常 (不正な繰り返し回数)" + +#: fe-auth-scram.c:685 +#, c-format +msgid "malformed SCRAM message (garbage at end of server-first-message)" +msgstr "SCRAMメッセージのフォーマット異常 (server-first-message 終端の余分なデータ)" + +#: fe-auth-scram.c:719 +#, c-format +msgid "error received from server in SCRAM exchange: %s" +msgstr "SCRAM交換中にサーバーからのエラーを受信しました: %s" + +#: fe-auth-scram.c:734 +#, c-format +msgid "malformed SCRAM message (garbage at end of server-final-message)" +msgstr "SCRAMメッセージのフォーマット異常 (server-final-message 終端の余分なデータ)" + +#: fe-auth-scram.c:751 +#, c-format +msgid "malformed SCRAM message (invalid server signature)" +msgstr "SCRAMメッセージのフォーマット異常 (不正なサーバー署名)" + +#: fe-auth-scram.c:923 +msgid "could not generate random salt" +msgstr "乱数ソルトを生成できませんでした" + +#: fe-auth.c:76 +#, c-format +msgid "out of memory allocating GSSAPI buffer (%d)" +msgstr "GSSAPIバッファの割り当ての際のメモリ不足(%d)" + +#: fe-auth.c:137 +msgid "GSSAPI continuation error" +msgstr "GSSAI続行エラー" + +#: fe-auth.c:167 fe-auth.c:396 fe-gssapi-common.c:97 fe-secure-common.c:99 +#: fe-secure-common.c:173 +#, c-format +msgid "host name must be specified" +msgstr "ホスト名を指定しなければなりません" + +#: fe-auth.c:173 +#, c-format +msgid "duplicate GSS authentication request" +msgstr "重複するGSS認証要求" + +#: fe-auth.c:237 +#, c-format +msgid "out of memory allocating SSPI buffer (%d)" +msgstr "SSPIバッファの割り当ての際のメモリ不足(%d)" + +#: fe-auth.c:284 +msgid "SSPI continuation error" +msgstr "SSPI続行エラー" + +#: fe-auth.c:358 +#, c-format +msgid "duplicate SSPI authentication request" +msgstr "重複したSSPI認証要求" + +#: fe-auth.c:383 +msgid "could not acquire SSPI credentials" +msgstr "SSPI資格を入手できませんでした" + +#: fe-auth.c:436 +#, c-format +msgid "channel binding required, but SSL not in use" +msgstr "チャネルバインディングが要求されていますが、SSLが使用されていません" + +#: fe-auth.c:442 +#, c-format +msgid "duplicate SASL authentication request" +msgstr "重複するSASL認証要求" + +#: fe-auth.c:500 +#, c-format +msgid "channel binding is required, but client does not support it" +msgstr "チャネルバインディングが要求されていますが、クライアントがサポートしていません" + +#: fe-auth.c:516 +#, c-format +msgid "server offered SCRAM-SHA-256-PLUS authentication over a non-SSL connection" +msgstr "サーバーが非SSL接続上で SCRAM-SHA-256-PLUS 認証を提示してきました" + +#: fe-auth.c:530 +#, c-format +msgid "none of the server's SASL authentication mechanisms are supported" +msgstr "サーバー側のいずれのSASL認証機構もサポートされていません" + +#: fe-auth.c:537 +#, c-format +msgid "channel binding is required, but server did not offer an authentication method that supports channel binding" +msgstr "チャネルバインディングが要求されていますが、サーバーがチャネルバインディングをサポートする認証方式を提供しませんでした" + +#: fe-auth.c:640 +#, c-format +msgid "out of memory allocating SASL buffer (%d)" +msgstr "SASLバッファの割り当ての際のメモリ不足(%d)" + +#: fe-auth.c:664 +#, c-format +msgid "AuthenticationSASLFinal received from server, but SASL authentication was not completed" +msgstr "サーバーからAuthenticationSASLFinalを受信しました、しかしSASL認証は完了していません" + +#: fe-auth.c:674 +#, c-format +msgid "no client response found after SASL exchange success" +msgstr "SASL交換の成功後にクライアントからの応答がありません" + +#: fe-auth.c:737 fe-auth.c:744 fe-auth.c:1357 fe-auth.c:1368 +#, c-format +msgid "could not encrypt password: %s" +msgstr "パスワードを暗号化できませんでした: %s" + +#: fe-auth.c:772 +msgid "server requested a cleartext password" +msgstr "サーバーが平文パスワードを要求してきました" + +#: fe-auth.c:774 +msgid "server requested a hashed password" +msgstr "サーバーがハッシュ化パスワードを要求してきました" + +#: fe-auth.c:777 +msgid "server requested GSSAPI authentication" +msgstr "サーバーがGSSAPI認証を要求してきました" + +#: fe-auth.c:779 +msgid "server requested SSPI authentication" +msgstr "サーバーがSSPI認証を要求してきました" + +#: fe-auth.c:783 +msgid "server requested SASL authentication" +msgstr "サーバーがSASL認証を要求してきました" + +#: fe-auth.c:786 +msgid "server requested an unknown authentication type" +msgstr "サーバーが不明な認証タイプを要求してきました" + +#: fe-auth.c:819 +#, c-format +msgid "server did not request an SSL certificate" +msgstr "サーバーがSSL証明書を要求してきませんでした" + +#: fe-auth.c:824 +#, c-format +msgid "server accepted connection without a valid SSL certificate" +msgstr "サーバーは有効なSSL証明書なしで接続を受け付けました" + +#: fe-auth.c:878 +msgid "server did not complete authentication" +msgstr "サーバーが認証を完了しませんでした" + +#: fe-auth.c:912 +#, c-format +msgid "authentication method requirement \"%s\" failed: %s" +msgstr "必須の認証方式\"%s\"が失敗しました: %s" + +#: fe-auth.c:935 +#, c-format +msgid "channel binding required, but server authenticated client without channel binding" +msgstr "チャネルバインディングが要求されていますが、サーバーはチャネルバインディングを使用せずに認証を行いました" + +#: fe-auth.c:940 +#, c-format +msgid "channel binding required but not supported by server's authentication request" +msgstr "チャネルバインディングが要求されていますが、サーバーの認証要求ではサポートされていません" + +#: fe-auth.c:974 +#, c-format +msgid "Kerberos 4 authentication not supported" +msgstr "Kerberos 4認証はサポートされていません" + +#: fe-auth.c:978 +#, c-format +msgid "Kerberos 5 authentication not supported" +msgstr "Kerberos 5認証はサポートされていません" + +#: fe-auth.c:1048 +#, c-format +msgid "GSSAPI authentication not supported" +msgstr "GSSAPI認証はサポートされていません" + +#: fe-auth.c:1079 +#, c-format +msgid "SSPI authentication not supported" +msgstr "SSPI認証はサポートされていません" + +#: fe-auth.c:1086 +#, c-format +msgid "Crypt authentication not supported" +msgstr "Crypt認証はサポートされていません" + +#: fe-auth.c:1150 +#, c-format +msgid "authentication method %u not supported" +msgstr "認証方式%uはサポートされていません" + +#: fe-auth.c:1196 +#, c-format +msgid "user name lookup failure: error code %lu" +msgstr "ユーザー名の参照に失敗: エラーコード %lu" + +#: fe-auth.c:1320 +#, c-format +msgid "unexpected shape of result set returned for SHOW" +msgstr "SHOW に対する予期しない形のリザルトセット" + +#: fe-auth.c:1328 +#, c-format +msgid "password_encryption value too long" +msgstr "password_encryptionの値が長すぎます" + +#: fe-auth.c:1378 +#, c-format +msgid "unrecognized password encryption algorithm \"%s\"" +msgstr "認識できないパスワード暗号化アルゴリズム \"%s\"" + +#: fe-connect.c:1132 +#, c-format +msgid "could not match %d host names to %d hostaddr values" +msgstr "%d個のホスト名と%d個のhostaddrの値との突き合せはできません" + +#: fe-connect.c:1212 +#, c-format +msgid "could not match %d port numbers to %d hosts" +msgstr "%d個のポート番号と%d個のホストとの突き合せはできません" + +#: fe-connect.c:1337 +#, c-format +msgid "negative require_auth method \"%s\" cannot be mixed with non-negative methods" +msgstr "require_authの方式否定\"%s\"は方式要求と同時に指定することはできません" + +#: fe-connect.c:1350 +#, c-format +msgid "require_auth method \"%s\" cannot be mixed with negative methods" +msgstr "require_authの方式要求\"%s\"は方式否定と同時に指定することはできません" + +#: fe-connect.c:1410 fe-connect.c:1461 fe-connect.c:1503 fe-connect.c:1559 +#: fe-connect.c:1567 fe-connect.c:1598 fe-connect.c:1644 fe-connect.c:1684 +#: fe-connect.c:1705 +#, c-format +msgid "invalid %s value: \"%s\"" +msgstr "%s の値が不正: \"%s\"" + +#: fe-connect.c:1443 +#, c-format +msgid "require_auth method \"%s\" is specified more than once" +msgstr "require_authで方式\"%s\"が複数回指定されました" + +#: fe-connect.c:1484 fe-connect.c:1523 fe-connect.c:1606 +#, c-format +msgid "%s value \"%s\" invalid when SSL support is not compiled in" +msgstr "%s 値\"%s\"はSSLサポートがコンパイルされていない場合は無効です" + +#: fe-connect.c:1546 +#, c-format +msgid "weak sslmode \"%s\" may not be used with sslrootcert=system (use \"verify-full\")" +msgstr "弱いsslmode\"%s\"はsslrootcert=systemとともには使用できません(\"verify-full\"を使用してください)" + +#: fe-connect.c:1584 +#, c-format +msgid "invalid SSL protocol version range" +msgstr "不正なSSLプロトコルバージョン範囲" + +#: fe-connect.c:1621 +#, c-format +msgid "%s value \"%s\" is not supported (check OpenSSL version)" +msgstr "%s 値\"%s\"はサポートされていません(OpenSSLのバージョンを確認してください)" + +#: fe-connect.c:1651 +#, c-format +msgid "gssencmode value \"%s\" invalid when GSSAPI support is not compiled in" +msgstr "gssencmodeの値\"%s\"はGSSAPIサポートがコンパイルされていない場合は不正" + +#: fe-connect.c:1944 +#, c-format +msgid "could not set socket to TCP no delay mode: %s" +msgstr "TCPソケットを非遅延モードに設定できませんでした: %s" + +#: fe-connect.c:2003 +#, c-format +msgid "connection to server on socket \"%s\" failed: " +msgstr "ソケット\"%s\"のサーバーへの接続に失敗しました: " + +#: fe-connect.c:2029 +#, c-format +msgid "connection to server at \"%s\" (%s), port %s failed: " +msgstr "\"%s\"(%s)、ポート%sのサーバーへの接続に失敗しました: " + +#: fe-connect.c:2034 +#, c-format +msgid "connection to server at \"%s\", port %s failed: " +msgstr "\"%s\"、ポート%sのサーバーへの接続に失敗しました: " + +#: fe-connect.c:2057 +#, c-format +msgid "\tIs the server running locally and accepting connections on that socket?" +msgstr "\tサーバーはローカルで稼働していてそのソケットで接続を受け付けていますか?" + +#: fe-connect.c:2059 +#, c-format +msgid "\tIs the server running on that host and accepting TCP/IP connections?" +msgstr "\tサーバーはそのホスト上で稼働していてTCP/IP接続を受け付けていますか?" + +#: fe-connect.c:2122 +#, c-format +msgid "invalid integer value \"%s\" for connection option \"%s\"" +msgstr "接続オプション\"%2$s\"に対する不正な整数値\"%1$s\"" + +#: fe-connect.c:2151 fe-connect.c:2185 fe-connect.c:2220 fe-connect.c:2318 +#: fe-connect.c:2973 +#, c-format +msgid "%s(%s) failed: %s" +msgstr "%s(%s)が失敗しました: %s" + +#: fe-connect.c:2284 +#, c-format +msgid "%s(%s) failed: error code %d" +msgstr "%s(%s)が失敗しました: エラーコード %d" + +#: fe-connect.c:2597 +#, c-format +msgid "invalid connection state, probably indicative of memory corruption" +msgstr "接続状態が不正です。メモリ障害の可能性があります" + +#: fe-connect.c:2676 +#, c-format +msgid "invalid port number: \"%s\"" +msgstr "不正なポート番号です: \"%s\"" + +#: fe-connect.c:2690 +#, c-format +msgid "could not translate host name \"%s\" to address: %s" +msgstr "ホスト名\"%s\"をアドレスに変換できませんでした: %s" + +#: fe-connect.c:2702 +#, c-format +msgid "could not parse network address \"%s\": %s" +msgstr "ネットワークアドレス\"%s\"をパースできませんでした: %s" + +#: fe-connect.c:2713 +#, c-format +msgid "Unix-domain socket path \"%s\" is too long (maximum %d bytes)" +msgstr "Unixドメインソケットのパス\"%s\"が長すぎます(最大 %d バイト)" + +#: fe-connect.c:2727 +#, c-format +msgid "could not translate Unix-domain socket path \"%s\" to address: %s" +msgstr "Unixドメインソケットのパス\"%s\"をアドレスに変換できませんでした: %s" + +#: fe-connect.c:2901 +#, c-format +msgid "could not create socket: %s" +msgstr "ソケットを作成できませんでした: %s" + +#: fe-connect.c:2932 +#, c-format +msgid "could not set socket to nonblocking mode: %s" +msgstr "ソケットを非ブロッキングモードに設定できませんでした: %s\\" + +#: fe-connect.c:2943 +#, c-format +msgid "could not set socket to close-on-exec mode: %s" +msgstr "ソケットをclose-on-execモードに設定できませんでした: %s" + +#: fe-connect.c:2961 +#, c-format +msgid "keepalives parameter must be an integer" +msgstr "keepaliveのパラメータは整数でなければなりません" + +#: fe-connect.c:3100 +#, c-format +msgid "could not get socket error status: %s" +msgstr "ソケットのエラー状態を取得できませんでした: %s" + +#: fe-connect.c:3127 +#, c-format +msgid "could not get client address from socket: %s" +msgstr "ソケットからクライアントアドレスを取得できませんでした: %s" + +#: fe-connect.c:3165 +#, c-format +msgid "requirepeer parameter is not supported on this platform" +msgstr "このプラットフォームでは requirepeer パラメータはサポートされていません" + +#: fe-connect.c:3167 +#, c-format +msgid "could not get peer credentials: %s" +msgstr "接続先の資格証明を取得できませんでした: %s" + +#: fe-connect.c:3180 +#, c-format +msgid "requirepeer specifies \"%s\", but actual peer user name is \"%s\"" +msgstr "requirepeerは\"%s\"を指定していますが、実際の接続先名は\"%s\"です" + +#: fe-connect.c:3221 +#, c-format +msgid "could not send GSSAPI negotiation packet: %s" +msgstr "GSSAPIネゴシエーションパケットを送信できませんでした: %s" + +#: fe-connect.c:3233 +#, c-format +msgid "GSSAPI encryption required but was impossible (possibly no credential cache, no server support, or using a local socket)" +msgstr "GSSAPI暗号化が要求されていますが、実行できませんでした(おそらく資格キャッシュがない、サーバーがサポートしていないあるいはローカルソケットで接続しています)" + +#: fe-connect.c:3274 +#, c-format +msgid "could not send SSL negotiation packet: %s" +msgstr "SSLネゴシエーションパケットを送信できませんでした: %s" + +#: fe-connect.c:3303 +#, c-format +msgid "could not send startup packet: %s" +msgstr "開始パケットを送信できませんでした: %s" + +#: fe-connect.c:3378 +#, c-format +msgid "server does not support SSL, but SSL was required" +msgstr "サーバーはSSLをサポートしていませんが、SSLが要求されました" + +#: fe-connect.c:3404 +#, c-format +msgid "received invalid response to SSL negotiation: %c" +msgstr "SSLネゴシエーションに対して不正な応答を受信しました: %c" + +#: fe-connect.c:3424 +#, c-format +msgid "received unencrypted data after SSL response" +msgstr "SSL応答の後に非暗号化データを受信しました" + +#: fe-connect.c:3504 +#, c-format +msgid "server doesn't support GSSAPI encryption, but it was required" +msgstr "サーバーはGSSAPI暗号化をサポートしていませんが、要求されました" + +#: fe-connect.c:3515 +#, c-format +msgid "received invalid response to GSSAPI negotiation: %c" +msgstr "GSSAPIネゴシエーションに対して不正な応答を受信しました: %c" + +#: fe-connect.c:3533 +#, c-format +msgid "received unencrypted data after GSSAPI encryption response" +msgstr "GSSAPI暗号化応答の後に非暗号化データを受信しました" + +#: fe-connect.c:3598 +#, c-format +msgid "expected authentication request from server, but received %c" +msgstr "サーバーからの認証要求を想定していましたが、%cを受信しました" + +#: fe-connect.c:3625 fe-connect.c:3794 +#, c-format +msgid "received invalid authentication request" +msgstr "不正な認証要求を受信しました" + +#: fe-connect.c:3630 fe-connect.c:3779 +#, c-format +msgid "received invalid protocol negotiation message" +msgstr "不正なプロトコルネゴシエーションメッセージを受信しました" + +#: fe-connect.c:3648 fe-connect.c:3702 +#, c-format +msgid "received invalid error message" +msgstr "不正なエラーメッセージを受信しました" + +#: fe-connect.c:3865 +#, c-format +msgid "unexpected message from server during startup" +msgstr "起動中にサーバーから想定外のメッセージがありました" + +#: fe-connect.c:3956 +#, c-format +msgid "session is read-only" +msgstr "セッションは読み取り専用です" + +#: fe-connect.c:3958 +#, c-format +msgid "session is not read-only" +msgstr "セッションは読み取り専用ではありません" + +#: fe-connect.c:4011 +#, c-format +msgid "server is in hot standby mode" +msgstr "サーバーはホットスタンバイモードです" + +#: fe-connect.c:4013 +#, c-format +msgid "server is not in hot standby mode" +msgstr "サーバーはスタンバイモードではありません" + +#: fe-connect.c:4129 fe-connect.c:4179 +#, c-format +msgid "\"%s\" failed" +msgstr "\"%s\"が失敗しました" + +#: fe-connect.c:4193 +#, c-format +msgid "invalid connection state %d, probably indicative of memory corruption" +msgstr "接続状態%dは不正です。メモリ障害の可能性があります" + +#: fe-connect.c:5174 +#, c-format +msgid "invalid LDAP URL \"%s\": scheme must be ldap://" +msgstr "不正なLDAP URL\"%s\":スキームはldap://でなければなりません" + +#: fe-connect.c:5189 +#, c-format +msgid "invalid LDAP URL \"%s\": missing distinguished name" +msgstr "不正なLDAP URL \"%s\": 識別名がありません" + +#: fe-connect.c:5201 fe-connect.c:5259 +#, c-format +msgid "invalid LDAP URL \"%s\": must have exactly one attribute" +msgstr "不正なLDAP URL \"%s\": ちょうど1つの属性を持たなければなりません" + +#: fe-connect.c:5213 fe-connect.c:5275 +#, c-format +msgid "invalid LDAP URL \"%s\": must have search scope (base/one/sub)" +msgstr "不正なLDAP URL \"%s\": 検索スコープ(base/one/sub)を持たなければなりません" + +#: fe-connect.c:5225 +#, c-format +msgid "invalid LDAP URL \"%s\": no filter" +msgstr "不正なLDAP URL \"%s\": フィルタがありません" + +#: fe-connect.c:5247 +#, c-format +msgid "invalid LDAP URL \"%s\": invalid port number" +msgstr "不正なLDAP URL \"%s\": ポート番号が不正です" + +#: fe-connect.c:5284 +#, c-format +msgid "could not create LDAP structure" +msgstr "LDAP構造体を作成できませんでした" + +#: fe-connect.c:5359 +#, c-format +msgid "lookup on LDAP server failed: %s" +msgstr "LDAPサーバーで検索に失敗しました: %s" + +#: fe-connect.c:5369 +#, c-format +msgid "more than one entry found on LDAP lookup" +msgstr "LDAP参照で複数のエントリが見つかりました" + +#: fe-connect.c:5371 fe-connect.c:5382 +#, c-format +msgid "no entry found on LDAP lookup" +msgstr "LDAP参照でエントリが見つかりません" + +#: fe-connect.c:5392 fe-connect.c:5404 +#, c-format +msgid "attribute has no values on LDAP lookup" +msgstr "LDAP参照で属性に値がありません" + +#: fe-connect.c:5455 fe-connect.c:5474 fe-connect.c:5998 +#, c-format +msgid "missing \"=\" after \"%s\" in connection info string" +msgstr "接続情報文字列において\"%s\"の後に\"=\"がありませんでした" + +#: fe-connect.c:5545 fe-connect.c:6181 fe-connect.c:6979 +#, c-format +msgid "invalid connection option \"%s\"" +msgstr "不正な接続オプション\"%s\"" + +#: fe-connect.c:5560 fe-connect.c:6046 +#, c-format +msgid "unterminated quoted string in connection info string" +msgstr "接続情報文字列内の閉じていない引用符" + +#: fe-connect.c:5640 +#, c-format +msgid "definition of service \"%s\" not found" +msgstr "サービス定義\"%s\"がみつかりません" + +#: fe-connect.c:5666 +#, c-format +msgid "service file \"%s\" not found" +msgstr "サービスファイル\"%s\"がみつかりません" + +#: fe-connect.c:5679 +#, c-format +msgid "line %d too long in service file \"%s\"" +msgstr "サービスファイル\"%2$s\"の行%1$dが長すぎます" + +#: fe-connect.c:5750 fe-connect.c:5793 +#, c-format +msgid "syntax error in service file \"%s\", line %d" +msgstr "サービスファイル\"%s\"の行%dで構文エラー" + +#: fe-connect.c:5761 +#, c-format +msgid "nested service specifications not supported in service file \"%s\", line %d" +msgstr "サービスファイル\"%s\"、行%dでのネストしたサービス指定はサポートされていません" + +#: fe-connect.c:6500 +#, c-format +msgid "invalid URI propagated to internal parser routine: \"%s\"" +msgstr "内部パーサ処理へ伝播した不正なURI: \"%s\"" + +#: fe-connect.c:6577 +#, c-format +msgid "end of string reached when looking for matching \"]\" in IPv6 host address in URI: \"%s\"" +msgstr "URI \"%s\"内のIPv6ホストアドレスにおいて対応する\"]\"を探している間に文字列が終わりました" + +#: fe-connect.c:6584 +#, c-format +msgid "IPv6 host address may not be empty in URI: \"%s\"" +msgstr "URI内ではIPv6ホストアドレスは空であってはなりません: \"%s\"" + +#: fe-connect.c:6599 +#, c-format +msgid "unexpected character \"%c\" at position %d in URI (expected \":\" or \"/\"): \"%s\"" +msgstr "URI内の位置%2$dに想定外の文字\"%1$c\"があります(\":\"または\"/\"を期待していました): \"%3$s\"" + +#: fe-connect.c:6728 +#, c-format +msgid "extra key/value separator \"=\" in URI query parameter: \"%s\"" +msgstr "URI問い合わせパラメータ内にキーと値を分ける\"=\"が余分にあります: \"%s\"" + +#: fe-connect.c:6748 +#, c-format +msgid "missing key/value separator \"=\" in URI query parameter: \"%s\"" +msgstr "URI問い合わせパラメータ内にキーと値を分ける\\\"=\\\"がありません: \"%s\"" + +#: fe-connect.c:6800 +#, c-format +msgid "invalid URI query parameter: \"%s\"" +msgstr "不正なURI問い合わせパラメータ:\"%s\"" + +#: fe-connect.c:6874 +#, c-format +msgid "invalid percent-encoded token: \"%s\"" +msgstr "不正なパーセント符号化トークン: \"%s\"" + +#: fe-connect.c:6884 +#, c-format +msgid "forbidden value %%00 in percent-encoded value: \"%s\"" +msgstr "パーセント符号化された値では値%%00は許されません: \"%s\"" + +#: fe-connect.c:7248 +msgid "connection pointer is NULL\n" +msgstr "接続ポインタはNULLです\n" + +#: fe-connect.c:7256 fe-exec.c:710 fe-exec.c:970 fe-exec.c:3292 +#: fe-protocol3.c:974 fe-protocol3.c:1007 +msgid "out of memory\n" +msgstr "メモリ不足\n" + +#: fe-connect.c:7547 +#, c-format +msgid "WARNING: password file \"%s\" is not a plain file\n" +msgstr "WARNING: パスワードファイル\"%s\"がテキストファイルではありません\n" + +#: fe-connect.c:7556 +#, c-format +msgid "WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n" +msgstr "警告: パスワードファイル \"%s\" がグループメンバもしくは他のユーザーから読める状態になっています。この権限はu=rw (0600)以下にすべきです\n" + +#: fe-connect.c:7663 +#, c-format +msgid "password retrieved from file \"%s\"" +msgstr "パスワードはファイル\"%s\"から取り出しました" + +#: fe-exec.c:466 fe-exec.c:3366 +#, c-format +msgid "row number %d is out of range 0..%d" +msgstr "行番号%dは0..%dの範囲を超えています" + +#: fe-exec.c:528 fe-protocol3.c:1976 +#, c-format +msgid "%s" +msgstr "%s" + +#: fe-exec.c:831 +#, c-format +msgid "write to server failed" +msgstr "サーバーへの書き込みに失敗" + +#: fe-exec.c:869 +#, c-format +msgid "no error text available" +msgstr "エラー文字列がありません" + +#: fe-exec.c:958 +msgid "NOTICE" +msgstr "注意" + +#: fe-exec.c:1016 +msgid "PGresult cannot support more than INT_MAX tuples" +msgstr "PGresultはINT_MAX個以上のタプルを扱えません" + +#: fe-exec.c:1028 +msgid "size_t overflow" +msgstr "size_t オーバーフロー" + +#: fe-exec.c:1444 fe-exec.c:1513 fe-exec.c:1559 +#, c-format +msgid "command string is a null pointer" +msgstr "コマンド文字列がヌルポインタです" + +#: fe-exec.c:1450 fe-exec.c:2888 +#, c-format +msgid "%s not allowed in pipeline mode" +msgstr "%sはパイプラインモードでは使用できません" + +#: fe-exec.c:1518 fe-exec.c:1564 fe-exec.c:1658 +#, c-format +msgid "number of parameters must be between 0 and %d" +msgstr "パラメータ数は0から%dまでの間でなければなりません" + +#: fe-exec.c:1554 fe-exec.c:1653 +#, c-format +msgid "statement name is a null pointer" +msgstr "文の名前がヌルポインタです" + +#: fe-exec.c:1695 fe-exec.c:3220 +#, c-format +msgid "no connection to the server" +msgstr "サーバーへの接続がありません" + +#: fe-exec.c:1703 fe-exec.c:3228 +#, c-format +msgid "another command is already in progress" +msgstr "他のコマンドがすでに処理中です" + +#: fe-exec.c:1733 +#, c-format +msgid "cannot queue commands during COPY" +msgstr "COPY中はコマンドのキューイングはできません" + +#: fe-exec.c:1850 +#, c-format +msgid "length must be given for binary parameter" +msgstr "バイナリパラメータには長さを指定する必要があります" + +#: fe-exec.c:2171 +#, c-format +msgid "unexpected asyncStatus: %d" +msgstr "想定外のasyncStatus: %d" + +#: fe-exec.c:2327 +#, c-format +msgid "synchronous command execution functions are not allowed in pipeline mode" +msgstr "同期的にコマンドを実行する関数はパイプラインモード中は実行できません" + +#: fe-exec.c:2344 +msgid "COPY terminated by new PQexec" +msgstr "新たなPQexec\"によりCOPYが終了しました" + +#: fe-exec.c:2360 +#, c-format +msgid "PQexec not allowed during COPY BOTH" +msgstr "COPY BOTH 実行中の PQexec は許可されていません" + +#: fe-exec.c:2586 fe-exec.c:2641 fe-exec.c:2709 fe-protocol3.c:1907 +#, c-format +msgid "no COPY in progress" +msgstr "実行中のCOPYはありません" + +#: fe-exec.c:2895 +#, c-format +msgid "connection in wrong state" +msgstr "接続状態が異常です" + +#: fe-exec.c:2938 +#, c-format +msgid "cannot enter pipeline mode, connection not idle" +msgstr "パイプラインモードに入れません、接続がアイドル状態ではありません" + +#: fe-exec.c:2974 fe-exec.c:2995 +#, c-format +msgid "cannot exit pipeline mode with uncollected results" +msgstr "未回収の結果が残っている状態でパイプラインモードを抜けることはできません" + +#: fe-exec.c:2978 +#, c-format +msgid "cannot exit pipeline mode while busy" +msgstr "ビジー状態でパイプラインモードを抜けることはできません" + +#: fe-exec.c:2989 +#, c-format +msgid "cannot exit pipeline mode while in COPY" +msgstr "COPY実行中にパイプラインモードを抜けることはできません" + +#: fe-exec.c:3154 +#, c-format +msgid "cannot send pipeline when not in pipeline mode" +msgstr "パイプラインモード外でパイプライン送出はできません" + +#: fe-exec.c:3255 +msgid "invalid ExecStatusType code" +msgstr "ExecStatusTypeコードが不正です" + +#: fe-exec.c:3282 +msgid "PGresult is not an error result\n" +msgstr "PGresutがエラー結果ではありません\n" + +#: fe-exec.c:3350 fe-exec.c:3373 +#, c-format +msgid "column number %d is out of range 0..%d" +msgstr "列番号%dは0..%dの範囲を超えています" + +#: fe-exec.c:3388 +#, c-format +msgid "parameter number %d is out of range 0..%d" +msgstr "パラメータ%dは0..%dの範囲を超えています" + +#: fe-exec.c:3699 +#, c-format +msgid "could not interpret result from server: %s" +msgstr "サーバーからの結果を解釈できませんでした: %s" + +#: fe-exec.c:3964 fe-exec.c:4054 +#, c-format +msgid "incomplete multibyte character" +msgstr "不完全なマルチバイト文字" + +#: fe-gssapi-common.c:122 +msgid "GSSAPI name import error" +msgstr "GSSAPI名のインポートエラー" + +#: fe-lobj.c:144 fe-lobj.c:207 fe-lobj.c:397 fe-lobj.c:487 fe-lobj.c:560 +#: fe-lobj.c:956 fe-lobj.c:963 fe-lobj.c:970 fe-lobj.c:977 fe-lobj.c:984 +#: fe-lobj.c:991 fe-lobj.c:998 fe-lobj.c:1005 +#, c-format +msgid "cannot determine OID of function %s" +msgstr "関数%sのOIDが特定できません" + +#: fe-lobj.c:160 +#, c-format +msgid "argument of lo_truncate exceeds integer range" +msgstr "lo_truncateの引数が整数の範囲を超えています" + +#: fe-lobj.c:262 +#, c-format +msgid "argument of lo_read exceeds integer range" +msgstr "lo_readの引数が整数の範囲を超えています" + +#: fe-lobj.c:313 +#, c-format +msgid "argument of lo_write exceeds integer range" +msgstr "lo_writeの引数が整数範囲を超えています" + +#: fe-lobj.c:669 fe-lobj.c:780 +#, c-format +msgid "could not open file \"%s\": %s" +msgstr "ファイル\"%s\"をオープンできませんでした: %s" + +#: fe-lobj.c:725 +#, c-format +msgid "could not read from file \"%s\": %s" +msgstr "ファイル\"%s\"を読み込めませんでした: %s" + +#: fe-lobj.c:801 fe-lobj.c:824 +#, c-format +msgid "could not write to file \"%s\": %s" +msgstr "ファイル\"%s\"に書き込めませんでした: %s" + +#: fe-lobj.c:908 +#, c-format +msgid "query to initialize large object functions did not return data" +msgstr "ラージオブジェクト機能を初期化する問い合わせがデータを返しませんでした" + +#: fe-misc.c:240 +#, c-format +msgid "integer of size %lu not supported by pqGetInt" +msgstr "サイズ%luの整数はpqGetIntでサポートされていません" + +#: fe-misc.c:273 +#, c-format +msgid "integer of size %lu not supported by pqPutInt" +msgstr "サイズ%luの整数はpqPutIntでサポートされていません" + +#: fe-misc.c:573 +#, c-format +msgid "connection not open" +msgstr "接続はオープンされていません" + +#: fe-misc.c:751 fe-secure-openssl.c:215 fe-secure-openssl.c:315 +#: fe-secure.c:257 fe-secure.c:419 +#, c-format +msgid "" +"server closed the connection unexpectedly\n" +"\tThis probably means the server terminated abnormally\n" +"\tbefore or while processing the request." +msgstr "" +"サーバーとの接続が想定外にクローズされました\n" +" おそらく要求の処理前または処理中にサーバーが異常終了\n" +" したことを意味しています。" + +#: fe-misc.c:818 +msgid "connection not open\n" +msgstr "接続はオープンされていません\n" + +#: fe-misc.c:1003 +#, c-format +msgid "timeout expired" +msgstr "タイムアウト期間が過ぎました" + +#: fe-misc.c:1047 +#, c-format +msgid "invalid socket" +msgstr "不正なソケットです" + +#: fe-misc.c:1069 +#, c-format +msgid "%s() failed: %s" +msgstr "%s() が失敗しました: %s" + +#: fe-protocol3.c:182 +#, c-format +msgid "message type 0x%02x arrived from server while idle" +msgstr "待機中にサーバーからメッセージ種類0x%02xが届きました" + +#: fe-protocol3.c:385 +#, c-format +msgid "server sent data (\"D\" message) without prior row description (\"T\" message)" +msgstr "サーバーが先行の行記述(\"T\"メッセージ)なしでデータ(\"D\"メッセージ)を送信しました" + +#: fe-protocol3.c:427 +#, c-format +msgid "unexpected response from server; first received character was \"%c\"" +msgstr "サーバーから想定外の応答がありました。受け付けた先頭文字は\"%c\"です" + +#: fe-protocol3.c:450 +#, c-format +msgid "message contents do not agree with length in message type \"%c\"" +msgstr "メッセージの内容がメッセージタイプ\"%c\"での長さと合っていません" + +#: fe-protocol3.c:468 +#, c-format +msgid "lost synchronization with server: got message type \"%c\", length %d" +msgstr "サーバーとの同期が失われました。受信したメッセージタイプは\"%c\"、長さは%d" + +#: fe-protocol3.c:520 fe-protocol3.c:560 +msgid "insufficient data in \"T\" message" +msgstr "\"T\"メッセージ内のデータが不十分です" + +#: fe-protocol3.c:631 fe-protocol3.c:837 +msgid "out of memory for query result" +msgstr "問い合わせ結果用のメモリが不足しています" + +#: fe-protocol3.c:700 +msgid "insufficient data in \"t\" message" +msgstr "\"t\"メッセージ内のデータが足りません" + +#: fe-protocol3.c:759 fe-protocol3.c:791 fe-protocol3.c:809 +msgid "insufficient data in \"D\" message" +msgstr "\"D\"\"メッセージ内のデータが不十分です" + +#: fe-protocol3.c:765 +msgid "unexpected field count in \"D\" message" +msgstr "\"D\"メッセージ内のフィールド数が想定外です。" + +#: fe-protocol3.c:1020 +msgid "no error message available\n" +msgstr "エラーメッセージがありません\n" + +#. translator: %s represents a digit string +#: fe-protocol3.c:1068 fe-protocol3.c:1087 +#, c-format +msgid " at character %s" +msgstr "(文字位置: %s)" + +#: fe-protocol3.c:1100 +#, c-format +msgid "DETAIL: %s\n" +msgstr "DETAIL: %s\n" + +#: fe-protocol3.c:1103 +#, c-format +msgid "HINT: %s\n" +msgstr "HINT: %s\n" + +#: fe-protocol3.c:1106 +#, c-format +msgid "QUERY: %s\n" +msgstr "QUERY: %s\n" + +#: fe-protocol3.c:1113 +#, c-format +msgid "CONTEXT: %s\n" +msgstr "CONTEXT: %s\n" + +#: fe-protocol3.c:1122 +#, c-format +msgid "SCHEMA NAME: %s\n" +msgstr "SCHEMA NAME: %s\n" + +#: fe-protocol3.c:1126 +#, c-format +msgid "TABLE NAME: %s\n" +msgstr "TABLE NAME: %s\n" + +#: fe-protocol3.c:1130 +#, c-format +msgid "COLUMN NAME: %s\n" +msgstr "COLUMN NAME: %s\n" + +#: fe-protocol3.c:1134 +#, c-format +msgid "DATATYPE NAME: %s\n" +msgstr "DATATYPE NAME: %s\n" + +#: fe-protocol3.c:1138 +#, c-format +msgid "CONSTRAINT NAME: %s\n" +msgstr "CONSTRAINT NAME: %s\n" + +#: fe-protocol3.c:1150 +msgid "LOCATION: " +msgstr "LOCATION: " + +#: fe-protocol3.c:1152 +#, c-format +msgid "%s, " +msgstr "%s, " + +#: fe-protocol3.c:1154 +#, c-format +msgid "%s:%s" +msgstr "%s:%s" + +#: fe-protocol3.c:1349 +#, c-format +msgid "LINE %d: " +msgstr "行 %d: " + +#: fe-protocol3.c:1423 +#, c-format +msgid "protocol version not supported by server: client uses %u.%u, server supports up to %u.%u" +msgstr "サーバーはこのプロトコルバージョンをサポートしていません。クライアントは%u.%uを使用、 サーバーは%u.%uまでをサポートします" + +#: fe-protocol3.c:1429 +#, c-format +msgid "protocol extension not supported by server: %s" +msgid_plural "protocol extensions not supported by server: %s" +msgstr[0] "サーバーでサポートされていないプロトコル拡張: %s" + +#: fe-protocol3.c:1437 +#, c-format +msgid "invalid %s message" +msgstr "不正な%sメッセージ" + +#: fe-protocol3.c:1802 +#, c-format +msgid "PQgetline: not doing text COPY OUT" +msgstr "PQgetline: テキストのCOPY OUTを行っていません" + +#: fe-protocol3.c:2176 +#, c-format +msgid "protocol error: no function result" +msgstr "プロトコルエラー: 関数の結果がありません" + +#: fe-protocol3.c:2187 +#, c-format +msgid "protocol error: id=0x%x" +msgstr "プロトコルエラー: id=0x%x" + +#: fe-secure-common.c:123 +#, c-format +msgid "SSL certificate's name contains embedded null" +msgstr "SSL証明書の名前の途中にnullが含まれています" + +#: fe-secure-common.c:228 +#, c-format +msgid "certificate contains IP address with invalid length %zu" +msgstr "証明書は不正な長さ%zuのIPアドレスを含んでいます" + +#: fe-secure-common.c:237 +#, c-format +msgid "could not convert certificate's IP address to string: %s" +msgstr "証明書のIPアドレスを文字列へ変換できませんでした: %s" + +#: fe-secure-common.c:269 +#, c-format +msgid "host name must be specified for a verified SSL connection" +msgstr "検証SSL接続ではホスト名を指定しなければなりません" + +#: fe-secure-common.c:286 +#, c-format +msgid "server certificate for \"%s\" (and %d other name) does not match host name \"%s\"" +msgid_plural "server certificate for \"%s\" (and %d other names) does not match host name \"%s\"" +msgstr[0] "\"%s\"のサーバー証明書(および%d個のほかの名前)はホスト名\"%s\"と一致しません" + +#: fe-secure-common.c:294 +#, c-format +msgid "server certificate for \"%s\" does not match host name \"%s\"" +msgstr "\"%s\"のサーバー証明書がホスト名\"%s\"とマッチしません" + +#: fe-secure-common.c:299 +#, c-format +msgid "could not get server's host name from server certificate" +msgstr "サーバー証明書からサーバーのホスト名を取得できませんでした" + +#: fe-secure-gssapi.c:201 +msgid "GSSAPI wrap error" +msgstr "GSSAPI名ラップエラー" + +#: fe-secure-gssapi.c:208 +#, c-format +msgid "outgoing GSSAPI message would not use confidentiality" +msgstr "送出されるGSSAPIメッセージに機密性が適用されません" + +#: fe-secure-gssapi.c:215 +#, c-format +msgid "client tried to send oversize GSSAPI packet (%zu > %zu)" +msgstr "クライアントは過大なGSSAPIパケットを送信しようとしました: (%zu > %zu)" + +#: fe-secure-gssapi.c:351 fe-secure-gssapi.c:593 +#, c-format +msgid "oversize GSSAPI packet sent by the server (%zu > %zu)" +msgstr "過大なGSSAPIパケットがサーバーから送出されました: (%zu > %zu)" + +#: fe-secure-gssapi.c:390 +msgid "GSSAPI unwrap error" +msgstr "GSSAPIアンラップエラー" + +#: fe-secure-gssapi.c:399 +#, c-format +msgid "incoming GSSAPI message did not use confidentiality" +msgstr "到着したGSSAPIメッセージには機密性が適用されていません" + +#: fe-secure-gssapi.c:656 +msgid "could not initiate GSSAPI security context" +msgstr "GSSAPIセキュリティコンテキストを開始できませんでした" + +#: fe-secure-gssapi.c:685 +msgid "GSSAPI size check error" +msgstr "GSSAPIサイズチェックエラー" + +#: fe-secure-gssapi.c:696 +msgid "GSSAPI context establishment error" +msgstr "GSSAPIコンテクスト確立エラー" + +#: fe-secure-openssl.c:219 fe-secure-openssl.c:319 fe-secure-openssl.c:1531 +#, c-format +msgid "SSL SYSCALL error: %s" +msgstr "SSL SYSCALLエラー: %s" + +#: fe-secure-openssl.c:225 fe-secure-openssl.c:325 fe-secure-openssl.c:1534 +#, c-format +msgid "SSL SYSCALL error: EOF detected" +msgstr "SSL SYSCALLエラー: EOFを検出" + +#: fe-secure-openssl.c:235 fe-secure-openssl.c:335 fe-secure-openssl.c:1542 +#, c-format +msgid "SSL error: %s" +msgstr "SSLエラー: %s" + +#: fe-secure-openssl.c:249 fe-secure-openssl.c:349 +#, c-format +msgid "SSL connection has been closed unexpectedly" +msgstr "SSL接続が意図せずにクローズされました" + +#: fe-secure-openssl.c:254 fe-secure-openssl.c:354 fe-secure-openssl.c:1589 +#, c-format +msgid "unrecognized SSL error code: %d" +msgstr "認識できないSSLエラーコード: %d" + +#: fe-secure-openssl.c:397 +#, c-format +msgid "could not determine server certificate signature algorithm" +msgstr "サーバー証明書の署名アルゴリズムを特定できませんでした" + +#: fe-secure-openssl.c:417 +#, c-format +msgid "could not find digest for NID %s" +msgstr "NID %sのダイジェストが見つかりませんでした" + +#: fe-secure-openssl.c:426 +#, c-format +msgid "could not generate peer certificate hash" +msgstr "接続先の証明書ハッシュの生成に失敗しました" + +#: fe-secure-openssl.c:509 +#, c-format +msgid "SSL certificate's name entry is missing" +msgstr "SSL証明書に名前のエントリがありません" + +#: fe-secure-openssl.c:543 +#, c-format +msgid "SSL certificate's address entry is missing" +msgstr "SSL証明書のアドレスのエントリがありません" + +#: fe-secure-openssl.c:960 +#, c-format +msgid "could not create SSL context: %s" +msgstr "SSLコンテキストを作成できませんでした: %s" + +#: fe-secure-openssl.c:1002 +#, c-format +msgid "invalid value \"%s\" for minimum SSL protocol version" +msgstr "SSLプロトコル最小バージョンに対する不正な値\"%s\"" + +#: fe-secure-openssl.c:1012 +#, c-format +msgid "could not set minimum SSL protocol version: %s" +msgstr "SSLプロトコル最小バージョンを設定できませんでした: %s" + +#: fe-secure-openssl.c:1028 +#, c-format +msgid "invalid value \"%s\" for maximum SSL protocol version" +msgstr "SSLプロトコル最大バージョンに対する不正な値\"%s\"" + +#: fe-secure-openssl.c:1038 +#, c-format +msgid "could not set maximum SSL protocol version: %s" +msgstr "SSLプロトコル最大バージョンを設定できませんでした: %s" + +#: fe-secure-openssl.c:1076 +#, c-format +msgid "could not load system root certificate paths: %s" +msgstr "システムルート証明書パスをロードできませんでした: %s" + +#: fe-secure-openssl.c:1093 +#, c-format +msgid "could not read root certificate file \"%s\": %s" +msgstr "ルート証明書ファイル\"%s\"を読み取れませんでした: %s" + +#: fe-secure-openssl.c:1145 +#, c-format +msgid "" +"could not get home directory to locate root certificate file\n" +"Either provide the file, use the system's trusted roots with sslrootcert=system, or change sslmode to disable server certificate verification." +msgstr "" +"ルート証明書ファイルを特定するためのホームディレクトリが取得できませんでした\n" +"ファイルを用意する、 sslrootcert=systemでシステムの信頼済みルート証明書を使用する、または sslmode を変更してサーバー証明書の検証を無効にしてください。" + +#: fe-secure-openssl.c:1148 +#, c-format +msgid "" +"root certificate file \"%s\" does not exist\n" +"Either provide the file, use the system's trusted roots with sslrootcert=system, or change sslmode to disable server certificate verification." +msgstr "" +"ルート証明書ファイル\"%s\"が存在しません\n" +"ファイルを用意する、sslrootcert=systemでシステムの信頼済みルート証明書を使用する、またはsslmodeを変更してサーバー証明書の検証を無効にしてください。" + +#: fe-secure-openssl.c:1183 +#, c-format +msgid "could not open certificate file \"%s\": %s" +msgstr "証明書ファイル\"%s\"をオープンできませんでした: %s" + +#: fe-secure-openssl.c:1201 +#, c-format +msgid "could not read certificate file \"%s\": %s" +msgstr "証明書ファイル\"%s\"を読み込めませんでした: %s" + +#: fe-secure-openssl.c:1225 +#, c-format +msgid "could not establish SSL connection: %s" +msgstr "SSL接続を確立できませんでした: %s" + +#: fe-secure-openssl.c:1257 +#, c-format +msgid "could not set SSL Server Name Indication (SNI): %s" +msgstr "SSLサーバー名表示(SNI)を設定できませんでした: %s" + +#: fe-secure-openssl.c:1300 +#, c-format +msgid "could not load SSL engine \"%s\": %s" +msgstr "SSLエンジン\"%s\"を読み込みできませんでした: %s" + +#: fe-secure-openssl.c:1311 +#, c-format +msgid "could not initialize SSL engine \"%s\": %s" +msgstr "SSLエンジン\"%s\"を初期化できませんでした: %s" + +#: fe-secure-openssl.c:1326 +#, c-format +msgid "could not read private SSL key \"%s\" from engine \"%s\": %s" +msgstr "SSL秘密鍵\"%s\"をエンジン\"%s\"から読み取れませんでした: %s" + +#: fe-secure-openssl.c:1339 +#, c-format +msgid "could not load private SSL key \"%s\" from engine \"%s\": %s" +msgstr "SSL秘密鍵\"%s\"をエンジン\"%s\"から読み取れませんでした: %s" + +#: fe-secure-openssl.c:1376 +#, c-format +msgid "certificate present, but not private key file \"%s\"" +msgstr "証明書はありますが、秘密鍵ファイル\"%s\"はありません" + +#: fe-secure-openssl.c:1379 +#, c-format +msgid "could not stat private key file \"%s\": %m" +msgstr "秘密鍵ファイル\"%s\"をstatできませんでした: %m" + +#: fe-secure-openssl.c:1387 +#, c-format +msgid "private key file \"%s\" is not a regular file" +msgstr "秘密鍵ファイル\"%s\"は通常のファイルではありません" + +#: fe-secure-openssl.c:1420 +#, c-format +msgid "private key file \"%s\" has group or world access; file must have permissions u=rw (0600) or less if owned by the current user, or permissions u=rw,g=r (0640) or less if owned by root" +msgstr "秘密鍵ファイル\"%s\"はグループに対して、もしくは無制限にアクセスを許可しています; ファイルのパーミッションは u=rw (0600) かそれよりも狭い必要があります、rootが所有している場合は u=rw,g=r (0640) かそれよりも狭い必要があります" + +#: fe-secure-openssl.c:1444 +#, c-format +msgid "could not load private key file \"%s\": %s" +msgstr "秘密鍵ファイル\"%s\"をロードできませんでした: %s" + +#: fe-secure-openssl.c:1460 +#, c-format +msgid "certificate does not match private key file \"%s\": %s" +msgstr "証明書と秘密鍵ファイル\"%s\"が一致しません: %s" + +#: fe-secure-openssl.c:1528 +#, c-format +msgid "SSL error: certificate verify failed: %s" +msgstr "SSLエラー: 証明書の検証に失敗しました: %s" + +#: fe-secure-openssl.c:1573 +#, c-format +msgid "This may indicate that the server does not support any SSL protocol version between %s and %s." +msgstr "このことは、クライアントがSSLプロトコルのバージョン%sから%sの間のいずれもサポートしていないことを示唆しているかもしれません。" + +#: fe-secure-openssl.c:1606 +#, c-format +msgid "certificate could not be obtained: %s" +msgstr "証明書を取得できませんでした: %s" + +#: fe-secure-openssl.c:1711 +#, c-format +msgid "no SSL error reported" +msgstr "SSLエラーはありませんでした" + +#: fe-secure-openssl.c:1720 +#, c-format +msgid "SSL error code %lu" +msgstr "SSLエラーコード: %lu" + +#: fe-secure-openssl.c:1986 +#, c-format +msgid "WARNING: sslpassword truncated\n" +msgstr "警告: sslpasswordが切り詰められました\n" + +#: fe-secure.c:263 +#, c-format +msgid "could not receive data from server: %s" +msgstr "サーバーからデータを受信できませんでした: %s" + +#: fe-secure.c:434 +#, c-format +msgid "could not send data to server: %s" +msgstr "サーバーにデータを送信できませんでした: %s" + +#: win32.c:310 +#, c-format +msgid "unrecognized socket error: 0x%08X/%d" +msgstr "不明なソケットエラー 0x%08X/%d" diff --git a/src/interfaces/libpq/po/ka.po b/src/interfaces/libpq/po/ka.po new file mode 100644 index 0000000..74b77b6 --- /dev/null +++ b/src/interfaces/libpq/po/ka.po @@ -0,0 +1,1525 @@ +# Georgian message translation file for libpq +# Copyright (C) 2022 PostgreSQL Global Development Group +# This file is distributed under the same license as the libpq (PostgreSQL) package. +# Temuri Doghonadze <temuri.doghonadze@gmail.com>, 2022. +# +msgid "" +msgstr "" +"Project-Id-Version: libpq (PostgreSQL) 16\n" +"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" +"POT-Creation-Date: 2023-07-05 06:10+0000\n" +"PO-Revision-Date: 2023-07-05 12:29+0200\n" +"Last-Translator: Temuri Doghonadze <temuri.doghonadze@gmail.com>\n" +"Language-Team: Georgian <nothing>\n" +"Language: ka\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 3.3.2\n" + +#: ../../port/thread.c:50 ../../port/thread.c:86 +#, c-format +msgid "could not look up local user ID %d: %s" +msgstr "ლოკალური მომხმარებლის ID-ის (%d) ამოხსნა შეუძლებელია: %s" + +#: ../../port/thread.c:55 ../../port/thread.c:91 +#, c-format +msgid "local user with ID %d does not exist" +msgstr "ლოკალური მომხმარებელი ID-ით %d არ არსებობს" + +#: fe-auth-scram.c:227 +#, c-format +msgid "malformed SCRAM message (empty message)" +msgstr "დამახინჯებული SCRAM-ის შეტყობინება (ცარიელი შეტყობინება)" + +#: fe-auth-scram.c:232 +#, c-format +msgid "malformed SCRAM message (length mismatch)" +msgstr "დამახინჯებული SCRAM-ის შეტყობინება (სიგრძე არ ემთხვევა)" + +#: fe-auth-scram.c:275 +#, c-format +msgid "could not verify server signature: %s" +msgstr "სერვერის ხელმოწერის შემოწმება შეუძლებელია: %s" + +#: fe-auth-scram.c:281 +#, c-format +msgid "incorrect server signature" +msgstr "სერვერის არასწორი ხელმოწერა" + +#: fe-auth-scram.c:290 +#, c-format +msgid "invalid SCRAM exchange state" +msgstr "არასწორი SCRAM-ის გაცვლის მდგომარეობა" + +#: fe-auth-scram.c:317 +#, c-format +msgid "malformed SCRAM message (attribute \"%c\" expected)" +msgstr "დამახინჯებული SCRAM-ის შეტყობინება (აკლია ატრიბუტი \"%c\")" + +#: fe-auth-scram.c:326 +#, c-format +msgid "malformed SCRAM message (expected character \"=\" for attribute \"%c\")" +msgstr "დამახინჯებული SCRAM-ის შეტყობინება (აკლია \"=\" ატრიბუტი \"%c\"-სთვის)" + +#: fe-auth-scram.c:366 +#, c-format +msgid "could not generate nonce" +msgstr "ერთჯერადი კოდის გენერაციის შეცდომა" + +#: fe-auth-scram.c:375 fe-auth-scram.c:448 fe-auth-scram.c:600 +#: fe-auth-scram.c:620 fe-auth-scram.c:644 fe-auth-scram.c:658 +#: fe-auth-scram.c:704 fe-auth-scram.c:740 fe-auth-scram.c:914 fe-auth.c:295 +#: fe-auth.c:368 fe-auth.c:402 fe-auth.c:617 fe-auth.c:728 fe-auth.c:1209 +#: fe-auth.c:1374 fe-connect.c:925 fe-connect.c:1759 fe-connect.c:1921 +#: fe-connect.c:3291 fe-connect.c:4496 fe-connect.c:5161 fe-connect.c:5416 +#: fe-connect.c:5534 fe-connect.c:5781 fe-connect.c:5861 fe-connect.c:5959 +#: fe-connect.c:6210 fe-connect.c:6237 fe-connect.c:6313 fe-connect.c:6336 +#: fe-connect.c:6360 fe-connect.c:6395 fe-connect.c:6481 fe-connect.c:6489 +#: fe-connect.c:6846 fe-connect.c:6996 fe-exec.c:527 fe-exec.c:1321 +#: fe-exec.c:3111 fe-exec.c:4071 fe-exec.c:4235 fe-gssapi-common.c:109 +#: fe-lobj.c:870 fe-protocol3.c:204 fe-protocol3.c:228 fe-protocol3.c:256 +#: fe-protocol3.c:273 fe-protocol3.c:353 fe-protocol3.c:720 fe-protocol3.c:959 +#: fe-protocol3.c:1770 fe-protocol3.c:2170 fe-secure-common.c:110 +#: fe-secure-gssapi.c:500 fe-secure-openssl.c:434 fe-secure-openssl.c:1285 +#, c-format +msgid "out of memory" +msgstr "მეხსიერებას გარეთ" + +#: fe-auth-scram.c:382 +#, c-format +msgid "could not encode nonce" +msgstr "ერთჯერადი კოდის კოდირების შეცდომა" + +#: fe-auth-scram.c:570 +#, c-format +msgid "could not calculate client proof: %s" +msgstr "კლიენტის მტკიცებულების გამოთვლის შეცდომა: %s" + +#: fe-auth-scram.c:585 +#, c-format +msgid "could not encode client proof" +msgstr "კლიენტის მტკიცებულების კოდირების შეცდომა" + +#: fe-auth-scram.c:637 +#, c-format +msgid "invalid SCRAM response (nonce mismatch)" +msgstr "არასწორი SCRAM-ის პასუხი (ერთჯერადი კოდი არ ემთხვევა)" + +#: fe-auth-scram.c:667 +#, c-format +msgid "malformed SCRAM message (invalid salt)" +msgstr "დამახინჯებული SCRAM-ის შეტყობინება (არასწორი მარილი)" + +#: fe-auth-scram.c:680 +#, c-format +msgid "malformed SCRAM message (invalid iteration count)" +msgstr "დამახინჯებული SCRAM-ის შეტყობინება (იტერაციების არასწორი რიცხვი)" + +#: fe-auth-scram.c:685 +#, c-format +msgid "malformed SCRAM message (garbage at end of server-first-message)" +msgstr "დამახინჯებული SCRAM-ის შეტყობინება (ნაპოვნია ნაგავი სერვერისთვის გასაგზავნი პირველი შეტყობინების ბოლოში)" + +#: fe-auth-scram.c:719 +#, c-format +msgid "error received from server in SCRAM exchange: %s" +msgstr "მიღებულია სერვერის შეცდომა SCRAM გგაცვლაში: %s" + +#: fe-auth-scram.c:734 +#, c-format +msgid "malformed SCRAM message (garbage at end of server-final-message)" +msgstr "დამახინჯებული SCRAM შეტყობინება (ნაგავი სერვერის-საბოლოო-შეტყობინების ბოლოში)" + +#: fe-auth-scram.c:751 +#, c-format +msgid "malformed SCRAM message (invalid server signature)" +msgstr "დამახინჯებული SCRAM-ის შეტყობინება (სერვერის არასწორი ხელმოწერა)" + +#: fe-auth-scram.c:923 +msgid "could not generate random salt" +msgstr "შემთხვევითი მარილის გენერაციის შეცდომა" + +#: fe-auth.c:76 +#, c-format +msgid "out of memory allocating GSSAPI buffer (%d)" +msgstr "არასაკმარისი მეხსიერება GSSAPI-ის ბაფერის გამოყოფისას (%d)" + +#: fe-auth.c:137 +msgid "GSSAPI continuation error" +msgstr "GSSAPI-ის განგრძობადობის შეცდომა" + +#: fe-auth.c:167 fe-auth.c:396 fe-gssapi-common.c:97 fe-secure-common.c:99 +#: fe-secure-common.c:173 +#, c-format +msgid "host name must be specified" +msgstr "ჰოსტის სახელის მითითება აუცილებელია" + +#: fe-auth.c:173 +#, c-format +msgid "duplicate GSS authentication request" +msgstr "დუბლირებული GSS ავთენტიკაციის მოთხოვნა" + +#: fe-auth.c:237 +#, c-format +msgid "out of memory allocating SSPI buffer (%d)" +msgstr "არასაკმარისი მეხსიერება SSPI-ის ბაფერის გამოყოფისას (%d)" + +#: fe-auth.c:284 +msgid "SSPI continuation error" +msgstr "SSPI-ის განგრძობადობის შეცდომა" + +#: fe-auth.c:358 +#, c-format +msgid "duplicate SSPI authentication request" +msgstr "დუბლირებული SSPI ავთენტიკაციის მოთხოვნა" + +#: fe-auth.c:383 +msgid "could not acquire SSPI credentials" +msgstr "შეცდომა SSPI-ის მომხმ./პაროლის მიღებისას" + +#: fe-auth.c:436 +#, c-format +msgid "channel binding required, but SSL not in use" +msgstr "მითითებულია არხის მიბმა, მაგრამ SSL არ გამოიყენება" + +#: fe-auth.c:442 +#, c-format +msgid "duplicate SASL authentication request" +msgstr "დუბლირებული SASL ავთენტიკაციის მოთხოვნა" + +#: fe-auth.c:500 +#, c-format +msgid "channel binding is required, but client does not support it" +msgstr "არხის მიბმა აუცილებელია, მაგრამ კლიენტს მხარდაჭერა არ გააჩნია" + +#: fe-auth.c:516 +#, c-format +msgid "server offered SCRAM-SHA-256-PLUS authentication over a non-SSL connection" +msgstr "სერვერი გვთავაზობს SCRAM-SHA-256-PLUS ავთენტიკაციას მაშინ, როცა SSL გამორთულია" + +#: fe-auth.c:530 +#, c-format +msgid "none of the server's SASL authentication mechanisms are supported" +msgstr "სერვერის SASL ავთენტიკაციის არც ერთი მექანიზმი მხარდაჭერილი არაა" + +#: fe-auth.c:537 +#, c-format +msgid "channel binding is required, but server did not offer an authentication method that supports channel binding" +msgstr "მოთხოვნილია არხზე მიბმა, მაგრამ სერვერმა არ შემოგვთავაზა ავთენტიკაციის მექანიზმი, რომელსაც არხზე მიბმის მხარდაჭერა გააჩნია" + +#: fe-auth.c:640 +#, c-format +msgid "out of memory allocating SASL buffer (%d)" +msgstr "არასაკმარისი მეხსიერება SASL ბაფერის გამოყოფისას (%d)" + +#: fe-auth.c:664 +#, c-format +msgid "AuthenticationSASLFinal received from server, but SASL authentication was not completed" +msgstr "სერვერიდან AuthenticationSASLFinal მიღებულია, მაგრამ SASL ავთენტიკაცია არ დასრულებულა" + +#: fe-auth.c:674 +#, c-format +msgid "no client response found after SASL exchange success" +msgstr "კლიენტის SASL გაცვლის წარმატების შემდეგ პასუხი არ გამოუგზავნია" + +#: fe-auth.c:737 fe-auth.c:744 fe-auth.c:1357 fe-auth.c:1368 +#, c-format +msgid "could not encrypt password: %s" +msgstr "პაროლის დაშიფვრის შეცდომა: %s" + +#: fe-auth.c:772 +msgid "server requested a cleartext password" +msgstr "სერვერმა ღია პაროლი მოითხოვა" + +#: fe-auth.c:774 +msgid "server requested a hashed password" +msgstr "სერვერმა დაჰეშილი პაროლი მოითხოვა" + +#: fe-auth.c:777 +msgid "server requested GSSAPI authentication" +msgstr "დუბლირებული SSPI ავთენტიკაციის მოთხოვნა" + +#: fe-auth.c:779 +msgid "server requested SSPI authentication" +msgstr "დუბლირებული SSPI ავთენტიკაციის მოთხოვნა" + +#: fe-auth.c:783 +msgid "server requested SASL authentication" +msgstr "დუბლირებული SASL ავთენტიკაციის მოთხოვნა" + +#: fe-auth.c:786 +msgid "server requested an unknown authentication type" +msgstr "სერვერმა უცნობი ავთენტიკაციის ტიპი მოითხოვა" + +#: fe-auth.c:819 +#, c-format +msgid "server did not request an SSL certificate" +msgstr "სერვერს SSL სერტიფიკატი არ მოუთხოვია" + +#: fe-auth.c:824 +#, c-format +msgid "server accepted connection without a valid SSL certificate" +msgstr "სერვერი მიერთების მცდელობას სწორი SSL სერტიფიკატის გარეშე დაეთანხმა" + +#: fe-auth.c:878 +msgid "server did not complete authentication" +msgstr "სერვერმა ავთენტიკაცია არ დაასრულა" + +#: fe-auth.c:912 +#, c-format +msgid "authentication method requirement \"%s\" failed: %s" +msgstr "ავთენტიკაციის მეთოდის (\"%s\") მოთხოვნის შეცდომა: %s" + +#: fe-auth.c:935 +#, c-format +msgid "channel binding required, but server authenticated client without channel binding" +msgstr "არხზე მიბმა მოთხოვნილია, მაგრამ სერვერმა კლიენტის ავთენტიკაცია არხზე მიბმის გარეშე მოახდინა" + +#: fe-auth.c:940 +#, c-format +msgid "channel binding required but not supported by server's authentication request" +msgstr "არხზე მიბმა მოთხოვნილია, მაგრამ მხარდაუჭერელია სერვერის ავთენტიკაციის მოთხოვნის მიერ" + +#: fe-auth.c:974 +#, c-format +msgid "Kerberos 4 authentication not supported" +msgstr "Kerberos 4 ავთენტიკაცია მხარდაჭერილი არაა" + +#: fe-auth.c:978 +#, c-format +msgid "Kerberos 5 authentication not supported" +msgstr "Kerberos 5 ავთენტიკაცია მხარდაჭერილი არაა" + +#: fe-auth.c:1048 +#, c-format +msgid "GSSAPI authentication not supported" +msgstr "GSSAPI ავთენტიკაცია მხარდაჭერილი არაა" + +#: fe-auth.c:1079 +#, c-format +msgid "SSPI authentication not supported" +msgstr "SSPI ავთენტიკაცია მხარდაუჭერელია" + +#: fe-auth.c:1086 +#, c-format +msgid "Crypt authentication not supported" +msgstr "Crypt ავთენტიკაცია მხარდაჭერილი არაა" + +#: fe-auth.c:1150 +#, c-format +msgid "authentication method %u not supported" +msgstr "ავთენტიკაციის მეთოდი მხარდაუჭერელია: %u" + +#: fe-auth.c:1196 +#, c-format +msgid "user name lookup failure: error code %lu" +msgstr "მომხარებლის სახელის ამოხსნის პრობლემა: შეცდომის კოდი: %lu" + +#: fe-auth.c:1320 +#, c-format +msgid "unexpected shape of result set returned for SHOW" +msgstr "ბრძანებისთვის SHOW დაბრუნებული შედეგის მოხაზულობა მოულოდნელია" + +#: fe-auth.c:1328 +#, c-format +msgid "password_encryption value too long" +msgstr "password_encryption -ის მნიშვნელობა ძალიან გრძელია" + +#: fe-auth.c:1378 +#, c-format +msgid "unrecognized password encryption algorithm \"%s\"" +msgstr "პაროლის დაშიფვრის უცნობი ალგორითმი: \"%s\"" + +#: fe-connect.c:1132 +#, c-format +msgid "could not match %d host names to %d hostaddr values" +msgstr "%d ჰოსტის სახელები %d ჰოსტის მისამართების მნიშვნელობებს არ ემთხვევა" + +#: fe-connect.c:1212 +#, c-format +msgid "could not match %d port numbers to %d hosts" +msgstr "%d პორტის ნომრები %d ჰოსტს არ ემთხვევა" + +#: fe-connect.c:1337 +#, c-format +msgid "negative require_auth method \"%s\" cannot be mixed with non-negative methods" +msgstr "უარყოფითი require_auth მეთოდი \"%s\" არ შეიძლება სხვა არაუარყოფით მეთოდებს შეურიოთ" + +#: fe-connect.c:1350 +#, c-format +msgid "require_auth method \"%s\" cannot be mixed with negative methods" +msgstr "require_auth-ის მეთოდს \"%s\" უარყოფით მეთოდებს ვერ შეურევთ" + +#: fe-connect.c:1410 fe-connect.c:1461 fe-connect.c:1503 fe-connect.c:1559 +#: fe-connect.c:1567 fe-connect.c:1598 fe-connect.c:1644 fe-connect.c:1684 +#: fe-connect.c:1705 +#, c-format +msgid "invalid %s value: \"%s\"" +msgstr "%s-ის არასწორი მნიშვნელობა: \"%s\"" + +#: fe-connect.c:1443 +#, c-format +msgid "require_auth method \"%s\" is specified more than once" +msgstr "პარამეტრი \"%s\" ერთზე მეტჯერაა მითითებული" + +#: fe-connect.c:1484 fe-connect.c:1523 fe-connect.c:1606 +#, c-format +msgid "%s value \"%s\" invalid when SSL support is not compiled in" +msgstr "%s-ის მნიშვნელობა \"%s\" არასწორია, როცა SSL-ის მხარდაჭერა გამორთული იყო აგების დროს" + +#: fe-connect.c:1546 +#, c-format +msgid "weak sslmode \"%s\" may not be used with sslrootcert=system (use \"verify-full\")" +msgstr "სუსტი sslmode \"%s\" არ შეიძლება გამოყენებული იქნას sslrootcert=system-თან ერთად (გამოიყენეთ \"verify-full\")" + +#: fe-connect.c:1584 +#, c-format +msgid "invalid SSL protocol version range" +msgstr "არასწორი SSL პროტოკოლის ვერსიის დიაპაზონი" + +#: fe-connect.c:1621 +#, c-format +msgid "%s value \"%s\" is not supported (check OpenSSL version)" +msgstr "%s-ის მნიშვნელობა \"%s\" მხარდაჭერილი არაა (შეამოწმეთ OpenSSL-ის ვერსია)" + +#: fe-connect.c:1651 +#, c-format +msgid "gssencmode value \"%s\" invalid when GSSAPI support is not compiled in" +msgstr "gssencmode -ის მნიშვნელობა \"%s\" არასწორია. GSSAPI-ის მხარდაჭერა გამორთული იყო აგების დროს" + +#: fe-connect.c:1944 +#, c-format +msgid "could not set socket to TCP no delay mode: %s" +msgstr "სოკეტის TCP no_delay რეჟიმის ჩართვის შეცდომა: %s" + +#: fe-connect.c:2003 +#, c-format +msgid "connection to server on socket \"%s\" failed: " +msgstr "სოკეტით (\"%s\")სერვერთან მიერთების შეცდომა: " + +#: fe-connect.c:2029 +#, c-format +msgid "connection to server at \"%s\" (%s), port %s failed: " +msgstr "სერვერის (\"%s\" (%s)) %s-ე პორტზე მიერთების შეცდომა: " + +#: fe-connect.c:2034 +#, c-format +msgid "connection to server at \"%s\", port %s failed: " +msgstr "სერვერის (\"%s\" ) %s-ე პორტზე მიერთების შეცდომა: " + +#: fe-connect.c:2057 +#, c-format +msgid "\tIs the server running locally and accepting connections on that socket?" +msgstr "\tარს სერვერი ლოკალურად გაშვებული და მზადაა სოკეტითა დასაკავშირებლად?" + +#: fe-connect.c:2059 +#, c-format +msgid "\tIs the server running on that host and accepting TCP/IP connections?" +msgstr "\tარის სერვერი გაშვებული ამ ჰოსტზე და ეთანხმება TCP/IP შეერთებებს?" + +#: fe-connect.c:2122 +#, c-format +msgid "invalid integer value \"%s\" for connection option \"%s\"" +msgstr "არასწორი მნიშვნელობა: \"%s\" (უნდა იყოს მთელი რიცხვი) შეერთების პარამეტრისთვის \"%s\"" + +#: fe-connect.c:2151 fe-connect.c:2185 fe-connect.c:2220 fe-connect.c:2318 +#: fe-connect.c:2973 +#, c-format +msgid "%s(%s) failed: %s" +msgstr "%s(%s) -ის შეცდომა: %s" + +#: fe-connect.c:2284 +#, c-format +msgid "%s(%s) failed: error code %d" +msgstr "%s(%s) -ის შეცდომა: შეცდომის კოდი %d" + +#: fe-connect.c:2597 +#, c-format +msgid "invalid connection state, probably indicative of memory corruption" +msgstr "შეერთების არასწორი მდგომარეობა. დიდი შანსით ნიშნავს მეხსიერების დაზიანებას" + +#: fe-connect.c:2676 +#, c-format +msgid "invalid port number: \"%s\"" +msgstr "პორტის არასწორი ნომერი: \"%s\"" + +#: fe-connect.c:2690 +#, c-format +msgid "could not translate host name \"%s\" to address: %s" +msgstr "ჰოსტის სახელის (%s) მისამართში თარგმნის შეცდომა: %s" + +#: fe-connect.c:2702 +#, c-format +msgid "could not parse network address \"%s\": %s" +msgstr "ქსელური მისამართის (\"%s\") დამუშავების პრობლემა: %s" + +#: fe-connect.c:2713 +#, c-format +msgid "Unix-domain socket path \"%s\" is too long (maximum %d bytes)" +msgstr "Unix-დომენის სოკეტის მისამართი \"%s\" ძალიან გრძელია (დასაშვებია %d ბაიტი)" + +#: fe-connect.c:2727 +#, c-format +msgid "could not translate Unix-domain socket path \"%s\" to address: %s" +msgstr "unix-დომენის სოკეტის ბილიკის (\"%s\") მისამართად თარგმნის შეცდომა: %s" + +#: fe-connect.c:2901 +#, c-format +msgid "could not create socket: %s" +msgstr "სოკეტის შექმნის შეცდომა: %s" + +#: fe-connect.c:2932 +#, c-format +msgid "could not set socket to nonblocking mode: %s" +msgstr "სოკეტის არაბლოკირებული რეჟიმის დაყენების შეცდომა: %s" + +#: fe-connect.c:2943 +#, c-format +msgid "could not set socket to close-on-exec mode: %s" +msgstr "სოკეტის დახურვა-შესრულებისას რეჟიმის დაყენების შეცდომა: %s" + +#: fe-connect.c:2961 +#, c-format +msgid "keepalives parameter must be an integer" +msgstr "პარამეტრი keepalives მთელი რიცხვი უნდა იყოს" + +#: fe-connect.c:3100 +#, c-format +msgid "could not get socket error status: %s" +msgstr "სოკეტის შეცდომის სტატუსის მიღების შეცდომა: %s" + +#: fe-connect.c:3127 +#, c-format +msgid "could not get client address from socket: %s" +msgstr "კლიენტის მისამართის სოკეტიდან მიღების შეცდომა: %s" + +#: fe-connect.c:3165 +#, c-format +msgid "requirepeer parameter is not supported on this platform" +msgstr "პარამეტრი requirepeer ამ პლატფორმაზე მხარდაჭერილი არაა" + +#: fe-connect.c:3167 +#, c-format +msgid "could not get peer credentials: %s" +msgstr "პარტნიორის ავტორიზაციის დეტალების მიღების შეცდომა: %s" + +#: fe-connect.c:3180 +#, c-format +msgid "requirepeer specifies \"%s\", but actual peer user name is \"%s\"" +msgstr "requrepeer-ის მნიშვნელობაა \"%s\", მაგრამ პარტნიორის მომხმარებლის ნამდვილი ასხელია: \"%s\"" + +#: fe-connect.c:3221 +#, c-format +msgid "could not send GSSAPI negotiation packet: %s" +msgstr "შეცდომა GSSAPI-ის მიმოცვლის პაკეტის გაგზავნისას: %s" + +#: fe-connect.c:3233 +#, c-format +msgid "GSSAPI encryption required but was impossible (possibly no credential cache, no server support, or using a local socket)" +msgstr "GSSAPI დაშიფვრა მოთხოვნილია, მაგრამ შეუძლებელი (შესაძლო მიზეზებია მომხმ/პაროლის ქეშის არარსებობა, სერვერის მხარეს მხარდაჭერის არ არსებობა ან ლოკალური სოკეტის გამოყენება)" + +#: fe-connect.c:3274 +#, c-format +msgid "could not send SSL negotiation packet: %s" +msgstr "შეცდომა SSL მიმოცვლის პაკეტის გაგზავნისას: %s" + +#: fe-connect.c:3303 +#, c-format +msgid "could not send startup packet: %s" +msgstr "გაშვების პაკეტის გაგზავნის შეცდომა: %s" + +#: fe-connect.c:3378 +#, c-format +msgid "server does not support SSL, but SSL was required" +msgstr "სერვერს SSL-ის მხარდაჭერა არ გააჩნია, მაგრამ SSL-ი აუცილებელია" + +#: fe-connect.c:3404 +#, c-format +msgid "received invalid response to SSL negotiation: %c" +msgstr "არასწორი პასუხი SSL მიმოცვლისას: %c" + +#: fe-connect.c:3424 +#, c-format +msgid "received unencrypted data after SSL response" +msgstr "'SSL' პასუხის შემდეგ მიღებული მონაცემები დაუშიფრავია" + +#: fe-connect.c:3504 +#, c-format +msgid "server doesn't support GSSAPI encryption, but it was required" +msgstr "სერვერს GSSAPI დაშიფვრის მხარდაჭერა არ გააჩნა, მაგრამ ის მოთხოვილია" + +#: fe-connect.c:3515 +#, c-format +msgid "received invalid response to GSSAPI negotiation: %c" +msgstr "'GSSAPI' მიმოცვლის არასწორი პასუხი: %c" + +#: fe-connect.c:3533 +#, c-format +msgid "received unencrypted data after GSSAPI encryption response" +msgstr "'GSSAPI' პასუხის შემდეგ მიღებული მონაცემები დაუშიფრავია" + +#: fe-connect.c:3598 +#, c-format +msgid "expected authentication request from server, but received %c" +msgstr "სერვერიდან მოსალოდნელი იყო ავთენტიკაციის მოთხოვნა, მაგრამ მიღებულია %c" + +#: fe-connect.c:3625 fe-connect.c:3794 +#, c-format +msgid "received invalid authentication request" +msgstr "დუბლირებული GSS ავთენტიკაციის მოთხოვნა" + +#: fe-connect.c:3630 fe-connect.c:3779 +#, c-format +msgid "received invalid protocol negotiation message" +msgstr "მიღებულია არასწორი პროტოკოლის მიმოცვლის შეტყობინება" + +#: fe-connect.c:3648 fe-connect.c:3702 +#, c-format +msgid "received invalid error message" +msgstr "მიღებულია არასწორი შეცდომის შეტყობინება" + +#: fe-connect.c:3865 +#, c-format +msgid "unexpected message from server during startup" +msgstr "სერვერის გაშვებისას მიღებულია მოულოდნელი შეტყობინება" + +#: fe-connect.c:3956 +#, c-format +msgid "session is read-only" +msgstr "სესია მხოლოდ კითხვადია" + +#: fe-connect.c:3958 +#, c-format +msgid "session is not read-only" +msgstr "სესია მხოლოდ კითხვადი არა" + +#: fe-connect.c:4011 +#, c-format +msgid "server is in hot standby mode" +msgstr "სერვერი მზა-უქმე რეჟიმშია" + +#: fe-connect.c:4013 +#, c-format +msgid "server is not in hot standby mode" +msgstr "სერვერი მზა-უქმე რეჟიმში არაა" + +#: fe-connect.c:4129 fe-connect.c:4179 +#, c-format +msgid "\"%s\" failed" +msgstr "\"%s\"-ის შეცდომა" + +#: fe-connect.c:4193 +#, c-format +msgid "invalid connection state %d, probably indicative of memory corruption" +msgstr "შეერთების არასწორი მდგომარეობა (%d). დიდი შანსით ნიშნავს მეხსიერების დაზიანებას" + +#: fe-connect.c:5174 +#, c-format +msgid "invalid LDAP URL \"%s\": scheme must be ldap://" +msgstr "'LDAP'-ის არასწორი URL: \"%s\": სქემა ldap:// უნდა იყოს" + +#: fe-connect.c:5189 +#, c-format +msgid "invalid LDAP URL \"%s\": missing distinguished name" +msgstr "'LDAP'-ის არასწორი URL: \"%s\": აკლია გამოყოფილი სახელი" + +#: fe-connect.c:5201 fe-connect.c:5259 +#, c-format +msgid "invalid LDAP URL \"%s\": must have exactly one attribute" +msgstr "'LDAP'-ის არასწორი URL \"%s\": ზუსტად ერთი ატრიბუტი უნდა ჰქონდეს" + +#: fe-connect.c:5213 fe-connect.c:5275 +#, c-format +msgid "invalid LDAP URL \"%s\": must have search scope (base/one/sub)" +msgstr "'LDAP'-ის არასწორი URL: \"%s\": საჭიროა ძებნის ფარგლების ქონა (საბაზისო/ერთი/ქვე)" + +#: fe-connect.c:5225 +#, c-format +msgid "invalid LDAP URL \"%s\": no filter" +msgstr "'LDAP'-ის არასწორი URL: \"%s\":ფილტრი არ არსებობს" + +#: fe-connect.c:5247 +#, c-format +msgid "invalid LDAP URL \"%s\": invalid port number" +msgstr "'LDAP'-ის არასწორი URL: \"%s\": პორტის არასწორი ნომერი" + +#: fe-connect.c:5284 +#, c-format +msgid "could not create LDAP structure" +msgstr "შეცდომა LDAP-ის სტრუქტურის შექმნისას" + +#: fe-connect.c:5359 +#, c-format +msgid "lookup on LDAP server failed: %s" +msgstr "'LDAP' სერვერის მოძებნის შეცდომა: %s" + +#: fe-connect.c:5369 +#, c-format +msgid "more than one entry found on LDAP lookup" +msgstr "ძებნისას (LDAP) ნაპოვნია ერთზე მეტი ჩანაწერი" + +#: fe-connect.c:5371 fe-connect.c:5382 +#, c-format +msgid "no entry found on LDAP lookup" +msgstr "ძებნისას (LDAP) ჩანაწერები ნაპოვნი არაა" + +#: fe-connect.c:5392 fe-connect.c:5404 +#, c-format +msgid "attribute has no values on LDAP lookup" +msgstr "'LDAP' ძებნის ატრიბუტს მნიშვნელობა არ გააჩნია" + +#: fe-connect.c:5455 fe-connect.c:5474 fe-connect.c:5998 +#, c-format +msgid "missing \"=\" after \"%s\" in connection info string" +msgstr "შეერთების სტრიქონში \"%s\"-ის შემდეგ \"=\" აკლია" + +#: fe-connect.c:5545 fe-connect.c:6181 fe-connect.c:6979 +#, c-format +msgid "invalid connection option \"%s\"" +msgstr "შეერთების არასწორი პარამეტრი: \"%s\"" + +#: fe-connect.c:5560 fe-connect.c:6046 +#, c-format +msgid "unterminated quoted string in connection info string" +msgstr "შეერთების ინფორმაციის სტრიქონში ბრჭყალებში ჩასმული სტრიქონი დაუსრულებელია" + +#: fe-connect.c:5640 +#, c-format +msgid "definition of service \"%s\" not found" +msgstr "სერვისის აღწერა არ არსებობს: \"%s\"" + +#: fe-connect.c:5666 +#, c-format +msgid "service file \"%s\" not found" +msgstr "სერვისის ფაილი არ არსებობს: \"%s\"" + +#: fe-connect.c:5679 +#, c-format +msgid "line %d too long in service file \"%s\"" +msgstr "ძალიან გრძელი ხაზი (%d) სერვისის ფაილში \"%s\"" + +#: fe-connect.c:5750 fe-connect.c:5793 +#, c-format +msgid "syntax error in service file \"%s\", line %d" +msgstr "სინტაქსის შეცდომა სერვისის ფაილში \"%s\" ხაზზე %d" + +#: fe-connect.c:5761 +#, c-format +msgid "nested service specifications not supported in service file \"%s\", line %d" +msgstr "სერვისის ფაილში \"%s\" ჩადგმული სერვისის მითითება მხარდაუჭერელია. ხაზი %d" + +#: fe-connect.c:6500 +#, c-format +msgid "invalid URI propagated to internal parser routine: \"%s\"" +msgstr "დამუშავებს შიდა ფუნქციაში გადაცემული URI არასწორია: %s" + +#: fe-connect.c:6577 +#, c-format +msgid "end of string reached when looking for matching \"]\" in IPv6 host address in URI: \"%s\"" +msgstr "სტრიქონის დასასრული \"]\"-ს IPv6 ჰოსტის მისამართში URI-ში ძებნისას: \"%s\"" + +#: fe-connect.c:6584 +#, c-format +msgid "IPv6 host address may not be empty in URI: \"%s\"" +msgstr "ჰოსტის IPv6 მისამართი URI-ში ცარიელი ვერ იქნება: \"%s\"" + +#: fe-connect.c:6599 +#, c-format +msgid "unexpected character \"%c\" at position %d in URI (expected \":\" or \"/\"): \"%s\"" +msgstr "უცნობი სიმბოლო (\"%c\") URI-ში პოზიციაზე %d (მოველოდი \":\"-ს ან \"/\"-ს): \"%s\"" + +#: fe-connect.c:6728 +#, c-format +msgid "extra key/value separator \"=\" in URI query parameter: \"%s\"" +msgstr "მოთხოვნის URI არამეტრში მითითებულია გასაღები/მნიშვნელობის ზედმეტი \"=\": \"%s\"" + +#: fe-connect.c:6748 +#, c-format +msgid "missing key/value separator \"=\" in URI query parameter: \"%s\"" +msgstr "მოთხოვნის URI პარამეტრში მითითებულია გასაღები/მნიშვნელობის წყვილს \"=\" აკლია: \"%s\"" + +#: fe-connect.c:6800 +#, c-format +msgid "invalid URI query parameter: \"%s\"" +msgstr "მოთხოვნის არასწორი პარამეტრი: \"%s\"" + +#: fe-connect.c:6874 +#, c-format +msgid "invalid percent-encoded token: \"%s\"" +msgstr "არასწორი პროცენტულად-კოდირებული კოდი: \"%s\"" + +#: fe-connect.c:6884 +#, c-format +msgid "forbidden value %%00 in percent-encoded value: \"%s\"" +msgstr "პროცენტში კოდირებული მნიშვნელობის აკრძალული მნიშვნელობა %%00: \"%s\"" + +#: fe-connect.c:7248 +msgid "connection pointer is NULL\n" +msgstr "შეერთების მაჩვენებელი ნულოვანია\n" + +#: fe-connect.c:7256 fe-exec.c:710 fe-exec.c:970 fe-exec.c:3292 +#: fe-protocol3.c:974 fe-protocol3.c:1007 +msgid "out of memory\n" +msgstr "არასაკმარისი მეხსიერება\n" + +#: fe-connect.c:7547 +#, c-format +msgid "WARNING: password file \"%s\" is not a plain file\n" +msgstr "გაფრთხილება. პაროლის ფაილი \"%s\" უბრალოდ ფაილს არ წარმოადგენს\n" + +#: fe-connect.c:7556 +#, c-format +msgid "WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n" +msgstr "გაფრთხილება: პაროლების ფაილს \"%s\" ჯგუფზე ან დანარჩენ ყველაზე წვდომა გააჩნია. წვდომა 0600 ან ნაკლები უნდა იყოს\n" + +#: fe-connect.c:7663 +#, c-format +msgid "password retrieved from file \"%s\"" +msgstr "პაროლი მიღებულია ფაილიდან \"%s\"" + +#: fe-exec.c:466 fe-exec.c:3366 +#, c-format +msgid "row number %d is out of range 0..%d" +msgstr "მწკრივების რაოდენობა %d ზღვარს (0..%d) გარეთაა" + +#: fe-exec.c:528 fe-protocol3.c:1976 +#, c-format +msgid "%s" +msgstr "%s" + +#: fe-exec.c:831 +#, c-format +msgid "write to server failed" +msgstr "სერვერზე ჩაწერის შეცდომა" + +#: fe-exec.c:869 +#, c-format +msgid "no error text available" +msgstr "შეცდომის ტექსტი ხელმიუწვდომელია" + +#: fe-exec.c:958 +msgid "NOTICE" +msgstr "გაფრთხილება" + +#: fe-exec.c:1016 +msgid "PGresult cannot support more than INT_MAX tuples" +msgstr "PGresult-ს INT_MAX-ზე მეტი სტრუქტურის მხარდაჭერა არ გააჩნია" + +#: fe-exec.c:1028 +msgid "size_t overflow" +msgstr "size_t -ის გადავსება" + +#: fe-exec.c:1444 fe-exec.c:1513 fe-exec.c:1559 +#, c-format +msgid "command string is a null pointer" +msgstr "ბრძანების სტრიქონი ნულოვანი მაჩვენებელია" + +#: fe-exec.c:1450 fe-exec.c:2888 +#, c-format +msgid "%s not allowed in pipeline mode" +msgstr "კომუნიკაციის არხის რეჟიმში %s დაუშვებელია" + +#: fe-exec.c:1518 fe-exec.c:1564 fe-exec.c:1658 +#, c-format +msgid "number of parameters must be between 0 and %d" +msgstr "პარამეტრების რაოდენობა 0-სა და %d-ს შორის შეიძლება იყოს" + +#: fe-exec.c:1554 fe-exec.c:1653 +#, c-format +msgid "statement name is a null pointer" +msgstr "გამოსახულების სახელი ნულოვანი მაჩვენებელია" + +#: fe-exec.c:1695 fe-exec.c:3220 +#, c-format +msgid "no connection to the server" +msgstr "სერვერთან შეერთება არ არსებობს" + +#: fe-exec.c:1703 fe-exec.c:3228 +#, c-format +msgid "another command is already in progress" +msgstr "უკვე გაშვებულია სხვა ბრძანება" + +#: fe-exec.c:1733 +#, c-format +msgid "cannot queue commands during COPY" +msgstr "როცა გაშვებულია ბრძანება COPY, სხვა ბრძანებებს ვერ გაუშვებთ" + +#: fe-exec.c:1850 +#, c-format +msgid "length must be given for binary parameter" +msgstr "ბინარული პარამეტრისთვის სიგრძის მითითება აუცილებელია" + +#: fe-exec.c:2171 +#, c-format +msgid "unexpected asyncStatus: %d" +msgstr "მოულოდნელი asyncStatus: %d" + +#: fe-exec.c:2327 +#, c-format +msgid "synchronous command execution functions are not allowed in pipeline mode" +msgstr "კომუნიკაციის არხის რეჟიმში ბრძანების სინქრონული შესრულების ფუნქციები მიუწვდომელია" + +#: fe-exec.c:2344 +msgid "COPY terminated by new PQexec" +msgstr "COPY შეწყვეტილია ახალი PQexec-ის მიერ" + +#: fe-exec.c:2360 +#, c-format +msgid "PQexec not allowed during COPY BOTH" +msgstr "COPY BOTH-ის დროს PQexec დაუშვებელია" + +#: fe-exec.c:2586 fe-exec.c:2641 fe-exec.c:2709 fe-protocol3.c:1907 +#, c-format +msgid "no COPY in progress" +msgstr "ბრძანება COPY გაშვებული არაა" + +#: fe-exec.c:2895 +#, c-format +msgid "connection in wrong state" +msgstr "შეერთების მდგომარეობა არასწორია" + +#: fe-exec.c:2938 +#, c-format +msgid "cannot enter pipeline mode, connection not idle" +msgstr "კომუნიკაციის არხის რეჟიმზე გადართვის შეცდომა. შეერთება უქმე არაა" + +#: fe-exec.c:2974 fe-exec.c:2995 +#, c-format +msgid "cannot exit pipeline mode with uncollected results" +msgstr "მოგროვებული შედეგების გარეშე კომუნიკაციის არხის რეჟიმიდან ვერ გახვალთ" + +#: fe-exec.c:2978 +#, c-format +msgid "cannot exit pipeline mode while busy" +msgstr "კომუნიკაციის არხის რეჟიმიდან გასვლა მაშინ, როცა ის დაკავებულია, შეუძლებელია" + +#: fe-exec.c:2989 +#, c-format +msgid "cannot exit pipeline mode while in COPY" +msgstr "კომუნიკაციის არხის რეჟიმიდან გასვლა მაშინ, როცა ის დაკავებულია, შეუძლებელია" + +#: fe-exec.c:3154 +#, c-format +msgid "cannot send pipeline when not in pipeline mode" +msgstr "კომუნიკაციის არხის გაგზავნა, როცა კომუნიკაციის არხის რეჟიმში არ ხართ, შეუძლებელია" + +#: fe-exec.c:3255 +msgid "invalid ExecStatusType code" +msgstr "'ExecStatusType'-ის არასწორი კოდი" + +#: fe-exec.c:3282 +msgid "PGresult is not an error result\n" +msgstr "PGresult შეცდომითი შედეგი არაა\n" + +#: fe-exec.c:3350 fe-exec.c:3373 +#, c-format +msgid "column number %d is out of range 0..%d" +msgstr "სვეტების რაოდენობა %d ზღვარს (0..%d) გარეთაა" + +#: fe-exec.c:3388 +#, c-format +msgid "parameter number %d is out of range 0..%d" +msgstr "პარამეტრების რაოდენობა %d ზღვარს (0..%d) გარეთაა" + +#: fe-exec.c:3699 +#, c-format +msgid "could not interpret result from server: %s" +msgstr "სერვერის პასუხის გაურკვეველია: %s" + +#: fe-exec.c:3964 fe-exec.c:4054 +#, c-format +msgid "incomplete multibyte character" +msgstr "დაუსრულებელი მრავალბაიტიანი სიმბოლო" + +#: fe-gssapi-common.c:122 +msgid "GSSAPI name import error" +msgstr "GSSAPI-ის სახელის შემოტანის შეცდომა" + +#: fe-lobj.c:144 fe-lobj.c:207 fe-lobj.c:397 fe-lobj.c:487 fe-lobj.c:560 +#: fe-lobj.c:956 fe-lobj.c:963 fe-lobj.c:970 fe-lobj.c:977 fe-lobj.c:984 +#: fe-lobj.c:991 fe-lobj.c:998 fe-lobj.c:1005 +#, c-format +msgid "cannot determine OID of function %s" +msgstr "ფუნქციის OID-ის გამოცნობის შეცდომა: %s" + +#: fe-lobj.c:160 +#, c-format +msgid "argument of lo_truncate exceeds integer range" +msgstr "lo_truncate-ის არგუმენტიმთელი რიცხვის დასაშვებ საზღვრებს სცდება" + +#: fe-lobj.c:262 +#, c-format +msgid "argument of lo_read exceeds integer range" +msgstr "lo_read -ის არგუმენტიმთელი რიცხვის დასაშვებ საზღვრებს სცდება" + +#: fe-lobj.c:313 +#, c-format +msgid "argument of lo_write exceeds integer range" +msgstr "lo_write -ის არგუმენტიმთელი რიცხვის დასაშვებ საზღვრებს სცდება" + +#: fe-lobj.c:669 fe-lobj.c:780 +#, c-format +msgid "could not open file \"%s\": %s" +msgstr "ფაილის გახსნის შეცდომა \"%s\": %s" + +#: fe-lobj.c:725 +#, c-format +msgid "could not read from file \"%s\": %s" +msgstr "ფაილიდან (\"%s\") კითხვის შეცდომა: %s" + +#: fe-lobj.c:801 fe-lobj.c:824 +#, c-format +msgid "could not write to file \"%s\": %s" +msgstr "ფაილში (\"%s\") ჩაწერის შეცდომა: %s" + +#: fe-lobj.c:908 +#, c-format +msgid "query to initialize large object functions did not return data" +msgstr "დიდი ობიექტის ფუნქციების ინიციალიზაციის მოთხოვნას შედეგ არ დაუბრუნებია" + +#: fe-misc.c:240 +#, c-format +msgid "integer of size %lu not supported by pqGetInt" +msgstr "%lu-ის მთელი რიცხვის ზომა მხარდაუჭერელია pqGetInt-is მიერ" + +#: fe-misc.c:273 +#, c-format +msgid "integer of size %lu not supported by pqPutInt" +msgstr "%lu-ის მთელი რიცხვის ზომა მხარდაუჭერელია pqPutInt-is მიერ" + +#: fe-misc.c:573 +#, c-format +msgid "connection not open" +msgstr "შეერთება ღია არაა" + +#: fe-misc.c:751 fe-secure-openssl.c:215 fe-secure-openssl.c:315 +#: fe-secure.c:257 fe-secure.c:419 +#, c-format +msgid "" +"server closed the connection unexpectedly\n" +"\tThis probably means the server terminated abnormally\n" +"\tbefore or while processing the request." +msgstr "" +"სერვერმა კავშირი მოულოდნელად დახურა\n" +"\tეს დიდი ალბათობით ნიშნავს, რომ სერვერის პროცესი \n" +"\tმოულოდნელად, მოთხოვნამდე ან მოთხოვნის შესრულებსას დასრულდა." + +#: fe-misc.c:818 +msgid "connection not open\n" +msgstr "შეერთება ღია არაა\n" + +#: fe-misc.c:1003 +#, c-format +msgid "timeout expired" +msgstr "მოლოდინის დრო გავიდა" + +#: fe-misc.c:1047 +#, c-format +msgid "invalid socket" +msgstr "არასწორი სოკეტი" + +#: fe-misc.c:1069 +#, c-format +msgid "%s() failed: %s" +msgstr "%s()-ის შეცდომა: %s" + +#: fe-protocol3.c:182 +#, c-format +msgid "message type 0x%02x arrived from server while idle" +msgstr "შეტყობინების ტიპი 0x%02x მოვიდა სერვერიდან, როცა უქმე ვიყავი" + +#: fe-protocol3.c:385 +#, c-format +msgid "server sent data (\"D\" message) without prior row description (\"T\" message)" +msgstr "სერვერმა მონაცემები (\"D\" შეტყობინება) მწკრივების წინასწარი აღწერის (\"T\" შეტყობინება) გარეშე გამოაგზავნა" + +#: fe-protocol3.c:427 +#, c-format +msgid "unexpected response from server; first received character was \"%c\"" +msgstr "სერვერის მოულოდნელი პასუხი; პირველი მიღებული სიმბოლოა \"%c\"" + +#: fe-protocol3.c:450 +#, c-format +msgid "message contents do not agree with length in message type \"%c\"" +msgstr "შეტყობინების შიგთავსი შეტყობინების ამ ტიპის (%c) სიგრძეს არ ემთხვევა" + +#: fe-protocol3.c:468 +#, c-format +msgid "lost synchronization with server: got message type \"%c\", length %d" +msgstr "სერვერთან სინქრონიზაციის შეცდომა: შეტყობინების ტიპი: \"%c\", სიგრძე %d" + +#: fe-protocol3.c:520 fe-protocol3.c:560 +msgid "insufficient data in \"T\" message" +msgstr "არასაკმარისი მონაცემები \"T\" შეტყობინებაში" + +#: fe-protocol3.c:631 fe-protocol3.c:837 +msgid "out of memory for query result" +msgstr "არასაკმარისი მეხსიერება მოთხოვნის შედეგისთვის" + +#: fe-protocol3.c:700 +msgid "insufficient data in \"t\" message" +msgstr "არასაკმარისი მონაცემები \"t\" შეტყობინებაში" + +#: fe-protocol3.c:759 fe-protocol3.c:791 fe-protocol3.c:809 +msgid "insufficient data in \"D\" message" +msgstr "არასაკმარისი მონაცემები \"D\" შეტყობინებაში" + +#: fe-protocol3.c:765 +msgid "unexpected field count in \"D\" message" +msgstr "ველების მოულოდნელი რაოდენობა \"D\" შეტყობინებაში" + +#: fe-protocol3.c:1020 +msgid "no error message available\n" +msgstr "შეცდომის შეტყობინების გარეშე\n" + +#. translator: %s represents a digit string +#: fe-protocol3.c:1068 fe-protocol3.c:1087 +#, c-format +msgid " at character %s" +msgstr " სიმბოლოსთან %s" + +#: fe-protocol3.c:1100 +#, c-format +msgid "DETAIL: %s\n" +msgstr "დეტალი: %s\n" + +#: fe-protocol3.c:1103 +#, c-format +msgid "HINT: %s\n" +msgstr "მინიშნება: %s\n" + +#: fe-protocol3.c:1106 +#, c-format +msgid "QUERY: %s\n" +msgstr "მოთხოვნა: %s\n" + +#: fe-protocol3.c:1113 +#, c-format +msgid "CONTEXT: %s\n" +msgstr "კონტექსტი: %s\n" + +#: fe-protocol3.c:1122 +#, c-format +msgid "SCHEMA NAME: %s\n" +msgstr "სქემის სახელი: %s\n" + +#: fe-protocol3.c:1126 +#, c-format +msgid "TABLE NAME: %s\n" +msgstr "ცხრილის სახელი: %s\n" + +#: fe-protocol3.c:1130 +#, c-format +msgid "COLUMN NAME: %s\n" +msgstr "სვეტის სახელი: %s\n" + +#: fe-protocol3.c:1134 +#, c-format +msgid "DATATYPE NAME: %s\n" +msgstr "მონ. ტიპის სახელი: %s\n" + +#: fe-protocol3.c:1138 +#, c-format +msgid "CONSTRAINT NAME: %s\n" +msgstr "შეზღუდვის სახელი: %s\n" + +#: fe-protocol3.c:1150 +msgid "LOCATION: " +msgstr "მდებარეობა: " + +#: fe-protocol3.c:1152 +#, c-format +msgid "%s, " +msgstr "%s, " + +#: fe-protocol3.c:1154 +#, c-format +msgid "%s:%s" +msgstr "%s:%s" + +#: fe-protocol3.c:1349 +#, c-format +msgid "LINE %d: " +msgstr "ხაზი %d: " + +#: fe-protocol3.c:1423 +#, c-format +msgid "protocol version not supported by server: client uses %u.%u, server supports up to %u.%u" +msgstr "პროტოკოლის ვერსია სერვერის მიერ მხარდაჭერილი არაა: კლიენტი იყენებს %u.%u, სერვერის მხარდაჭერილი ვერსიის მაქსიმუმია %u.%u" + +#: fe-protocol3.c:1429 +#, c-format +msgid "protocol extension not supported by server: %s" +msgid_plural "protocol extensions not supported by server: %s" +msgstr[0] "პროტოკოლის გაფართოება სერვერის მიერ მხარდაჭერილი არაა: %s" +msgstr[1] "პროტოკოლის გაფართოებები სერვერის მიერ მხარდაჭერილი არაა: %s" + +#: fe-protocol3.c:1437 +#, c-format +msgid "invalid %s message" +msgstr "არასწორი %s შეტყობინება" + +#: fe-protocol3.c:1802 +#, c-format +msgid "PQgetline: not doing text COPY OUT" +msgstr "PQgetline: ტექსტის COPY OUT-ს არ გავაკეთებ" + +#: fe-protocol3.c:2176 +#, c-format +msgid "protocol error: no function result" +msgstr "პროტოკოლის შეცდომა: ფუნქციის შედეგის გარეშე" + +#: fe-protocol3.c:2187 +#, c-format +msgid "protocol error: id=0x%x" +msgstr "პროტოკოლის შეცდომა: id=0x%x" + +#: fe-secure-common.c:123 +#, c-format +msgid "SSL certificate's name contains embedded null" +msgstr "SSL სერტიფიკატი ჩადგმულ ნულოვანს შეიცავს" + +#: fe-secure-common.c:228 +#, c-format +msgid "certificate contains IP address with invalid length %zu" +msgstr "სერტიფიკატში მითითებული IP მისამართის სიგრძე არასწორია: %zu" + +#: fe-secure-common.c:237 +#, c-format +msgid "could not convert certificate's IP address to string: %s" +msgstr "სერტიფიკატის IP მისამართის სტრიქონად გარდაქმნის შეცდომა: %s" + +#: fe-secure-common.c:269 +#, c-format +msgid "host name must be specified for a verified SSL connection" +msgstr "შემოწმებულ SSL შეერთებაში ჰოსტის სახელის მითითება აუცილებელია" + +#: fe-secure-common.c:286 +#, c-format +msgid "server certificate for \"%s\" (and %d other name) does not match host name \"%s\"" +msgid_plural "server certificate for \"%s\" (and %d other names) does not match host name \"%s\"" +msgstr[0] "სერვერის სერტიფიკატი \"%s\"-თვის (და კიდევ %d სახელი) ჰოსტის სახელს (\"%s\") არ ემთხვევა" +msgstr[1] "სერვერის სერტიფიკატი \"%s\"-თვის (და კიდევ %d სახელი) ჰოსტის სახელს (\"%s\") არ ემთხვევა" + +#: fe-secure-common.c:294 +#, c-format +msgid "server certificate for \"%s\" does not match host name \"%s\"" +msgstr "სერვერის სერტიფიკატი \"%s\"-თვის ჰოსტის სახელს (\"%s\") არ ემთხვევა" + +#: fe-secure-common.c:299 +#, c-format +msgid "could not get server's host name from server certificate" +msgstr "სერვერის სერტიფიკატიდან ჰოსტის სახელის მიღების შეცდომა" + +#: fe-secure-gssapi.c:201 +msgid "GSSAPI wrap error" +msgstr "GSSAPI -ის გადატანის შეცდომა" + +#: fe-secure-gssapi.c:208 +#, c-format +msgid "outgoing GSSAPI message would not use confidentiality" +msgstr "გამავალი GSSAPI შეტყობინება კონფიდენციალობას ვერ იყენებს" + +#: fe-secure-gssapi.c:215 +#, c-format +msgid "client tried to send oversize GSSAPI packet (%zu > %zu)" +msgstr "კლიენტი ძალიან დიდი GSSAPI პაკეტების გაგზავნას ცდილობს (%zu > %zu)" + +#: fe-secure-gssapi.c:351 fe-secure-gssapi.c:593 +#, c-format +msgid "oversize GSSAPI packet sent by the server (%zu > %zu)" +msgstr "სერვერის მიერ გამოგზავნილი GSSAPI-ის პაკეტი ძალიან დიდია (%zu > %zu)" + +#: fe-secure-gssapi.c:390 +msgid "GSSAPI unwrap error" +msgstr "GSSAPI-ის გადატანის მოხსნის შეცდომა" + +#: fe-secure-gssapi.c:399 +#, c-format +msgid "incoming GSSAPI message did not use confidentiality" +msgstr "შემომავალი GSSAPI შეტყობინება კონფიდენციალობას ვერ იყენებს" + +#: fe-secure-gssapi.c:656 +msgid "could not initiate GSSAPI security context" +msgstr "'GSSAPI' უსაფრთხოების კონტექსტის დაწყების შეცდომა" + +#: fe-secure-gssapi.c:685 +msgid "GSSAPI size check error" +msgstr "GSSAPI-ის ზომის შემოწმების შეცდომა" + +#: fe-secure-gssapi.c:696 +msgid "GSSAPI context establishment error" +msgstr "GSSAPI-ის კონტექსტის დამყარებულობის შეცდომა" + +#: fe-secure-openssl.c:219 fe-secure-openssl.c:319 fe-secure-openssl.c:1531 +#, c-format +msgid "SSL SYSCALL error: %s" +msgstr "SSL SYSCALL-ის შეცდომა: %s" + +#: fe-secure-openssl.c:225 fe-secure-openssl.c:325 fe-secure-openssl.c:1534 +#, c-format +msgid "SSL SYSCALL error: EOF detected" +msgstr "SSL SYSCALL -ის შეცდომა: ნაპოვნია EOF" + +#: fe-secure-openssl.c:235 fe-secure-openssl.c:335 fe-secure-openssl.c:1542 +#, c-format +msgid "SSL error: %s" +msgstr "SSL-ის შეცდომა: %s" + +#: fe-secure-openssl.c:249 fe-secure-openssl.c:349 +#, c-format +msgid "SSL connection has been closed unexpectedly" +msgstr "SSL შეერთება მოულოდნელად დაიხურა" + +#: fe-secure-openssl.c:254 fe-secure-openssl.c:354 fe-secure-openssl.c:1589 +#, c-format +msgid "unrecognized SSL error code: %d" +msgstr "უცნობი SSL-ის შეცდომის კოდი: %d" + +#: fe-secure-openssl.c:397 +#, c-format +msgid "could not determine server certificate signature algorithm" +msgstr "სერვერის სერტიფიკატის ხელმოწერის ალგორითმის დადგენა შეუძლებელია" + +#: fe-secure-openssl.c:417 +#, c-format +msgid "could not find digest for NID %s" +msgstr "'NID'-ისთვის (%s) დაიჯესტის პოვნა შეუძლებელია" + +#: fe-secure-openssl.c:426 +#, c-format +msgid "could not generate peer certificate hash" +msgstr "პარტნიორის სერტიფიკატის ჰეშის გენერირების შეცდომა" + +#: fe-secure-openssl.c:509 +#, c-format +msgid "SSL certificate's name entry is missing" +msgstr "SSL სერტიფიკატის სახელის ჩანაწერი არ არსებობს" + +#: fe-secure-openssl.c:543 +#, c-format +msgid "SSL certificate's address entry is missing" +msgstr "SSL სერტიფიკატის მისამართის ჩანაწერი არ არსებობს" + +#: fe-secure-openssl.c:960 +#, c-format +msgid "could not create SSL context: %s" +msgstr "შეცდომა SSL კონტექსტის შექმნისას: %s" + +#: fe-secure-openssl.c:1002 +#, c-format +msgid "invalid value \"%s\" for minimum SSL protocol version" +msgstr "'SSL' პროტოკოლის ვერსიის არასწორი მინიმალური მნიშვნელობა: %s" + +#: fe-secure-openssl.c:1012 +#, c-format +msgid "could not set minimum SSL protocol version: %s" +msgstr "'SSL' პროტოკოლის ვერსიის მინიმალური მნიშვნელობის დაყენების შეცდომა: %s" + +#: fe-secure-openssl.c:1028 +#, c-format +msgid "invalid value \"%s\" for maximum SSL protocol version" +msgstr "'SSL' პროტოკოლის ვერსიის არასწორი მაქსიმალური მნიშვნელობა: %s" + +#: fe-secure-openssl.c:1038 +#, c-format +msgid "could not set maximum SSL protocol version: %s" +msgstr "'SSL' პროტოკოლის ვერსიის მაქსიმალური მნიშვნელობის დაყენების შეცდომა: %s" + +#: fe-secure-openssl.c:1076 +#, c-format +msgid "could not load system root certificate paths: %s" +msgstr "სისტემური root სერტიფიკატების ბილიკების ჩატვირთვის შეცდომა: %s" + +#: fe-secure-openssl.c:1093 +#, c-format +msgid "could not read root certificate file \"%s\": %s" +msgstr "root სერტიფიკატის ფაილის (\"%s\") წაკითხვის შეცდომა: %s" + +#: fe-secure-openssl.c:1145 +#, c-format +msgid "" +"could not get home directory to locate root certificate file\n" +"Either provide the file, use the system's trusted roots with sslrootcert=system, or change sslmode to disable server certificate verification." +msgstr "" +"root სერტიფიკატის ფაილის მოსაძებნად საწყისი საქაღალდის მიღება შეუძლებელია\n" +"ამ წარმოადგინეთ ფაილი, ან გამოიყენეთ სისტემის სანდო root-ები პარამეტრით sslrootcert=system, ან sslmode სერვერის სერტიფიკატის შემოწმება გამორთეთ." + +#: fe-secure-openssl.c:1148 +#, c-format +msgid "" +"root certificate file \"%s\" does not exist\n" +"Either provide the file, use the system's trusted roots with sslrootcert=system, or change sslmode to disable server certificate verification." +msgstr "" +"root სერტიფიკატის ფაილი \"%s\" არ არსებობს\n" +"წარმოადგინეთ ფაილი ან გამორთეთ sslmode სერვერის სერტიფიკატის შემოწმება." + +#: fe-secure-openssl.c:1183 +#, c-format +msgid "could not open certificate file \"%s\": %s" +msgstr "სერტიფიკატის ფაილის გახსნის შეცდომა \"%s\": %s" + +#: fe-secure-openssl.c:1201 +#, c-format +msgid "could not read certificate file \"%s\": %s" +msgstr "სერტიფიკატის ფაილის წაკითხვის შეცდომა \"%s\": %s" + +#: fe-secure-openssl.c:1225 +#, c-format +msgid "could not establish SSL connection: %s" +msgstr "'SSL' შეერთების დამყარების შეცდომა: %s" + +#: fe-secure-openssl.c:1257 +#, c-format +msgid "could not set SSL Server Name Indication (SNI): %s" +msgstr "'SSL' სერვერის სახელის ინდიკაციის (SNI) დაყენების შეცდომა: %s" + +#: fe-secure-openssl.c:1300 +#, c-format +msgid "could not load SSL engine \"%s\": %s" +msgstr "'SSL' ძრავის (\"%s\") ჩატვირთვის შეცდომა: %s" + +#: fe-secure-openssl.c:1311 +#, c-format +msgid "could not initialize SSL engine \"%s\": %s" +msgstr "'SSL' ძრავის (\"%s\") ინიციალიზაციის შეცდომა: %s" + +#: fe-secure-openssl.c:1326 +#, c-format +msgid "could not read private SSL key \"%s\" from engine \"%s\": %s" +msgstr "'SSL'-ის პირადი გასაღების (\"%s\") ძრავიდან (\"%s\") წაკითხვის შეცდომა: %s" + +#: fe-secure-openssl.c:1339 +#, c-format +msgid "could not load private SSL key \"%s\" from engine \"%s\": %s" +msgstr "'SSL'-ის პირადი გასაღების (\"%s\") ძრავიდან (\"%s\") წაკითხვის შეცდომა: %s" + +#: fe-secure-openssl.c:1376 +#, c-format +msgid "certificate present, but not private key file \"%s\"" +msgstr "სერტიფიკატისგან განსხვავებით, პირადი გასაღების ფაილი \"%s\" არ არსებობს" + +#: fe-secure-openssl.c:1379 +#, c-format +msgid "could not stat private key file \"%s\": %m" +msgstr "პირადი გასაღების ფაილი \"%s\" არ არსებობს: %m" + +#: fe-secure-openssl.c:1387 +#, c-format +msgid "private key file \"%s\" is not a regular file" +msgstr "პირადი გასაღების ფაილი \"%s\" ჩვეულებრივი ფაილი არაა" + +#: fe-secure-openssl.c:1420 +#, c-format +msgid "private key file \"%s\" has group or world access; file must have permissions u=rw (0600) or less if owned by the current user, or permissions u=rw,g=r (0640) or less if owned by root" +msgstr "პირადი გასაღების ფაილს \"%s\" აქვს ჯგუფური ან ყველა სხვაზე წვდომა; ფაილს უნდა ჰქონდეს ნებართვები u=rw (0600) ან ნაკლები, თუ ეკუთვნის ამჟამინდელ მომხმარებელს, ან ნებართვები u=rw,g=r (0640) ან ნაკლები, თუ ეკუთვნის root-ს" + +#: fe-secure-openssl.c:1444 +#, c-format +msgid "could not load private key file \"%s\": %s" +msgstr "პირადი გასაღების ფაილის \"%s\" ჩატვირთვის შეცდომა: %s" + +#: fe-secure-openssl.c:1460 +#, c-format +msgid "certificate does not match private key file \"%s\": %s" +msgstr "სერტიფიკატი პირადი გასაღების ფაილს (\"%s\") არ ემთხვევა: %s" + +#: fe-secure-openssl.c:1528 +#, c-format +msgid "SSL error: certificate verify failed: %s" +msgstr "SSL-ის შეცდომა: სერტიფიკატის გადამოწმების შეცდომა: %s" + +#: fe-secure-openssl.c:1573 +#, c-format +msgid "This may indicate that the server does not support any SSL protocol version between %s and %s." +msgstr "ეს შეიძლება ნიშნავდეს, რომ სერვერს SSL პროტოკოლის %s-სა და %s-ს შორის ვერსიების მხარდაჭერა არ გააჩნია." + +#: fe-secure-openssl.c:1606 +#, c-format +msgid "certificate could not be obtained: %s" +msgstr "სერტიფიკატის მიღების შეცდომა: %s" + +#: fe-secure-openssl.c:1711 +#, c-format +msgid "no SSL error reported" +msgstr "'SSL'-ის შეცდომების გარეშე" + +#: fe-secure-openssl.c:1720 +#, c-format +msgid "SSL error code %lu" +msgstr "SSL-ის შეცდომის კოდი %lu" + +#: fe-secure-openssl.c:1986 +#, c-format +msgid "WARNING: sslpassword truncated\n" +msgstr "გაფრთხილება: sslpasswrord შეკვეცილია\n" + +#: fe-secure.c:263 +#, c-format +msgid "could not receive data from server: %s" +msgstr "სერვერიდან მონაცემების მიღების შეცდომა: %s" + +#: fe-secure.c:434 +#, c-format +msgid "could not send data to server: %s" +msgstr "სერვერისთვის მონაცემების გაგზავნის შეცდომა: %s" + +#: win32.c:310 +#, c-format +msgid "unrecognized socket error: 0x%08X/%d" +msgstr "სოკეტის უცნობი შეცდომა: 0x%08X/%d" + +#, c-format +#~ msgid "%s(%s) failed: error code %d\n" +#~ msgstr "%s(%s) -ის შეცდომა: შეცდომის კოდი %d\n" + +#~ msgid "SCM_CRED authentication method not supported\n" +#~ msgstr "SCM_CRED ავთენტიკაციის მეთოდი მხარდაუჭერელია\n" + +#, c-format +#~ msgid "SSL error: %s\n" +#~ msgstr "SSL-ის შეცდომა: %s\n" + +#, c-format +#~ msgid "Unix-domain socket path \"%s\" is too long (maximum %d bytes)\n" +#~ msgstr "Unix-დომენის სოკეტის მისამართი \"%s\" ძალიან გრძელია (დასაშვებია %d ბაიტი)\n" + +#, c-format +#~ msgid "could not create SSL context: %s\n" +#~ msgstr "შეცდომა SSL კონტექსტის შექმნისას: %s\n" + +#, c-format +#~ msgid "could not load private key file \"%s\": %s\n" +#~ msgstr "პირადი გასაღების ფაილის \"%s\" ჩატვირთვის შეცდომა: %s\n" + +#, c-format +#~ msgid "could not open file \"%s\": %s\n" +#~ msgstr "ფაილის გახსნის შეცდომა \"%s\": %s\n" + +#~ msgid "incoming GSSAPI message did not use confidentiality\n" +#~ msgstr "შემომავალი GSSAPI შეტყობინება კონფიდენციალობას არ იყენებს\n" + +#, c-format +#~ msgid "invalid require_auth method: \"%s\"" +#~ msgstr "require_auth-ის არასწორი მეთოდი: \"%s\"" + +#~ msgid "outgoing GSSAPI message would not use confidentiality\n" +#~ msgstr "გამავალი GSSAPI შეტყობინება კონფიდენციალობას არ იყენებს\n" + +#, c-format +#~ msgid "private key file \"%s\" is not a regular file\n" +#~ msgstr "პირადი გასაღების ფაილი \"%s\" ჩვეულებრივი ფაილი არაა\n" + +#, c-format +#~ msgid "sslrootcert value \"%s\" invalid when SSL support is not compiled in" +#~ msgstr "sslmode-ის მნიშვნელობა \"%s\" არასწორია, როცა SSL-ის მხარდაჭერა გამორთული იყო აგების დროს" + +#, c-format +#~ msgid "unrecognized SSL error code: %d\n" +#~ msgstr "უცნობი SSL-ის შეცდომის კოდი: %d\n" + +#, c-format +#~ msgid "user name lookup failure: error code %lu\n" +#~ msgstr "მომხარებლის სახელის ამოხსნის პრობლემა: შეცდომის კოდი: %lu\n" diff --git a/src/interfaces/libpq/po/ko.po b/src/interfaces/libpq/po/ko.po new file mode 100644 index 0000000..e2cdc4e --- /dev/null +++ b/src/interfaces/libpq/po/ko.po @@ -0,0 +1,1537 @@ +# Korean message translation file for libpq +# Ioseph Kim. <ioseph@uri.sarang.net>, 2004. +# +msgid "" +msgstr "" +"Project-Id-Version: libpq (PostgreSQL) 16\n" +"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" +"POT-Creation-Date: 2023-09-07 05:40+0000\n" +"PO-Revision-Date: 2023-07-05 11:21+0900\n" +"Last-Translator: YOUR NAME <E-MAIL@ADDRESS>\n" +"Language-Team: Korean <pgsql-kr@postgresql.kr>\n" +"Language: ko\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: ../../port/thread.c:50 ../../port/thread.c:86 +#, c-format +msgid "could not look up local user ID %d: %s" +msgstr "UID %d 해당하는 로컬 사용자를 찾을 수 없음: %s" + +#: ../../port/thread.c:55 ../../port/thread.c:91 +#, c-format +msgid "local user with ID %d does not exist" +msgstr "ID %d 로컬 사용자 없음" + +#: fe-auth-scram.c:227 +#, c-format +msgid "malformed SCRAM message (empty message)" +msgstr "SCRAM 메시지가 형식에 안맞음 (메시지 비었음)" + +#: fe-auth-scram.c:232 +#, c-format +msgid "malformed SCRAM message (length mismatch)" +msgstr "SCRAM 메시지가 형식에 안맞음 (길이 불일치)" + +#: fe-auth-scram.c:275 +#, c-format +msgid "could not verify server signature: %s" +msgstr "서버 서명을 검사 할 수 없음: %s" + +#: fe-auth-scram.c:281 +#, c-format +msgid "incorrect server signature" +msgstr "잘못된 서버 서명" + +#: fe-auth-scram.c:290 +#, c-format +msgid "invalid SCRAM exchange state" +msgstr "SCRAM 교환 상태가 바르지 않음" + +#: fe-auth-scram.c:317 +#, c-format +msgid "malformed SCRAM message (attribute \"%c\" expected)" +msgstr "SCRAM 메시지가 형식에 안맞음 (\"%c\" 속성이 예상됨)" + +#: fe-auth-scram.c:326 +#, c-format +msgid "malformed SCRAM message (expected character \"=\" for attribute \"%c\")" +msgstr "SCRAM 메시지가 형식에 안맞음 (\"%c\" 속성 예상값은 \"=\")" + +#: fe-auth-scram.c:366 +#, c-format +msgid "could not generate nonce" +msgstr "암호화 토큰(nonce)을 만들 수 없음" + +#: fe-auth-scram.c:375 fe-auth-scram.c:448 fe-auth-scram.c:600 +#: fe-auth-scram.c:620 fe-auth-scram.c:644 fe-auth-scram.c:658 +#: fe-auth-scram.c:704 fe-auth-scram.c:740 fe-auth-scram.c:914 fe-auth.c:296 +#: fe-auth.c:369 fe-auth.c:403 fe-auth.c:618 fe-auth.c:729 fe-auth.c:1210 +#: fe-auth.c:1375 fe-connect.c:925 fe-connect.c:1759 fe-connect.c:1921 +#: fe-connect.c:3291 fe-connect.c:4496 fe-connect.c:5161 fe-connect.c:5416 +#: fe-connect.c:5534 fe-connect.c:5781 fe-connect.c:5861 fe-connect.c:5959 +#: fe-connect.c:6210 fe-connect.c:6237 fe-connect.c:6313 fe-connect.c:6336 +#: fe-connect.c:6360 fe-connect.c:6395 fe-connect.c:6481 fe-connect.c:6489 +#: fe-connect.c:6846 fe-connect.c:6996 fe-exec.c:527 fe-exec.c:1321 +#: fe-exec.c:3111 fe-exec.c:4071 fe-exec.c:4235 fe-gssapi-common.c:109 +#: fe-lobj.c:870 fe-protocol3.c:204 fe-protocol3.c:228 fe-protocol3.c:256 +#: fe-protocol3.c:273 fe-protocol3.c:353 fe-protocol3.c:720 fe-protocol3.c:959 +#: fe-protocol3.c:1770 fe-protocol3.c:2170 fe-secure-common.c:110 +#: fe-secure-gssapi.c:500 fe-secure-openssl.c:434 fe-secure-openssl.c:1285 +#, c-format +msgid "out of memory" +msgstr "메모리 부족" + +#: fe-auth-scram.c:382 +#, c-format +msgid "could not encode nonce" +msgstr "암호화 토큰(nonce)을 인코딩할 수 없음" + +#: fe-auth-scram.c:570 +#, c-format +msgid "could not calculate client proof: %s" +msgstr "클라이언트 프루프(proof)를 계산할 수 없음: %s" + +#: fe-auth-scram.c:585 +#, c-format +msgid "could not encode client proof" +msgstr "클라이언트 프루프(proof)를 인코딩할 수 없음" + +#: fe-auth-scram.c:637 +#, c-format +msgid "invalid SCRAM response (nonce mismatch)" +msgstr "잘못된 SCRAM 응답 (토큰 불일치)" + +#: fe-auth-scram.c:667 +#, c-format +msgid "malformed SCRAM message (invalid salt)" +msgstr "형식에 맞지 않은 SCRAM 메시지 (잘못된 소금 salt)" + +#: fe-auth-scram.c:680 +#, c-format +msgid "malformed SCRAM message (invalid iteration count)" +msgstr "형식에 맞지 않은 SCRAM 메시지 (나열 숫자가 이상함)" + +#: fe-auth-scram.c:685 +#, c-format +msgid "malformed SCRAM message (garbage at end of server-first-message)" +msgstr "" +"형식에 맞지 않은 SCRAM 메시지 (서버 첫 메시지 끝에 쓸모 없는 값이 있음)" + +#: fe-auth-scram.c:719 +#, c-format +msgid "error received from server in SCRAM exchange: %s" +msgstr "SCRAM 교환작업에서 서버로부터 데이터를 받지 못했음: %s" + +#: fe-auth-scram.c:734 +#, c-format +msgid "malformed SCRAM message (garbage at end of server-final-message)" +msgstr "" +"형식에 맞지 않은 SCRAM 메시지 (서버 끝 메시지 뒤에 쓸모 없는 값이 있음)" + +#: fe-auth-scram.c:751 +#, c-format +msgid "malformed SCRAM message (invalid server signature)" +msgstr "형식에 맞지 않은 SCRAM 메시지 (서버 서명이 이상함)" + +#: fe-auth-scram.c:923 +msgid "could not generate random salt" +msgstr "무작위 솔트 생성 실패" + +#: fe-auth.c:77 +#, c-format +msgid "out of memory allocating GSSAPI buffer (%d)" +msgstr "GSSAPI 버퍼(%d)에 할당할 메모리 부족" + +#: fe-auth.c:138 +msgid "GSSAPI continuation error" +msgstr "GSSAPI 연속 오류" + +#: fe-auth.c:168 fe-auth.c:397 fe-gssapi-common.c:97 fe-secure-common.c:99 +#: fe-secure-common.c:173 +#, c-format +msgid "host name must be specified" +msgstr "호스트 이름을 지정해야 함" + +#: fe-auth.c:174 +#, c-format +msgid "duplicate GSS authentication request" +msgstr "중복된 GSS 인증 요청" + +#: fe-auth.c:238 +#, c-format +msgid "out of memory allocating SSPI buffer (%d)" +msgstr "SSPI 버퍼(%d)에 할당할 메모리 부족" + +#: fe-auth.c:285 +msgid "SSPI continuation error" +msgstr "SSPI 연속 오류" + +#: fe-auth.c:359 +#, c-format +msgid "duplicate SSPI authentication request" +msgstr "중복된 SSPI 인증 요청" + +#: fe-auth.c:384 +msgid "could not acquire SSPI credentials" +msgstr "SSPI 자격 증명을 가져올 수 없음" + +#: fe-auth.c:437 +#, c-format +msgid "channel binding required, but SSL not in use" +msgstr "채널 바인딩이 필요한데, SSL 기능이 꺼져있음" + +#: fe-auth.c:443 +#, c-format +msgid "duplicate SASL authentication request" +msgstr "중복된 SASL 인증 요청" + +#: fe-auth.c:501 +#, c-format +msgid "channel binding is required, but client does not support it" +msgstr "채널 바인딩이 필요한데, 클라이언트에서 지원하지 않음" + +#: fe-auth.c:517 +#, c-format +msgid "" +"server offered SCRAM-SHA-256-PLUS authentication over a non-SSL connection" +msgstr "서버는 non-SSL 접속으로 SCRAM-SHA-256-PLUS 인증을 제공함" + +#: fe-auth.c:531 +#, c-format +msgid "none of the server's SASL authentication mechanisms are supported" +msgstr "SASL 인증 메커니즘을 지원하는 서버가 없습니다." + +#: fe-auth.c:538 +#, c-format +msgid "" +"channel binding is required, but server did not offer an authentication " +"method that supports channel binding" +msgstr "" +"채널 바인딩 기능을 사용하도록 지정했지만, 서버가 이 기능을 지원하지 않음" + +#: fe-auth.c:641 +#, c-format +msgid "out of memory allocating SASL buffer (%d)" +msgstr "SASL 버퍼(%d)에 할당할 메모리 부족" + +#: fe-auth.c:665 +#, c-format +msgid "" +"AuthenticationSASLFinal received from server, but SASL authentication was " +"not completed" +msgstr "" +"서버에서 AuthenticationSASLFinal 응답을 받았지만, SASL 인증이 끝나지 않았음" + +#: fe-auth.c:675 +#, c-format +msgid "no client response found after SASL exchange success" +msgstr "SASL 교환 성공 후 클라이언트 반응 없음" + +#: fe-auth.c:738 fe-auth.c:745 fe-auth.c:1358 fe-auth.c:1369 +#, c-format +msgid "could not encrypt password: %s" +msgstr "비밀번호를 암호화 할 수 없음: %s" + +#: fe-auth.c:773 +msgid "server requested a cleartext password" +msgstr "서버가 평문 비밀번호를 요청했음" + +#: fe-auth.c:775 +msgid "server requested a hashed password" +msgstr "서버가 해시된 비밀번호를 요청했음" + +#: fe-auth.c:778 +msgid "server requested GSSAPI authentication" +msgstr "서버가 GSSAPI 인증을 요청했음" + +#: fe-auth.c:780 +msgid "server requested SSPI authentication" +msgstr "서버가 SSPI 인증을 요청했음" + +#: fe-auth.c:784 +msgid "server requested SASL authentication" +msgstr "서버가 SASL 인증을 요청했음" + +#: fe-auth.c:787 +msgid "server requested an unknown authentication type" +msgstr "서버가 알 수 없는 인증 형식을 요청했음" + +#: fe-auth.c:820 +#, c-format +msgid "server did not request an SSL certificate" +msgstr "서버가 SSL 인증서를 요청하지 않았음" + +#: fe-auth.c:825 +#, c-format +msgid "server accepted connection without a valid SSL certificate" +msgstr "서버가 SSL 인증서 유효성 검사 없이 접속을 허용했음" + +#: fe-auth.c:879 +msgid "server did not complete authentication" +msgstr "서버가 인증 절차를 완료하지 못했음" + +#: fe-auth.c:913 +#, c-format +msgid "authentication method requirement \"%s\" failed: %s" +msgstr "\"%s\" 인증 방법 요구 사항 실패: %s" + +#: fe-auth.c:936 +#, c-format +msgid "" +"channel binding required, but server authenticated client without channel " +"binding" +msgstr "채널 바인딩이 필요한데, 서버가 체널 바인딩 없이 클라이언트를 인증함" + +#: fe-auth.c:941 +#, c-format +msgid "" +"channel binding required but not supported by server's authentication request" +msgstr "채널 바인딩이 필요한데, 서버 인증 요청에서 지원하지 않음" + +#: fe-auth.c:975 +#, c-format +msgid "Kerberos 4 authentication not supported" +msgstr "Kerberos 4 인증 방법이 지원되지 않음" + +#: fe-auth.c:979 +#, c-format +msgid "Kerberos 5 authentication not supported" +msgstr "Kerberos 5 인증 방법이 지원되지 않음" + +#: fe-auth.c:1049 +#, c-format +msgid "GSSAPI authentication not supported" +msgstr "GSSAPI 인증은 지원되지 않음" + +#: fe-auth.c:1080 +#, c-format +msgid "SSPI authentication not supported" +msgstr "SSPI 인증은 지원되지 않음" + +#: fe-auth.c:1087 +#, c-format +msgid "Crypt authentication not supported" +msgstr "crypt 인증은 지원되지 않음" + +#: fe-auth.c:1151 +#, c-format +msgid "authentication method %u not supported" +msgstr "%u 인증 방법이 지원되지 않음" + +#: fe-auth.c:1197 +#, c-format +msgid "user name lookup failure: error code %lu" +msgstr "사용자 이름 찾기 실패: 오류 코드 %lu" + +#: fe-auth.c:1321 +#, c-format +msgid "unexpected shape of result set returned for SHOW" +msgstr "SHOW 명령의 결과 자료가 비정상임" + +#: fe-auth.c:1329 +#, c-format +msgid "password_encryption value too long" +msgstr "password_encryption 너무 긺" + +#: fe-auth.c:1379 +#, c-format +msgid "unrecognized password encryption algorithm \"%s\"" +msgstr "알 수 없는 비밀번호 암호화 알고리즘: \"%s\"" + +#: fe-connect.c:1132 +#, c-format +msgid "could not match %d host names to %d hostaddr values" +msgstr "호스트 이름은 %d개인데, 호스트 주소는 %d개임" + +#: fe-connect.c:1212 +#, c-format +msgid "could not match %d port numbers to %d hosts" +msgstr "포트 번호는 %d개인데, 호스트는 %d개입니다." + +#: fe-connect.c:1337 +#, c-format +msgid "" +"negative require_auth method \"%s\" cannot be mixed with non-negative methods" +msgstr "" +"\"%s\" negative require_auth 방법은 non-negative 방법과 함께 쓸 수 없음" + +#: fe-connect.c:1350 +#, c-format +msgid "require_auth method \"%s\" cannot be mixed with negative methods" +msgstr "\"%s\" require_auth 방법은 negative 방법과 함께 쓸 수 없음" + +#: fe-connect.c:1410 fe-connect.c:1461 fe-connect.c:1503 fe-connect.c:1559 +#: fe-connect.c:1567 fe-connect.c:1598 fe-connect.c:1644 fe-connect.c:1684 +#: fe-connect.c:1705 +#, c-format +msgid "invalid %s value: \"%s\"" +msgstr "잘못된 %s 값: \"%s\"" + +#: fe-connect.c:1443 +#, c-format +msgid "require_auth method \"%s\" is specified more than once" +msgstr "\"%s\" require_auth 방법을 한 번 이상 지정했음" + +#: fe-connect.c:1484 fe-connect.c:1523 fe-connect.c:1606 +#, c-format +msgid "%s value \"%s\" invalid when SSL support is not compiled in" +msgstr "" +"SSL 연결 기능을 지원하지 않고 컴파일 된 경우는 %s 값으로 \"%s\" 값은 타당치 " +"않습니다." + +#: fe-connect.c:1546 +#, c-format +msgid "" +"weak sslmode \"%s\" may not be used with sslrootcert=system (use \"verify-" +"full\")" +msgstr "" +"\"%s\" 엄격하지 않은 sslmode 설정일 때는 sslrootcert=system 설정을 할 수 없" +"음 (\"verify-full\" 설정을 사용하세요)" + +#: fe-connect.c:1584 +#, c-format +msgid "invalid SSL protocol version range" +msgstr "잘못된 SSL 프로토콜 버전 범위" + +#: fe-connect.c:1621 +#, c-format +msgid "%s value \"%s\" is not supported (check OpenSSL version)" +msgstr "%s 설정 \"%s\" 값은 지원하지 않음 (OpenSSL 버전을 확인하세요)" + +#: fe-connect.c:1651 +#, c-format +msgid "gssencmode value \"%s\" invalid when GSSAPI support is not compiled in" +msgstr "" +"GSSAPI 접속을 지원하지 않는 서버에서는 gssencmode 값(\"%s\")이 적당하지 않음" + +#: fe-connect.c:1944 +#, c-format +msgid "could not set socket to TCP no delay mode: %s" +msgstr "소켓을 TCP에 no delay 모드로 지정할 수 없음: %s" + +#: fe-connect.c:2003 +#, c-format +msgid "connection to server on socket \"%s\" failed: " +msgstr "\"%s\" 소켓으로 서버 접속 할 수 없음: " + +#: fe-connect.c:2029 +#, c-format +msgid "connection to server at \"%s\" (%s), port %s failed: " +msgstr "\"%s\" (%s), %s 포트로 서버 접속 할 수 없음: " + +#: fe-connect.c:2034 +#, c-format +msgid "connection to server at \"%s\", port %s failed: " +msgstr "\"%s\" 포트 %s 서버에 접속 할 수 없음: " + +#: fe-connect.c:2057 +#, c-format +msgid "" +"\tIs the server running locally and accepting connections on that socket?" +msgstr "" +"\t로컬 연결을 시도 중이고, 유닉스 도메인 소켓 접속을 허용하는지 확인하세요." + +#: fe-connect.c:2059 +#, c-format +msgid "\tIs the server running on that host and accepting TCP/IP connections?" +msgstr "" +"\t해당 호스트에 서버가 실행 중이고, TCP/IP 접속을 허용하는지 확인하세요." + +#: fe-connect.c:2122 +#, c-format +msgid "invalid integer value \"%s\" for connection option \"%s\"" +msgstr "잘못된 정수값: \"%s\", 해당 연결 옵션: \"%s\"" + +#: fe-connect.c:2151 fe-connect.c:2185 fe-connect.c:2220 fe-connect.c:2318 +#: fe-connect.c:2973 +#, c-format +msgid "%s(%s) failed: %s" +msgstr "%s(%s) 실패: %s" + +#: fe-connect.c:2284 +#, c-format +msgid "%s(%s) failed: error code %d" +msgstr "%s(%s) 실패: 오류 코드 %d" + +#: fe-connect.c:2597 +#, c-format +msgid "invalid connection state, probably indicative of memory corruption" +msgstr "잘못된 연결 상태, 메모리 손상일 가능성이 큼" + +#: fe-connect.c:2676 +#, c-format +msgid "invalid port number: \"%s\"" +msgstr "잘못된 포트 번호: \"%s\"" + +#: fe-connect.c:2690 +#, c-format +msgid "could not translate host name \"%s\" to address: %s" +msgstr "\"%s\" 호스트 이름 IP 주소로 바꿀 수 없음: %s" + +#: fe-connect.c:2702 +#, c-format +msgid "could not parse network address \"%s\": %s" +msgstr "\"%s\" 네트워크 주소를 해석할 수 없음: %s" + +#: fe-connect.c:2713 +#, c-format +msgid "Unix-domain socket path \"%s\" is too long (maximum %d bytes)" +msgstr "\"%s\" 유닉스 도메인 소켓 경로가 너무 깁니다 (최대 %d 바이트)" + +#: fe-connect.c:2727 +#, c-format +msgid "could not translate Unix-domain socket path \"%s\" to address: %s" +msgstr "\"%s\" 유닉스 도메인 소켓 경로를 주소로 바꿀 수 없음: %s" + +#: fe-connect.c:2901 +#, c-format +msgid "could not create socket: %s" +msgstr "소켓을 만들 수 없음: %s" + +#: fe-connect.c:2932 +#, c-format +msgid "could not set socket to nonblocking mode: %s" +msgstr "소켓을 nonblocking 모드로 지정할 수 없음: %s" + +#: fe-connect.c:2943 +#, c-format +msgid "could not set socket to close-on-exec mode: %s" +msgstr "소켓을 close-on-exec 모드로 지정할 수 없음: %s" + +#: fe-connect.c:2961 +#, c-format +msgid "keepalives parameter must be an integer" +msgstr "keepalives 매개변수값은 정수여야 합니다." + +#: fe-connect.c:3100 +#, c-format +msgid "could not get socket error status: %s" +msgstr "소켓 오류 상태를 구할 수 없음: %s" + +#: fe-connect.c:3127 +#, c-format +msgid "could not get client address from socket: %s" +msgstr "소켓에서 클라이언트 주소를 구할 수 없음: %s" + +#: fe-connect.c:3165 +#, c-format +msgid "requirepeer parameter is not supported on this platform" +msgstr "requirepeer 매개변수는 이 운영체제에서 지원하지 않음" + +#: fe-connect.c:3167 +#, c-format +msgid "could not get peer credentials: %s" +msgstr "신뢰성 피어를 얻을 수 없습니다: %s" + +#: fe-connect.c:3180 +#, c-format +msgid "requirepeer specifies \"%s\", but actual peer user name is \"%s\"" +msgstr "" +"\"%s\" 이름으로 requirepeer를 지정했지만, 실재 사용자 이름은 \"%s\" 입니다." + +#: fe-connect.c:3221 +#, c-format +msgid "could not send GSSAPI negotiation packet: %s" +msgstr "GSSAPI 교섭 패킷을 보낼 수 없음: %s" + +#: fe-connect.c:3233 +#, c-format +msgid "" +"GSSAPI encryption required but was impossible (possibly no credential cache, " +"no server support, or using a local socket)" +msgstr "" +"GSSAPI 암호화가 필요하지만 사용할 수 없음 (자격 증명 캐시가 없거나, 서버가 지" +"원하지 않거나, 로컬 소켓을 사용하고 있는 듯합니다.)" + +#: fe-connect.c:3274 +#, c-format +msgid "could not send SSL negotiation packet: %s" +msgstr "SSL 교섭 패킷을 보낼 수 없음: %s" + +#: fe-connect.c:3303 +#, c-format +msgid "could not send startup packet: %s" +msgstr "시작 패킷을 보낼 수 없음: %s" + +#: fe-connect.c:3378 +#, c-format +msgid "server does not support SSL, but SSL was required" +msgstr "서버가 SSL 기능을 지원하지 않는데, SSL 기능을 요구했음" + +#: fe-connect.c:3404 +#, c-format +msgid "received invalid response to SSL negotiation: %c" +msgstr "SSL 교섭에 대한 잘못된 응답을 감지했음: %c" + +#: fe-connect.c:3424 +#, c-format +msgid "received unencrypted data after SSL response" +msgstr "SSL 응답 후에 비암호화 데이터를 받았음" + +#: fe-connect.c:3504 +#, c-format +msgid "server doesn't support GSSAPI encryption, but it was required" +msgstr "서버가 GSSAPI 암호화 기능을 지원하지 않는데, 이것이 필요함" + +#: fe-connect.c:3515 +#, c-format +msgid "received invalid response to GSSAPI negotiation: %c" +msgstr "GSSAPI 교섭에 대한 잘못된 응답을 감지했음: %c" + +#: fe-connect.c:3533 +#, c-format +msgid "received unencrypted data after GSSAPI encryption response" +msgstr "GSSAPI 암호화 응답 후 비암호화 데이터 받았음" + +#: fe-connect.c:3598 +#, c-format +msgid "expected authentication request from server, but received %c" +msgstr "서버가 인증을 요구했지만, %c 받았음" + +#: fe-connect.c:3625 fe-connect.c:3794 +#, c-format +msgid "received invalid authentication request" +msgstr "잘못된 인증 요청을 받았음" + +#: fe-connect.c:3630 fe-connect.c:3779 +#, c-format +msgid "received invalid protocol negotiation message" +msgstr "잘못된 프로토콜 교섭 메시지를 받았음" + +#: fe-connect.c:3648 fe-connect.c:3702 +#, c-format +msgid "received invalid error message" +msgstr "잘못된 오류 메시지를 받았음" + +#: fe-connect.c:3865 +#, c-format +msgid "unexpected message from server during startup" +msgstr "시작하는 동안 서버로부터 기대되지 않는 메시지" + +#: fe-connect.c:3956 +#, c-format +msgid "session is read-only" +msgstr "세션이 읽기 전용임" + +#: fe-connect.c:3958 +#, c-format +msgid "session is not read-only" +msgstr "세션이 읽기 전용이 아님" + +#: fe-connect.c:4011 +#, c-format +msgid "server is in hot standby mode" +msgstr "서버가 hot standby 모드 상태임" + +#: fe-connect.c:4013 +#, c-format +msgid "server is not in hot standby mode" +msgstr "서버가 hot standby 모드 상태가 아님" + +#: fe-connect.c:4129 fe-connect.c:4179 +#, c-format +msgid "\"%s\" failed" +msgstr "\"%s\" 실패" + +#: fe-connect.c:4193 +#, c-format +msgid "invalid connection state %d, probably indicative of memory corruption" +msgstr "잘못된 연결 상태 %d, 메모리 손상일 가능성이 큼" + +#: fe-connect.c:5174 +#, c-format +msgid "invalid LDAP URL \"%s\": scheme must be ldap://" +msgstr "잘못된 LDAP URL \"%s\": 스키마는 ldap:// 여야함" + +#: fe-connect.c:5189 +#, c-format +msgid "invalid LDAP URL \"%s\": missing distinguished name" +msgstr "잘못된 LDAP URL \"%s\": 식별자 이름이 빠졌음" + +#: fe-connect.c:5201 fe-connect.c:5259 +#, c-format +msgid "invalid LDAP URL \"%s\": must have exactly one attribute" +msgstr "잘못된 LDAP URL \"%s\": 단 하나의 속성만 가져야함" + +#: fe-connect.c:5213 fe-connect.c:5275 +#, c-format +msgid "invalid LDAP URL \"%s\": must have search scope (base/one/sub)" +msgstr "잘못된 LDAP URL \"%s\": 검색범위(base/one/sub)를 지정해야함" + +#: fe-connect.c:5225 +#, c-format +msgid "invalid LDAP URL \"%s\": no filter" +msgstr "잘못된 LDAP URL \"%s\": 필터 없음" + +#: fe-connect.c:5247 +#, c-format +msgid "invalid LDAP URL \"%s\": invalid port number" +msgstr "잘못된 LDAP URL \"%s\": 포트번호가 잘못됨" + +#: fe-connect.c:5284 +#, c-format +msgid "could not create LDAP structure" +msgstr "LDAP 구조를 만들 수 없음" + +#: fe-connect.c:5359 +#, c-format +msgid "lookup on LDAP server failed: %s" +msgstr "LDAP 서버를 찾을 수 없음: %s" + +#: fe-connect.c:5369 +#, c-format +msgid "more than one entry found on LDAP lookup" +msgstr "LDAP 검색에서 하나 이상의 엔트리가 발견되었음" + +#: fe-connect.c:5371 fe-connect.c:5382 +#, c-format +msgid "no entry found on LDAP lookup" +msgstr "LDAP 검색에서 해당 항목 없음" + +#: fe-connect.c:5392 fe-connect.c:5404 +#, c-format +msgid "attribute has no values on LDAP lookup" +msgstr "LDAP 검색에서 속성의 값이 없음" + +#: fe-connect.c:5455 fe-connect.c:5474 fe-connect.c:5998 +#, c-format +msgid "missing \"=\" after \"%s\" in connection info string" +msgstr "연결문자열에서 \"%s\" 다음에 \"=\" 문자 빠졌음" + +#: fe-connect.c:5545 fe-connect.c:6181 fe-connect.c:6979 +#, c-format +msgid "invalid connection option \"%s\"" +msgstr "잘못된 연결 옵션 \"%s\"" + +#: fe-connect.c:5560 fe-connect.c:6046 +#, c-format +msgid "unterminated quoted string in connection info string" +msgstr "연결문자열에서 완성되지 못한 따옴표문자열이 있음" + +#: fe-connect.c:5640 +#, c-format +msgid "definition of service \"%s\" not found" +msgstr "\"%s\" 서비스 정의를 찾을 수 없음" + +#: fe-connect.c:5666 +#, c-format +msgid "service file \"%s\" not found" +msgstr "\"%s\" 서비스 파일을 찾을 수 없음" + +#: fe-connect.c:5679 +#, c-format +msgid "line %d too long in service file \"%s\"" +msgstr "%d번째 줄이 \"%s\" 서비스 파일에서 너무 깁니다" + +#: fe-connect.c:5750 fe-connect.c:5793 +#, c-format +msgid "syntax error in service file \"%s\", line %d" +msgstr "\"%s\" 서비스 파일의 %d번째 줄에 구문 오류 있음" + +#: fe-connect.c:5761 +#, c-format +msgid "" +"nested service specifications not supported in service file \"%s\", line %d" +msgstr "\"%s\" 서비스 파일의 %d번째 줄에 설정을 지원하지 않음" + +#: fe-connect.c:6500 +#, c-format +msgid "invalid URI propagated to internal parser routine: \"%s\"" +msgstr "URI 구문 분석을 할 수 없음: \"%s\"" + +#: fe-connect.c:6577 +#, c-format +msgid "" +"end of string reached when looking for matching \"]\" in IPv6 host address " +"in URI: \"%s\"" +msgstr "" +"URI의 IPv6 호스트 주소에서 \"]\" 매칭 검색을 실패했습니다, 해당 URI: \"%s\"" + +#: fe-connect.c:6584 +#, c-format +msgid "IPv6 host address may not be empty in URI: \"%s\"" +msgstr "IPv6 호스트 주소가 없습니다, 해당 URI: \"%s\"" + +#: fe-connect.c:6599 +#, c-format +msgid "" +"unexpected character \"%c\" at position %d in URI (expected \":\" or \"/\"): " +"\"%s\"" +msgstr "" +"잘못된 \"%c\" 문자가 URI 문자열 가운데 %d 번째 있습니다(\":\" 또는 \"/\" 문자" +"가 있어야 함): \"%s\"" + +#: fe-connect.c:6728 +#, c-format +msgid "extra key/value separator \"=\" in URI query parameter: \"%s\"" +msgstr "" +"키/밸류 구분자 \"=\" 문자가 필요 이상 더 있음, 해당 URI 쿼리 매개변수: \"%s\"" + +#: fe-connect.c:6748 +#, c-format +msgid "missing key/value separator \"=\" in URI query parameter: \"%s\"" +msgstr "키/밸류 구분자 \"=\" 문자가 필요함, 해당 URI 쿼리 매개변수: \"%s\"" + +#: fe-connect.c:6800 +#, c-format +msgid "invalid URI query parameter: \"%s\"" +msgstr "잘못된 URL 쿼리 매개변수값: \"%s\"" + +#: fe-connect.c:6874 +#, c-format +msgid "invalid percent-encoded token: \"%s\"" +msgstr "잘못된 퍼센트 인코드 토큰: \"%s\"" + +#: fe-connect.c:6884 +#, c-format +msgid "forbidden value %%00 in percent-encoded value: \"%s\"" +msgstr "퍼센트 인코드 값에 %%00 숨김 값이 있음: \"%s\"" + +#: fe-connect.c:7248 +msgid "connection pointer is NULL\n" +msgstr "연결 포인터가 NULL\n" + +#: fe-connect.c:7256 fe-exec.c:710 fe-exec.c:970 fe-exec.c:3292 +#: fe-protocol3.c:974 fe-protocol3.c:1007 +msgid "out of memory\n" +msgstr "메모리 부족\n" + +#: fe-connect.c:7547 +#, c-format +msgid "WARNING: password file \"%s\" is not a plain file\n" +msgstr "경고: \"%s\" 패스워드 파일이 plain 파일이 아님\n" + +#: fe-connect.c:7556 +#, c-format +msgid "" +"WARNING: password file \"%s\" has group or world access; permissions should " +"be u=rw (0600) or less\n" +msgstr "" +"경고: 패스워드 파일 \"%s\"에 그룹 또는 범용 액세스 권한이 있습니다. 권한은 " +"u=rw(0600) 이하여야 합니다.\n" + +#: fe-connect.c:7663 +#, c-format +msgid "password retrieved from file \"%s\"" +msgstr "\"%s\" 파일에서 암호를 찾을 수 없음" + +#: fe-exec.c:466 fe-exec.c:3366 +#, c-format +msgid "row number %d is out of range 0..%d" +msgstr "%d 번째 행(row)은 0..%d 범위를 벗어났음" + +#: fe-exec.c:528 fe-protocol3.c:1976 +#, c-format +msgid "%s" +msgstr "%s" + +#: fe-exec.c:831 +#, c-format +msgid "write to server failed" +msgstr "서버에 쓰기 실패" + +#: fe-exec.c:869 +#, c-format +msgid "no error text available" +msgstr "보여줄 오류 메시지가 없음" + +#: fe-exec.c:958 +msgid "NOTICE" +msgstr "알림" + +#: fe-exec.c:1016 +msgid "PGresult cannot support more than INT_MAX tuples" +msgstr "PGresult 함수는 INT_MAX 튜플보다 많은 경우를 지원하지 않음" + +#: fe-exec.c:1028 +msgid "size_t overflow" +msgstr "size_t 초과" + +#: fe-exec.c:1444 fe-exec.c:1513 fe-exec.c:1559 +#, c-format +msgid "command string is a null pointer" +msgstr "명령 문자열이 null 포인터" + +#: fe-exec.c:1450 fe-exec.c:2888 +#, c-format +msgid "%s not allowed in pipeline mode" +msgstr "파이프라인 모드에서는 %s 사용할 수 없음" + +#: fe-exec.c:1518 fe-exec.c:1564 fe-exec.c:1658 +#, c-format +msgid "number of parameters must be between 0 and %d" +msgstr "매개변수값으로 숫자는 0에서 %d까지만 쓸 수 있음" + +#: fe-exec.c:1554 fe-exec.c:1653 +#, c-format +msgid "statement name is a null pointer" +msgstr "실행 구문 이름이 null 포인트(값이 없음)입니다" + +#: fe-exec.c:1695 fe-exec.c:3220 +#, c-format +msgid "no connection to the server" +msgstr "서버에 대한 연결이 없음" + +#: fe-exec.c:1703 fe-exec.c:3228 +#, c-format +msgid "another command is already in progress" +msgstr "처리 중에 이미 다른 명령이 존재함" + +#: fe-exec.c:1733 +#, c-format +msgid "cannot queue commands during COPY" +msgstr "COPY 작업 중 명령들을 큐에 담을 수 없음" + +#: fe-exec.c:1850 +#, c-format +msgid "length must be given for binary parameter" +msgstr "바이너리 자료 매개 변수를 사용할 때는 그 길이를 지정해야 함" + +#: fe-exec.c:2171 +#, c-format +msgid "unexpected asyncStatus: %d" +msgstr "기대되지 않은 asyncStatus: %d" + +#: fe-exec.c:2327 +#, c-format +msgid "" +"synchronous command execution functions are not allowed in pipeline mode" +msgstr "파이프라인 모드에서는 동기식 명령 실행 함수는 사용할 수 없음" + +#: fe-exec.c:2344 +msgid "COPY terminated by new PQexec" +msgstr "새 PQexec 호출로 COPY 작업이 중지 되었습니다" + +#: fe-exec.c:2360 +#, c-format +msgid "PQexec not allowed during COPY BOTH" +msgstr "COPY BOTH 작업 중에는 PQexec 사용할 수 없음" + +#: fe-exec.c:2586 fe-exec.c:2641 fe-exec.c:2709 fe-protocol3.c:1907 +#, c-format +msgid "no COPY in progress" +msgstr "처리 가운데 COPY가 없음" + +#: fe-exec.c:2895 +#, c-format +msgid "connection in wrong state" +msgstr "잘못된 상태의 연결" + +#: fe-exec.c:2938 +#, c-format +msgid "cannot enter pipeline mode, connection not idle" +msgstr "파이프라인 모드로 바꿀 수 없음, 연결이 idle 상태가 아님" + +#: fe-exec.c:2974 fe-exec.c:2995 +#, c-format +msgid "cannot exit pipeline mode with uncollected results" +msgstr "수집할 수 없는 결과로 파이프라인 모드를 종료할 수 없음" + +#: fe-exec.c:2978 +#, c-format +msgid "cannot exit pipeline mode while busy" +msgstr "바빠서 파이프라인 모드를 종료할 수 없음" + +#: fe-exec.c:2989 +#, c-format +msgid "cannot exit pipeline mode while in COPY" +msgstr "COPY 하고 있어 파이프라인 모드를 종료할 수 없음" + +#: fe-exec.c:3154 +#, c-format +msgid "cannot send pipeline when not in pipeline mode" +msgstr "파이프라인 모드 상태가 아닐 때는 파이프라인을 보낼 수 없음" + +#: fe-exec.c:3255 +msgid "invalid ExecStatusType code" +msgstr "잘못된 ExecStatusType 코드" + +#: fe-exec.c:3282 +msgid "PGresult is not an error result\n" +msgstr "PGresult가 오류 결과가 아님\n" + +#: fe-exec.c:3350 fe-exec.c:3373 +#, c-format +msgid "column number %d is out of range 0..%d" +msgstr "%d 번째 열은 0..%d 범위를 벗어났음" + +#: fe-exec.c:3388 +#, c-format +msgid "parameter number %d is out of range 0..%d" +msgstr "%d개의 매개 변수는 0..%d 범위를 벗어났음" + +#: fe-exec.c:3699 +#, c-format +msgid "could not interpret result from server: %s" +msgstr "서버로부터 결과처리를 중지 시킬 수 없음: %s" + +#: fe-exec.c:3964 fe-exec.c:4054 +#, c-format +msgid "incomplete multibyte character" +msgstr "완성되지 않은 멀티바이트 문자" + +#: fe-gssapi-common.c:122 +msgid "GSSAPI name import error" +msgstr "GSSAPI 이름 가져오기 오류" + +#: fe-lobj.c:144 fe-lobj.c:207 fe-lobj.c:397 fe-lobj.c:487 fe-lobj.c:560 +#: fe-lobj.c:956 fe-lobj.c:963 fe-lobj.c:970 fe-lobj.c:977 fe-lobj.c:984 +#: fe-lobj.c:991 fe-lobj.c:998 fe-lobj.c:1005 +#, c-format +msgid "cannot determine OID of function %s" +msgstr "%s 함수의 OID 조사를 할 수 없음" + +#: fe-lobj.c:160 +#, c-format +msgid "argument of lo_truncate exceeds integer range" +msgstr "lo_truncate 함수의 인자값이 정수 범위가 아님" + +#: fe-lobj.c:262 +#, c-format +msgid "argument of lo_read exceeds integer range" +msgstr "lo_read 함수의 인자값이 정수 범위가 아님" + +#: fe-lobj.c:313 +#, c-format +msgid "argument of lo_write exceeds integer range" +msgstr "lo_write 함수의 인자값이 정수 범위가 아님" + +#: fe-lobj.c:669 fe-lobj.c:780 +#, c-format +msgid "could not open file \"%s\": %s" +msgstr "\"%s\" 파일을 열 수 없음: %s" + +#: fe-lobj.c:725 +#, c-format +msgid "could not read from file \"%s\": %s" +msgstr "\"%s\" 파일을 읽을 수 없음: %s" + +#: fe-lobj.c:801 fe-lobj.c:824 +#, c-format +msgid "could not write to file \"%s\": %s" +msgstr "\"%s\" 파일을 쓸 수 없음: %s" + +#: fe-lobj.c:908 +#, c-format +msgid "query to initialize large object functions did not return data" +msgstr "large object function을 초기화 하는 쿼리가 데이터를 리턴하지 않았음" + +#: fe-misc.c:240 +#, c-format +msgid "integer of size %lu not supported by pqGetInt" +msgstr "%lu 정수형 크기는 pqGetInt 함수에서 지원하지 않음" + +#: fe-misc.c:273 +#, c-format +msgid "integer of size %lu not supported by pqPutInt" +msgstr "%lu 정수형 크기는 pqPutInt 함수에서 지원하지 않음" + +#: fe-misc.c:573 +#, c-format +msgid "connection not open" +msgstr "연결 열기 실패" + +#: fe-misc.c:751 fe-secure-openssl.c:215 fe-secure-openssl.c:315 +#: fe-secure.c:257 fe-secure.c:419 +#, c-format +msgid "" +"server closed the connection unexpectedly\n" +"\tThis probably means the server terminated abnormally\n" +"\tbefore or while processing the request." +msgstr "" +"서버가 갑자기 연결을 닫았음.\n" +"\t이런 처리는 클라이언트의 요구를 처리하는 동안이나\n" +"\t처리하기 전에 서버가 갑자기 종료되었음을 의미함." + +#: fe-misc.c:818 +msgid "connection not open\n" +msgstr "연결 열기 실패\n" + +#: fe-misc.c:1003 +#, c-format +msgid "timeout expired" +msgstr "시간 초과" + +#: fe-misc.c:1047 +#, c-format +msgid "invalid socket" +msgstr "잘못된 소켓" + +#: fe-misc.c:1069 +#, c-format +msgid "%s() failed: %s" +msgstr "%s() 실패: %s" + +#: fe-protocol3.c:182 +#, c-format +msgid "message type 0x%02x arrived from server while idle" +msgstr "휴지(idle)동안 서버로 부터 0x%02x 형태 메시지를 받았음" + +#: fe-protocol3.c:385 +#, c-format +msgid "" +"server sent data (\"D\" message) without prior row description (\"T\" " +"message)" +msgstr "" +"서버에서 먼저 행(row) 설명(\"T\" 메시지) 없이 자료(\"D\" 메시지)를 보냈음" + +#: fe-protocol3.c:427 +#, c-format +msgid "unexpected response from server; first received character was \"%c\"" +msgstr "서버로부터 예상치 못한 응답을 받았음; \"%c\" 문자를 첫문자로 받았음" + +#: fe-protocol3.c:450 +#, c-format +msgid "message contents do not agree with length in message type \"%c\"" +msgstr "메시지 내용이 \"%c\" 메시지 형태의 길이를 허락하지 않음" + +#: fe-protocol3.c:468 +#, c-format +msgid "lost synchronization with server: got message type \"%c\", length %d" +msgstr "서버와의 동기화가 끊김: \"%c\" 형태 길이 %d 메시지 받음" + +#: fe-protocol3.c:520 fe-protocol3.c:560 +msgid "insufficient data in \"T\" message" +msgstr "\"T\" 메시지 안에 부족자 데이터" + +#: fe-protocol3.c:631 fe-protocol3.c:837 +msgid "out of memory for query result" +msgstr "쿼리 결과 처리를 위한 메모리 부족" + +#: fe-protocol3.c:700 +msgid "insufficient data in \"t\" message" +msgstr "\"t\" 메시지 안에 데이터가 충분하지 않음" + +#: fe-protocol3.c:759 fe-protocol3.c:791 fe-protocol3.c:809 +msgid "insufficient data in \"D\" message" +msgstr "\"D\" 메시지 안에 불충분한 데이터" + +#: fe-protocol3.c:765 +msgid "unexpected field count in \"D\" message" +msgstr "\"D\" 메시지 안에 예상치 못한 필드 수" + +#: fe-protocol3.c:1020 +msgid "no error message available\n" +msgstr "보여줄 오류 메시지가 없음\n" + +#. translator: %s represents a digit string +#: fe-protocol3.c:1068 fe-protocol3.c:1087 +#, c-format +msgid " at character %s" +msgstr " 위치: %s" + +#: fe-protocol3.c:1100 +#, c-format +msgid "DETAIL: %s\n" +msgstr "상세정보: %s\n" + +#: fe-protocol3.c:1103 +#, c-format +msgid "HINT: %s\n" +msgstr "힌트: %s\n" + +#: fe-protocol3.c:1106 +#, c-format +msgid "QUERY: %s\n" +msgstr "쿼리: %s\n" + +#: fe-protocol3.c:1113 +#, c-format +msgid "CONTEXT: %s\n" +msgstr "구문: %s\n" + +#: fe-protocol3.c:1122 +#, c-format +msgid "SCHEMA NAME: %s\n" +msgstr "스키마 이름: %s\n" + +#: fe-protocol3.c:1126 +#, c-format +msgid "TABLE NAME: %s\n" +msgstr "테이블 이름: %s\n" + +#: fe-protocol3.c:1130 +#, c-format +msgid "COLUMN NAME: %s\n" +msgstr "칼럼 이름: %s\n" + +#: fe-protocol3.c:1134 +#, c-format +msgid "DATATYPE NAME: %s\n" +msgstr "자료형 이름: %s\n" + +#: fe-protocol3.c:1138 +#, c-format +msgid "CONSTRAINT NAME: %s\n" +msgstr "제약조건 이름: %s\n" + +#: fe-protocol3.c:1150 +msgid "LOCATION: " +msgstr "위치: " + +#: fe-protocol3.c:1152 +#, c-format +msgid "%s, " +msgstr "%s, " + +#: fe-protocol3.c:1154 +#, c-format +msgid "%s:%s" +msgstr "%s:%s" + +#: fe-protocol3.c:1349 +#, c-format +msgid "LINE %d: " +msgstr "줄 %d: " + +#: fe-protocol3.c:1423 +#, c-format +msgid "" +"protocol version not supported by server: client uses %u.%u, server supports " +"up to %u.%u" +msgstr "" +"서버가 해당 프로토콜 버전을 지원하지 않음: 클라이언트=%u.%u, 서버=%u.%u" + +#: fe-protocol3.c:1429 +#, c-format +msgid "protocol extension not supported by server: %s" +msgid_plural "protocol extensions not supported by server: %s" +msgstr[0] "서버가 해당 프로토콜 확장을 지원하지 않음: %s" + +#: fe-protocol3.c:1437 +#, c-format +msgid "invalid %s message" +msgstr "잘못된 %s 메시지" + +#: fe-protocol3.c:1802 +#, c-format +msgid "PQgetline: not doing text COPY OUT" +msgstr "PQgetline: text COPY OUT 작업을 할 수 없음" + +#: fe-protocol3.c:2176 +#, c-format +msgid "protocol error: no function result" +msgstr "프로토콜 오류: 함수 결과 없음" + +#: fe-protocol3.c:2187 +#, c-format +msgid "protocol error: id=0x%x" +msgstr "프로토콜 오류: id=0x%x" + +#: fe-secure-common.c:123 +#, c-format +msgid "SSL certificate's name contains embedded null" +msgstr "SSL 인증서의 이름에 null 문자가 있음" + +#: fe-secure-common.c:228 +#, c-format +msgid "certificate contains IP address with invalid length %zu" +msgstr "인증서에 IP 주소용 %zu 길이가 잘못됨" + +#: fe-secure-common.c:237 +#, c-format +msgid "could not convert certificate's IP address to string: %s" +msgstr "인증서의 IP 주소를 문자열로 바꿀 수 없음: %s" + +#: fe-secure-common.c:269 +#, c-format +msgid "host name must be specified for a verified SSL connection" +msgstr "인증된 SSL 접속을 위해서는 호스트 이름을 지정해야 함" + +#: fe-secure-common.c:286 +#, c-format +msgid "" +"server certificate for \"%s\" (and %d other name) does not match host name " +"\"%s\"" +msgid_plural "" +"server certificate for \"%s\" (and %d other names) does not match host name " +"\"%s\"" +msgstr[0] "" +"서버 인증서의 이름 \"%s\" (%d 기타 이름)이 \"%s\" 호스트 이름과 일치하지 않음" + +#: fe-secure-common.c:294 +#, c-format +msgid "server certificate for \"%s\" does not match host name \"%s\"" +msgstr "서버 인증서의 이름 \"%s\"이(가) \"%s\" 호스트 이름과 일치하지 않음" + +#: fe-secure-common.c:299 +#, c-format +msgid "could not get server's host name from server certificate" +msgstr "서버 인증서에서 서버 호스트 이름을 찾을 수 없음" + +#: fe-secure-gssapi.c:201 +msgid "GSSAPI wrap error" +msgstr "GSSAPI 감싸기 오류" + +#: fe-secure-gssapi.c:208 +#, c-format +msgid "outgoing GSSAPI message would not use confidentiality" +msgstr "GSSAPI 송출 메시지는 기밀성을 사용하지 말아야함" + +#: fe-secure-gssapi.c:215 +#, c-format +msgid "client tried to send oversize GSSAPI packet (%zu > %zu)" +msgstr "클라이언트의 GSSAPI 패킷이 너무 큼 (%zu > %zu)" + +#: fe-secure-gssapi.c:351 fe-secure-gssapi.c:593 +#, c-format +msgid "oversize GSSAPI packet sent by the server (%zu > %zu)" +msgstr "서버의 GSSAPI 패킷이 너무 큼 (%zu > %zu)" + +#: fe-secure-gssapi.c:390 +msgid "GSSAPI unwrap error" +msgstr "GSSAPI 벗기기 오류" + +#: fe-secure-gssapi.c:399 +#, c-format +msgid "incoming GSSAPI message did not use confidentiality" +msgstr "GSSAPI 수신 메시지는 기밀성을 사용하지 말아야 함" + +#: fe-secure-gssapi.c:656 +msgid "could not initiate GSSAPI security context" +msgstr "GSSAPI 보안 context 초기화 실패" + +#: fe-secure-gssapi.c:685 +msgid "GSSAPI size check error" +msgstr "GSSAPI 크기 검사 오류" + +#: fe-secure-gssapi.c:696 +msgid "GSSAPI context establishment error" +msgstr "GSSAPI context 설정 오류" + +#: fe-secure-openssl.c:219 fe-secure-openssl.c:319 fe-secure-openssl.c:1531 +#, c-format +msgid "SSL SYSCALL error: %s" +msgstr "SSL SYSCALL 오류: %s" + +#: fe-secure-openssl.c:225 fe-secure-openssl.c:325 fe-secure-openssl.c:1534 +#, c-format +msgid "SSL SYSCALL error: EOF detected" +msgstr "SSL SYSCALL 오류: EOF 감지됨" + +#: fe-secure-openssl.c:235 fe-secure-openssl.c:335 fe-secure-openssl.c:1542 +#, c-format +msgid "SSL error: %s" +msgstr "SSL 오류: %s" + +#: fe-secure-openssl.c:249 fe-secure-openssl.c:349 +#, c-format +msgid "SSL connection has been closed unexpectedly" +msgstr "SSL 연결이 예상치 못하게 끊김" + +#: fe-secure-openssl.c:254 fe-secure-openssl.c:354 fe-secure-openssl.c:1589 +#, c-format +msgid "unrecognized SSL error code: %d" +msgstr "알 수 없는 SSL 오류 코드: %d" + +#: fe-secure-openssl.c:397 +#, c-format +msgid "could not determine server certificate signature algorithm" +msgstr "서버 인증서 서명 알고리즘을 알 수 없음" + +#: fe-secure-openssl.c:417 +#, c-format +msgid "could not find digest for NID %s" +msgstr "%s NID용 다이제스트를 찾을 수 없음" + +#: fe-secure-openssl.c:426 +#, c-format +msgid "could not generate peer certificate hash" +msgstr "피어 인증 해시 값을 만들 수 없음" + +#: fe-secure-openssl.c:509 +#, c-format +msgid "SSL certificate's name entry is missing" +msgstr "SSL 인증서의 이름 항목이 잘못됨" + +#: fe-secure-openssl.c:543 +#, c-format +msgid "SSL certificate's address entry is missing" +msgstr "SSL 인증서의 주소 항목이 빠졌음" + +#: fe-secure-openssl.c:960 +#, c-format +msgid "could not create SSL context: %s" +msgstr "SSL context를 만들 수 없음: %s" + +#: fe-secure-openssl.c:1002 +#, c-format +msgid "invalid value \"%s\" for minimum SSL protocol version" +msgstr "잘못된 값: \"%s\", 대상: 최소 SSL 프로토콜 버전" + +#: fe-secure-openssl.c:1012 +#, c-format +msgid "could not set minimum SSL protocol version: %s" +msgstr "최소 SSL 프로토콜 버전을 지정할 수 없음: %s" + +#: fe-secure-openssl.c:1028 +#, c-format +msgid "invalid value \"%s\" for maximum SSL protocol version" +msgstr "잘못된 값: \"%s\", 대상: 최대 SSL 프로토콜 버전" + +#: fe-secure-openssl.c:1038 +#, c-format +msgid "could not set maximum SSL protocol version: %s" +msgstr "최대 SSL 프로토콜 버전을 지정할 수 없음: %s" + +#: fe-secure-openssl.c:1076 +#, c-format +msgid "could not load system root certificate paths: %s" +msgstr "시스템 루트 인증서 경로 불러오기 실패: %s" + +#: fe-secure-openssl.c:1093 +#, c-format +msgid "could not read root certificate file \"%s\": %s" +msgstr "\"%s\" 루트 인증서 파일을 읽을 수 없음: %s" + +#: fe-secure-openssl.c:1145 +#, c-format +msgid "" +"could not get home directory to locate root certificate file\n" +"Either provide the file, use the system's trusted roots with " +"sslrootcert=system, or change sslmode to disable server certificate " +"verification." +msgstr "" +"루트 인증서 파일이 있는 홈 디렉터리를 찾을 수 없음\n" +"해당 파일을 제공하거나, sslrootcert=system 설정으로 신뢰할 수 있는 시스템 루" +"트 인증서를 사용하거나, 서버 인증서 확인을 사용하지 않도록 sslmode를 변경하십" +"시오." + +#: fe-secure-openssl.c:1148 +#, c-format +msgid "" +"root certificate file \"%s\" does not exist\n" +"Either provide the file, use the system's trusted roots with " +"sslrootcert=system, or change sslmode to disable server certificate " +"verification." +msgstr "" +"루트 인증서 파일 \"%s\"이(가) 없습니다.\n" +"해당 파일을 제공하거나, sslrootcert=system 설정으로 신뢰할 수 있는 시스템 루" +"트 인증서를 사용하거나, 서버 인증서 확인을 사용하지 않도록 sslmode를 변경하십" +"시오." + +#: fe-secure-openssl.c:1183 +#, c-format +msgid "could not open certificate file \"%s\": %s" +msgstr "\"%s\" 인증서 파일을 열수 없음: %s" + +#: fe-secure-openssl.c:1201 +#, c-format +msgid "could not read certificate file \"%s\": %s" +msgstr "\"%s\" 인증서 파일을 읽을 수 없음: %s" + +#: fe-secure-openssl.c:1225 +#, c-format +msgid "could not establish SSL connection: %s" +msgstr "SSL 연결을 확립할 수 없음: %s" + +#: fe-secure-openssl.c:1257 +#, c-format +msgid "could not set SSL Server Name Indication (SNI): %s" +msgstr "서버 이름 표시(SNI)를 설정할 수 없음: %s" + +#: fe-secure-openssl.c:1300 +#, c-format +msgid "could not load SSL engine \"%s\": %s" +msgstr "SSL 엔진 \"%s\"을(를) 로드할 수 없음: %s" + +#: fe-secure-openssl.c:1311 +#, c-format +msgid "could not initialize SSL engine \"%s\": %s" +msgstr "SSL 엔진 \"%s\"을(를) 초기화할 수 없음: %s" + +#: fe-secure-openssl.c:1326 +#, c-format +msgid "could not read private SSL key \"%s\" from engine \"%s\": %s" +msgstr "개인 SSL 키 \"%s\"을(를) \"%s\" 엔진에서 읽을 수 없음: %s" + +#: fe-secure-openssl.c:1339 +#, c-format +msgid "could not load private SSL key \"%s\" from engine \"%s\": %s" +msgstr "개인 SSL 키 \"%s\"을(를) \"%s\" 엔진에서 읽을 수 없음: %s" + +#: fe-secure-openssl.c:1376 +#, c-format +msgid "certificate present, but not private key file \"%s\"" +msgstr "인증서가 있지만, \"%s\" 개인키가 아닙니다." + +#: fe-secure-openssl.c:1379 +#, c-format +msgid "could not stat private key file \"%s\": %m" +msgstr "\"%s\" 개인키 파일 상태를 알 수 없음: %m" + +#: fe-secure-openssl.c:1387 +#, c-format +msgid "private key file \"%s\" is not a regular file" +msgstr "\"%s\" 개인키 파일은 일반 파일이 아님" + +#: fe-secure-openssl.c:1420 +#, c-format +msgid "" +"private key file \"%s\" has group or world access; file must have " +"permissions u=rw (0600) or less if owned by the current user, or permissions " +"u=rw,g=r (0640) or less if owned by root" +msgstr "" +"\"%s\" 개인키 파일의 접근권한이 그룹 또는 그외 사용자도 접근 가능함; 파일 소" +"유주가 현재 사용자라면, 접근권한을 u=rw (0600) 또는 더 작게 설정하고, root가 " +"소유주라면 u=rw,g=r (0640) 권한으로 지정하세요." + +#: fe-secure-openssl.c:1444 +#, c-format +msgid "could not load private key file \"%s\": %s" +msgstr "\"%s\" 개인키 파일을 불러들일 수 없습니다: %s" + +#: fe-secure-openssl.c:1460 +#, c-format +msgid "certificate does not match private key file \"%s\": %s" +msgstr "인증서가 \"%s\" 개인키 파일과 맞지 않습니다: %s" + +#: fe-secure-openssl.c:1528 +#, c-format +msgid "SSL error: certificate verify failed: %s" +msgstr "SSL 오류: 인증서 유효성 검사 실패: %s" + +#: fe-secure-openssl.c:1573 +#, c-format +msgid "" +"This may indicate that the server does not support any SSL protocol version " +"between %s and %s." +msgstr "해당 서버는 SSL 프로토콜 버전 %s - %s 사이를 지원하지 않습니다." + +#: fe-secure-openssl.c:1606 +#, c-format +msgid "certificate could not be obtained: %s" +msgstr "인증서를 구하질 못했습니다: %s" + +#: fe-secure-openssl.c:1711 +#, c-format +msgid "no SSL error reported" +msgstr "SSL 오류 없음이 보고됨" + +#: fe-secure-openssl.c:1720 +#, c-format +msgid "SSL error code %lu" +msgstr "SSL 오류 번호 %lu" + +#: fe-secure-openssl.c:1986 +#, c-format +msgid "WARNING: sslpassword truncated\n" +msgstr "경고: sslpassword 삭제됨\n" + +#: fe-secure.c:263 +#, c-format +msgid "could not receive data from server: %s" +msgstr "서버로부터 데이터를 받지 못했음: %s" + +#: fe-secure.c:434 +#, c-format +msgid "could not send data to server: %s" +msgstr "서버에 데이터를 보낼 수 없음: %s" + +#: win32.c:310 +#, c-format +msgid "unrecognized socket error: 0x%08X/%d" +msgstr "알 수 없는 소켓오류: 0x%08X/%d" diff --git a/src/interfaces/libpq/po/meson.build b/src/interfaces/libpq/po/meson.build new file mode 100644 index 0000000..a7a1df8 --- /dev/null +++ b/src/interfaces/libpq/po/meson.build @@ -0,0 +1,3 @@ +# Copyright (c) 2022-2023, PostgreSQL Global Development Group + +nls_targets += [i18n.gettext('libpq' + '5' + '-' + pg_version_major.to_string())] diff --git a/src/interfaces/libpq/po/pl.po b/src/interfaces/libpq/po/pl.po new file mode 100644 index 0000000..330c0d7 --- /dev/null +++ b/src/interfaces/libpq/po/pl.po @@ -0,0 +1,1069 @@ +# LIBPQ Translated Messages into the Polish Language +# Copyright (c) 2005 toczek, xxxtoczekxxx@wp.pl +# Distributed under the same licensing terms as PostgreSQL itself. +# Begina Felicysym <begina.felicysym@wp.eu>, 2011, 2012, 2013. +# grzegorz <begina.felicysym@wp.eu>, 2015, 2016, 2017. +msgid "" +msgstr "" +"Project-Id-Version: libpq (PostgreSQL 9.1)\n" +"Report-Msgid-Bugs-To: pgsql-bugs@postgresql.org\n" +"POT-Creation-Date: 2017-03-14 17:38+0000\n" +"PO-Revision-Date: 2017-03-14 19:21+0200\n" +"Last-Translator: grzegorz <begina.felicysym@wp.eu>\n" +"Language-Team: begina.felicysym@wp.eu\n" +"Language: pl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " +"|| n%100>=20) ? 1 : 2);\n" +"X-Generator: Virtaal 0.7.1\n" + +#: fe-auth.c:149 +msgid "GSSAPI continuation error" +msgstr "błąd kontynuowania GSSAPI" + +#: fe-auth.c:179 fe-auth.c:415 +msgid "host name must be specified\n" +msgstr "nazwa hosta musi być określona\n" + +#: fe-auth.c:186 +msgid "duplicate GSS authentication request\n" +msgstr "podwójne żądanie autoryzacji GSS\n" + +#: fe-auth.c:199 fe-auth.c:311 fe-auth.c:386 fe-auth.c:421 fe-auth.c:465 +#: fe-auth.c:599 fe-auth.c:902 fe-connect.c:716 fe-connect.c:1086 +#: fe-connect.c:1262 fe-connect.c:1798 fe-connect.c:2326 fe-connect.c:4000 +#: fe-connect.c:4252 fe-connect.c:4371 fe-connect.c:4611 fe-connect.c:4691 +#: fe-connect.c:4790 fe-connect.c:5046 fe-connect.c:5075 fe-connect.c:5147 +#: fe-connect.c:5165 fe-connect.c:5266 fe-connect.c:5275 fe-connect.c:5631 +#: fe-connect.c:5781 fe-exec.c:2651 fe-exec.c:3398 fe-exec.c:3563 +#: fe-lobj.c:896 fe-protocol2.c:1206 fe-protocol3.c:992 fe-protocol3.c:1678 +#: fe-secure-openssl.c:514 fe-secure-openssl.c:1137 +msgid "out of memory\n" +msgstr "brak pamięci\n" + +#: fe-auth.c:212 +msgid "GSSAPI name import error" +msgstr "błąd importu nazwy GSSAPI" + +#: fe-auth.c:300 +msgid "SSPI continuation error" +msgstr "błąd kontynuowania SSPI" + +#: fe-auth.c:401 +msgid "could not acquire SSPI credentials" +msgstr "nie można nabyć poświadczeń SSPI" + +#: fe-auth.c:474 +#, c-format +msgid "SASL authentication mechanism %s not supported\n" +msgstr "mechanizm autoryzacji %s SASL nie jest dostępny\n" + +#: fe-auth.c:574 +msgid "SCM_CRED authentication method not supported\n" +msgstr "Metoda autoryzacji SCM_CRED nie jest dostępna\n" + +#: fe-auth.c:650 +msgid "Kerberos 4 authentication not supported\n" +msgstr "metoda autoryzacji Kerberos 4 nie jest dostępna\n" + +#: fe-auth.c:655 +msgid "Kerberos 5 authentication not supported\n" +msgstr "metoda autoryzacji Kerberos 5 nie jest dostępna\n" + +#: fe-auth.c:726 +msgid "GSSAPI authentication not supported\n" +msgstr "Metoda autoryzacji GSSAPI nie jest dostępna\n" + +#: fe-auth.c:758 +msgid "SSPI authentication not supported\n" +msgstr "Metoda autoryzacji SSPI nie jest dostępna\n" + +#: fe-auth.c:766 +msgid "Crypt authentication not supported\n" +msgstr "metoda autoryzacji Crypt nie jest dostępna\n" + +#: fe-auth.c:830 +#, c-format +msgid "authentication method %u not supported\n" +msgstr "metoda autoryzacji %u nie jest dostępna\n" + +#: fe-auth.c:877 +#, c-format +msgid "user name lookup failure: error code %lu\n" +msgstr "niepowodzenie wyszukiwania nazwy użytkownika: kod błędu %lu\n" + +#: fe-auth.c:887 fe-connect.c:2253 +#, c-format +msgid "could not look up local user ID %d: %s\n" +msgstr "nie udało się odnaleźć lokalnego ID użytkownika %d: %s\n" + +#: fe-auth.c:892 fe-connect.c:2258 +#, c-format +msgid "local user with ID %d does not exist\n" +msgstr "lokalny użytkownik o ID %d nie istnieje\n" + +#: fe-connect.c:918 +#, c-format +msgid "could not match %d port numbers to %d hosts\n" +msgstr "nie można dopasować %d numerów portów do %d hostów\n" + +#: fe-connect.c:970 +msgid "could not get home directory to locate password file\n" +msgstr "nie można pobrać katalogu domowego aby zlokalizować plik haseł\n" + +#: fe-connect.c:1012 +#, c-format +msgid "invalid sslmode value: \"%s\"\n" +msgstr "błędna wartość sslmode: \"%s\"\n" + +#: fe-connect.c:1033 +#, c-format +msgid "sslmode value \"%s\" invalid when SSL support is not compiled in\n" +msgstr "błędna wartość sslmode \"%s\" gdyż obsługa SSL nie została skompilowana\n" + +#: fe-connect.c:1068 +#, c-format +msgid "invalid target_session_attrs value: \"%s\"\n" +msgstr "błędna wartość target_session_attrs: \"%s\"\n" + +#: fe-connect.c:1286 +#, c-format +msgid "could not set socket to TCP no delay mode: %s\n" +msgstr "nie można ustawić gniazda TCP w tryb bez opóźnień: %s\n" + +#: fe-connect.c:1316 +#, c-format +msgid "" +"could not connect to server: %s\n" +"\tIs the server running locally and accepting\n" +"\tconnections on Unix domain socket \"%s\"?\n" +msgstr "" +"nie można połączyć się z serwerem: %s\n" +"\tCzy serwer działa lokalnie i akceptuje\n" +"\tpołączenia przy pomocy gniazd dziedziny Uniksa \"%s\"?\n" + +#: fe-connect.c:1371 +#, c-format +msgid "" +"could not connect to server: %s\n" +"\tIs the server running on host \"%s\" (%s) and accepting\n" +"\tTCP/IP connections on port %s?\n" +msgstr "" +"nie można połączyć się z serwerem: %s\n" +"\tCzy serwer działa na serwerze \"%s\" (%s) i akceptuje\n" +"\tpołączenia TCP/IP na porcie %s?\n" + +#: fe-connect.c:1380 +#, c-format +msgid "" +"could not connect to server: %s\n" +"\tIs the server running on host \"%s\" and accepting\n" +"\tTCP/IP connections on port %s?\n" +msgstr "" +"nie można połączyć się z serwerem: %s\n" +"\tCzy serwer działa na stacji sieciowej \"%s\" i akceptuje\n" +"\tpołączenia TCP/IP na porcie %s?\n" + +#: fe-connect.c:1431 +#, c-format +msgid "setsockopt(TCP_KEEPIDLE) failed: %s\n" +msgstr "nie powiodło się setsockopt(TCP_KEEPIDLE): %s\n" + +#: fe-connect.c:1444 +#, c-format +msgid "setsockopt(TCP_KEEPALIVE) failed: %s\n" +msgstr "nie powiodło się setsockopt(TCP_KEEPALIVE): %s\n" + +#: fe-connect.c:1476 +#, c-format +msgid "setsockopt(TCP_KEEPINTVL) failed: %s\n" +msgstr "nie powiodło się setsockopt(TCP_KEEPINTVL): %s\n" + +#: fe-connect.c:1508 +#, c-format +msgid "setsockopt(TCP_KEEPCNT) failed: %s\n" +msgstr "nie powiodło się setsockopt(TCP_KEEPCNT): %s\n" + +#: fe-connect.c:1556 +#, c-format +msgid "WSAIoctl(SIO_KEEPALIVE_VALS) failed: %ui\n" +msgstr "nie powiodło się WSAIoctl(SIO_KEEPALIVE_VALS): %ui\n" + +#: fe-connect.c:1614 +#, c-format +msgid "invalid port number: \"%s\"\n" +msgstr "nieprawidłowy numer portu: \"%s\"\n" + +#: fe-connect.c:1638 +#, c-format +msgid "Unix-domain socket path \"%s\" is too long (maximum %d bytes)\n" +msgstr "Za długa ścieżka gniazda domeny Unix \"%s\" (maks %d bajtów)\n" + +#: fe-connect.c:1656 +#, c-format +msgid "could not translate host name \"%s\" to address: %s\n" +msgstr "nie można przetłumaczyć nazwy hosta \"%s\" na adres: %s\n" + +#: fe-connect.c:1660 +#, c-format +msgid "could not translate Unix-domain socket path \"%s\" to address: %s\n" +msgstr "nie można przetłumaczyć ścieżki gniazda domeny Uniks \"%s\" na adres: %s\n" + +#: fe-connect.c:1904 +msgid "invalid connection state, probably indicative of memory corruption\n" +msgstr "błędny stan połączenia, prawdopodobnie oznajmiający uszkodzenie pamięci\n" + +#: fe-connect.c:1961 +#, c-format +msgid "could not create socket: %s\n" +msgstr "nie można utworzyć gniazda: %s\n" + +#: fe-connect.c:1983 +#, c-format +msgid "could not set socket to nonblocking mode: %s\n" +msgstr "nie można ustawić gniazda w tryb nieblokujący: %s\n" + +#: fe-connect.c:1994 +#, c-format +msgid "could not set socket to close-on-exec mode: %s\n" +msgstr "nie można ustawić gniazda obsługi zamknięcia przy uruchomieniu: %s\n" + +#: fe-connect.c:2013 +msgid "keepalives parameter must be an integer\n" +msgstr "parametr keepalives musi być liczbą całkowitą\n" + +#: fe-connect.c:2026 +#, c-format +msgid "setsockopt(SO_KEEPALIVE) failed: %s\n" +msgstr "nie powiodło się setsockopt(SO_KEEPALIVE): %s\n" + +#: fe-connect.c:2163 +#, c-format +msgid "could not get socket error status: %s\n" +msgstr "nie można otrzymać błędu gniazda: %s\n" + +#: fe-connect.c:2198 +#, c-format +msgid "could not get client address from socket: %s\n" +msgstr "nie można otrzymać adresu klienta z gniazda: %s\n" + +#: fe-connect.c:2240 +msgid "requirepeer parameter is not supported on this platform\n" +msgstr "parametr requirepeer nie jest obsługiwany na tej platformie\n" + +#: fe-connect.c:2243 +#, c-format +msgid "could not get peer credentials: %s\n" +msgstr "nie można pobrać poświadczeń wzajemnych: %s\n" + +#: fe-connect.c:2266 +#, c-format +msgid "requirepeer specifies \"%s\", but actual peer user name is \"%s\"\n" +msgstr "requirepeer wskazuje \"%s\", ale nazwa bieżącego użytkownika równorzędnego to " +"\"%s\"\n" + +#: fe-connect.c:2300 +#, c-format +msgid "could not send SSL negotiation packet: %s\n" +msgstr "nie można wysłać pakietu negocjacji SSL: %s\n" + +#: fe-connect.c:2339 +#, c-format +msgid "could not send startup packet: %s\n" +msgstr "nie można wysłać pakietu rozpoczynającego: %s\n" + +#: fe-connect.c:2409 +msgid "server does not support SSL, but SSL was required\n" +msgstr "serwer nie obsługuje SSL, ale SSL było wymagane\n" + +#: fe-connect.c:2435 +#, c-format +msgid "received invalid response to SSL negotiation: %c\n" +msgstr "otrzymano niepoprawną odpowiedź negocjacji SSL: %c\n" + +#: fe-connect.c:2510 fe-connect.c:2543 +#, c-format +msgid "expected authentication request from server, but received %c\n" +msgstr "oczekiwano prośby autoryzacji z serwera ale otrzymano %c\n" + +#: fe-connect.c:2710 +#, c-format +msgid "out of memory allocating GSSAPI buffer (%d)" +msgstr "brak pamięci podczas alokacji bufora GSSAPI (%d)" + +#: fe-connect.c:2748 +#, c-format +msgid "out of memory allocating SASL buffer (%d)" +msgstr "brak pamięci podczas alokacji bufora SASL (%d)" + +#: fe-connect.c:2838 +msgid "unexpected message from server during startup\n" +msgstr "niespodziewana wiadomość z serwera podczas startu\n" + +#: fe-connect.c:3042 +#, c-format +msgid "could not make a writable connection to server \"%s:%s\"\n" +msgstr "nie można ustanowić połączenia z serwerem do zapisu: \"%s:%s\"\n" + +#: fe-connect.c:3084 +#, c-format +msgid "test \"show transaction_read_only\" failed on \"%s:%s\" \n" +msgstr "niepowodzenie testu \"show transaction_read_only\" na \"%s:%s\" \n" + +#: fe-connect.c:3106 +#, c-format +msgid "invalid connection state %d, probably indicative of memory corruption\n" +msgstr "nieprawidłowy stan połączenia %d, prawdopodobnie wskazujący na uszkodzenie " +"pamięci\n" + +#: fe-connect.c:3606 fe-connect.c:3666 +#, c-format +msgid "PGEventProc \"%s\" failed during PGEVT_CONNRESET event\n" +msgstr "PGEventProc \"%s\" zawiodła podczas zdarzenia PGEVT_CONNRESET\n" + +#: fe-connect.c:4013 +#, c-format +msgid "invalid LDAP URL \"%s\": scheme must be ldap://\n" +msgstr "Niepoprawny adres URL LDAP \"%s\": schemat musi być ldap://\n" + +#: fe-connect.c:4028 +#, c-format +msgid "invalid LDAP URL \"%s\": missing distinguished name\n" +msgstr "niepoprawny adres URL LDAP \"%s\": brakująca nazwa wyróżniająca\n" + +#: fe-connect.c:4039 fe-connect.c:4092 +#, c-format +msgid "invalid LDAP URL \"%s\": must have exactly one attribute\n" +msgstr "niepoprawny adres URL LDAP \"%s\": musi mieć dokładnie jeden atrybut\n" + +#: fe-connect.c:4049 fe-connect.c:4106 +#, c-format +msgid "invalid LDAP URL \"%s\": must have search scope (base/one/sub)\n" +msgstr "niepoprawny adres URL LDAP \"%s\": musi mieć zakres wyszukiwania " +"(base/one/sub)\n" + +#: fe-connect.c:4060 +#, c-format +msgid "invalid LDAP URL \"%s\": no filter\n" +msgstr "niepoprawny adres URL LDAP \"%s\": brak filtra\n" + +#: fe-connect.c:4081 +#, c-format +msgid "invalid LDAP URL \"%s\": invalid port number\n" +msgstr "niepoprawny adres URL LDAP \"%s\": niepoprawny numer portu\n" + +#: fe-connect.c:4115 +msgid "could not create LDAP structure\n" +msgstr "nie można utworzyć struktury LDAP\n" + +#: fe-connect.c:4191 +#, c-format +msgid "lookup on LDAP server failed: %s\n" +msgstr "przeszukiwanie LDAP nie powiodło się: %s\n" + +#: fe-connect.c:4202 +msgid "more than one entry found on LDAP lookup\n" +msgstr "ponad jeden wpis znaleziono podczas przeszukiwania LDAP\n" + +#: fe-connect.c:4203 fe-connect.c:4215 +msgid "no entry found on LDAP lookup\n" +msgstr "nie znaleziono wpisu podczas przeszukiwania LDAP\n" + +#: fe-connect.c:4226 fe-connect.c:4239 +msgid "attribute has no values on LDAP lookup\n" +msgstr "atrybut nie ma wartości w przeszukiwaniu LDAP\n" + +#: fe-connect.c:4291 fe-connect.c:4310 fe-connect.c:4829 +#, c-format +msgid "missing \"=\" after \"%s\" in connection info string\n" +msgstr "brakujące \"=\" po \"%s\" w łańcuchu informacyjnym połączenia\n" + +#: fe-connect.c:4383 fe-connect.c:5014 fe-connect.c:5764 +#, c-format +msgid "invalid connection option \"%s\"\n" +msgstr "błędna opcja połączenia \"%s\"\n" + +#: fe-connect.c:4399 fe-connect.c:4878 +msgid "unterminated quoted string in connection info string\n" +msgstr "niezamknięty cudzysłów w łańcuchu informacyjnym połączenia\n" + +#: fe-connect.c:4439 +msgid "could not get home directory to locate service definition file" +msgstr "" +"nie można pobrać katalogu domowego aby zlokalizować plik definicji usługi" + +#: fe-connect.c:4472 +#, c-format +msgid "definition of service \"%s\" not found\n" +msgstr "nie znaleziono definicji usługi \"%s\"\n" + +#: fe-connect.c:4495 +#, c-format +msgid "service file \"%s\" not found\n" +msgstr "nie znaleziono pliku usługi \"%s\"\n" + +#: fe-connect.c:4508 +#, c-format +msgid "line %d too long in service file \"%s\"\n" +msgstr "zbyt długa linia %d w pliku usługi \"%s\"\n" + +#: fe-connect.c:4579 fe-connect.c:4623 +#, c-format +msgid "syntax error in service file \"%s\", line %d\n" +msgstr "błąd składni w pliku usługi \"%s\", linia %d\n" + +#: fe-connect.c:4590 +#, c-format +msgid "nested service specifications not supported in service file \"%s\", line %d\n" +msgstr "zagnieżdżone specyfikacje usług nie są obsługiwane w pliku usługi \"%s\", " +"linia %d\n" + +#: fe-connect.c:5286 +#, c-format +msgid "invalid URI propagated to internal parser routine: \"%s\"\n" +msgstr "niepoprawny URI przekazany do wewnętrznej procedury parsującej: \"%s\"\n" + +#: fe-connect.c:5363 +#, c-format +msgid "end of string reached when looking for matching \"]\" in IPv6 host address in URI: \"%s\"\n" +msgstr "osiągnięto koniec ciągu znaków podczas wyszukiwania kończącego \"]\" w adresie " +"IPv6 hosta w URI: \"%s\"\n" + +#: fe-connect.c:5370 +#, c-format +msgid "IPv6 host address may not be empty in URI: \"%s\"\n" +msgstr "adres IPv6 hosta nie może być pusty w URI: \"%s\"\n" + +#: fe-connect.c:5385 +#, c-format +msgid "unexpected character \"%c\" at position %d in URI (expected \":\" or \"/\"): \"%s\"\n" +msgstr "nieoczekiwany znak \"%c\" w URI na pozycji %d (oczekiwano \":\" lub \"/\"): \"%s\"\n" + +#: fe-connect.c:5514 +#, c-format +msgid "extra key/value separator \"=\" in URI query parameter: \"%s\"\n" +msgstr "nadmiarowy znak \"=\" rozdzielający klucz/wartość w parametrze zapytania URI: " +"\"%s\"\n" + +#: fe-connect.c:5534 +#, c-format +msgid "missing key/value separator \"=\" in URI query parameter: \"%s\"\n" +msgstr "brak znaku \"=\" rozdzielającego klucz/wartość w parametrze zapytania URI: \"%" +"s\"\n" + +#: fe-connect.c:5585 +#, c-format +msgid "invalid URI query parameter: \"%s\"\n" +msgstr "nieprawidłowy parametr zapytania URI: \"%s\"\n" + +#: fe-connect.c:5659 +#, c-format +msgid "invalid percent-encoded token: \"%s\"\n" +msgstr "niepoprawny kodowany procentem znak: \"%s\"\n" + +#: fe-connect.c:5669 +#, c-format +msgid "forbidden value %%00 in percent-encoded value: \"%s\"\n" +msgstr "zabroniona wartość %%00 w znaku kodowanym procentem: \"%s\"\n" + +#: fe-connect.c:6014 +msgid "connection pointer is NULL\n" +msgstr "wskaźnik połączenia ma wartość NULL\n" + +#: fe-connect.c:6312 +#, c-format +msgid "WARNING: password file \"%s\" is not a plain file\n" +msgstr "OSTRZEŻENIE: plik hasła \"%s\" nie jest zwykłym plikiem\n" + +#: fe-connect.c:6321 +#, c-format +msgid "WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n" +msgstr "" +"UWAGA: plik hasła \"%s\" posiada globalne lub grupowe uprawnienia odczytu;\n" +"uprawniania powinny być ustawione na u=rw (0600) lub słabsze\n" + +#: fe-connect.c:6413 +#, c-format +msgid "password retrieved from file \"%s\"\n" +msgstr "hasło odczytane z pliku \"%s\"\n" + +#: fe-exec.c:826 +msgid "NOTICE" +msgstr "UWAGA" + +#: fe-exec.c:1141 fe-exec.c:1199 fe-exec.c:1245 +msgid "command string is a null pointer\n" +msgstr "łańcuch polecenia jest wskaźnikiem null\n" + +#: fe-exec.c:1205 fe-exec.c:1251 fe-exec.c:1346 +msgid "number of parameters must be between 0 and 65535\n" +msgstr "liczba parametrów musi być pomiędzy 0 i 65535\n" + +#: fe-exec.c:1239 fe-exec.c:1340 +msgid "statement name is a null pointer\n" +msgstr "nazwa instrukcji jest wskaźnikiem null\n" + +#: fe-exec.c:1259 fe-exec.c:1422 fe-exec.c:2140 fe-exec.c:2339 +msgid "function requires at least protocol version 3.0\n" +msgstr "funkcja wymaga przynajmniej protokołu w wersji 3.0\n" + +#: fe-exec.c:1377 +msgid "no connection to the server\n" +msgstr "brak połączenia z serwerem\n" + +#: fe-exec.c:1384 +msgid "another command is already in progress\n" +msgstr "inne polecenie jest aktualnie wykonywane\n" + +#: fe-exec.c:1498 +msgid "length must be given for binary parameter\n" +msgstr "musi być podana długość parametru binarnego\n" + +#: fe-exec.c:1770 +#, c-format +msgid "unexpected asyncStatus: %d\n" +msgstr "nieoczekiwany asyncStatus: %d\n" + +#: fe-exec.c:1790 +#, c-format +msgid "PGEventProc \"%s\" failed during PGEVT_RESULTCREATE event\n" +msgstr "PGEventProc \"%s\" zawiodła podczas zdarzenia PGEVT_RESULTCREATE\n" + +#: fe-exec.c:1950 +msgid "COPY terminated by new PQexec" +msgstr "COPY zakończone przez nowe PQexec" + +#: fe-exec.c:1958 +msgid "COPY IN state must be terminated first\n" +msgstr "stan COPY IN musi zostać wcześniej zakończony\n" + +#: fe-exec.c:1978 +msgid "COPY OUT state must be terminated first\n" +msgstr "stan COPY OUT musi zostać wcześniej zakończony\n" + +#: fe-exec.c:1986 +msgid "PQexec not allowed during COPY BOTH\n" +msgstr "PQexec niedozwolone podczas COPY BOTH\n" + +#: fe-exec.c:2229 fe-exec.c:2296 fe-exec.c:2386 fe-protocol2.c:1352 +#: fe-protocol3.c:1817 +msgid "no COPY in progress\n" +msgstr "brak COPY w toku\n" + +#: fe-exec.c:2576 +msgid "connection in wrong state\n" +msgstr "połączenie posiada błędny stan\n" + +#: fe-exec.c:2607 +msgid "invalid ExecStatusType code" +msgstr "błędny kod ExecStatusType" + +#: fe-exec.c:2634 +msgid "PGresult is not an error result\n" +msgstr "PGresult nie jest wynikiem błedu\n" + +#: fe-exec.c:2709 fe-exec.c:2732 +#, c-format +msgid "column number %d is out of range 0..%d" +msgstr "numer kolumny %d wykracza poza zakres 0..%d" + +#: fe-exec.c:2725 +#, c-format +msgid "row number %d is out of range 0..%d" +msgstr "numer wiersza %d wykracza poza zakres 0..%d" + +#: fe-exec.c:2747 +#, c-format +msgid "parameter number %d is out of range 0..%d" +msgstr "numer parametru %d wykracza poza zakres 0..%d" + +#: fe-exec.c:3057 +#, c-format +msgid "could not interpret result from server: %s" +msgstr "nie można zinterpretować wyników z serwera: %s" + +#: fe-exec.c:3296 fe-exec.c:3380 +msgid "incomplete multibyte character\n" +msgstr "niepełny znak wielobajtowy\n" + +#: fe-lobj.c:155 +msgid "cannot determine OID of function lo_truncate\n" +msgstr "nie można ustalić OID funkcji lo_truncate\n" + +#: fe-lobj.c:171 +msgid "argument of lo_truncate exceeds integer range\n" +msgstr "argument lo_truncate jest spoza zakresu typu integer\n" + +#: fe-lobj.c:222 +msgid "cannot determine OID of function lo_truncate64\n" +msgstr "nie można ustalić OID funkcji lo_truncate64\n" + +#: fe-lobj.c:280 +msgid "argument of lo_read exceeds integer range\n" +msgstr "argument lo_read jest spoza zakresu typu integer\n" + +#: fe-lobj.c:335 +msgid "argument of lo_write exceeds integer range\n" +msgstr "argument lo_write jest spoza zakresu typu integer\n" + +#: fe-lobj.c:426 +msgid "cannot determine OID of function lo_lseek64\n" +msgstr "nie można ustalić OID funkcji lo_lseek64\n" + +#: fe-lobj.c:522 +msgid "cannot determine OID of function lo_create\n" +msgstr "nie można ustalić OID funkcji lo_create\n" + +#: fe-lobj.c:601 +msgid "cannot determine OID of function lo_tell64\n" +msgstr "nie można ustalić OID funkcji lo_tell64\n" + +#: fe-lobj.c:707 fe-lobj.c:816 +#, c-format +msgid "could not open file \"%s\": %s\n" +msgstr "nie można otworzyć pliku \"%s\": %s\n" + +#: fe-lobj.c:762 +#, c-format +msgid "could not read from file \"%s\": %s\n" +msgstr "nie można czytać z pliku \"%s\": %s\n" + +#: fe-lobj.c:836 fe-lobj.c:860 +#, c-format +msgid "could not write to file \"%s\": %s\n" +msgstr "nie można pisać do pliku \"%s\": %s\n" + +#: fe-lobj.c:947 +msgid "query to initialize large object functions did not return data\n" +msgstr "zapytanie inicjujące duży obiekt nie zwróciło żadnych danych\n" + +#: fe-lobj.c:996 +msgid "cannot determine OID of function lo_open\n" +msgstr "nie można ustalić OID funkcji lo_open\n" + +#: fe-lobj.c:1003 +msgid "cannot determine OID of function lo_close\n" +msgstr "nie można ustalić OID funkcji lo_close\n" + +#: fe-lobj.c:1010 +msgid "cannot determine OID of function lo_creat\n" +msgstr "nie można ustalić OID funkcji lo_creat\n" + +#: fe-lobj.c:1017 +msgid "cannot determine OID of function lo_unlink\n" +msgstr "nie można ustalić OID funkcji lo_unlink\n" + +#: fe-lobj.c:1024 +msgid "cannot determine OID of function lo_lseek\n" +msgstr "nie można ustalić OID funkcji lo_lseek\n" + +#: fe-lobj.c:1031 +msgid "cannot determine OID of function lo_tell\n" +msgstr "nie można ustalić OID funkcji lo_tell\n" + +#: fe-lobj.c:1038 +msgid "cannot determine OID of function loread\n" +msgstr "nie można ustalić OID funkcji loread\n" + +#: fe-lobj.c:1045 +msgid "cannot determine OID of function lowrite\n" +msgstr "nie można ustalić OID funkcji lowrite\n" + +#: fe-misc.c:295 +#, c-format +msgid "integer of size %lu not supported by pqGetInt" +msgstr "typ integer o rozmiarze %lu nie jest obsługiwany przez pqGetInt" + +#: fe-misc.c:331 +#, c-format +msgid "integer of size %lu not supported by pqPutInt" +msgstr "typ integer o rozmiarze %lu nie jest obsługiwany przez pqPutInt" + +#: fe-misc.c:642 fe-misc.c:843 +msgid "connection not open\n" +msgstr "połączenie nie jest otwarte\n" + +#: fe-misc.c:812 fe-secure-openssl.c:229 fe-secure-openssl.c:338 +#: fe-secure.c:253 fe-secure.c:362 +msgid "" +"server closed the connection unexpectedly\n" +"\tThis probably means the server terminated abnormally\n" +"\tbefore or while processing the request.\n" +msgstr "" +"serwer zamknął połączenie niespodziewanie\n" +"\tOznacza to prawdopodobnie iż serwer zakończył działanie niepoprawnie\n" +"\tprzed lub podczas przetwarzania zapytania.\n" + +#: fe-misc.c:1016 +msgid "timeout expired\n" +msgstr "upłynął limit czasu rządania\n" + +#: fe-misc.c:1061 +msgid "invalid socket\n" +msgstr "nieprawidłowe gniazdo\n" + +#: fe-misc.c:1084 +#, c-format +msgid "select() failed: %s\n" +msgstr "select() nie udało się: %s\n" + +#: fe-protocol2.c:91 +#, c-format +msgid "invalid setenv state %c, probably indicative of memory corruption\n" +msgstr "niepoprawny stan setenv %c, prawdopodobnie oznajmiający uszkodzenie pamięci\n" + +#: fe-protocol2.c:390 +#, c-format +msgid "invalid state %c, probably indicative of memory corruption\n" +msgstr "niepoprawny stan %c, prawdopodobnie oznajmiający uszkodzenie pamięci\n" + +#: fe-protocol2.c:479 fe-protocol3.c:186 +#, c-format +msgid "message type 0x%02x arrived from server while idle" +msgstr "otrzymano wiadomość typu 0x%02x z serwera podczas procesu bezczynności" + +#: fe-protocol2.c:503 fe-protocol2.c:538 fe-protocol2.c:1049 +#: fe-protocol3.c:209 fe-protocol3.c:236 fe-protocol3.c:253 fe-protocol3.c:333 +#: fe-protocol3.c:728 fe-protocol3.c:951 +msgid "out of memory" +msgstr "brak pamięci" + +#: fe-protocol2.c:529 +#, c-format +msgid "unexpected character %c following empty query response (\"I\" message)" +msgstr "" +"nieznany znak %c następujący po odpowiedzi pustego zapytania (wiadomość \"I\")" + +#: fe-protocol2.c:595 +#, c-format +msgid "server sent data (\"D\" message) without prior row description (\"T\" message)" +msgstr "" +"serwer wysłał dane (wiadomość \"D\") bez wcześniejszego opisu wiersza " +"(wiadomość \"T\")" + +#: fe-protocol2.c:613 +#, c-format +msgid "server sent binary data (\"B\" message) without prior row description (\"T\" message)" +msgstr "" +"serwer wysłał dane binarne (wiadomość \"B\") bez wcześniejszego opisu wiersza " +"(wiadomość \"T\")" + +#: fe-protocol2.c:633 fe-protocol3.c:412 +#, c-format +msgid "unexpected response from server; first received character was \"%c\"\n" +msgstr "nieznana odpowiedź z serwera: pierwszym znakiem otrzymanym był \"%c\"\n" + +#: fe-protocol2.c:762 fe-protocol2.c:937 fe-protocol3.c:627 fe-protocol3.c:854 +msgid "out of memory for query result" +msgstr "brak pamięci dla wyników zapytania" + +#: fe-protocol2.c:1395 fe-protocol3.c:1886 +#, c-format +msgid "%s" +msgstr "%s" + +#: fe-protocol2.c:1407 +#, c-format +msgid "lost synchronization with server, resetting connection" +msgstr "utracono synchronizację z serwerem, resetuję połączenie" + +#: fe-protocol2.c:1541 fe-protocol2.c:1573 fe-protocol3.c:2089 +#, c-format +msgid "protocol error: id=0x%x\n" +msgstr "błąd protokołu: id=0x%x\n" + +#: fe-protocol3.c:368 +msgid "server sent data (\"D\" message) without prior row description (\"T\" message)\n" +msgstr "serwer wysłał dane (wiadomość \"D\") bez wcześniejszego opisu wiersza " +"(wiadomość \"T\")\n" + +#: fe-protocol3.c:433 +#, c-format +msgid "message contents do not agree with length in message type \"%c\"\n" +msgstr "zawartość wiadomości nie zgadza się z długością wiadomości typu \"%c\"\n" + +#: fe-protocol3.c:454 +#, c-format +msgid "lost synchronization with server: got message type \"%c\", length %d\n" +msgstr "utracono synchronizację z serwerem: otrzymano wiadomość typu\"%c\", długość %d\n" + +#: fe-protocol3.c:505 fe-protocol3.c:545 +msgid "insufficient data in \"T\" message" +msgstr "niewystarczająca ilość danych w wiadomości \"T\"" + +#: fe-protocol3.c:578 +msgid "extraneous data in \"T\" message" +msgstr "nadmiarowe dane w wiadomości \"T\"" + +#: fe-protocol3.c:691 +msgid "extraneous data in \"t\" message" +msgstr "nadmiarowe dane w wiadomości \"t\"" + +#: fe-protocol3.c:762 fe-protocol3.c:794 fe-protocol3.c:812 +msgid "insufficient data in \"D\" message" +msgstr "niewystarczająca ilość danych w wiadomości \"D\"" + +#: fe-protocol3.c:768 +msgid "unexpected field count in \"D\" message" +msgstr "nieoczekiwana liczba pól we wiadomości \"D\"" + +#: fe-protocol3.c:821 +msgid "extraneous data in \"D\" message" +msgstr "nadmiarowe dane w wiadomości \"D\"" + +#: fe-protocol3.c:1005 +msgid "no error message available\n" +msgstr "brak dostępnego komunikatu błędu\n" + +#. translator: %s represents a digit string +#: fe-protocol3.c:1035 fe-protocol3.c:1054 +#, c-format +msgid " at character %s" +msgstr " znak %s" + +#: fe-protocol3.c:1067 +#, c-format +msgid "DETAIL: %s\n" +msgstr "SZCZEGÓŁY: %s\n" + +#: fe-protocol3.c:1070 +#, c-format +msgid "HINT: %s\n" +msgstr "PODPOWIEDŹ: %s\n" + +#: fe-protocol3.c:1073 +#, c-format +msgid "QUERY: %s\n" +msgstr "ZAPYTANIE: %s\n" + +#: fe-protocol3.c:1080 +#, c-format +msgid "CONTEXT: %s\n" +msgstr "KONTEKST: %s\n" + +#: fe-protocol3.c:1089 +#, c-format +msgid "SCHEMA NAME: %s\n" +msgstr "NAZWA SCHEMATU: %s\n" + +#: fe-protocol3.c:1093 +#, c-format +msgid "TABLE NAME: %s\n" +msgstr "NAZWA TABELI: %s\n" + +#: fe-protocol3.c:1097 +#, c-format +msgid "COLUMN NAME: %s\n" +msgstr "NAZWA KOLUMNY: %s\n" + +#: fe-protocol3.c:1101 +#, c-format +msgid "DATATYPE NAME: %s\n" +msgstr "NAZWA TYPU DANYCH: %s\n" + +#: fe-protocol3.c:1105 +#, c-format +msgid "CONSTRAINT NAME: %s\n" +msgstr "NAZWA OGRANICZENIA: %s\n" + +#: fe-protocol3.c:1117 +msgid "LOCATION: " +msgstr "POŁOŻENIE: " + +#: fe-protocol3.c:1119 +#, c-format +msgid "%s, " +msgstr "%s, " + +#: fe-protocol3.c:1121 +#, c-format +msgid "%s:%s" +msgstr "%s:%s" + +#: fe-protocol3.c:1316 +#, c-format +msgid "LINE %d: " +msgstr "LINIA %d: " + +#: fe-protocol3.c:1711 +msgid "PQgetline: not doing text COPY OUT\n" +msgstr "PQgetline: nie działam aktualnie w stanie COPY OUT\n" + +#: fe-secure-openssl.c:234 fe-secure-openssl.c:343 fe-secure-openssl.c:1321 +#, c-format +msgid "SSL SYSCALL error: %s\n" +msgstr "błąd SSL SYSCALL: %s\n" + +#: fe-secure-openssl.c:241 fe-secure-openssl.c:350 fe-secure-openssl.c:1325 +msgid "SSL SYSCALL error: EOF detected\n" +msgstr "błąd SSL SYSCALL: wykryto EOF\n" + +#: fe-secure-openssl.c:252 fe-secure-openssl.c:361 fe-secure-openssl.c:1334 +#, c-format +msgid "SSL error: %s\n" +msgstr "błąd SSL: %s\n" + +#: fe-secure-openssl.c:267 fe-secure-openssl.c:376 +msgid "SSL connection has been closed unexpectedly\n" +msgstr "Połączenie SSL zostało nieoczekiwanie zamknięte\n" + +#: fe-secure-openssl.c:273 fe-secure-openssl.c:382 fe-secure-openssl.c:1343 +#, c-format +msgid "unrecognized SSL error code: %d\n" +msgstr "nieznany błąd SSL o kodzie: %d\n" + +#: fe-secure-openssl.c:494 +msgid "SSL certificate's name entry is missing\n" +msgstr "brak wejścia nazwy certyfikatu SSL\n" + +#: fe-secure-openssl.c:528 +msgid "SSL certificate's name contains embedded null\n" +msgstr "nazwa certyfikatu SSL zawiera osadzony null\n" + +#: fe-secure-openssl.c:580 +msgid "host name must be specified for a verified SSL connection\n" +msgstr "nazwa hosta musi zostać podana dla zweryfikowanego połączenia SSL\n" + +#: fe-secure-openssl.c:680 +#, c-format +msgid "server certificate for \"%s\" does not match host name \"%s\"\n" +msgstr "certyfikat dla serwera \"%s\" nie odpowiada nazwie hosta \"%s\"\n" + +#: fe-secure-openssl.c:686 +msgid "could not get server's host name from server certificate\n" +msgstr "nie można odczytać nazwy serwera z jego certyfikatu\n" + +#: fe-secure-openssl.c:928 +#, c-format +msgid "could not create SSL context: %s\n" +msgstr "nie można utworzyć kontekstu SSL: %s\n" + +#: fe-secure-openssl.c:965 +#, c-format +msgid "could not read root certificate file \"%s\": %s\n" +msgstr "nie można odczytać pliku z certyfikatem użytkownika root \"%s\": %s\n" + +#: fe-secure-openssl.c:993 +#, c-format +msgid "SSL library does not support CRL certificates (file \"%s\")\n" +msgstr "biblioteka SSL nie wspiera certyfikatów CRL (plik \"%s\")\n" + +#: fe-secure-openssl.c:1021 +msgid "" +"could not get home directory to locate root certificate file\n" +"Either provide the file or change sslmode to disable server certificate verification.\n" +msgstr "" +"nie można pobrać folderu domowego aby zlokalizować plik certyfikatu głównego\n" +"Albo dostarcz plik albo zmień tryb ssl by zablokować weryfikację certyfikatu " +"serwera.\n" + +#: fe-secure-openssl.c:1025 +#, c-format +msgid "" +"root certificate file \"%s\" does not exist\n" +"Either provide the file or change sslmode to disable server certificate verification.\n" +msgstr "" +"plik certyfikatu głównego \"%s\" nie istnieje\n" +"Albo dostarcz plik albo zmień tryb ssl by zablokować weryfikację certyfikatu " +"serwera.\n" + +#: fe-secure-openssl.c:1056 +#, c-format +msgid "could not open certificate file \"%s\": %s\n" +msgstr "nie można otworzyć pliku certyfikatu \"%s\": %s\n" + +#: fe-secure-openssl.c:1075 +#, c-format +msgid "could not read certificate file \"%s\": %s\n" +msgstr "nie można odczytać pliku certyfikatu \"%s\": %s\n" + +#: fe-secure-openssl.c:1099 +#, c-format +msgid "could not establish SSL connection: %s\n" +msgstr "nie można ustanowić połączenia SSL: %s\n" + +#: fe-secure-openssl.c:1153 +#, c-format +msgid "could not load SSL engine \"%s\": %s\n" +msgstr "nie można wczytać silnika SSL \"%s\": %s\n" + +#: fe-secure-openssl.c:1165 +#, c-format +msgid "could not initialize SSL engine \"%s\": %s\n" +msgstr "nie można zainicjować silnika SSL \"%s\": %s\n" + +#: fe-secure-openssl.c:1181 +#, c-format +msgid "could not read private SSL key \"%s\" from engine \"%s\": %s\n" +msgstr "nie można odczytać prywatnego klucza SSL \"%s\" z silnika \"%s\": %s\n" + +#: fe-secure-openssl.c:1195 +#, c-format +msgid "could not load private SSL key \"%s\" from engine \"%s\": %s\n" +msgstr "nie można pobrać prywatnego klucza SSL \"%s\" z silnika \"%s\": %s\n" + +#: fe-secure-openssl.c:1232 +#, c-format +msgid "certificate present, but not private key file \"%s\"\n" +msgstr "znaleziono certyfikat ale nie znaleziono pliku z prywatnym kluczem \"%s\"\n" + +#: fe-secure-openssl.c:1240 +#, c-format +msgid "private key file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n" +msgstr "" +"plik hasła \"%s\" posiada globalne lub grupowe uprawnienia odczytu;\n" +"uprawniania powinny być ustawione na u=rw (0600) lub niżej\n" + +#: fe-secure-openssl.c:1251 +#, c-format +msgid "could not load private key file \"%s\": %s\n" +msgstr "nie można pobrać pliku z kluczem prywatnym \"%s\": %s\n" + +#: fe-secure-openssl.c:1265 +#, c-format +msgid "certificate does not match private key file \"%s\": %s\n" +msgstr "certyfikat nie pokrywa się z prywatnym kluczem w pliku \"%s\": %s\n" + +#: fe-secure-openssl.c:1364 +#, c-format +msgid "certificate could not be obtained: %s\n" +msgstr "certyfikat nie może zostać otrzymany: %s\n" + +#: fe-secure-openssl.c:1456 +#, c-format +msgid "no SSL error reported" +msgstr "nie zgłoszono błędu SSL" + +#: fe-secure-openssl.c:1465 +#, c-format +msgid "SSL error code %lu" +msgstr "kod błędu SSL %lu" + +#: fe-secure.c:261 +#, c-format +msgid "could not receive data from server: %s\n" +msgstr "nie można otrzymać danych z serwera: %s\n" + +#: fe-secure.c:369 +#, c-format +msgid "could not send data to server: %s\n" +msgstr "nie można wysłać danych do serwera: %s\n" + +#: win32.c:317 +#, c-format +msgid "unrecognized socket error: 0x%08X/%d" +msgstr "nierozpoznany błąd gniazda: 0x%08X/%d" + +#~ msgid "socket not open\n" +#~ msgstr "gniazdo nie jest otwarte\n" + +#~ msgid "Kerberos 5 authentication rejected: %*s\n" +#~ msgstr "Kerberos 5 autoryzacja odrzucona: %*s\n" + +#~ msgid "could not set socket to blocking mode: %s\n" +#~ msgstr "nie można ustawić gniazda w tryb blokowania: %s\n" + +#~ msgid "could not acquire mutex: %s\n" +#~ msgstr "nie można uzyskać muteksu: %s\n" diff --git a/src/interfaces/libpq/po/pt_BR.po b/src/interfaces/libpq/po/pt_BR.po new file mode 100644 index 0000000..daef5f6 --- /dev/null +++ b/src/interfaces/libpq/po/pt_BR.po @@ -0,0 +1,1480 @@ +# Brazilian Portuguese message translation file for libpq +# Copyright (C) 2009 PostgreSQL Global Development Group +# This file is distributed under the same license as the PostgreSQL package. +# Cesar Suga <sartre@linuxbr.com>, 2002. +# Roberto Mello <rmello@fslc.usu.edu>, 2002. +# Euler Taveira de Oliveira <euler@timbira.com>, 2003-2016. +# Halley Pacheco de Oliveira <halley@vivaldi.net>, 2023-2024. +# +msgid "" +msgstr "" +"Project-Id-Version: PostgreSQL 16\n" +"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" +"POT-Creation-Date: 2024-01-02 15:53-0300\n" +"PO-Revision-Date: 2024-01-02 14:35-0300\n" +"Last-Translator: Halley Pacheco de Oliveira <halley@vivaldi.net>\n" +"Language-Team: Brazilian Portuguese <pgsql-translators@postgresql.org>\n" +"Language: pt_BR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Generator: Poedit 3.4.1\n" + +#: ../../port/thread.c:50 ../../port/thread.c:86 +#, c-format +msgid "could not look up local user ID %d: %s" +msgstr "não foi possível procurar o ID do usuário local %d: %s" + +#: ../../port/thread.c:55 ../../port/thread.c:91 +#, c-format +msgid "local user with ID %d does not exist" +msgstr "o usuário local com ID %d não existe" + +#: fe-auth-scram.c:227 +#, c-format +msgid "malformed SCRAM message (empty message)" +msgstr "mensagem SCRAM malformada (mensagem vazia)" + +#: fe-auth-scram.c:232 +#, c-format +msgid "malformed SCRAM message (length mismatch)" +msgstr "mensagem SCRAM malformada (o comprimento não corresponde)" + +#: fe-auth-scram.c:275 +#, c-format +msgid "could not verify server signature: %s" +msgstr "não foi possível verificar a assinatura do servidor: %s" + +#: fe-auth-scram.c:281 +#, c-format +msgid "incorrect server signature" +msgstr "assinatura do servidor incorreta" + +#: fe-auth-scram.c:290 +#, c-format +msgid "invalid SCRAM exchange state" +msgstr "estado de troca SCRAM inválido" + +#: fe-auth-scram.c:317 +#, c-format +msgid "malformed SCRAM message (attribute \"%c\" expected)" +msgstr "mensagem SCRAM malformada (esperado o atributo \"%c\")" + +#: fe-auth-scram.c:326 +#, c-format +msgid "malformed SCRAM message (expected character \"=\" for attribute \"%c\")" +msgstr "mensagem SCRAM malformada (esperado o caractere \"=\" para o atributo \"%c\")" + +#: fe-auth-scram.c:366 +#, c-format +msgid "could not generate nonce" +msgstr "não foi possível gerar nonce" + +#: fe-auth-scram.c:375 fe-auth-scram.c:448 fe-auth-scram.c:600 +#: fe-auth-scram.c:620 fe-auth-scram.c:644 fe-auth-scram.c:658 +#: fe-auth-scram.c:704 fe-auth-scram.c:740 fe-auth-scram.c:914 fe-auth.c:296 +#: fe-auth.c:369 fe-auth.c:403 fe-auth.c:618 fe-auth.c:729 fe-auth.c:1210 +#: fe-auth.c:1375 fe-connect.c:925 fe-connect.c:1759 fe-connect.c:1921 +#: fe-connect.c:3291 fe-connect.c:4496 fe-connect.c:5161 fe-connect.c:5416 +#: fe-connect.c:5534 fe-connect.c:5781 fe-connect.c:5861 fe-connect.c:5959 +#: fe-connect.c:6210 fe-connect.c:6237 fe-connect.c:6313 fe-connect.c:6336 +#: fe-connect.c:6360 fe-connect.c:6395 fe-connect.c:6481 fe-connect.c:6489 +#: fe-connect.c:6846 fe-connect.c:6996 fe-exec.c:527 fe-exec.c:1321 +#: fe-exec.c:3130 fe-exec.c:4098 fe-exec.c:4262 fe-gssapi-common.c:109 +#: fe-lobj.c:870 fe-protocol3.c:204 fe-protocol3.c:228 fe-protocol3.c:251 +#: fe-protocol3.c:268 fe-protocol3.c:348 fe-protocol3.c:715 fe-protocol3.c:954 +#: fe-protocol3.c:1765 fe-protocol3.c:2165 fe-secure-common.c:110 +#: fe-secure-gssapi.c:496 fe-secure-openssl.c:440 fe-secure-openssl.c:1291 +#, c-format +msgid "out of memory" +msgstr "sem memória" + +#: fe-auth-scram.c:382 +#, c-format +msgid "could not encode nonce" +msgstr "não foi possível codificar nonce" + +#: fe-auth-scram.c:570 +#, c-format +msgid "could not calculate client proof: %s" +msgstr "não foi possível calcular a prova do cliente: %s" + +#: fe-auth-scram.c:585 +#, c-format +msgid "could not encode client proof" +msgstr "não foi possível codificar a prova do cliente" + +#: fe-auth-scram.c:637 +#, c-format +msgid "invalid SCRAM response (nonce mismatch)" +msgstr "resposta SCRAM inválida (nonce não corresponde)" + +#: fe-auth-scram.c:667 +#, c-format +msgid "malformed SCRAM message (invalid salt)" +msgstr "mensagem SCRAM malformada (sal inválido)" + +#: fe-auth-scram.c:680 +#, c-format +msgid "malformed SCRAM message (invalid iteration count)" +msgstr "mensagem SCRAM malformada (contagem de iteração inválida)" + +#: fe-auth-scram.c:685 +#, c-format +msgid "malformed SCRAM message (garbage at end of server-first-message)" +msgstr "mensagem SCRAM malformada (lixo no final da primeira mensagem do servidor)" + +#: fe-auth-scram.c:719 +#, c-format +msgid "error received from server in SCRAM exchange: %s" +msgstr "erro recebido do servidor na troca SCRAM: %s" + +#: fe-auth-scram.c:734 +#, c-format +msgid "malformed SCRAM message (garbage at end of server-final-message)" +msgstr "mensagem SCRAM malformada (lixo no final da mensagem final do servidor)" + +#: fe-auth-scram.c:751 +#, c-format +msgid "malformed SCRAM message (invalid server signature)" +msgstr "mensagem SCRAM malformada (assinatura do servidor inválida)" + +#: fe-auth-scram.c:923 +msgid "could not generate random salt" +msgstr "não foi possível gerar sal aleatório" + +#: fe-auth.c:77 +#, c-format +msgid "out of memory allocating GSSAPI buffer (%d)" +msgstr "sem memória para alocar buffer para GSSAPI (%d)" + +#: fe-auth.c:138 +msgid "GSSAPI continuation error" +msgstr "erro de continuação do GSSAPI" + +#: fe-auth.c:168 fe-auth.c:397 fe-gssapi-common.c:97 fe-secure-common.c:99 +#: fe-secure-common.c:173 +#, c-format +msgid "host name must be specified" +msgstr "deve ser especificado o nome do hospedeiro" + +#: fe-auth.c:174 +#, c-format +msgid "duplicate GSS authentication request" +msgstr "solicitação de autenticação GSS duplicada" + +#: fe-auth.c:238 +#, c-format +msgid "out of memory allocating SSPI buffer (%d)" +msgstr "sem memória para alocar o buffer SSPI (%d)" + +#: fe-auth.c:285 +msgid "SSPI continuation error" +msgstr "erro de continuação SSPI" + +#: fe-auth.c:359 +#, c-format +msgid "duplicate SSPI authentication request" +msgstr "solicitação de autenticação SSPI duplicada" + +#: fe-auth.c:384 +msgid "could not acquire SSPI credentials" +msgstr "não foi possível adquirir credenciais SSPI" + +#: fe-auth.c:437 +#, c-format +msgid "channel binding required, but SSL not in use" +msgstr "vinculação de canal necessária, mas SSL não está em uso" + +#: fe-auth.c:443 +#, c-format +msgid "duplicate SASL authentication request" +msgstr "solicitação de autenticação SASL duplicada" + +#: fe-auth.c:501 +#, c-format +msgid "channel binding is required, but client does not support it" +msgstr "a vinculação de canal é necessária, mas o cliente não oferece suporte" + +#: fe-auth.c:517 +#, c-format +msgid "server offered SCRAM-SHA-256-PLUS authentication over a non-SSL connection" +msgstr "o servidor ofereceu autenticação SCRAM-SHA-256-PLUS em uma conexão não-SSL" + +#: fe-auth.c:531 +#, c-format +msgid "none of the server's SASL authentication mechanisms are supported" +msgstr "nenhum dos mecanismos de autenticação SASL do servidor tem suporte" + +#: fe-auth.c:538 +#, c-format +msgid "channel binding is required, but server did not offer an authentication method that supports channel binding" +msgstr "a vinculação de canal é necessária, mas o servidor não oferece um método de autenticação que dê suporte a vinculação de canal" + +#: fe-auth.c:641 +#, c-format +msgid "out of memory allocating SASL buffer (%d)" +msgstr "sem memória para alocar o buffer SASL (%d)" + +#: fe-auth.c:665 +#, c-format +msgid "AuthenticationSASLFinal received from server, but SASL authentication was not completed" +msgstr "AuthenticationSASLFinal recebida do servidor, mas a autenticação SASL não foi concluída" + +#: fe-auth.c:675 +#, c-format +msgid "no client response found after SASL exchange success" +msgstr "nenhuma resposta do cliente encontrada após a troca SASL bem-sucedida" + +#: fe-auth.c:738 fe-auth.c:745 fe-auth.c:1358 fe-auth.c:1369 +#, c-format +msgid "could not encrypt password: %s" +msgstr "não foi possível encriptar a senha: %s" + +#: fe-auth.c:773 +msgid "server requested a cleartext password" +msgstr "o servidor solicitou uma senha em texto puro" + +#: fe-auth.c:775 +msgid "server requested a hashed password" +msgstr "o servidor solicitou uma senha com hash" + +#: fe-auth.c:778 +msgid "server requested GSSAPI authentication" +msgstr "o servidor solicitou autenticação GSSAPI" + +#: fe-auth.c:780 +msgid "server requested SSPI authentication" +msgstr "o servidor solicitou autenticação SSPI" + +#: fe-auth.c:784 +msgid "server requested SASL authentication" +msgstr "o servidor solicitou autenticação SASL" + +#: fe-auth.c:787 +msgid "server requested an unknown authentication type" +msgstr "o servidor solicitou um tipo de autenticação desconhecido" + +#: fe-auth.c:820 +#, c-format +msgid "server did not request an SSL certificate" +msgstr "o servidor não solicitou um certificado SSL" + +#: fe-auth.c:825 +#, c-format +msgid "server accepted connection without a valid SSL certificate" +msgstr "o servidor aceitou uma conexão sem um certificado SSL válido" + +#: fe-auth.c:879 +msgid "server did not complete authentication" +msgstr "o servidor não concluiu a autenticação" + +#: fe-auth.c:913 +#, c-format +msgid "authentication method requirement \"%s\" failed: %s" +msgstr "o requisito do método de autenticação \"%s\" falhou: %s" + +#: fe-auth.c:936 +#, c-format +msgid "channel binding required, but server authenticated client without channel binding" +msgstr "vinculação de canal requerida, mas o servidor autenticou o cliente sem vinculação de canal" + +#: fe-auth.c:941 +#, c-format +msgid "channel binding required but not supported by server's authentication request" +msgstr "vinculação de canal requerida, mas não tem suporte pelo pedido de autenticação do servidor" + +#: fe-auth.c:975 +#, c-format +msgid "Kerberos 4 authentication not supported" +msgstr "autenticação Kerberos 4 não tem suporte" + +#: fe-auth.c:979 +#, c-format +msgid "Kerberos 5 authentication not supported" +msgstr "autenticação Kerberos 5 não tem suporte" + +#: fe-auth.c:1049 +#, c-format +msgid "GSSAPI authentication not supported" +msgstr "autenticação GSSAPI não tem suporte" + +#: fe-auth.c:1080 +#, c-format +msgid "SSPI authentication not supported" +msgstr "autenticação SSPI não tem suporte" + +#: fe-auth.c:1087 +#, c-format +msgid "Crypt authentication not supported" +msgstr "autenticação Crypt não tem suporte" + +#: fe-auth.c:1151 +#, c-format +msgid "authentication method %u not supported" +msgstr "o método de autenticação %u não tem suporte" + +#: fe-auth.c:1197 +#, c-format +msgid "user name lookup failure: error code %lu" +msgstr "falha na procura do nome de usuário: código de erro %lu" + +#: fe-auth.c:1321 +#, c-format +msgid "unexpected shape of result set returned for SHOW" +msgstr "forma não esperada do conjunto de resultados retornado para SHOW" + +#: fe-auth.c:1329 +#, c-format +msgid "password_encryption value too long" +msgstr "valor de password_encryption muito longo" + +#: fe-auth.c:1379 +#, c-format +msgid "unrecognized password encryption algorithm \"%s\"" +msgstr "algoritmo de encriptação de senha não reconhecido \"%s\"" + +#: fe-connect.c:1132 +#, c-format +msgid "could not match %d host names to %d hostaddr values" +msgstr "não é possível corresponder %d nomes de hospedeiro com %d valores de endereço" + +#: fe-connect.c:1212 +#, c-format +msgid "could not match %d port numbers to %d hosts" +msgstr "não é possível corresponder %d número de portas com %d hospedeiros" + +#: fe-connect.c:1337 +#, c-format +msgid "negative require_auth method \"%s\" cannot be mixed with non-negative methods" +msgstr "o método require_auth negativo \"%s\" não pode ser misturado com métodos não negativos" + +#: fe-connect.c:1350 +#, c-format +msgid "require_auth method \"%s\" cannot be mixed with negative methods" +msgstr "o método require_auth \"%s\" não pode ser misturado com métodos negativos" + +#: fe-connect.c:1410 fe-connect.c:1461 fe-connect.c:1503 fe-connect.c:1559 +#: fe-connect.c:1567 fe-connect.c:1598 fe-connect.c:1644 fe-connect.c:1684 +#: fe-connect.c:1705 +#, c-format +msgid "invalid %s value: \"%s\"" +msgstr "valor %s inválido: \"%s\"" + +#: fe-connect.c:1443 +#, c-format +msgid "require_auth method \"%s\" is specified more than once" +msgstr "o método require_auth \"%s\" foi especificado mais de uma vez" + +#: fe-connect.c:1484 fe-connect.c:1523 fe-connect.c:1606 +#, c-format +msgid "%s value \"%s\" invalid when SSL support is not compiled in" +msgstr "o valor «%2$s» de %1$s não é válido quando o suporte a SSL não está compilado" + +#: fe-connect.c:1546 +#, c-format +msgid "weak sslmode \"%s\" may not be used with sslrootcert=system (use \"verify-full\")" +msgstr "sslmode fraco \"%s\" não pode ser usado com sslrootcert=system (use \"verify-full\")" + +#: fe-connect.c:1584 +#, c-format +msgid "invalid SSL protocol version range" +msgstr "intervalo de versões do protocolo SSL inválido" + +#: fe-connect.c:1621 +#, c-format +msgid "%s value \"%s\" is not supported (check OpenSSL version)" +msgstr "o valor %s \"%s\" não tem suporte (verifique a versão do OpenSSL)" + +#: fe-connect.c:1651 +#, c-format +msgid "gssencmode value \"%s\" invalid when GSSAPI support is not compiled in" +msgstr "o valor de gssencmode \"%s\" não é válido quando o suporte a GSSAPI não foi compilado" + +#: fe-connect.c:1944 +#, c-format +msgid "could not set socket to TCP no delay mode: %s" +msgstr "não foi possível definir o soquete no modo TCP sem atraso: %s" + +#: fe-connect.c:2003 +#, c-format +msgid "connection to server on socket \"%s\" failed: " +msgstr "a conexão com o servidor no soquete \"%s\" falhou: " + +#: fe-connect.c:2029 +#, c-format +msgid "connection to server at \"%s\" (%s), port %s failed: " +msgstr "a conexão com o servidor em \"%s\" (%s), porta %s falhou: " + +#: fe-connect.c:2034 +#, c-format +msgid "connection to server at \"%s\", port %s failed: " +msgstr "a conexão com o servidor em \"%s\", porta %s falhou: " + +#: fe-connect.c:2057 +#, c-format +msgid "\tIs the server running locally and accepting connections on that socket?" +msgstr "\tO servidor está em execução localmente e aceitando conexões nesse soquete?" + +#: fe-connect.c:2059 +#, c-format +msgid "\tIs the server running on that host and accepting TCP/IP connections?" +msgstr "\tO servidor está em execução nesse hospedeiro e aceitando conexões TCP/IP?" + +#: fe-connect.c:2122 +#, c-format +msgid "invalid integer value \"%s\" for connection option \"%s\"" +msgstr "valor inteiro inválido \"%s\" para a opção de conexão \"%s\"" + +#: fe-connect.c:2151 fe-connect.c:2185 fe-connect.c:2220 fe-connect.c:2318 +#: fe-connect.c:2973 +#, c-format +msgid "%s(%s) failed: %s" +msgstr "%s(%s) falhou: %s" + +#: fe-connect.c:2284 +#, c-format +msgid "%s(%s) failed: error code %d" +msgstr "%s(%s) falhou: código de erro %d" + +#: fe-connect.c:2597 +#, c-format +msgid "invalid connection state, probably indicative of memory corruption" +msgstr "estado da conexão inválido, provável indicação de corrupção de memória" + +#: fe-connect.c:2676 +#, c-format +msgid "invalid port number: \"%s\"" +msgstr "número da porta inválido: \"%s\"" + +#: fe-connect.c:2690 +#, c-format +msgid "could not translate host name \"%s\" to address: %s" +msgstr "não foi possível traduzir o nome de hospedeiro \"%s\" para um endereço: %s" + +#: fe-connect.c:2702 +#, c-format +msgid "could not parse network address \"%s\": %s" +msgstr "não foi possível analisar o endereço de rede \"%s\": %s" + +#: fe-connect.c:2713 +#, c-format +msgid "Unix-domain socket path \"%s\" is too long (maximum %d bytes)" +msgstr "caminho do soquete de domínio Unix \"%s\" é muito longo (máximo de %d bytes)" + +#: fe-connect.c:2727 +#, c-format +msgid "could not translate Unix-domain socket path \"%s\" to address: %s" +msgstr "não foi possível traduzir o caminho do soquete de domínio Unix \"%s\" para um endereço: %s" + +#: fe-connect.c:2901 +#, c-format +msgid "could not create socket: %s" +msgstr "não foi possível criar o soquete: %s" + +#: fe-connect.c:2932 +#, c-format +msgid "could not set socket to nonblocking mode: %s" +msgstr "não foi possível definir o soquete para o modo não bloqueante: %s" + +#: fe-connect.c:2943 +#, c-format +msgid "could not set socket to close-on-exec mode: %s" +msgstr "não foi possível definir o soquete para o modo close-on-exec: %s" + +#: fe-connect.c:2961 +#, c-format +msgid "keepalives parameter must be an integer" +msgstr "o parâmetro keepalives deve ser um número inteiro" + +#: fe-connect.c:3100 +#, c-format +msgid "could not get socket error status: %s" +msgstr "não foi possível obter o status de erro do soquete: %s" + +#: fe-connect.c:3127 +#, c-format +msgid "could not get client address from socket: %s" +msgstr "não foi possível obter o endereço do cliente do soquete: %s" + +#: fe-connect.c:3165 +#, c-format +msgid "requirepeer parameter is not supported on this platform" +msgstr "o parâmetro requirepeer não tem suporte nessa plataforma" + +#: fe-connect.c:3167 +#, c-format +msgid "could not get peer credentials: %s" +msgstr "não foi possível obter as credenciais do parceiro: %s" + +#: fe-connect.c:3180 +#, c-format +msgid "requirepeer specifies \"%s\", but actual peer user name is \"%s\"" +msgstr "requirepeer especifica \"%s\", mas o nome real do usuário parceiro é \"%s\"" + +#: fe-connect.c:3221 +#, c-format +msgid "could not send GSSAPI negotiation packet: %s" +msgstr "não foi possível enviar o pacote de negociação GSSAPI: %s" + +#: fe-connect.c:3233 +#, c-format +msgid "GSSAPI encryption required but was impossible (possibly no credential cache, no server support, or using a local socket)" +msgstr "A encriptação GSSAPI é requerida, mas não foi possível (possivelmente sem cache de credenciais, sem suporte do servidor, ou usando um soquete local)" + +#: fe-connect.c:3274 +#, c-format +msgid "could not send SSL negotiation packet: %s" +msgstr "não foi possível enviar o pacote de negociação SSL: %s" + +#: fe-connect.c:3303 +#, c-format +msgid "could not send startup packet: %s" +msgstr "não foi possível enviar o pacote de inicialização: %s" + +#: fe-connect.c:3378 +#, c-format +msgid "server does not support SSL, but SSL was required" +msgstr "o servidor não oferece suporte a SSL, mas SSL é requerido" + +#: fe-connect.c:3404 +#, c-format +msgid "received invalid response to SSL negotiation: %c" +msgstr "recebida resposta inválida para negociação SSL: %c" + +#: fe-connect.c:3424 +#, c-format +msgid "received unencrypted data after SSL response" +msgstr "recebidos dados não encriptados após resposta SSL" + +#: fe-connect.c:3504 +#, c-format +msgid "server doesn't support GSSAPI encryption, but it was required" +msgstr "o servidor não oferece suporte a encriptação GSSAPI, mas é requerida" + +#: fe-connect.c:3515 +#, c-format +msgid "received invalid response to GSSAPI negotiation: %c" +msgstr "recebida resposta inválida para negociação GSSAPI: %c" + +#: fe-connect.c:3533 +#, c-format +msgid "received unencrypted data after GSSAPI encryption response" +msgstr "recebidos dados não encriptados após resposta de encriptação GSSAPI" + +#: fe-connect.c:3598 +#, c-format +msgid "expected authentication request from server, but received %c" +msgstr "esperada uma solicitação de autenticação do servidor, mas não foi recebida %c" + +#: fe-connect.c:3625 fe-connect.c:3794 +#, c-format +msgid "received invalid authentication request" +msgstr "recebida uma solicitação de autenticação inválida" + +#: fe-connect.c:3630 fe-connect.c:3779 +#, c-format +msgid "received invalid protocol negotiation message" +msgstr "recebida uma mensagem de negociação de protocolo inválida" + +#: fe-connect.c:3648 fe-connect.c:3702 +#, c-format +msgid "received invalid error message" +msgstr "recebida uma mensagem de erro inválida" + +#: fe-connect.c:3865 +#, c-format +msgid "unexpected message from server during startup" +msgstr "recebida uma mensagem não esperada do servidor durante a inicialização" + +#: fe-connect.c:3956 +#, c-format +msgid "session is read-only" +msgstr "a sessão é de leitura-apenas" + +#: fe-connect.c:3958 +#, c-format +msgid "session is not read-only" +msgstr "a sessão não é de leitura-apenas" + +#: fe-connect.c:4011 +#, c-format +msgid "server is in hot standby mode" +msgstr "o servidor está no modo hot-standby (ativo, em-espera)" + +#: fe-connect.c:4013 +#, c-format +msgid "server is not in hot standby mode" +msgstr "o servidor não está no modo hot-standby (ativo, em-espera)" + +#: fe-connect.c:4129 fe-connect.c:4179 +#, c-format +msgid "\"%s\" failed" +msgstr "\"%s\" falhou" + +#: fe-connect.c:4193 +#, c-format +msgid "invalid connection state %d, probably indicative of memory corruption" +msgstr "estado da conexão inválido (%d), provavelmente indicativo de corrupção de memória" + +#: fe-connect.c:5174 +#, c-format +msgid "invalid LDAP URL \"%s\": scheme must be ldap://" +msgstr "URL LDAP \"%s\" inválido: o esquema deve ser ldap://" + +#: fe-connect.c:5189 +#, c-format +msgid "invalid LDAP URL \"%s\": missing distinguished name" +msgstr "URL LDAP \"%s\" inválido: nome distinto ausente" + +#: fe-connect.c:5201 fe-connect.c:5259 +#, c-format +msgid "invalid LDAP URL \"%s\": must have exactly one attribute" +msgstr "URL LDAP \"%s\" inválido: deve ter exatamente um atributo" + +#: fe-connect.c:5213 fe-connect.c:5275 +#, c-format +msgid "invalid LDAP URL \"%s\": must have search scope (base/one/sub)" +msgstr "URL LDAP \"%s\" inválido: deve ter o escopo da procura (base/one/sub)" + +#: fe-connect.c:5225 +#, c-format +msgid "invalid LDAP URL \"%s\": no filter" +msgstr "URL LDAP \"%s\" inválido: sem filtro" + +#: fe-connect.c:5247 +#, c-format +msgid "invalid LDAP URL \"%s\": invalid port number" +msgstr "URL LDAP \"%s\" inválido: número de porta inválido" + +#: fe-connect.c:5284 +#, c-format +msgid "could not create LDAP structure" +msgstr "não foi possível criar a estrutura LDAP" + +#: fe-connect.c:5359 +#, c-format +msgid "lookup on LDAP server failed: %s" +msgstr "falha na procura no servidor LDAP: %s" + +#: fe-connect.c:5369 +#, c-format +msgid "more than one entry found on LDAP lookup" +msgstr "mais de uma entrada encontrada na procura LDAP" + +#: fe-connect.c:5371 fe-connect.c:5382 +#, c-format +msgid "no entry found on LDAP lookup" +msgstr "nenhuma entrada encontrada na procura LDAP" + +#: fe-connect.c:5392 fe-connect.c:5404 +#, c-format +msgid "attribute has no values on LDAP lookup" +msgstr "o atributo não tem valores na procura LDAP" + +#: fe-connect.c:5455 fe-connect.c:5474 fe-connect.c:5998 +#, c-format +msgid "missing \"=\" after \"%s\" in connection info string" +msgstr "faltando \"=\" após \"%s\" na cadeia de caracteres de informações da conexão" + +#: fe-connect.c:5545 fe-connect.c:6181 fe-connect.c:6979 +#, c-format +msgid "invalid connection option \"%s\"" +msgstr "opção de conexão inválida \"%s\"" + +#: fe-connect.c:5560 fe-connect.c:6046 +#, c-format +msgid "unterminated quoted string in connection info string" +msgstr "cadeia de caracteres delimitada não terminada na cadeia de caracteres de informações da conexão" + +#: fe-connect.c:5640 +#, c-format +msgid "definition of service \"%s\" not found" +msgstr "definição de serviço \"%s\" não encontrada" + +#: fe-connect.c:5666 +#, c-format +msgid "service file \"%s\" not found" +msgstr "arquivo de serviço \"%s\" não encontrado" + +#: fe-connect.c:5679 +#, c-format +msgid "line %d too long in service file \"%s\"" +msgstr "linha %d muito longa no arquivo de serviço \"%s\"" + +#: fe-connect.c:5750 fe-connect.c:5793 +#, c-format +msgid "syntax error in service file \"%s\", line %d" +msgstr "erro de sintaxe no arquivo de serviço \"%s\", linha %d" + +#: fe-connect.c:5761 +#, c-format +msgid "nested service specifications not supported in service file \"%s\", line %d" +msgstr "especificações de serviço aninhadas sem suporte no arquivo de serviço \"%s\", linha %d" + +#: fe-connect.c:6500 +#, c-format +msgid "invalid URI propagated to internal parser routine: \"%s\"" +msgstr "URI inválido propagado para a rotina do analisador interno: \"%s\"" + +#: fe-connect.c:6577 +#, c-format +msgid "end of string reached when looking for matching \"]\" in IPv6 host address in URI: \"%s\"" +msgstr "alcançado o fim da cadeia de caracteres ao procurar pelo \"]\" correspondente no endereço de hospedeiro IPv6 no URI: \"%s\"" + +#: fe-connect.c:6584 +#, c-format +msgid "IPv6 host address may not be empty in URI: \"%s\"" +msgstr "o endereço de hospedeiro IPv6 não pode estar vazio no URI: \"%s\"" + +#: fe-connect.c:6599 +#, c-format +msgid "unexpected character \"%c\" at position %d in URI (expected \":\" or \"/\"): \"%s\"" +msgstr "caractere não esperado \"%c\" na posição %d no URI (esperado \":\" ou \"/\"): \"%s\"" + +#: fe-connect.c:6728 +#, c-format +msgid "extra key/value separator \"=\" in URI query parameter: \"%s\"" +msgstr "separador extra de chave/valor \"=\" no parâmetro de consulta URI: \"%s\"" + +#: fe-connect.c:6748 +#, c-format +msgid "missing key/value separator \"=\" in URI query parameter: \"%s\"" +msgstr "falta o separador \"=\" de chave/valor no parâmetro da consulta URI: \"%s\"" + +#: fe-connect.c:6800 +#, c-format +msgid "invalid URI query parameter: \"%s\"" +msgstr "parâmetro da consulta de URI inválido: \"%s\"" + +#: fe-connect.c:6874 +#, c-format +msgid "invalid percent-encoded token: \"%s\"" +msgstr "elemento codificado por porcentagem inválido: \"%s\"" + +#: fe-connect.c:6884 +#, c-format +msgid "forbidden value %%00 in percent-encoded value: \"%s\"" +msgstr "valor %%00 proibido em valor codificado com porcentagem: \"%s\"" + +#: fe-connect.c:7248 +msgid "connection pointer is NULL\n" +msgstr "o ponteiro da conexão é nulo\n" + +#: fe-connect.c:7256 fe-exec.c:710 fe-exec.c:970 fe-exec.c:3319 +#: fe-protocol3.c:969 fe-protocol3.c:1002 +msgid "out of memory\n" +msgstr "sem memória\n" + +#: fe-connect.c:7547 +#, c-format +msgid "WARNING: password file \"%s\" is not a plain file\n" +msgstr "ADVERTÊNCIA: o arquivo de senhas \"%s\" não é um arquivo de texto puro\n" + +#: fe-connect.c:7556 +#, c-format +msgid "WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n" +msgstr "ADVERTÊNCIA: o arquivo de senhas \"%s\" possui acesso para grupo ou para todos; as permissões devem ser u=rw (0600) ou menor\n" + +#: fe-connect.c:7663 +#, c-format +msgid "password retrieved from file \"%s\"" +msgstr "senha recuperada do arquivo \"%s\"" + +#: fe-exec.c:466 fe-exec.c:3393 +#, c-format +msgid "row number %d is out of range 0..%d" +msgstr "o número da linha %d está fora do intervalo 0..%d" + +#: fe-exec.c:528 fe-protocol3.c:1971 +#, c-format +msgid "%s" +msgstr "%s" + +#: fe-exec.c:831 +#, c-format +msgid "write to server failed" +msgstr "a escrita no servidor falhou" + +#: fe-exec.c:869 +#, c-format +msgid "no error text available" +msgstr "nenhum texto de erro disponível" + +#: fe-exec.c:958 +msgid "NOTICE" +msgstr "AVISO" + +#: fe-exec.c:1016 +msgid "PGresult cannot support more than INT_MAX tuples" +msgstr "PGresult não dá suporte a mais do que INT_MAX tuplas" + +#: fe-exec.c:1028 +msgid "size_t overflow" +msgstr "size_t acima do permitido" + +#: fe-exec.c:1444 fe-exec.c:1513 fe-exec.c:1559 +#, c-format +msgid "command string is a null pointer" +msgstr "a cadeia de caracteres de comando é um ponteiro nulo" + +#: fe-exec.c:1450 fe-exec.c:2881 +#, c-format +msgid "%s not allowed in pipeline mode" +msgstr "%s não permitido no modo pipeline" + +#: fe-exec.c:1518 fe-exec.c:1564 fe-exec.c:1658 +#, c-format +msgid "number of parameters must be between 0 and %d" +msgstr "o número de parâmetros deve estar entre 0 e %d" + +#: fe-exec.c:1554 fe-exec.c:1653 +#, c-format +msgid "statement name is a null pointer" +msgstr "o nome da instrução é um ponteiro nulo" + +#: fe-exec.c:1695 fe-exec.c:3239 +#, c-format +msgid "no connection to the server" +msgstr "sem conexão com o servidor" + +#: fe-exec.c:1703 fe-exec.c:3247 +#, c-format +msgid "another command is already in progress" +msgstr "outro comando já está em andamento" + +#: fe-exec.c:1733 +#, c-format +msgid "cannot queue commands during COPY" +msgstr "não é possível enfileirar comandos durante o COPY" + +#: fe-exec.c:1850 +#, c-format +msgid "length must be given for binary parameter" +msgstr "deve ser fornecido o comprimento para parâmetro binário" + +#: fe-exec.c:2164 +#, c-format +msgid "unexpected asyncStatus: %d" +msgstr "asyncStatus não esperado: %d" + +#: fe-exec.c:2320 +#, c-format +msgid "synchronous command execution functions are not allowed in pipeline mode" +msgstr "as funções de execução de comando síncrono não são permitidas no modo pipeline" + +#: fe-exec.c:2337 +msgid "COPY terminated by new PQexec" +msgstr "COPY terminado por novo PQexec" + +#: fe-exec.c:2353 +#, c-format +msgid "PQexec not allowed during COPY BOTH" +msgstr "PQexec não é permitido durante COPY BOTH" + +#: fe-exec.c:2579 fe-exec.c:2634 fe-exec.c:2702 fe-protocol3.c:1902 +#, c-format +msgid "no COPY in progress" +msgstr "nenhuma COPY em andamento" + +#: fe-exec.c:2888 +#, c-format +msgid "connection in wrong state" +msgstr "conexão em estado errado" + +#: fe-exec.c:2931 +#, c-format +msgid "cannot enter pipeline mode, connection not idle" +msgstr "não é possível entrar no modo pipeline, a conexão não está ociosa" + +#: fe-exec.c:2967 fe-exec.c:2988 +#, c-format +msgid "cannot exit pipeline mode with uncollected results" +msgstr "não é possível sair do modo pipeline com resultados não coletados" + +#: fe-exec.c:2971 +#, c-format +msgid "cannot exit pipeline mode while busy" +msgstr "não é possível sair do modo pipeline enquanto estiver ocupado" + +#: fe-exec.c:2982 +#, c-format +msgid "cannot exit pipeline mode while in COPY" +msgstr "não é possível sair do modo pipeline enquanto estiver em COPY" + +#: fe-exec.c:3173 +#, c-format +msgid "cannot send pipeline when not in pipeline mode" +msgstr "não é possível enviar pipeline quando não se está no modo pipeline" + +#: fe-exec.c:3282 +msgid "invalid ExecStatusType code" +msgstr "código de ExecStatusType inválido" + +#: fe-exec.c:3309 +msgid "PGresult is not an error result\n" +msgstr "PGresult não é um resultado de erro\n" + +#: fe-exec.c:3377 fe-exec.c:3400 +#, c-format +msgid "column number %d is out of range 0..%d" +msgstr "a coluna número %d está fora do intervalo 0..%d" + +#: fe-exec.c:3415 +#, c-format +msgid "parameter number %d is out of range 0..%d" +msgstr "o parâmetro número %d está fora do intervalo 0..%d" + +#: fe-exec.c:3726 +#, c-format +msgid "could not interpret result from server: %s" +msgstr "não foi possível interpretar o resultado do servidor: %s" + +#: fe-exec.c:3991 fe-exec.c:4081 +#, c-format +msgid "incomplete multibyte character" +msgstr "caractere multibyte incompleto" + +#: fe-gssapi-common.c:122 +msgid "GSSAPI name import error" +msgstr "erro de importação de nome GSSAPI" + +#: fe-lobj.c:144 fe-lobj.c:207 fe-lobj.c:397 fe-lobj.c:487 fe-lobj.c:560 +#: fe-lobj.c:956 fe-lobj.c:963 fe-lobj.c:970 fe-lobj.c:977 fe-lobj.c:984 +#: fe-lobj.c:991 fe-lobj.c:998 fe-lobj.c:1005 +#, c-format +msgid "cannot determine OID of function %s" +msgstr "não foi possível determinar o OID da função %s" + +#: fe-lobj.c:160 +#, c-format +msgid "argument of lo_truncate exceeds integer range" +msgstr "o argumento de lo_truncate excede o intervalo inteiro" + +#: fe-lobj.c:262 +#, c-format +msgid "argument of lo_read exceeds integer range" +msgstr "o argumento de lo_read excede o intervalo de inteiros" + +#: fe-lobj.c:313 +#, c-format +msgid "argument of lo_write exceeds integer range" +msgstr "o argumento de lo_write excede o intervalo de inteiros" + +#: fe-lobj.c:669 fe-lobj.c:780 +#, c-format +msgid "could not open file \"%s\": %s" +msgstr "não foi possível abrir o arquivo \"%s\": %s" + +#: fe-lobj.c:725 +#, c-format +msgid "could not read from file \"%s\": %s" +msgstr "não foi possível ler do arquivo \"%s\": %s" + +#: fe-lobj.c:801 fe-lobj.c:824 +#, c-format +msgid "could not write to file \"%s\": %s" +msgstr "não foi possível escrever no arquivo \"%s\": %s" + +#: fe-lobj.c:908 +#, c-format +msgid "query to initialize large object functions did not return data" +msgstr "a consulta para inicializar funções de objetos grandes não retornou dados" + +#: fe-misc.c:240 +#, c-format +msgid "integer of size %lu not supported by pqGetInt" +msgstr "número inteiro de tamanho %lu não tem suporte por pqGetInt" + +#: fe-misc.c:273 +#, c-format +msgid "integer of size %lu not supported by pqPutInt" +msgstr "número inteiro de tamanho %lu não tem suporte por pqPutInt" + +#: fe-misc.c:573 +#, c-format +msgid "connection not open" +msgstr "a conexão não está aberta" + +#: fe-misc.c:751 fe-secure-openssl.c:215 fe-secure-openssl.c:321 +#: fe-secure.c:259 fe-secure.c:426 +#, c-format +msgid "" +"server closed the connection unexpectedly\n" +"\tThis probably means the server terminated abnormally\n" +"\tbefore or while processing the request." +msgstr "" +"o servidor fechou a conexão de forma não esperada\n" +"\tIsso provavelmente significa que o servidor\tfoi encerrado de forma não normal antes ou\n" +"\tdurante o processamento da solicitação." + +#: fe-misc.c:818 +msgid "connection not open\n" +msgstr "a conexão não está aberta\n" + +#: fe-misc.c:1003 +#, c-format +msgid "timeout expired" +msgstr "o tempo limite expirou" + +#: fe-misc.c:1047 +#, c-format +msgid "invalid socket" +msgstr "soquete inválido" + +#: fe-misc.c:1069 +#, c-format +msgid "%s() failed: %s" +msgstr "%s() falhou: %s" + +#: fe-protocol3.c:182 +#, c-format +msgid "message type 0x%02x arrived from server while idle" +msgstr "tipo de mensagem 0x%02x chegou do servidor enquanto estava ocioso" + +#: fe-protocol3.c:380 +#, c-format +msgid "server sent data (\"D\" message) without prior row description (\"T\" message)" +msgstr "servidor enviou dados (mensagem \"D\") sem descrição de linha anterior (mensagem \"T\")" + +#: fe-protocol3.c:422 +#, c-format +msgid "unexpected response from server; first received character was \"%c\"" +msgstr "resposta não esperada do servidor; o primeiro caractere recebido foi \"%c\"" + +#: fe-protocol3.c:445 +#, c-format +msgid "message contents do not agree with length in message type \"%c\"" +msgstr "o conteúdo da mensagem não corresponde ao comprimento no tipo de mensagem \"%c\"" + +#: fe-protocol3.c:463 +#, c-format +msgid "lost synchronization with server: got message type \"%c\", length %d" +msgstr "sincronização com o servidor perdida: recebida mensagem do tipo \"%c\", comprimento %d" + +#: fe-protocol3.c:515 fe-protocol3.c:555 +msgid "insufficient data in \"T\" message" +msgstr "dados insuficientes na mensagem \"T\"" + +#: fe-protocol3.c:626 fe-protocol3.c:832 +msgid "out of memory for query result" +msgstr "sem memória para os resultado da consulta" + +#: fe-protocol3.c:695 +msgid "insufficient data in \"t\" message" +msgstr "dados insuficientes na mensagem \"t\"" + +#: fe-protocol3.c:754 fe-protocol3.c:786 fe-protocol3.c:804 +msgid "insufficient data in \"D\" message" +msgstr "dados insuficientes na mensagem \"D\"" + +#: fe-protocol3.c:760 +msgid "unexpected field count in \"D\" message" +msgstr "contagem de campos não esperada na mensagem \"D\"" + +#: fe-protocol3.c:1015 +msgid "no error message available\n" +msgstr "nenhuma mensagem de erro disponível\n" + +#. translator: %s represents a digit string +#: fe-protocol3.c:1063 fe-protocol3.c:1082 +#, c-format +msgid " at character %s" +msgstr " no caractere %s" + +#: fe-protocol3.c:1095 +#, c-format +msgid "DETAIL: %s\n" +msgstr "DETALHE: %s\n" + +#: fe-protocol3.c:1098 +#, c-format +msgid "HINT: %s\n" +msgstr "DICA: %s\n" + +#: fe-protocol3.c:1101 +#, c-format +msgid "QUERY: %s\n" +msgstr "CONSULTA: %s\n" + +#: fe-protocol3.c:1108 +#, c-format +msgid "CONTEXT: %s\n" +msgstr "CONTEXTO: %s\n" + +#: fe-protocol3.c:1117 +#, c-format +msgid "SCHEMA NAME: %s\n" +msgstr "NOME DO ESQUEMA: %s\n" + +#: fe-protocol3.c:1121 +#, c-format +msgid "TABLE NAME: %s\n" +msgstr "NOME DA TABELA: %s\n" + +#: fe-protocol3.c:1125 +#, c-format +msgid "COLUMN NAME: %s\n" +msgstr "NOME DA COLUNA: %s\n" + +#: fe-protocol3.c:1129 +#, c-format +msgid "DATATYPE NAME: %s\n" +msgstr "NOME DO TIPO DE DADOS: %s\n" + +#: fe-protocol3.c:1133 +#, c-format +msgid "CONSTRAINT NAME: %s\n" +msgstr "NOME DA RESTRIÇÃO: %s\n" + +#: fe-protocol3.c:1145 +msgid "LOCATION: " +msgstr "LOCALIZAÇÃO: " + +#: fe-protocol3.c:1147 +#, c-format +msgid "%s, " +msgstr "%s, " + +#: fe-protocol3.c:1149 +#, c-format +msgid "%s:%s" +msgstr "%s:%s" + +#: fe-protocol3.c:1344 +#, c-format +msgid "LINE %d: " +msgstr "LINHA %d: " + +#: fe-protocol3.c:1418 +#, c-format +msgid "protocol version not supported by server: client uses %u.%u, server supports up to %u.%u" +msgstr "versão do protocolo sem suporte pelo servidor: o cliente usa %u.%u, o servidor oferece suporte até %u.%u" + +#: fe-protocol3.c:1424 +#, c-format +msgid "protocol extension not supported by server: %s" +msgid_plural "protocol extensions not supported by server: %s" +msgstr[0] "extensão do protocolo sem suporte pelo servidor: %s" +msgstr[1] "extensões do protocolo sem suporte pelo servidor: %s" + +#: fe-protocol3.c:1432 +#, c-format +msgid "invalid %s message" +msgstr "mensagem %s inválida" + +#: fe-protocol3.c:1797 +#, c-format +msgid "PQgetline: not doing text COPY OUT" +msgstr "Qgetline: não está realizando COPY OUT no formato de texto" + +#: fe-protocol3.c:2171 +#, c-format +msgid "protocol error: no function result" +msgstr "erro de protocolo: nenhum resultado de função" + +#: fe-protocol3.c:2182 +#, c-format +msgid "protocol error: id=0x%x" +msgstr "erro de protocolo: id=0x%x" + +#: fe-secure-common.c:123 +#, c-format +msgid "SSL certificate's name contains embedded null" +msgstr "o nome do certificado SSL contém nulo incorporado" + +#: fe-secure-common.c:228 +#, c-format +msgid "certificate contains IP address with invalid length %zu" +msgstr "o certificado contém endereço IP com comprimento inválido %zu" + +#: fe-secure-common.c:237 +#, c-format +msgid "could not convert certificate's IP address to string: %s" +msgstr "não foi possível converter o endereço IP do certificado em cadeia de caracteres: %s" + +#: fe-secure-common.c:269 +#, c-format +msgid "host name must be specified for a verified SSL connection" +msgstr "deve ser especificado o nome do hospedeiro para uma conexão SSL verificada" + +#: fe-secure-common.c:286 +#, c-format +msgid "server certificate for \"%s\" (and %d other name) does not match host name \"%s\"" +msgid_plural "server certificate for \"%s\" (and %d other names) does not match host name \"%s\"" +msgstr[0] "o certificado do servidor para \"%s\" (e %d outro nome) não corresponde ao nome do hospedeiro \"%s\"" +msgstr[1] "o certificado do servidor para \"%s\" (e %d outros nomes) não corresponde ao nome do hospedeiro \"%s\"" + +#: fe-secure-common.c:294 +#, c-format +msgid "server certificate for \"%s\" does not match host name \"%s\"" +msgstr "o certificado do servidor para \"%s\" não corresponde ao nome do hospedeiro \"%s\"" + +#: fe-secure-common.c:299 +#, c-format +msgid "could not get server's host name from server certificate" +msgstr "não foi possível obter o nome do hospedeiro do servidor do certificado do servidor" + +#: fe-secure-gssapi.c:194 +msgid "GSSAPI wrap error" +msgstr "erro de empacotamento GSSAPI" + +#: fe-secure-gssapi.c:201 +#, c-format +msgid "outgoing GSSAPI message would not use confidentiality" +msgstr "a mensagem GSSAPI de saída não usa confidencialidade" + +#: fe-secure-gssapi.c:208 +#, c-format +msgid "client tried to send oversize GSSAPI packet (%zu > %zu)" +msgstr "o cliente tentou enviar um pacote GSSAPI sobredimensionado (%zu > %zu)" + +#: fe-secure-gssapi.c:347 fe-secure-gssapi.c:589 +#, c-format +msgid "oversize GSSAPI packet sent by the server (%zu > %zu)" +msgstr "pacote GSSAPI sobredimensionado enviado pelo servidor (%zu > %zu)" + +#: fe-secure-gssapi.c:386 +msgid "GSSAPI unwrap error" +msgstr "erro de desempacotamento GSSAPI" + +#: fe-secure-gssapi.c:395 +#, c-format +msgid "incoming GSSAPI message did not use confidentiality" +msgstr "a mensagem GSSAPI recebida não usa confidencialidade" + +#: fe-secure-gssapi.c:652 +msgid "could not initiate GSSAPI security context" +msgstr "não foi possível iniciar o contexto de segurança GSSAPI" + +#: fe-secure-gssapi.c:681 +msgid "GSSAPI size check error" +msgstr "erro de verificação de tamanho GSSAPI" + +#: fe-secure-gssapi.c:692 +msgid "GSSAPI context establishment error" +msgstr "erro de estabelecimento de contexto GSSAPI" + +#: fe-secure-openssl.c:219 fe-secure-openssl.c:325 fe-secure-openssl.c:1538 +#, c-format +msgid "SSL SYSCALL error: %s" +msgstr "erro de SYSCALL SSL: %s" + +#: fe-secure-openssl.c:225 fe-secure-openssl.c:331 fe-secure-openssl.c:1541 +#, c-format +msgid "SSL SYSCALL error: EOF detected" +msgstr "erro de SYSCALL SSL: EOF detectado" + +#: fe-secure-openssl.c:235 fe-secure-openssl.c:341 fe-secure-openssl.c:1549 +#, c-format +msgid "SSL error: %s" +msgstr "erro de SSL: %s" + +#: fe-secure-openssl.c:249 fe-secure-openssl.c:355 +#, c-format +msgid "SSL connection has been closed unexpectedly" +msgstr "a conexão SSL foi fechada inesperadamente" + +#: fe-secure-openssl.c:254 fe-secure-openssl.c:360 fe-secure-openssl.c:1596 +#, c-format +msgid "unrecognized SSL error code: %d" +msgstr "código de erro SSL não reconhecido: %d" + +#: fe-secure-openssl.c:403 +#, c-format +msgid "could not determine server certificate signature algorithm" +msgstr "não foi possível determinar o algoritmo de assinatura do certificado do servidor" + +#: fe-secure-openssl.c:423 +#, c-format +msgid "could not find digest for NID %s" +msgstr "não foi possível encontrar o resumo do NID %s" + +#: fe-secure-openssl.c:432 +#, c-format +msgid "could not generate peer certificate hash" +msgstr "não foi possível gerar o hash de certificado do parceiro" + +#: fe-secure-openssl.c:515 +#, c-format +msgid "SSL certificate's name entry is missing" +msgstr "está faltando a entrada do nome do certificado SSL" + +#: fe-secure-openssl.c:549 +#, c-format +msgid "SSL certificate's address entry is missing" +msgstr "está faltando a entrada do endereço do certificado SSL" + +#: fe-secure-openssl.c:966 +#, c-format +msgid "could not create SSL context: %s" +msgstr "não foi possível criar o contexto SSL: %s" + +#: fe-secure-openssl.c:1008 +#, c-format +msgid "invalid value \"%s\" for minimum SSL protocol version" +msgstr "valor inválido \"%s\" para a versão mínima do protocolo SSL" + +#: fe-secure-openssl.c:1018 +#, c-format +msgid "could not set minimum SSL protocol version: %s" +msgstr "não foi possível definir a versão mínima do protocolo SSL: %s" + +#: fe-secure-openssl.c:1034 +#, c-format +msgid "invalid value \"%s\" for maximum SSL protocol version" +msgstr "valor inválido \"%s\" para a versão máxima do protocolo SSL" + +#: fe-secure-openssl.c:1044 +#, c-format +msgid "could not set maximum SSL protocol version: %s" +msgstr "não foi possível definir a versão máxima do protocolo SSL: %s" + +#: fe-secure-openssl.c:1082 +#, c-format +msgid "could not load system root certificate paths: %s" +msgstr "não foi possível carregar os caminhos do certificado raiz do sistema: %s" + +#: fe-secure-openssl.c:1099 +#, c-format +msgid "could not read root certificate file \"%s\": %s" +msgstr "não foi possível ler o arquivo de certificado raiz \"%s\": %s" + +#: fe-secure-openssl.c:1151 +#, c-format +msgid "" +"could not get home directory to locate root certificate file\n" +"Either provide the file, use the system's trusted roots with sslrootcert=system, or change sslmode to disable server certificate verification." +msgstr "" +"não foi possível obter o diretório inicial para localizar o arquivo de certificado raiz\n" +"Forneça o arquivo, use as raízes confiáveis do sistema com sslrootcert=system,\n" +"ou altere sslmode para desativar a verificação de certificado do servidor." + +#: fe-secure-openssl.c:1154 +#, c-format +msgid "" +"root certificate file \"%s\" does not exist\n" +"Either provide the file, use the system's trusted roots with sslrootcert=system, or change sslmode to disable server certificate verification." +msgstr "" +"o arquivo de certificado raiz \"%s\" não existe\n" +"Forneça o arquivo, use as raízes confiáveis do sistema com sslrootcert=system,\n" +"ou altere sslmode para desativar a verificação de certificado do servidor." + +#: fe-secure-openssl.c:1189 +#, c-format +msgid "could not open certificate file \"%s\": %s" +msgstr "não foi possível abrir o arquivo de certificado \"%s\": %s" + +#: fe-secure-openssl.c:1207 +#, c-format +msgid "could not read certificate file \"%s\": %s" +msgstr "não foi possível ler o arquivo de certificado \"%s\": %s" + +#: fe-secure-openssl.c:1231 +#, c-format +msgid "could not establish SSL connection: %s" +msgstr "não foi possível estabelecer uma conexão SSL: %s" + +#: fe-secure-openssl.c:1263 +#, c-format +msgid "could not set SSL Server Name Indication (SNI): %s" +msgstr "não foi possível definir a Indicação de Nome de Servidor (SNI) SSL: %s" + +#: fe-secure-openssl.c:1306 +#, c-format +msgid "could not load SSL engine \"%s\": %s" +msgstr "não foi possível carregar o mecanismo SSL \"%s\": %s" + +#: fe-secure-openssl.c:1317 +#, c-format +msgid "could not initialize SSL engine \"%s\": %s" +msgstr "não foi possível inicializar o mecanismo SSL \"%s\": %s" + +#: fe-secure-openssl.c:1332 +#, c-format +msgid "could not read private SSL key \"%s\" from engine \"%s\": %s" +msgstr "não foi possível ler a chave SSL privada \"%s\" do mecanismo \"%s\": %s" + +#: fe-secure-openssl.c:1345 +#, c-format +msgid "could not load private SSL key \"%s\" from engine \"%s\": %s" +msgstr "não foi possível carregar a chave SSL privada \"%s\" do mecanismo \"%s\": %s" + +#: fe-secure-openssl.c:1382 +#, c-format +msgid "certificate present, but not private key file \"%s\"" +msgstr "certificado presente, mas não o arquivo de chave privada \"%s\"" + +#: fe-secure-openssl.c:1385 +#, c-format +msgid "could not stat private key file \"%s\": %m" +msgstr "não foi possível conferir o status do arquivo de chave privada \"%s\": %m" + +#: fe-secure-openssl.c:1393 +#, c-format +msgid "private key file \"%s\" is not a regular file" +msgstr "o arquivo de chave privada \"%s\" não é um arquivo regular" + +#: fe-secure-openssl.c:1426 +#, c-format +msgid "private key file \"%s\" has group or world access; file must have permissions u=rw (0600) or less if owned by the current user, or permissions u=rw,g=r (0640) or less if owned by root" +msgstr "" +"o arquivo de chave privada \"%s\" tem acesso para grupo ou para todos;\n" +"o arquivo deve ter permissões u=rw (0600) ou inferior se pertencer ao usuário corrente,\n" +"ou permissões u=rw,g=r (0640) ou inferior se pertencer ao usuário root" + +#: fe-secure-openssl.c:1450 +#, c-format +msgid "could not load private key file \"%s\": %s" +msgstr "não foi possível carregar o arquivo de chave privada \"%s\": %s" + +#: fe-secure-openssl.c:1466 +#, c-format +msgid "certificate does not match private key file \"%s\": %s" +msgstr "o certificado não corresponde ao arquivo de chave privada \"%s\": %s" + +#: fe-secure-openssl.c:1535 +#, c-format +msgid "SSL error: certificate verify failed: %s" +msgstr "Erro de SSL: falha na verificação do certificado: %s" + +#: fe-secure-openssl.c:1580 +#, c-format +msgid "This may indicate that the server does not support any SSL protocol version between %s and %s." +msgstr "Isso pode indicar que o servidor não oferece suporte a nenhuma versão do protocolo SSL entre %s e %s." + +#: fe-secure-openssl.c:1613 +#, c-format +msgid "certificate could not be obtained: %s" +msgstr "não foi possível obter o certificado: %s" + +#: fe-secure-openssl.c:1718 +#, c-format +msgid "no SSL error reported" +msgstr "nenhum erro de SSL relatado" + +#: fe-secure-openssl.c:1727 +#, c-format +msgid "SSL error code %lu" +msgstr "código de erro SSL %lu" + +#: fe-secure-openssl.c:2017 +#, c-format +msgid "WARNING: sslpassword truncated\n" +msgstr "ADVERTÊNCIA: sslpassword truncada\n" + +#: fe-secure.c:270 +#, c-format +msgid "could not receive data from server: %s" +msgstr "não foi possível receber dados do servidor: %s" + +#: fe-secure.c:441 +#, c-format +msgid "could not send data to server: %s" +msgstr "não foi possível enviar dados para o servidor: %s" + +#: win32.c:310 +#, c-format +msgid "unrecognized socket error: 0x%08X/%d" +msgstr "erro de soquete não reconhecido: 0x%08X/%d" diff --git a/src/interfaces/libpq/po/ru.po b/src/interfaces/libpq/po/ru.po new file mode 100644 index 0000000..1cf3b28 --- /dev/null +++ b/src/interfaces/libpq/po/ru.po @@ -0,0 +1,1738 @@ +# Russian message translation file for libpq +# Copyright (C) 2001-2016 PostgreSQL Global Development Group +# This file is distributed under the same license as the PostgreSQL package. +# Serguei A. Mokhov <mokhov@cs.concordia.ca>, 2001-2004. +# Oleg Bartunov <oleg@sai.msu.su>, 2005. +# Andrey Sudnik <sudnikand@yandex.ru>, 2010. +# Alexander Lakhin <exclusion@gmail.com>, 2012-2017, 2018, 2019, 2020, 2021, 2022, 2023. +# Maxim Yablokov <m.yablokov@postgrespro.ru>, 2021. +msgid "" +msgstr "" +"Project-Id-Version: libpq (PostgreSQL current)\n" +"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" +"POT-Creation-Date: 2024-02-02 18:10+0300\n" +"PO-Revision-Date: 2023-08-30 15:09+0300\n" +"Last-Translator: Alexander Lakhin <exclusion@gmail.com>\n" +"Language-Team: Russian <pgsql-ru-general@postgresql.org>\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#: ../../port/thread.c:50 ../../port/thread.c:86 +#, c-format +msgid "could not look up local user ID %d: %s" +msgstr "найти локального пользователя по идентификатору (%d) не удалось: %s" + +#: ../../port/thread.c:55 ../../port/thread.c:91 +#, c-format +msgid "local user with ID %d does not exist" +msgstr "локальный пользователь с ID %d не существует" + +#: fe-auth-scram.c:227 +#, c-format +msgid "malformed SCRAM message (empty message)" +msgstr "неправильное сообщение SCRAM (пустое содержимое)" + +#: fe-auth-scram.c:232 +#, c-format +msgid "malformed SCRAM message (length mismatch)" +msgstr "неправильное сообщение SCRAM (некорректная длина)" + +#: fe-auth-scram.c:275 +#, c-format +msgid "could not verify server signature: %s" +msgstr "не удалось проверить сигнатуру сервера: %s" + +#: fe-auth-scram.c:281 +#, c-format +msgid "incorrect server signature" +msgstr "некорректная сигнатура сервера" + +#: fe-auth-scram.c:290 +#, c-format +msgid "invalid SCRAM exchange state" +msgstr "ошибочное состояние обмена SCRAM" + +#: fe-auth-scram.c:317 +#, c-format +msgid "malformed SCRAM message (attribute \"%c\" expected)" +msgstr "неправильное сообщение SCRAM (ожидался атрибут \"%c\")" + +#: fe-auth-scram.c:326 +#, c-format +msgid "malformed SCRAM message (expected character \"=\" for attribute \"%c\")" +msgstr "" +"неправильное сообщение SCRAM (для атрибута \"%c\" ожидался символ \"=\")" + +#: fe-auth-scram.c:366 +#, c-format +msgid "could not generate nonce" +msgstr "не удалось сгенерировать разовый код" + +#: fe-auth-scram.c:375 fe-auth-scram.c:448 fe-auth-scram.c:600 +#: fe-auth-scram.c:620 fe-auth-scram.c:644 fe-auth-scram.c:658 +#: fe-auth-scram.c:704 fe-auth-scram.c:740 fe-auth-scram.c:914 fe-auth.c:296 +#: fe-auth.c:369 fe-auth.c:403 fe-auth.c:618 fe-auth.c:729 fe-auth.c:1210 +#: fe-auth.c:1375 fe-connect.c:925 fe-connect.c:1759 fe-connect.c:1921 +#: fe-connect.c:3291 fe-connect.c:4496 fe-connect.c:5161 fe-connect.c:5416 +#: fe-connect.c:5534 fe-connect.c:5781 fe-connect.c:5861 fe-connect.c:5959 +#: fe-connect.c:6210 fe-connect.c:6237 fe-connect.c:6313 fe-connect.c:6336 +#: fe-connect.c:6360 fe-connect.c:6395 fe-connect.c:6481 fe-connect.c:6489 +#: fe-connect.c:6846 fe-connect.c:6996 fe-exec.c:527 fe-exec.c:1323 +#: fe-exec.c:3132 fe-exec.c:4100 fe-exec.c:4264 fe-gssapi-common.c:109 +#: fe-lobj.c:870 fe-protocol3.c:204 fe-protocol3.c:228 fe-protocol3.c:251 +#: fe-protocol3.c:268 fe-protocol3.c:348 fe-protocol3.c:715 fe-protocol3.c:954 +#: fe-protocol3.c:1765 fe-protocol3.c:2165 fe-secure-common.c:110 +#: fe-secure-gssapi.c:496 fe-secure-openssl.c:440 fe-secure-openssl.c:1291 +#, c-format +msgid "out of memory" +msgstr "нехватка памяти" + +#: fe-auth-scram.c:382 +#, c-format +msgid "could not encode nonce" +msgstr "не удалось оформить разовый код" + +#: fe-auth-scram.c:570 +#, c-format +msgid "could not calculate client proof: %s" +msgstr "не удалось вычислить подтверждение клиента: %s" + +#: fe-auth-scram.c:585 +#, c-format +msgid "could not encode client proof" +msgstr "не удалось закодировать подтверждение клиента" + +#: fe-auth-scram.c:637 +#, c-format +msgid "invalid SCRAM response (nonce mismatch)" +msgstr "неверный ответ SCRAM (несовпадение разового кода)" + +#: fe-auth-scram.c:667 +#, c-format +msgid "malformed SCRAM message (invalid salt)" +msgstr "неправильное сообщение SCRAM (некорректная соль)" + +#: fe-auth-scram.c:680 +#, c-format +msgid "malformed SCRAM message (invalid iteration count)" +msgstr "неправильное сообщение SCRAM (некорректное число итераций)" + +#: fe-auth-scram.c:685 +#, c-format +msgid "malformed SCRAM message (garbage at end of server-first-message)" +msgstr "неправильное сообщение SCRAM (мусор в конце первого сообщения сервера)" + +#: fe-auth-scram.c:719 +#, c-format +msgid "error received from server in SCRAM exchange: %s" +msgstr "в ходе обмена SCRAM от сервера получена ошибка: %s" + +#: fe-auth-scram.c:734 +#, c-format +msgid "malformed SCRAM message (garbage at end of server-final-message)" +msgstr "" +"неправильное сообщение SCRAM (мусор в конце последнего сообщения сервера)" + +#: fe-auth-scram.c:751 +#, c-format +msgid "malformed SCRAM message (invalid server signature)" +msgstr "неправильное сообщение SCRAM (неверная сигнатура сервера)" + +#: fe-auth-scram.c:923 +msgid "could not generate random salt" +msgstr "не удалось сгенерировать случайную соль" + +#: fe-auth.c:77 +#, c-format +msgid "out of memory allocating GSSAPI buffer (%d)" +msgstr "недостаточно памяти для буфера GSSAPI (%d)" + +#: fe-auth.c:138 +msgid "GSSAPI continuation error" +msgstr "ошибка продолжения в GSSAPI" + +#: fe-auth.c:168 fe-auth.c:397 fe-gssapi-common.c:97 fe-secure-common.c:99 +#: fe-secure-common.c:173 +#, c-format +msgid "host name must be specified" +msgstr "требуется указать имя сервера" + +#: fe-auth.c:174 +#, c-format +msgid "duplicate GSS authentication request" +msgstr "повторный запрос аутентификации GSS" + +#: fe-auth.c:238 +#, c-format +msgid "out of memory allocating SSPI buffer (%d)" +msgstr "недостаточно памяти для буфера SSPI (%d)" + +#: fe-auth.c:285 +msgid "SSPI continuation error" +msgstr "ошибка продолжения в SSPI" + +#: fe-auth.c:359 +#, c-format +msgid "duplicate SSPI authentication request" +msgstr "повторный запрос аутентификации SSPI" + +#: fe-auth.c:384 +msgid "could not acquire SSPI credentials" +msgstr "не удалось получить удостоверение SSPI" + +#: fe-auth.c:437 +#, c-format +msgid "channel binding required, but SSL not in use" +msgstr "требуется привязка каналов, но SSL не используется" + +#: fe-auth.c:443 +#, c-format +msgid "duplicate SASL authentication request" +msgstr "повторный запрос аутентификации SASL" + +#: fe-auth.c:501 +#, c-format +msgid "channel binding is required, but client does not support it" +msgstr "требуется привязка каналов, но клиент её не поддерживает" + +#: fe-auth.c:517 +#, c-format +msgid "" +"server offered SCRAM-SHA-256-PLUS authentication over a non-SSL connection" +msgstr "" +"сервер предложил аутентификацию SCRAM-SHA-256-PLUS для соединения, не " +"защищённого SSL" + +#: fe-auth.c:531 +#, c-format +msgid "none of the server's SASL authentication mechanisms are supported" +msgstr "ни один из серверных механизмов аутентификации SASL не поддерживается" + +#: fe-auth.c:538 +#, c-format +msgid "" +"channel binding is required, but server did not offer an authentication " +"method that supports channel binding" +msgstr "" +"требуется привязка каналов, но сервер не предложил поддерживающий её метод " +"аутентификации" + +#: fe-auth.c:641 +#, c-format +msgid "out of memory allocating SASL buffer (%d)" +msgstr "недостаточно памяти для буфера SASL (%d)" + +#: fe-auth.c:665 +#, c-format +msgid "" +"AuthenticationSASLFinal received from server, but SASL authentication was " +"not completed" +msgstr "" +"c сервера получено сообщение AuthenticationSASLFinal, но аутентификация SASL " +"ещё не завершена" + +#: fe-auth.c:675 +#, c-format +msgid "no client response found after SASL exchange success" +msgstr "после успешного обмена по протоколу SASL не получен ответ клиента" + +#: fe-auth.c:738 fe-auth.c:745 fe-auth.c:1358 fe-auth.c:1369 +#, c-format +msgid "could not encrypt password: %s" +msgstr "не удалось зашифровать пароль: %s" + +#: fe-auth.c:773 +msgid "server requested a cleartext password" +msgstr "сервер запросил незашифрованный пароль" + +#: fe-auth.c:775 +msgid "server requested a hashed password" +msgstr "сервер запросил хешированный пароль" + +#: fe-auth.c:778 +msgid "server requested GSSAPI authentication" +msgstr "сервер запросил аутентификацию GSSAPI" + +#: fe-auth.c:780 +msgid "server requested SSPI authentication" +msgstr "сервер запросил аутентификацию SSPI" + +#: fe-auth.c:784 +msgid "server requested SASL authentication" +msgstr "сервер запросил аутентификацию SASL" + +#: fe-auth.c:787 +msgid "server requested an unknown authentication type" +msgstr "сервер запросил аутентификацию неизвестного типа" + +#: fe-auth.c:820 +#, c-format +msgid "server did not request an SSL certificate" +msgstr "сервер не запросил сертификат SSL" + +#: fe-auth.c:825 +#, c-format +msgid "server accepted connection without a valid SSL certificate" +msgstr "сервер принял подключение, не проверив сертификат SSL" + +#: fe-auth.c:879 +msgid "server did not complete authentication" +msgstr "сервер не завершил аутентификацию" + +#: fe-auth.c:913 +#, c-format +msgid "authentication method requirement \"%s\" failed: %s" +msgstr "требование метода аутентификации \"%s\" не выполнено: %s" + +#: fe-auth.c:936 +#, c-format +msgid "" +"channel binding required, but server authenticated client without channel " +"binding" +msgstr "" +"требуется привязка каналов, но сервер аутентифицировал клиента без привязки" + +#: fe-auth.c:941 +#, c-format +msgid "" +"channel binding required but not supported by server's authentication request" +msgstr "" +"требуется привязка каналов, но она не поддерживается при том запросе " +"аутентификации, который передал сервер" + +#: fe-auth.c:975 +#, c-format +msgid "Kerberos 4 authentication not supported" +msgstr "аутентификация Kerberos 4 не поддерживается" + +#: fe-auth.c:979 +#, c-format +msgid "Kerberos 5 authentication not supported" +msgstr "аутентификация Kerberos 5 не поддерживается" + +#: fe-auth.c:1049 +#, c-format +msgid "GSSAPI authentication not supported" +msgstr "аутентификация через GSSAPI не поддерживается" + +#: fe-auth.c:1080 +#, c-format +msgid "SSPI authentication not supported" +msgstr "аутентификация через SSPI не поддерживается" + +#: fe-auth.c:1087 +#, c-format +msgid "Crypt authentication not supported" +msgstr "аутентификация Crypt не поддерживается" + +#: fe-auth.c:1151 +#, c-format +msgid "authentication method %u not supported" +msgstr "метод аутентификации %u не поддерживается" + +#: fe-auth.c:1197 +#, c-format +msgid "user name lookup failure: error code %lu" +msgstr "распознать имя пользователя не удалось (код ошибки: %lu)" + +#: fe-auth.c:1321 +#, c-format +msgid "unexpected shape of result set returned for SHOW" +msgstr "неожиданная форма набора результатов, возвращённого для SHOW" + +#: fe-auth.c:1329 +#, c-format +msgid "password_encryption value too long" +msgstr "слишком длинное значение password_encryption" + +#: fe-auth.c:1379 +#, c-format +msgid "unrecognized password encryption algorithm \"%s\"" +msgstr "нераспознанный алгоритм шифрования пароля \"%s\"" + +#: fe-connect.c:1132 +#, c-format +msgid "could not match %d host names to %d hostaddr values" +msgstr "не удалось сопоставить имена узлов (%d) со значениями hostaddr (%d)" + +#: fe-connect.c:1212 +#, c-format +msgid "could not match %d port numbers to %d hosts" +msgstr "не удалось сопоставить номера портов (%d) с узлами (%d)" + +#: fe-connect.c:1337 +#, c-format +msgid "" +"negative require_auth method \"%s\" cannot be mixed with non-negative methods" +msgstr "" +"отрицательный метод require_auth \"%s\" не может совмещаться с " +"неотрицательными методами" + +#: fe-connect.c:1350 +#, c-format +msgid "require_auth method \"%s\" cannot be mixed with negative methods" +msgstr "" +"метод require_auth \"%s\" не может совмещаться с отрицательными методами" + +#: fe-connect.c:1410 fe-connect.c:1461 fe-connect.c:1503 fe-connect.c:1559 +#: fe-connect.c:1567 fe-connect.c:1598 fe-connect.c:1644 fe-connect.c:1684 +#: fe-connect.c:1705 +#, c-format +msgid "invalid %s value: \"%s\"" +msgstr "неверное значение %s: \"%s\"" + +#: fe-connect.c:1443 +#, c-format +msgid "require_auth method \"%s\" is specified more than once" +msgstr "метод require_auth \"%s\" указан неоднократно" + +#: fe-connect.c:1484 fe-connect.c:1523 fe-connect.c:1606 +#, c-format +msgid "%s value \"%s\" invalid when SSL support is not compiled in" +msgstr "значение %s \"%s\" недопустимо для сборки без поддержки SSL" + +#: fe-connect.c:1546 +#, c-format +msgid "" +"weak sslmode \"%s\" may not be used with sslrootcert=system (use \"verify-" +"full\")" +msgstr "" +"слабый режим sslmode \"%s\" не может использоваться с sslrootcert=system " +"(используйте режим \"verify-full\")" + +#: fe-connect.c:1584 +#, c-format +msgid "invalid SSL protocol version range" +msgstr "неверный диапазон версий протокола SSL" + +#: fe-connect.c:1621 +#, c-format +msgid "%s value \"%s\" is not supported (check OpenSSL version)" +msgstr "значение %s \"%s\" не поддерживается (проверьте версию OpenSSL)" + +#: fe-connect.c:1651 +#, c-format +msgid "gssencmode value \"%s\" invalid when GSSAPI support is not compiled in" +msgstr "значение gssencmode \"%s\" недопустимо для сборки без поддержки GSSAPI" + +#: fe-connect.c:1944 +#, c-format +msgid "could not set socket to TCP no delay mode: %s" +msgstr "не удалось перевести сокет в режим TCP-передачи без задержки: %s" + +#: fe-connect.c:2003 +#, c-format +msgid "connection to server on socket \"%s\" failed: " +msgstr "подключиться к серверу через сокет \"%s\" не удалось: " + +#: fe-connect.c:2029 +#, c-format +msgid "connection to server at \"%s\" (%s), port %s failed: " +msgstr "подключиться к серверу \"%s\" (%s), порту %s не удалось: " + +#: fe-connect.c:2034 +#, c-format +msgid "connection to server at \"%s\", port %s failed: " +msgstr "подключиться к серверу \"%s\", порту %s не удалось: " + +#: fe-connect.c:2057 +#, c-format +msgid "" +"\tIs the server running locally and accepting connections on that socket?" +msgstr "" +"\tСервер действительно работает локально и принимает подключения через этот " +"сокет?" + +#: fe-connect.c:2059 +#, c-format +msgid "\tIs the server running on that host and accepting TCP/IP connections?" +msgstr "" +"\tСервер действительно работает по данному адресу и принимает TCP-соединения?" + +#: fe-connect.c:2122 +#, c-format +msgid "invalid integer value \"%s\" for connection option \"%s\"" +msgstr "неверное целочисленное значение \"%s\" для параметра соединения \"%s\"" + +#: fe-connect.c:2151 fe-connect.c:2185 fe-connect.c:2220 fe-connect.c:2318 +#: fe-connect.c:2973 +#, c-format +msgid "%s(%s) failed: %s" +msgstr "ошибка в %s(%s): %s" + +#: fe-connect.c:2284 +#, c-format +msgid "%s(%s) failed: error code %d" +msgstr "ошибка в %s(%s): код ошибки %d" + +#: fe-connect.c:2597 +#, c-format +msgid "invalid connection state, probably indicative of memory corruption" +msgstr "неверное состояние соединения - возможно разрушение памяти" + +#: fe-connect.c:2676 +#, c-format +msgid "invalid port number: \"%s\"" +msgstr "неверный номер порта: \"%s\"" + +#: fe-connect.c:2690 +#, c-format +msgid "could not translate host name \"%s\" to address: %s" +msgstr "преобразовать имя \"%s\" в адрес не удалось: %s" + +#: fe-connect.c:2702 +#, c-format +msgid "could not parse network address \"%s\": %s" +msgstr "не удалось разобрать сетевой адрес \"%s\": %s" + +#: fe-connect.c:2713 +#, c-format +msgid "Unix-domain socket path \"%s\" is too long (maximum %d bytes)" +msgstr "длина пути Unix-сокета \"%s\" превышает предел (%d байт)" + +#: fe-connect.c:2727 +#, c-format +msgid "could not translate Unix-domain socket path \"%s\" to address: %s" +msgstr "преобразовать путь Unix-сокета \"%s\" в адрес не удалось: %s" + +#: fe-connect.c:2901 +#, c-format +msgid "could not create socket: %s" +msgstr "не удалось создать сокет: %s" + +#: fe-connect.c:2932 +#, c-format +msgid "could not set socket to nonblocking mode: %s" +msgstr "не удалось перевести сокет в неблокирующий режим: %s" + +#: fe-connect.c:2943 +#, c-format +msgid "could not set socket to close-on-exec mode: %s" +msgstr "" +"не удалось перевести сокет в режим закрытия при выполнении (close-on-exec): " +"%s" + +#: fe-connect.c:2961 +#, c-format +msgid "keepalives parameter must be an integer" +msgstr "параметр keepalives должен быть целым числом" + +#: fe-connect.c:3100 +#, c-format +msgid "could not get socket error status: %s" +msgstr "не удалось получить статус ошибки сокета: %s" + +#: fe-connect.c:3127 +#, c-format +msgid "could not get client address from socket: %s" +msgstr "не удалось получить адрес клиента из сокета: %s" + +#: fe-connect.c:3165 +#, c-format +msgid "requirepeer parameter is not supported on this platform" +msgstr "параметр requirepeer не поддерживается в этой ОС" + +#: fe-connect.c:3167 +#, c-format +msgid "could not get peer credentials: %s" +msgstr "не удалось получить учётные данные сервера: %s" + +#: fe-connect.c:3180 +#, c-format +msgid "requirepeer specifies \"%s\", but actual peer user name is \"%s\"" +msgstr "" +"requirepeer допускает подключение только к \"%s\", но сервер работает под " +"именем \"%s\"" + +#: fe-connect.c:3221 +#, c-format +msgid "could not send GSSAPI negotiation packet: %s" +msgstr "не удалось отправить пакет согласования GSSAPI: %s" + +#: fe-connect.c:3233 +#, c-format +msgid "" +"GSSAPI encryption required but was impossible (possibly no credential cache, " +"no server support, or using a local socket)" +msgstr "" +"затребовано шифрование GSSAPI, но это требование невыполнимо (возможно, " +"отсутствует кеш учётных данных, нет поддержки на сервере или используется " +"локальный сокет)" + +#: fe-connect.c:3274 +#, c-format +msgid "could not send SSL negotiation packet: %s" +msgstr "не удалось отправить пакет согласования SSL: %s" + +#: fe-connect.c:3303 +#, c-format +msgid "could not send startup packet: %s" +msgstr "не удалось отправить стартовый пакет: %s" + +#: fe-connect.c:3378 +#, c-format +msgid "server does not support SSL, but SSL was required" +msgstr "затребовано подключение через SSL, но сервер не поддерживает SSL" + +#: fe-connect.c:3404 +#, c-format +msgid "received invalid response to SSL negotiation: %c" +msgstr "получен неверный ответ при согласовании SSL: %c" + +#: fe-connect.c:3424 +#, c-format +msgid "received unencrypted data after SSL response" +msgstr "после ответа SSL получены незашифрованные данные" + +#: fe-connect.c:3504 +#, c-format +msgid "server doesn't support GSSAPI encryption, but it was required" +msgstr "затребовано шифрование GSSAPI, но сервер его не поддерживает" + +#: fe-connect.c:3515 +#, c-format +msgid "received invalid response to GSSAPI negotiation: %c" +msgstr "получен неверный ответ при согласовании GSSAPI: %c" + +#: fe-connect.c:3533 +#, c-format +msgid "received unencrypted data after GSSAPI encryption response" +msgstr "" +"после ответа на запрос шифрования GSSAPI получены незашифрованные данные" + +#: fe-connect.c:3598 +#, c-format +msgid "expected authentication request from server, but received %c" +msgstr "ожидался запрос аутентификации от сервера, но получено: %c" + +#: fe-connect.c:3625 fe-connect.c:3794 +#, c-format +msgid "received invalid authentication request" +msgstr "получен некорректный запрос аутентификации" + +#: fe-connect.c:3630 fe-connect.c:3779 +#, c-format +msgid "received invalid protocol negotiation message" +msgstr "получено некорректное сообщение согласования протокола" + +#: fe-connect.c:3648 fe-connect.c:3702 +#, c-format +msgid "received invalid error message" +msgstr "получено некорректное сообщение об ошибке" + +#: fe-connect.c:3865 +#, c-format +msgid "unexpected message from server during startup" +msgstr "неожиданное сообщение от сервера в начале работы" + +#: fe-connect.c:3956 +#, c-format +msgid "session is read-only" +msgstr "сеанс не допускает запись" + +#: fe-connect.c:3958 +#, c-format +msgid "session is not read-only" +msgstr "сеанс допускает запись" + +#: fe-connect.c:4011 +#, c-format +msgid "server is in hot standby mode" +msgstr "сервер работает в режиме горячего резерва" + +#: fe-connect.c:4013 +#, c-format +msgid "server is not in hot standby mode" +msgstr "сервер работает не в режиме горячего резерва" + +#: fe-connect.c:4129 fe-connect.c:4179 +#, c-format +msgid "\"%s\" failed" +msgstr "выполнить \"%s\" не удалось" + +#: fe-connect.c:4193 +#, c-format +msgid "invalid connection state %d, probably indicative of memory corruption" +msgstr "неверное состояние соединения %d - возможно разрушение памяти" + +#: fe-connect.c:5174 +#, c-format +msgid "invalid LDAP URL \"%s\": scheme must be ldap://" +msgstr "некорректный адрес LDAP \"%s\": схема должна быть ldap://" + +#: fe-connect.c:5189 +#, c-format +msgid "invalid LDAP URL \"%s\": missing distinguished name" +msgstr "некорректный адрес LDAP \"%s\": отсутствует уникальное имя" + +#: fe-connect.c:5201 fe-connect.c:5259 +#, c-format +msgid "invalid LDAP URL \"%s\": must have exactly one attribute" +msgstr "некорректный адрес LDAP \"%s\": должен быть только один атрибут" + +#: fe-connect.c:5213 fe-connect.c:5275 +#, c-format +msgid "invalid LDAP URL \"%s\": must have search scope (base/one/sub)" +msgstr "" +"некорректный адрес LDAP \"%s\": не указана область поиска (base/one/sub)" + +#: fe-connect.c:5225 +#, c-format +msgid "invalid LDAP URL \"%s\": no filter" +msgstr "некорректный адрес LDAP \"%s\": нет фильтра" + +#: fe-connect.c:5247 +#, c-format +msgid "invalid LDAP URL \"%s\": invalid port number" +msgstr "некорректный адрес LDAP \"%s\": неверный номер порта" + +#: fe-connect.c:5284 +#, c-format +msgid "could not create LDAP structure" +msgstr "не удалось создать структуру LDAP" + +#: fe-connect.c:5359 +#, c-format +msgid "lookup on LDAP server failed: %s" +msgstr "ошибка поиска на сервере LDAP: %s" + +#: fe-connect.c:5369 +#, c-format +msgid "more than one entry found on LDAP lookup" +msgstr "при поиске LDAP найдено более одного вхождения" + +#: fe-connect.c:5371 fe-connect.c:5382 +#, c-format +msgid "no entry found on LDAP lookup" +msgstr "при поиске LDAP ничего не найдено" + +#: fe-connect.c:5392 fe-connect.c:5404 +#, c-format +msgid "attribute has no values on LDAP lookup" +msgstr "атрибут не содержит значений при поиске LDAP" + +#: fe-connect.c:5455 fe-connect.c:5474 fe-connect.c:5998 +#, c-format +msgid "missing \"=\" after \"%s\" in connection info string" +msgstr "в строке соединения нет \"=\" после \"%s\"" + +#: fe-connect.c:5545 fe-connect.c:6181 fe-connect.c:6979 +#, c-format +msgid "invalid connection option \"%s\"" +msgstr "неверный параметр соединения \"%s\"" + +#: fe-connect.c:5560 fe-connect.c:6046 +#, c-format +msgid "unterminated quoted string in connection info string" +msgstr "в строке соединения не хватает закрывающей кавычки" + +#: fe-connect.c:5640 +#, c-format +msgid "definition of service \"%s\" not found" +msgstr "определение службы \"%s\" не найдено" + +#: fe-connect.c:5666 +#, c-format +msgid "service file \"%s\" not found" +msgstr "файл определений служб \"%s\" не найден" + +#: fe-connect.c:5679 +#, c-format +msgid "line %d too long in service file \"%s\"" +msgstr "слишком длинная строка (%d) в файле определений служб \"%s\"" + +#: fe-connect.c:5750 fe-connect.c:5793 +#, c-format +msgid "syntax error in service file \"%s\", line %d" +msgstr "синтаксическая ошибка в файле определения служб \"%s\" (строка %d)" + +#: fe-connect.c:5761 +#, c-format +msgid "" +"nested service specifications not supported in service file \"%s\", line %d" +msgstr "" +"рекурсивные определения служб не поддерживаются (файл определения служб " +"\"%s\", строка %d)" + +#: fe-connect.c:6500 +#, c-format +msgid "invalid URI propagated to internal parser routine: \"%s\"" +msgstr "во внутреннюю процедуру разбора строки передан ошибочный URI: \"%s\"" + +#: fe-connect.c:6577 +#, c-format +msgid "" +"end of string reached when looking for matching \"]\" in IPv6 host address " +"in URI: \"%s\"" +msgstr "URI не содержит символ \"]\" после адреса IPv6: \"%s\"" + +#: fe-connect.c:6584 +#, c-format +msgid "IPv6 host address may not be empty in URI: \"%s\"" +msgstr "IPv6, содержащийся в URI, не может быть пустым: \"%s\"" + +#: fe-connect.c:6599 +#, c-format +msgid "" +"unexpected character \"%c\" at position %d in URI (expected \":\" or \"/\"): " +"\"%s\"" +msgstr "" +"неожиданный символ \"%c\" в позиции %d в URI (ожидалось \":\" или \"/\"): " +"\"%s\"" + +#: fe-connect.c:6728 +#, c-format +msgid "extra key/value separator \"=\" in URI query parameter: \"%s\"" +msgstr "лишний разделитель ключа/значения \"=\" в параметрах URI: \"%s\"" + +#: fe-connect.c:6748 +#, c-format +msgid "missing key/value separator \"=\" in URI query parameter: \"%s\"" +msgstr "в параметрах URI не хватает разделителя ключа/значения \"=\": \"%s\"" + +#: fe-connect.c:6800 +#, c-format +msgid "invalid URI query parameter: \"%s\"" +msgstr "неверный параметр в URI: \"%s\"" + +#: fe-connect.c:6874 +#, c-format +msgid "invalid percent-encoded token: \"%s\"" +msgstr "неверный символ, закодированный с %%: \"%s\"" + +#: fe-connect.c:6884 +#, c-format +msgid "forbidden value %%00 in percent-encoded value: \"%s\"" +msgstr "недопустимое значение %%00 для символа, закодированного с %%: \"%s\"" + +#: fe-connect.c:7248 +msgid "connection pointer is NULL\n" +msgstr "нулевой указатель соединения\n" + +#: fe-connect.c:7256 fe-exec.c:710 fe-exec.c:972 fe-exec.c:3321 +#: fe-protocol3.c:969 fe-protocol3.c:1002 +msgid "out of memory\n" +msgstr "нехватка памяти\n" + +#: fe-connect.c:7547 +#, c-format +msgid "WARNING: password file \"%s\" is not a plain file\n" +msgstr "ПРЕДУПРЕЖДЕНИЕ: файл паролей \"%s\" - не обычный файл\n" + +#: fe-connect.c:7556 +#, c-format +msgid "" +"WARNING: password file \"%s\" has group or world access; permissions should " +"be u=rw (0600) or less\n" +msgstr "" +"ПРЕДУПРЕЖДЕНИЕ: к файлу паролей \"%s\" имеют доступ все или группа; права " +"должны быть u=rw (0600) или более ограниченные\n" + +#: fe-connect.c:7663 +#, c-format +msgid "password retrieved from file \"%s\"" +msgstr "пароль получен из файла \"%s\"" + +#: fe-exec.c:466 fe-exec.c:3395 +#, c-format +msgid "row number %d is out of range 0..%d" +msgstr "номер записи %d вне диапазона 0..%d" + +#: fe-exec.c:528 fe-protocol3.c:1971 +#, c-format +msgid "%s" +msgstr "%s" + +#: fe-exec.c:831 +#, c-format +msgid "write to server failed" +msgstr "ошибка при передаче данных серверу" + +#: fe-exec.c:871 +#, c-format +msgid "no error text available" +msgstr "текст ошибки отсутствует" + +#: fe-exec.c:960 +msgid "NOTICE" +msgstr "ЗАМЕЧАНИЕ" + +#: fe-exec.c:1018 +msgid "PGresult cannot support more than INT_MAX tuples" +msgstr "PGresult не может вместить больше чем INT_MAX кортежей" + +#: fe-exec.c:1030 +msgid "size_t overflow" +msgstr "переполнение size_t" + +#: fe-exec.c:1446 fe-exec.c:1515 fe-exec.c:1561 +#, c-format +msgid "command string is a null pointer" +msgstr "указатель на командную строку нулевой" + +#: fe-exec.c:1452 fe-exec.c:2883 +#, c-format +msgid "%s not allowed in pipeline mode" +msgstr "%s не допускается в конвейерном режиме" + +#: fe-exec.c:1520 fe-exec.c:1566 fe-exec.c:1660 +#, c-format +msgid "number of parameters must be between 0 and %d" +msgstr "число параметров должно быть от 0 до %d" + +#: fe-exec.c:1556 fe-exec.c:1655 +#, c-format +msgid "statement name is a null pointer" +msgstr "указатель на имя оператора нулевой" + +#: fe-exec.c:1697 fe-exec.c:3241 +#, c-format +msgid "no connection to the server" +msgstr "нет соединения с сервером" + +#: fe-exec.c:1705 fe-exec.c:3249 +#, c-format +msgid "another command is already in progress" +msgstr "уже выполняется другая команда" + +#: fe-exec.c:1735 +#, c-format +msgid "cannot queue commands during COPY" +msgstr "во время COPY нельзя добавлять команды в очередь" + +#: fe-exec.c:1852 +#, c-format +msgid "length must be given for binary parameter" +msgstr "для двоичного параметра должна быть указана длина" + +#: fe-exec.c:2166 +#, c-format +msgid "unexpected asyncStatus: %d" +msgstr "неожиданный asyncStatus: %d" + +#: fe-exec.c:2322 +#, c-format +msgid "" +"synchronous command execution functions are not allowed in pipeline mode" +msgstr "" +"функции синхронного выполнения команд не допускаются в конвейерном режиме" + +#: fe-exec.c:2339 +msgid "COPY terminated by new PQexec" +msgstr "операция COPY прервана вызовом PQexec" + +#: fe-exec.c:2355 +#, c-format +msgid "PQexec not allowed during COPY BOTH" +msgstr "вызов PQexec не допускается в процессе COPY BOTH" + +#: fe-exec.c:2581 fe-exec.c:2636 fe-exec.c:2704 fe-protocol3.c:1902 +#, c-format +msgid "no COPY in progress" +msgstr "операция COPY не выполняется" + +#: fe-exec.c:2890 +#, c-format +msgid "connection in wrong state" +msgstr "соединение в неправильном состоянии" + +#: fe-exec.c:2933 +#, c-format +msgid "cannot enter pipeline mode, connection not idle" +msgstr "перейти в конвейерный режиме нельзя, соединение не простаивает" + +#: fe-exec.c:2969 fe-exec.c:2990 +#, c-format +msgid "cannot exit pipeline mode with uncollected results" +msgstr "выйти из конвейерного режима нельзя, не собрав все результаты" + +#: fe-exec.c:2973 +#, c-format +msgid "cannot exit pipeline mode while busy" +msgstr "выйти из конвейерного режима в занятом состоянии нельзя" + +#: fe-exec.c:2984 +#, c-format +msgid "cannot exit pipeline mode while in COPY" +msgstr "выйти из конвейерного режима во время COPY нельзя" + +#: fe-exec.c:3175 +#, c-format +msgid "cannot send pipeline when not in pipeline mode" +msgstr "отправить конвейер, не перейдя в конвейерный режим, нельзя" + +#: fe-exec.c:3284 +msgid "invalid ExecStatusType code" +msgstr "неверный код ExecStatusType" + +#: fe-exec.c:3311 +msgid "PGresult is not an error result\n" +msgstr "В PGresult не передан результат ошибки\n" + +#: fe-exec.c:3379 fe-exec.c:3402 +#, c-format +msgid "column number %d is out of range 0..%d" +msgstr "номер столбца %d вне диапазона 0..%d" + +#: fe-exec.c:3417 +#, c-format +msgid "parameter number %d is out of range 0..%d" +msgstr "номер параметра %d вне диапазона 0..%d" + +#: fe-exec.c:3728 +#, c-format +msgid "could not interpret result from server: %s" +msgstr "не удалось интерпретировать ответ сервера: %s" + +#: fe-exec.c:3993 fe-exec.c:4083 +#, c-format +msgid "incomplete multibyte character" +msgstr "неполный многобайтный символ" + +#: fe-gssapi-common.c:122 +msgid "GSSAPI name import error" +msgstr "ошибка импорта имени в GSSAPI" + +#: fe-lobj.c:144 fe-lobj.c:207 fe-lobj.c:397 fe-lobj.c:487 fe-lobj.c:560 +#: fe-lobj.c:956 fe-lobj.c:963 fe-lobj.c:970 fe-lobj.c:977 fe-lobj.c:984 +#: fe-lobj.c:991 fe-lobj.c:998 fe-lobj.c:1005 +#, c-format +msgid "cannot determine OID of function %s" +msgstr "определить OID функции %s нельзя" + +#: fe-lobj.c:160 +#, c-format +msgid "argument of lo_truncate exceeds integer range" +msgstr "аргумент lo_truncate не умещается в обычном целом" + +#: fe-lobj.c:262 +#, c-format +msgid "argument of lo_read exceeds integer range" +msgstr "аргумент lo_read не умещается в обычном целом" + +#: fe-lobj.c:313 +#, c-format +msgid "argument of lo_write exceeds integer range" +msgstr "аргумент lo_write не умещается в обычном целом" + +#: fe-lobj.c:669 fe-lobj.c:780 +#, c-format +msgid "could not open file \"%s\": %s" +msgstr "не удалось открыть файл \"%s\": %s" + +#: fe-lobj.c:725 +#, c-format +msgid "could not read from file \"%s\": %s" +msgstr "не удалось прочитать файл \"%s\": %s" + +#: fe-lobj.c:801 fe-lobj.c:824 +#, c-format +msgid "could not write to file \"%s\": %s" +msgstr "не удалось записать файл \"%s\": %s" + +#: fe-lobj.c:908 +#, c-format +msgid "query to initialize large object functions did not return data" +msgstr "запрос инициализации функций для больших объектов не вернул данные" + +#: fe-misc.c:240 +#, c-format +msgid "integer of size %lu not supported by pqGetInt" +msgstr "функция pqGetInt не поддерживает integer размером %lu байт" + +#: fe-misc.c:273 +#, c-format +msgid "integer of size %lu not supported by pqPutInt" +msgstr "функция pqPutInt не поддерживает integer размером %lu байт" + +#: fe-misc.c:573 +#, c-format +msgid "connection not open" +msgstr "соединение не открыто" + +#: fe-misc.c:751 fe-secure-openssl.c:215 fe-secure-openssl.c:321 +#: fe-secure.c:259 fe-secure.c:426 +#, c-format +msgid "" +"server closed the connection unexpectedly\n" +"\tThis probably means the server terminated abnormally\n" +"\tbefore or while processing the request." +msgstr "" +"сервер неожиданно закрыл соединение\n" +"\tСкорее всего сервер прекратил работу из-за сбоя\n" +"\tдо или в процессе выполнения запроса." + +#: fe-misc.c:818 +msgid "connection not open\n" +msgstr "соединение не открыто\n" + +#: fe-misc.c:1003 +#, c-format +msgid "timeout expired" +msgstr "тайм-аут" + +#: fe-misc.c:1047 +#, c-format +msgid "invalid socket" +msgstr "неверный сокет" + +#: fe-misc.c:1069 +#, c-format +msgid "%s() failed: %s" +msgstr "ошибка в %s(): %s" + +#: fe-protocol3.c:182 +#, c-format +msgid "message type 0x%02x arrived from server while idle" +msgstr "от сервера во время простоя получено сообщение типа 0x%02x" + +#: fe-protocol3.c:380 +#, c-format +msgid "" +"server sent data (\"D\" message) without prior row description (\"T\" " +"message)" +msgstr "" +"сервер отправил данные (сообщение \"D\") без предварительного описания " +"строки (сообщение \"T\")" + +#: fe-protocol3.c:422 +#, c-format +msgid "unexpected response from server; first received character was \"%c\"" +msgstr "неожиданный ответ сервера; первый полученный символ: \"%c\"" + +#: fe-protocol3.c:445 +#, c-format +msgid "message contents do not agree with length in message type \"%c\"" +msgstr "содержимое не соответствует длине в сообщении типа \"%c\"" + +#: fe-protocol3.c:463 +#, c-format +msgid "lost synchronization with server: got message type \"%c\", length %d" +msgstr "" +"потеряна синхронизация с сервером: получено сообщение типа \"%c\", длина %d" + +#: fe-protocol3.c:515 fe-protocol3.c:555 +msgid "insufficient data in \"T\" message" +msgstr "недостаточно данных в сообщении \"T\"" + +#: fe-protocol3.c:626 fe-protocol3.c:832 +msgid "out of memory for query result" +msgstr "недостаточно памяти для результата запроса" + +#: fe-protocol3.c:695 +msgid "insufficient data in \"t\" message" +msgstr "недостаточно данных в сообщении \"t\"" + +#: fe-protocol3.c:754 fe-protocol3.c:786 fe-protocol3.c:804 +msgid "insufficient data in \"D\" message" +msgstr "недостаточно данных в сообщении \"D\"" + +#: fe-protocol3.c:760 +msgid "unexpected field count in \"D\" message" +msgstr "неверное число полей в сообщении \"D\"" + +#: fe-protocol3.c:1015 +msgid "no error message available\n" +msgstr "нет сообщения об ошибке\n" + +#. translator: %s represents a digit string +#: fe-protocol3.c:1063 fe-protocol3.c:1082 +#, c-format +msgid " at character %s" +msgstr " символ %s" + +#: fe-protocol3.c:1095 +#, c-format +msgid "DETAIL: %s\n" +msgstr "ПОДРОБНОСТИ: %s\n" + +#: fe-protocol3.c:1098 +#, c-format +msgid "HINT: %s\n" +msgstr "ПОДСКАЗКА: %s\n" + +#: fe-protocol3.c:1101 +#, c-format +msgid "QUERY: %s\n" +msgstr "ЗАПРОС: %s\n" + +#: fe-protocol3.c:1108 +#, c-format +msgid "CONTEXT: %s\n" +msgstr "КОНТЕКСТ: %s\n" + +#: fe-protocol3.c:1117 +#, c-format +msgid "SCHEMA NAME: %s\n" +msgstr "СХЕМА: %s\n" + +#: fe-protocol3.c:1121 +#, c-format +msgid "TABLE NAME: %s\n" +msgstr "ТАБЛИЦА: %s\n" + +#: fe-protocol3.c:1125 +#, c-format +msgid "COLUMN NAME: %s\n" +msgstr "СТОЛБЕЦ: %s\n" + +#: fe-protocol3.c:1129 +#, c-format +msgid "DATATYPE NAME: %s\n" +msgstr "ТИП ДАННЫХ: %s\n" + +#: fe-protocol3.c:1133 +#, c-format +msgid "CONSTRAINT NAME: %s\n" +msgstr "ОГРАНИЧЕНИЕ: %s\n" + +#: fe-protocol3.c:1145 +msgid "LOCATION: " +msgstr "ПОЛОЖЕНИЕ: " + +#: fe-protocol3.c:1147 +#, c-format +msgid "%s, " +msgstr "%s, " + +#: fe-protocol3.c:1149 +#, c-format +msgid "%s:%s" +msgstr "%s:%s" + +#: fe-protocol3.c:1344 +#, c-format +msgid "LINE %d: " +msgstr "СТРОКА %d: " + +#: fe-protocol3.c:1418 +#, c-format +msgid "" +"protocol version not supported by server: client uses %u.%u, server supports " +"up to %u.%u" +msgstr "" +"сервер не поддерживает нужную версию протокола: клиент использует %u.%u, " +"сервер поддерживает версии до %u.%u" + +#: fe-protocol3.c:1424 +#, c-format +msgid "protocol extension not supported by server: %s" +msgid_plural "protocol extensions not supported by server: %s" +msgstr[0] "сервер не поддерживает это расширение протокола: %s" +msgstr[1] "сервер не поддерживает эти расширения протокола: %s" +msgstr[2] "сервер не поддерживает эти расширения протокола: %s" + +#: fe-protocol3.c:1432 +#, c-format +msgid "invalid %s message" +msgstr "неверное сообщение %s" + +#: fe-protocol3.c:1797 +#, c-format +msgid "PQgetline: not doing text COPY OUT" +msgstr "PQgetline можно вызывать только во время COPY OUT с текстом" + +#: fe-protocol3.c:2171 +#, c-format +msgid "protocol error: no function result" +msgstr "ошибка протокола: нет результата функции" + +#: fe-protocol3.c:2182 +#, c-format +msgid "protocol error: id=0x%x" +msgstr "ошибка протокола: id=0x%x" + +#: fe-secure-common.c:123 +#, c-format +msgid "SSL certificate's name contains embedded null" +msgstr "имя в SSL-сертификате включает нулевой байт" + +#: fe-secure-common.c:228 +#, c-format +msgid "certificate contains IP address with invalid length %zu" +msgstr "сертификат содержит IP-адрес неверной длины %zu" + +#: fe-secure-common.c:237 +#, c-format +msgid "could not convert certificate's IP address to string: %s" +msgstr "не удалось преобразовать в строку IP-адрес из сертификата: %s" + +#: fe-secure-common.c:269 +#, c-format +msgid "host name must be specified for a verified SSL connection" +msgstr "для проверенного SSL-соединения должно указываться имя узла" + +#: fe-secure-common.c:286 +#, c-format +msgid "" +"server certificate for \"%s\" (and %d other name) does not match host name " +"\"%s\"" +msgid_plural "" +"server certificate for \"%s\" (and %d other names) does not match host name " +"\"%s\"" +msgstr[0] "" +"серверный сертификат для \"%s\" (и %d другого имени) не соответствует имени " +"сервера \"%s\"" +msgstr[1] "" +"серверный сертификат для \"%s\" (и %d других имён) не соответствует имени " +"сервера \"%s\"" +msgstr[2] "" +"серверный сертификат для \"%s\" (и %d других имён) не соответствует имени " +"сервера \"%s\"" + +#: fe-secure-common.c:294 +#, c-format +msgid "server certificate for \"%s\" does not match host name \"%s\"" +msgstr "серверный сертификат для \"%s\" не соответствует имени сервера \"%s\"" + +#: fe-secure-common.c:299 +#, c-format +msgid "could not get server's host name from server certificate" +msgstr "не удалось получить имя сервера из серверного сертификата" + +#: fe-secure-gssapi.c:194 +msgid "GSSAPI wrap error" +msgstr "ошибка обёртывания сообщения в GSSAPI" + +#: fe-secure-gssapi.c:201 +#, c-format +msgid "outgoing GSSAPI message would not use confidentiality" +msgstr "исходящее сообщение GSSAPI не будет защищено" + +#: fe-secure-gssapi.c:208 +#, c-format +msgid "client tried to send oversize GSSAPI packet (%zu > %zu)" +msgstr "клиент попытался передать чрезмерно большой пакет GSSAPI (%zu > %zu)" + +#: fe-secure-gssapi.c:347 fe-secure-gssapi.c:589 +#, c-format +msgid "oversize GSSAPI packet sent by the server (%zu > %zu)" +msgstr "сервер передал чрезмерно большой пакет GSSAPI (%zu > %zu)" + +#: fe-secure-gssapi.c:386 +msgid "GSSAPI unwrap error" +msgstr "ошибка развёртывания сообщения в GSSAPI" + +#: fe-secure-gssapi.c:395 +#, c-format +msgid "incoming GSSAPI message did not use confidentiality" +msgstr "входящее сообщение GSSAPI не защищено" + +#: fe-secure-gssapi.c:652 +msgid "could not initiate GSSAPI security context" +msgstr "не удалось инициализировать контекст безопасности GSSAPI" + +#: fe-secure-gssapi.c:681 +msgid "GSSAPI size check error" +msgstr "ошибка проверки размера в GSSAPI" + +#: fe-secure-gssapi.c:692 +msgid "GSSAPI context establishment error" +msgstr "ошибка установления контекста в GSSAPI" + +#: fe-secure-openssl.c:219 fe-secure-openssl.c:325 fe-secure-openssl.c:1538 +#, c-format +msgid "SSL SYSCALL error: %s" +msgstr "ошибка SSL SYSCALL: %s" + +#: fe-secure-openssl.c:225 fe-secure-openssl.c:331 fe-secure-openssl.c:1541 +#, c-format +msgid "SSL SYSCALL error: EOF detected" +msgstr "ошибка SSL SYSCALL: конец файла (EOF)" + +#: fe-secure-openssl.c:235 fe-secure-openssl.c:341 fe-secure-openssl.c:1549 +#, c-format +msgid "SSL error: %s" +msgstr "ошибка SSL: %s" + +#: fe-secure-openssl.c:249 fe-secure-openssl.c:355 +#, c-format +msgid "SSL connection has been closed unexpectedly" +msgstr "SSL-соединение было неожиданно закрыто" + +#: fe-secure-openssl.c:254 fe-secure-openssl.c:360 fe-secure-openssl.c:1596 +#, c-format +msgid "unrecognized SSL error code: %d" +msgstr "нераспознанный код ошибки SSL: %d" + +#: fe-secure-openssl.c:403 +#, c-format +msgid "could not determine server certificate signature algorithm" +msgstr "не удалось определить алгоритм подписи сертификата сервера" + +#: fe-secure-openssl.c:423 +#, c-format +msgid "could not find digest for NID %s" +msgstr "не удалось найти алгоритм хеширования по NID %s" + +#: fe-secure-openssl.c:432 +#, c-format +msgid "could not generate peer certificate hash" +msgstr "не удалось сгенерировать хеш сертификата сервера" + +#: fe-secure-openssl.c:515 +#, c-format +msgid "SSL certificate's name entry is missing" +msgstr "в SSL-сертификате отсутствует запись имени" + +#: fe-secure-openssl.c:549 +#, c-format +msgid "SSL certificate's address entry is missing" +msgstr "в SSL-сертификате отсутствует запись адреса" + +#: fe-secure-openssl.c:966 +#, c-format +msgid "could not create SSL context: %s" +msgstr "не удалось создать контекст SSL: %s" + +#: fe-secure-openssl.c:1008 +#, c-format +msgid "invalid value \"%s\" for minimum SSL protocol version" +msgstr "неверное значение \"%s\" для минимальной версии протокола SSL" + +#: fe-secure-openssl.c:1018 +#, c-format +msgid "could not set minimum SSL protocol version: %s" +msgstr "не удалось задать минимальную версию протокола SSL: %s" + +#: fe-secure-openssl.c:1034 +#, c-format +msgid "invalid value \"%s\" for maximum SSL protocol version" +msgstr "неверное значение \"%s\" для максимальной версии протокола SSL" + +#: fe-secure-openssl.c:1044 +#, c-format +msgid "could not set maximum SSL protocol version: %s" +msgstr "не удалось задать максимальную версию протокола SSL: %s" + +#: fe-secure-openssl.c:1082 +#, c-format +msgid "could not load system root certificate paths: %s" +msgstr "не удалось выбрать системные пути для корневых сертификатов: %s" + +#: fe-secure-openssl.c:1099 +#, c-format +msgid "could not read root certificate file \"%s\": %s" +msgstr "не удалось прочитать файл корневых сертификатов \"%s\": %s" + +#: fe-secure-openssl.c:1151 +#, c-format +msgid "" +"could not get home directory to locate root certificate file\n" +"Either provide the file, use the system's trusted roots with " +"sslrootcert=system, or change sslmode to disable server certificate " +"verification." +msgstr "" +"не удалось получить домашний каталог для поиска файла корневых сертификатов\n" +"Укажите полный путь к файлу, используйте системные доверенные сертификаты " +"(sslrootcert=system) или отключите проверку сертификата сервера, изменив " +"sslmode." + +#: fe-secure-openssl.c:1154 +#, c-format +msgid "" +"root certificate file \"%s\" does not exist\n" +"Either provide the file, use the system's trusted roots with " +"sslrootcert=system, or change sslmode to disable server certificate " +"verification." +msgstr "" +"файл корневых сертификатов \"%s\" не существует\n" +"Укажите полный путь к файлу, используйте системные доверенные сертификаты " +"(sslrootcert=system) или отключите проверку сертификата сервера, изменив " +"sslmode." + +#: fe-secure-openssl.c:1189 +#, c-format +msgid "could not open certificate file \"%s\": %s" +msgstr "не удалось открыть файл сертификата \"%s\": %s" + +#: fe-secure-openssl.c:1207 +#, c-format +msgid "could not read certificate file \"%s\": %s" +msgstr "не удалось прочитать файл сертификата \"%s\": %s" + +#: fe-secure-openssl.c:1231 +#, c-format +msgid "could not establish SSL connection: %s" +msgstr "не удалось установить SSL-соединение: %s" + +#: fe-secure-openssl.c:1263 +#, c-format +msgid "could not set SSL Server Name Indication (SNI): %s" +msgstr "не удалось задать SNI (Server Name Indication) для SSL-подключения: %s" + +#: fe-secure-openssl.c:1306 +#, c-format +msgid "could not load SSL engine \"%s\": %s" +msgstr "не удалось загрузить модуль SSL ENGINE \"%s\": %s" + +#: fe-secure-openssl.c:1317 +#, c-format +msgid "could not initialize SSL engine \"%s\": %s" +msgstr "не удалось инициализировать модуль SSL ENGINE \"%s\": %s" + +#: fe-secure-openssl.c:1332 +#, c-format +msgid "could not read private SSL key \"%s\" from engine \"%s\": %s" +msgstr "не удалось прочитать закрытый ключ SSL \"%s\" из модуля \"%s\": %s" + +#: fe-secure-openssl.c:1345 +#, c-format +msgid "could not load private SSL key \"%s\" from engine \"%s\": %s" +msgstr "не удалось загрузить закрытый ключ SSL \"%s\" из модуля \"%s\": %s" + +#: fe-secure-openssl.c:1382 +#, c-format +msgid "certificate present, but not private key file \"%s\"" +msgstr "при наличии сертификата отсутствует файл закрытого ключа \"%s\"" + +#: fe-secure-openssl.c:1385 +#, c-format +msgid "could not stat private key file \"%s\": %m" +msgstr "не удалось получить информацию о файле закрытого ключа \"%s\": %m" + +#: fe-secure-openssl.c:1393 +#, c-format +msgid "private key file \"%s\" is not a regular file" +msgstr "файл закрытого ключа \"%s\" - не обычный файл" + +#: fe-secure-openssl.c:1426 +#, c-format +msgid "" +"private key file \"%s\" has group or world access; file must have " +"permissions u=rw (0600) or less if owned by the current user, or permissions " +"u=rw,g=r (0640) or less if owned by root" +msgstr "" +"к файлу закрытого ключа \"%s\" имеют доступ все или группа; для него должны " +"быть заданы разрешения u=rw (0600) или более строгие, если он принадлежит " +"текущему пользователю, либо u=rw,g=r (0640) или более строгие, если он " +"принадлежит root" + +#: fe-secure-openssl.c:1450 +#, c-format +msgid "could not load private key file \"%s\": %s" +msgstr "не удалось загрузить файл закрытого ключа \"%s\": %s" + +#: fe-secure-openssl.c:1466 +#, c-format +msgid "certificate does not match private key file \"%s\": %s" +msgstr "сертификат не соответствует файлу закрытого ключа \"%s\": %s" + +#: fe-secure-openssl.c:1535 +#, c-format +msgid "SSL error: certificate verify failed: %s" +msgstr "ошибка SSL: не удалось проверить сертификат: %s" + +#: fe-secure-openssl.c:1580 +#, c-format +msgid "" +"This may indicate that the server does not support any SSL protocol version " +"between %s and %s." +msgstr "" +"Это может указывать на то, что сервер не поддерживает ни одну версию " +"протокола SSL между %s и %s." + +#: fe-secure-openssl.c:1613 +#, c-format +msgid "certificate could not be obtained: %s" +msgstr "не удалось получить сертификат: %s" + +#: fe-secure-openssl.c:1718 +#, c-format +msgid "no SSL error reported" +msgstr "нет сообщения об ошибке SSL" + +#: fe-secure-openssl.c:1727 +#, c-format +msgid "SSL error code %lu" +msgstr "код ошибки SSL: %lu" + +#: fe-secure-openssl.c:2017 +#, c-format +msgid "WARNING: sslpassword truncated\n" +msgstr "ПРЕДУПРЕЖДЕНИЕ: значение sslpassword усечено\n" + +#: fe-secure.c:270 +#, c-format +msgid "could not receive data from server: %s" +msgstr "не удалось получить данные с сервера: %s" + +#: fe-secure.c:441 +#, c-format +msgid "could not send data to server: %s" +msgstr "не удалось передать данные серверу: %s" + +#: win32.c:310 +#, c-format +msgid "unrecognized socket error: 0x%08X/%d" +msgstr "нераспознанная ошибка сокета: 0x%08X/%d" + +#~ msgid "SCM_CRED authentication method not supported\n" +#~ msgstr "аутентификация SCM_CRED не поддерживается\n" + +#~ msgid "" +#~ "server sent data (\"D\" message) without prior row description (\"T\" " +#~ "message)\n" +#~ msgstr "" +#~ "сервер отправил данные (сообщение \"D\") без предварительного описания " +#~ "строки (сообщение \"T\")\n" + +#~ msgid "PGEventProc \"%s\" failed during PGEVT_CONNRESET event\n" +#~ msgstr "ошибка в PGEventProc \"%s\" при обработке события PGEVT_CONNRESET\n" + +#~ msgid "PGEventProc \"%s\" failed during PGEVT_RESULTCREATE event\n" +#~ msgstr "" +#~ "ошибка в PGEventProc \"%s\" при обработке события PGEVT_RESULTCREATE\n" + +#~ msgid "invalid channel_binding value: \"%s\"\n" +#~ msgstr "неверное значение channel_binding: \"%s\"\n" + +#~ msgid "invalid ssl_min_protocol_version value: \"%s\"\n" +#~ msgstr "неверное значение ssl_min_protocol_version: \"%s\"\n" + +#~ msgid "invalid ssl_max_protocol_version value: \"%s\"\n" +#~ msgstr "неверное значение ssl_max_protocol_version: \"%s\"\n" + +#~ msgid "invalid gssencmode value: \"%s\"\n" +#~ msgstr "неверное значение gssencmode: \"%s\"\n" + +#~ msgid "invalid target_session_attrs value: \"%s\"\n" +#~ msgstr "неверное значение target_session_attrs: \"%s\"\n" + +#~ msgid "" +#~ "could not connect to server: %s\n" +#~ "\tIs the server running on host \"%s\" (%s) and accepting\n" +#~ "\tTCP/IP connections on port %s?\n" +#~ msgstr "" +#~ "не удалось подключиться к серверу: %s\n" +#~ "\tОн действительно работает по адресу \"%s\" (%s)\n" +#~ "\t и принимает TCP-соединения (порт %s)?\n" + +#~ msgid "setsockopt(%s) failed: %s\n" +#~ msgstr "ошибка в setsockopt(%s): %s\n" + +#~ msgid "WSAIoctl(SIO_KEEPALIVE_VALS) failed: %ui\n" +#~ msgstr "ошибка в WSAIoctl(SIO_KEEPALIVE_VALS): %ui\n" + +#~ msgid "could not make a writable connection to server \"%s:%s\"\n" +#~ msgstr "" +#~ "не удалось установить подключение для чтения/записи к серверу \"%s:%s\"\n" + +#~ msgid "test \"SHOW transaction_read_only\" failed on server \"%s:%s\"\n" +#~ msgstr "" +#~ "проверка \"SHOW transaction_read_only\" не пройдена на сервере \"%s:%s\"\n" + +#~ msgid "function requires at least protocol version 3.0\n" +#~ msgstr "функция требует протокол минимум версии 3.0\n" + +#~ msgid "COPY IN state must be terminated first\n" +#~ msgstr "сначала должно завершиться состояние COPY IN\n" + +#~ msgid "COPY OUT state must be terminated first\n" +#~ msgstr "сначала должно завершиться состояние COPY OUT\n" + +#~ msgid "cannot determine OID of function lo_truncate\n" +#~ msgstr "не удалось определить OID функции lo_truncate\n" + +#~ msgid "cannot determine OID of function lo_truncate64\n" +#~ msgstr "не удалось определить OID функции lo_truncate64\n" + +#~ msgid "cannot determine OID of function lo_lseek64\n" +#~ msgstr "не удалось определить OID функции lo_lseek64\n" + +#~ msgid "cannot determine OID of function lo_create\n" +#~ msgstr "не удалось определить OID функции lo_create\n" + +#~ msgid "cannot determine OID of function lo_tell64\n" +#~ msgstr "не удалось определить OID функции lo_tell64\n" + +#~ msgid "cannot determine OID of function lo_open\n" +#~ msgstr "не удалось определить OID функции lo_open\n" + +#~ msgid "cannot determine OID of function lo_creat\n" +#~ msgstr "не удалось определить OID функции lo_creat\n" + +#~ msgid "cannot determine OID of function lo_unlink\n" +#~ msgstr "не удалось определить OID функции lo_unlink\n" + +#~ msgid "cannot determine OID of function lo_lseek\n" +#~ msgstr "не удалось определить OID функции lo_lseek\n" + +#~ msgid "cannot determine OID of function loread\n" +#~ msgstr "не удалось определить OID функции loread\n" + +#~ msgid "cannot determine OID of function lowrite\n" +#~ msgstr "не удалось определить OID функции lowrite\n" + +#~ msgid "invalid setenv state %c, probably indicative of memory corruption\n" +#~ msgstr "неверное состояние setenv %c - возможно разрушение памяти\n" + +#~ msgid "invalid state %c, probably indicative of memory corruption\n" +#~ msgstr "неверное состояние %c - возможно разрушение памяти\n" + +#~ msgid "" +#~ "unexpected character %c following empty query response (\"I\" message)" +#~ msgstr "неожиданный символ %c вслед за пустым ответом (сообщение \"I\")" + +#~ msgid "" +#~ "server sent binary data (\"B\" message) without prior row description " +#~ "(\"T\" message)" +#~ msgstr "" +#~ "сервер отправил двоичные данные (сообщение \"B\") без предварительного " +#~ "описания строки (сообщение \"T\")" + +#~ msgid "lost synchronization with server, resetting connection" +#~ msgstr "потеряна синхронизация с сервером; попытка восстановить соединение" + +#~ msgid "extraneous data in \"T\" message" +#~ msgstr "лишние данные в сообщении \"T\"" + +#~ msgid "extraneous data in \"t\" message" +#~ msgstr "лишние данные в сообщении \"t\"" + +#~ msgid "extraneous data in \"D\" message" +#~ msgstr "лишние данные в сообщении \"D\"" + +#~ msgid "SSL library does not support CRL certificates (file \"%s\")\n" +#~ msgstr "Библиотека SSL не поддерживает проверку CRL (файл \"%s\")\n" + +#~ msgid "could not get home directory to locate password file\n" +#~ msgstr "не удалось получить домашний каталог для загрузки файла паролей\n" + +#~ msgid "could not get home directory to locate service definition file" +#~ msgstr "" +#~ "не удалось получить домашний каталог для загрузки файла определений служб" + +#~ msgid "setsockopt(TCP_KEEPIDLE) failed: %s\n" +#~ msgstr "ошибка в setsockopt(TCP_KEEPIDLE): %s\n" + +#~ msgid "setsockopt(TCP_KEEPALIVE) failed: %s\n" +#~ msgstr "ошибка в setsockopt(TCP_KEEPALIVE): %s\n" + +#~ msgid "setsockopt(TCP_KEEPINTVL) failed: %s\n" +#~ msgstr "ошибка в setsockopt(TCP_KEEPINTVL): %s\n" + +#~ msgid "setsockopt(SO_KEEPALIVE) failed: %s\n" +#~ msgstr "ошибка в setsockopt(SO_KEEPALIVE): %s\n" + +#~ msgid "could not acquire mutex: %s\n" +#~ msgstr "не удалось заблокировать семафор: %s\n" + +#~ msgid "socket not open\n" +#~ msgstr "сокет не открыт\n" + +#~ msgid "unrecognized return value from row processor" +#~ msgstr "процессор строк вернул нераспознанное значение" + +#~ msgid "could not restore nonblocking mode on socket: %s\n" +#~ msgstr "не удалось вернуть сокет в неблокирующий режим: %s\n" + +#~ msgid "Kerberos 5 authentication rejected: %*s\n" +#~ msgstr "аутентификация Kerberos 5 не пройдена: %*s\n" + +#~ msgid "could not set socket to blocking mode: %s\n" +#~ msgstr "не удалось перевести сокет в блокирующий режим: %s\n" diff --git a/src/interfaces/libpq/po/sv.po b/src/interfaces/libpq/po/sv.po new file mode 100644 index 0000000..263b5eb --- /dev/null +++ b/src/interfaces/libpq/po/sv.po @@ -0,0 +1,1517 @@ +# Swedish message translation file for libpq +# Peter Eisentraut <peter_e@gmx.net>, 2001, 2010. +# Dennis Björklund <db@zigo.dhs.org>, 2002, 2003, 2004, 2005, 2006, 2017, 2018, 2019, 2020, 2021, 2022, 2023. +# +# Use these quotes: "%s" +# +msgid "" +msgstr "" +"Project-Id-Version: PostgreSQL 16\n" +"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" +"POT-Creation-Date: 2023-08-01 14:10+0000\n" +"PO-Revision-Date: 2023-08-01 22:08+0200\n" +"Last-Translator: Dennis Björklund <db@zigo.dhs.org>\n" +"Language-Team: Swedish <pgsql-translators@postgresql.org>\n" +"Language: sv\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#: ../../port/thread.c:50 ../../port/thread.c:86 +#, c-format +msgid "could not look up local user ID %d: %s" +msgstr "kunde inte slå upp lokalt användar-id %d: %s" + +#: ../../port/thread.c:55 ../../port/thread.c:91 +#, c-format +msgid "local user with ID %d does not exist" +msgstr "lokal användare med ID %d existerar inte" + +#: fe-auth-scram.c:227 +#, c-format +msgid "malformed SCRAM message (empty message)" +msgstr "felaktigt SCRAM-meddelande (tomt meddelande)" + +#: fe-auth-scram.c:232 +#, c-format +msgid "malformed SCRAM message (length mismatch)" +msgstr "felaktigt SCRAM-meddelande (längden stämmer inte)" + +#: fe-auth-scram.c:275 +#, c-format +msgid "could not verify server signature: %s" +msgstr "kunde inte verifiera serversignaturen: %s" + +#: fe-auth-scram.c:281 +#, c-format +msgid "incorrect server signature" +msgstr "felaktig serversignatur" + +#: fe-auth-scram.c:290 +#, c-format +msgid "invalid SCRAM exchange state" +msgstr "ogiltig SCRAM-utbytesstatus" + +#: fe-auth-scram.c:317 +#, c-format +msgid "malformed SCRAM message (attribute \"%c\" expected)" +msgstr "felaktigt SCRAM-meddelande (förväntade attribut \"%c\")" + +#: fe-auth-scram.c:326 +#, c-format +msgid "malformed SCRAM message (expected character \"=\" for attribute \"%c\")" +msgstr "felaktigt SCRAM-meddelande (förväntade tecken \"=\" för attribut \"%c\")" + +#: fe-auth-scram.c:366 +#, c-format +msgid "could not generate nonce" +msgstr "kunde inte skapa engångsnummer" + +#: fe-auth-scram.c:375 fe-auth-scram.c:448 fe-auth-scram.c:600 +#: fe-auth-scram.c:620 fe-auth-scram.c:644 fe-auth-scram.c:658 +#: fe-auth-scram.c:704 fe-auth-scram.c:740 fe-auth-scram.c:914 fe-auth.c:296 +#: fe-auth.c:369 fe-auth.c:403 fe-auth.c:618 fe-auth.c:729 fe-auth.c:1210 +#: fe-auth.c:1375 fe-connect.c:925 fe-connect.c:1759 fe-connect.c:1921 +#: fe-connect.c:3291 fe-connect.c:4496 fe-connect.c:5161 fe-connect.c:5416 +#: fe-connect.c:5534 fe-connect.c:5781 fe-connect.c:5861 fe-connect.c:5959 +#: fe-connect.c:6210 fe-connect.c:6237 fe-connect.c:6313 fe-connect.c:6336 +#: fe-connect.c:6360 fe-connect.c:6395 fe-connect.c:6481 fe-connect.c:6489 +#: fe-connect.c:6846 fe-connect.c:6996 fe-exec.c:527 fe-exec.c:1321 +#: fe-exec.c:3111 fe-exec.c:4071 fe-exec.c:4235 fe-gssapi-common.c:109 +#: fe-lobj.c:870 fe-protocol3.c:204 fe-protocol3.c:228 fe-protocol3.c:256 +#: fe-protocol3.c:273 fe-protocol3.c:353 fe-protocol3.c:720 fe-protocol3.c:959 +#: fe-protocol3.c:1770 fe-protocol3.c:2170 fe-secure-common.c:110 +#: fe-secure-gssapi.c:500 fe-secure-openssl.c:434 fe-secure-openssl.c:1285 +#, c-format +msgid "out of memory" +msgstr "slut på minne" + +#: fe-auth-scram.c:382 +#, c-format +msgid "could not encode nonce" +msgstr "kunde inte koda engångsnummer" + +#: fe-auth-scram.c:570 +#, c-format +msgid "could not calculate client proof: %s" +msgstr "kunde inte räkna ut klientbevis: %s" + +#: fe-auth-scram.c:585 +#, c-format +msgid "could not encode client proof" +msgstr "kunde inte koda klientbevis" + +#: fe-auth-scram.c:637 +#, c-format +msgid "invalid SCRAM response (nonce mismatch)" +msgstr "ogiltigt SCRAM-svar (engångsnummer matchar inte)" + +#: fe-auth-scram.c:667 +#, c-format +msgid "malformed SCRAM message (invalid salt)" +msgstr "felaktigt SCRAM-meddelande (ogiltigt salt)" + +#: fe-auth-scram.c:680 +#, c-format +msgid "malformed SCRAM message (invalid iteration count)" +msgstr "felaktigt SCRAM-meddelande (ogiltig iterationsräknare)" + +#: fe-auth-scram.c:685 +#, c-format +msgid "malformed SCRAM message (garbage at end of server-first-message)" +msgstr "felaktigt SCRAM-meddelande (skräp i slutet på server-first-message)" + +#: fe-auth-scram.c:719 +#, c-format +msgid "error received from server in SCRAM exchange: %s" +msgstr "fel mottaget från server i SCRAM-utbyte: %s" + +#: fe-auth-scram.c:734 +#, c-format +msgid "malformed SCRAM message (garbage at end of server-final-message)" +msgstr "felaktigt SCRAM-meddelande (skräp i slutet av server-final-message)" + +#: fe-auth-scram.c:751 +#, c-format +msgid "malformed SCRAM message (invalid server signature)" +msgstr "felaktigt SCRAM-meddelande (ogiltigt serversignatur)" + +#: fe-auth-scram.c:923 +msgid "could not generate random salt" +msgstr "kunde inte generera slumpat salt" + +#: fe-auth.c:77 +#, c-format +msgid "out of memory allocating GSSAPI buffer (%d)" +msgstr "slut på minne vid allokering av buffer till GSSAPI (%d)" + +#: fe-auth.c:138 +msgid "GSSAPI continuation error" +msgstr "GSSAPI fortsättningsfel" + +#: fe-auth.c:168 fe-auth.c:397 fe-gssapi-common.c:97 fe-secure-common.c:99 +#: fe-secure-common.c:173 +#, c-format +msgid "host name must be specified" +msgstr "värdnamn måste anges" + +#: fe-auth.c:174 +#, c-format +msgid "duplicate GSS authentication request" +msgstr "duplicerad autentiseringsbegäran från GSS" + +#: fe-auth.c:238 +#, c-format +msgid "out of memory allocating SSPI buffer (%d)" +msgstr "slut på minne vid allokering av buffer till SSPI (%d)" + +#: fe-auth.c:285 +msgid "SSPI continuation error" +msgstr "SSPI fortsättningsfel" + +#: fe-auth.c:359 +#, c-format +msgid "duplicate SSPI authentication request" +msgstr "duplicerad autentiseringsbegäran från SSPI" + +#: fe-auth.c:384 +msgid "could not acquire SSPI credentials" +msgstr "kunde inte hämta SSPI-autentiseringsuppgifter" + +#: fe-auth.c:437 +#, c-format +msgid "channel binding required, but SSL not in use" +msgstr "kräver kanalbindning, men SSL används inte" + +#: fe-auth.c:443 +#, c-format +msgid "duplicate SASL authentication request" +msgstr "duplicerad autentiseringsbegäran från SASL" + +#: fe-auth.c:501 +#, c-format +msgid "channel binding is required, but client does not support it" +msgstr "kanalbindning krävs men klienten stöder inte det" + +#: fe-auth.c:517 +#, c-format +msgid "server offered SCRAM-SHA-256-PLUS authentication over a non-SSL connection" +msgstr "servern erbjöd SCRAM-SHA-256-PLUS-autentisering över en icke-SSL-anslutning" + +#: fe-auth.c:531 +#, c-format +msgid "none of the server's SASL authentication mechanisms are supported" +msgstr "ingen av serverns SASL-autentiseringsmekanismer stöds" + +#: fe-auth.c:538 +#, c-format +msgid "channel binding is required, but server did not offer an authentication method that supports channel binding" +msgstr "kräver kanalbindning, men servern erbjöd ingen autentiseringsmetod som stöder kanalbindning" + +#: fe-auth.c:641 +#, c-format +msgid "out of memory allocating SASL buffer (%d)" +msgstr "slut på minne vid allokering av buffer till SASL (%d)" + +#: fe-auth.c:665 +#, c-format +msgid "AuthenticationSASLFinal received from server, but SASL authentication was not completed" +msgstr "mottog AuthenticationSASLFinal från server, men SASL-autentisering slutfördes ej" + +#: fe-auth.c:675 +#, c-format +msgid "no client response found after SASL exchange success" +msgstr "hittade inget klientsvar efter lyckat SASL-utbyte" + +#: fe-auth.c:738 fe-auth.c:745 fe-auth.c:1358 fe-auth.c:1369 +#, c-format +msgid "could not encrypt password: %s" +msgstr "kan inte kryptera lösenord: %s" + +#: fe-auth.c:773 +msgid "server requested a cleartext password" +msgstr "servern begärde ett lösenord i klartext" + +#: fe-auth.c:775 +msgid "server requested a hashed password" +msgstr "servern begärde ett hashat lösenord" + +#: fe-auth.c:778 +msgid "server requested GSSAPI authentication" +msgstr "servern begärde GSSAPI-autentisering" + +#: fe-auth.c:780 +msgid "server requested SSPI authentication" +msgstr "servern begärde SSPI-autentisering" + +#: fe-auth.c:784 +msgid "server requested SASL authentication" +msgstr "servern begärde SASL-autentisering" + +#: fe-auth.c:787 +msgid "server requested an unknown authentication type" +msgstr "servern begärde en okänd autentiseringstyp" + +#: fe-auth.c:820 +#, c-format +msgid "server did not request an SSL certificate" +msgstr "servern begärde inte ett SSL-certifikat" + +#: fe-auth.c:825 +#, c-format +msgid "server accepted connection without a valid SSL certificate" +msgstr "serven accepterade en anslutning utan giltigt SSL-certifikat" + +#: fe-auth.c:879 +msgid "server did not complete authentication" +msgstr "servern slutförde inte autenticeringen" + +#: fe-auth.c:913 +#, c-format +msgid "authentication method requirement \"%s\" failed: %s" +msgstr "autentiseringsmetodens krav \"%s\" misslyckades: %s" + +#: fe-auth.c:936 +#, c-format +msgid "channel binding required, but server authenticated client without channel binding" +msgstr "kräver kanalbindning, men servern autentiserade klienten utan kanalbindning" + +#: fe-auth.c:941 +#, c-format +msgid "channel binding required but not supported by server's authentication request" +msgstr "kanalbindning krävs men stöds inte av serverns autentiseringsförfrågan" + +#: fe-auth.c:975 +#, c-format +msgid "Kerberos 4 authentication not supported" +msgstr "Kerberos-4-autentisering stöds ej" + +#: fe-auth.c:979 +#, c-format +msgid "Kerberos 5 authentication not supported" +msgstr "Kerberos-5-autentisering stöds ej" + +#: fe-auth.c:1049 +#, c-format +msgid "GSSAPI authentication not supported" +msgstr "GSSAPI-autentisering stöds ej" + +#: fe-auth.c:1080 +#, c-format +msgid "SSPI authentication not supported" +msgstr "SSPI-autentisering stöds ej" + +#: fe-auth.c:1087 +#, c-format +msgid "Crypt authentication not supported" +msgstr "Crypt-autentisering stöds ej" + +#: fe-auth.c:1151 +#, c-format +msgid "authentication method %u not supported" +msgstr "autentiseringsmetod %u stöds ej" + +#: fe-auth.c:1197 +#, c-format +msgid "user name lookup failure: error code %lu" +msgstr "misslyckad sökning efter användarnamn: felkod %lu" + +#: fe-auth.c:1321 +#, c-format +msgid "unexpected shape of result set returned for SHOW" +msgstr "oväntad form på resultatmängden som returnerades för SHOW" + +#: fe-auth.c:1329 +#, c-format +msgid "password_encryption value too long" +msgstr "password_encryption-värdet är för långt" + +#: fe-auth.c:1379 +#, c-format +msgid "unrecognized password encryption algorithm \"%s\"" +msgstr "okänd lösenordskrypteringsalgoritm \"%s\"" + +#: fe-connect.c:1132 +#, c-format +msgid "could not match %d host names to %d hostaddr values" +msgstr "kunde inte matcha %d värdnamn till %d värdadresser" + +#: fe-connect.c:1212 +#, c-format +msgid "could not match %d port numbers to %d hosts" +msgstr "kunde inte matcha %d portnummer med %d värdar" + +#: fe-connect.c:1337 +#, c-format +msgid "negative require_auth method \"%s\" cannot be mixed with non-negative methods" +msgstr "negativ require_auth-metod \"%s\" kan inte blandas med icke-negativa metoder" + +#: fe-connect.c:1350 +#, c-format +msgid "require_auth method \"%s\" cannot be mixed with negative methods" +msgstr "require_auth-metod \"%s\" kan inte blandas med negativa metoder" + +#: fe-connect.c:1410 fe-connect.c:1461 fe-connect.c:1503 fe-connect.c:1559 +#: fe-connect.c:1567 fe-connect.c:1598 fe-connect.c:1644 fe-connect.c:1684 +#: fe-connect.c:1705 +#, c-format +msgid "invalid %s value: \"%s\"" +msgstr "ogiltigt %s-värde: \"%s\"" + +#: fe-connect.c:1443 +#, c-format +msgid "require_auth method \"%s\" is specified more than once" +msgstr "require_auth-metod \"%s\" angiven mer än en gång" + +#: fe-connect.c:1484 fe-connect.c:1523 fe-connect.c:1606 +#, c-format +msgid "%s value \"%s\" invalid when SSL support is not compiled in" +msgstr "%s värde \"%s\", är ogiltigt när SSL-stöd inte kompilerats in" + +#: fe-connect.c:1546 +#, c-format +msgid "weak sslmode \"%s\" may not be used with sslrootcert=system (use \"verify-full\")" +msgstr "svagt ssl-läge \"%s\" kan inte användas med sslrootcert=system (använd \"verify-full\")" + +#: fe-connect.c:1584 +#, c-format +msgid "invalid SSL protocol version range" +msgstr "ogiltigt intervall för SSL-protokollversion" + +#: fe-connect.c:1621 +#, c-format +msgid "%s value \"%s\" is not supported (check OpenSSL version)" +msgstr "%s-värde \"%s\" stöds inte (kontrollera OpenSSL-versionen)" + +#: fe-connect.c:1651 +#, c-format +msgid "gssencmode value \"%s\" invalid when GSSAPI support is not compiled in" +msgstr "värde för gssenc-läge, \"%s\", är ogiltigt när GSSAPI-stöd inte kompilerats in" + +#: fe-connect.c:1944 +#, c-format +msgid "could not set socket to TCP no delay mode: %s" +msgstr "kunde inte sätta socket till läget TCP-ingen-fördröjning: %s" + +#: fe-connect.c:2003 +#, c-format +msgid "connection to server on socket \"%s\" failed: " +msgstr "anslutning till server på socket \"%s\" misslyckades: " + +#: fe-connect.c:2029 +#, c-format +msgid "connection to server at \"%s\" (%s), port %s failed: " +msgstr "anslutning til server på \"%s\" (%s), port %s misslyckades: " + +#: fe-connect.c:2034 +#, c-format +msgid "connection to server at \"%s\", port %s failed: " +msgstr "anslutning till server på \"%s\", port %s misslyckades: " + +#: fe-connect.c:2057 +#, c-format +msgid "\tIs the server running locally and accepting connections on that socket?" +msgstr "\tKör servern lokalt och accepterar den anslutningar till denna socket?" + +#: fe-connect.c:2059 +#, c-format +msgid "\tIs the server running on that host and accepting TCP/IP connections?" +msgstr "\tKör servern på den värden och accepterar den TCP/IP-anslutningar?" + +#: fe-connect.c:2122 +#, c-format +msgid "invalid integer value \"%s\" for connection option \"%s\"" +msgstr "ogiltigt heltalsvärde \"%s\" för anslutningsflagga \"%s\"" + +#: fe-connect.c:2151 fe-connect.c:2185 fe-connect.c:2220 fe-connect.c:2318 +#: fe-connect.c:2973 +#, c-format +msgid "%s(%s) failed: %s" +msgstr "%s(%s) misslyckades: %s" + +#: fe-connect.c:2284 +#, c-format +msgid "%s(%s) failed: error code %d" +msgstr "%s(%s) misslyckades: felkod %d" + +#: fe-connect.c:2597 +#, c-format +msgid "invalid connection state, probably indicative of memory corruption" +msgstr "ogiltigt tillstånd i anslutning, antagligen korrupt minne" + +#: fe-connect.c:2676 +#, c-format +msgid "invalid port number: \"%s\"" +msgstr "ogiltigt portnummer \"%s\"" + +#: fe-connect.c:2690 +#, c-format +msgid "could not translate host name \"%s\" to address: %s" +msgstr "kunde inte översätta värdnamn \"%s\" till adress: %s" + +#: fe-connect.c:2702 +#, c-format +msgid "could not parse network address \"%s\": %s" +msgstr "kunde inte parsa nätverksadress \"%s\": %s" + +#: fe-connect.c:2713 +#, c-format +msgid "Unix-domain socket path \"%s\" is too long (maximum %d bytes)" +msgstr "Sökväg till unix-socket \"%s\" är för lång (maximalt %d byte)" + +#: fe-connect.c:2727 +#, c-format +msgid "could not translate Unix-domain socket path \"%s\" to address: %s" +msgstr "kunde inte översätta sökväg till Unix-socket \"%s\" till adress: %s" + +#: fe-connect.c:2901 +#, c-format +msgid "could not create socket: %s" +msgstr "kan inte skapa socket: %s" + +#: fe-connect.c:2932 +#, c-format +msgid "could not set socket to nonblocking mode: %s" +msgstr "kunde inte sätta socket till ickeblockerande läge: %s" + +#: fe-connect.c:2943 +#, c-format +msgid "could not set socket to close-on-exec mode: %s" +msgstr "kunde inte ställa in socket i \"close-on-exec\"-läge: %s" + +#: fe-connect.c:2961 +#, c-format +msgid "keepalives parameter must be an integer" +msgstr "keepalives-parameter måste vara ett heltal" + +#: fe-connect.c:3100 +#, c-format +msgid "could not get socket error status: %s" +msgstr "kunde inte hämta felstatus för socket: %s" + +#: fe-connect.c:3127 +#, c-format +msgid "could not get client address from socket: %s" +msgstr "kunde inte få klientadressen från socket: %s" + +#: fe-connect.c:3165 +#, c-format +msgid "requirepeer parameter is not supported on this platform" +msgstr "requirepeer-parameter stöds inte på denna plattform" + +#: fe-connect.c:3167 +#, c-format +msgid "could not get peer credentials: %s" +msgstr "kunde inte hämta andra sidans autentiseringsuppgifter: %s" + +#: fe-connect.c:3180 +#, c-format +msgid "requirepeer specifies \"%s\", but actual peer user name is \"%s\"" +msgstr "requirepeer anger \"%s\", men andra sidans användarnamn är \"%s\"" + +#: fe-connect.c:3221 +#, c-format +msgid "could not send GSSAPI negotiation packet: %s" +msgstr "kunde inte skicka GSSAPI-paket för anslutningsförhandling: %s" + +#: fe-connect.c:3233 +#, c-format +msgid "GSSAPI encryption required but was impossible (possibly no credential cache, no server support, or using a local socket)" +msgstr "GSSAPI-kryptering krävdes men var omöjligt (kanske ingen credential-cache, inget serverstöd eller använder en lokalt socket)" + +#: fe-connect.c:3274 +#, c-format +msgid "could not send SSL negotiation packet: %s" +msgstr "kunde inte skicka SSL-paket för anslutningsförhandling: %s" + +#: fe-connect.c:3303 +#, c-format +msgid "could not send startup packet: %s" +msgstr "kan inte skicka startpaketet: %s" + +#: fe-connect.c:3378 +#, c-format +msgid "server does not support SSL, but SSL was required" +msgstr "SSL stöds inte av servern, men SSL krävdes" + +#: fe-connect.c:3404 +#, c-format +msgid "received invalid response to SSL negotiation: %c" +msgstr "tog emot ogiltigt svar till SSL-anslutningsförhandling: %c" + +#: fe-connect.c:3424 +#, c-format +msgid "received unencrypted data after SSL response" +msgstr "tog emot okrypterad data efter SSL-svar" + +#: fe-connect.c:3504 +#, c-format +msgid "server doesn't support GSSAPI encryption, but it was required" +msgstr "GSSAPI-kryptering stöds inte av servern, men det krävdes" + +#: fe-connect.c:3515 +#, c-format +msgid "received invalid response to GSSAPI negotiation: %c" +msgstr "tog emot ogiltigt svar till GSSAPI-anslutningsförhandling: %c" + +#: fe-connect.c:3533 +#, c-format +msgid "received unencrypted data after GSSAPI encryption response" +msgstr "tog emot okrypterad data efter GSSAPI-krypteringssvar" + +#: fe-connect.c:3598 +#, c-format +msgid "expected authentication request from server, but received %c" +msgstr "förväntade autentiseringsförfrågan från servern, men fick %c" + +#: fe-connect.c:3625 fe-connect.c:3794 +#, c-format +msgid "received invalid authentication request" +msgstr "tog emot ogiltig autentiseringsförfrågan" + +#: fe-connect.c:3630 fe-connect.c:3779 +#, c-format +msgid "received invalid protocol negotiation message" +msgstr "tog emot ogiltigt meddelande för protokollets anslutningsförhandling" + +#: fe-connect.c:3648 fe-connect.c:3702 +#, c-format +msgid "received invalid error message" +msgstr "tog emot ogiltigt felmeddelande" + +#: fe-connect.c:3865 +#, c-format +msgid "unexpected message from server during startup" +msgstr "oväntat meddelande från servern under uppstarten" + +#: fe-connect.c:3956 +#, c-format +msgid "session is read-only" +msgstr "sessionen är i readonly-läge" + +#: fe-connect.c:3958 +#, c-format +msgid "session is not read-only" +msgstr "sessionen är inte i readonly-läge" + +#: fe-connect.c:4011 +#, c-format +msgid "server is in hot standby mode" +msgstr "servern är i \"hot standby\"-läge" + +#: fe-connect.c:4013 +#, c-format +msgid "server is not in hot standby mode" +msgstr "servern är inte i \"hot standby\"-läge" + +#: fe-connect.c:4129 fe-connect.c:4179 +#, c-format +msgid "\"%s\" failed" +msgstr "\"%s\" misslyckades" + +#: fe-connect.c:4193 +#, c-format +msgid "invalid connection state %d, probably indicative of memory corruption" +msgstr "ogiltigt tillstånd %d i anslutning, antagligen korrupt minne" + +#: fe-connect.c:5174 +#, c-format +msgid "invalid LDAP URL \"%s\": scheme must be ldap://" +msgstr "ogiltig LDAP URL \"%s\": schemat måste vara ldap://" + +#: fe-connect.c:5189 +#, c-format +msgid "invalid LDAP URL \"%s\": missing distinguished name" +msgstr "ogiltig LDAP URL \"%s\": saknar \"distinguished name\"" + +#: fe-connect.c:5201 fe-connect.c:5259 +#, c-format +msgid "invalid LDAP URL \"%s\": must have exactly one attribute" +msgstr "ogiltig LDAP URL \"%s\": måste finnas exakt ett attribut" + +#: fe-connect.c:5213 fe-connect.c:5275 +#, c-format +msgid "invalid LDAP URL \"%s\": must have search scope (base/one/sub)" +msgstr "ogiltig LDAP URL \"%s\": måste ha sök-scope (base/one/sub)" + +#: fe-connect.c:5225 +#, c-format +msgid "invalid LDAP URL \"%s\": no filter" +msgstr "ogiltigt LDAP URL \"%s\": inget filter" + +#: fe-connect.c:5247 +#, c-format +msgid "invalid LDAP URL \"%s\": invalid port number" +msgstr "ogiltig LDAP URL \"%s\": ogiltigt portnummer" + +#: fe-connect.c:5284 +#, c-format +msgid "could not create LDAP structure" +msgstr "kunde inte skapa LDAP-struktur" + +#: fe-connect.c:5359 +#, c-format +msgid "lookup on LDAP server failed: %s" +msgstr "uppslagning av LDAP-server misslyckades: %s" + +#: fe-connect.c:5369 +#, c-format +msgid "more than one entry found on LDAP lookup" +msgstr "mer än en post hittad i LDAP-uppslagning" + +#: fe-connect.c:5371 fe-connect.c:5382 +#, c-format +msgid "no entry found on LDAP lookup" +msgstr "ingen post hittad i LDAP-uppslagning" + +#: fe-connect.c:5392 fe-connect.c:5404 +#, c-format +msgid "attribute has no values on LDAP lookup" +msgstr "attributet har inga värden i LDAP-uppslagning" + +#: fe-connect.c:5455 fe-connect.c:5474 fe-connect.c:5998 +#, c-format +msgid "missing \"=\" after \"%s\" in connection info string" +msgstr "\"=\" efter \"%s\" saknas i anslutningssträng" + +#: fe-connect.c:5545 fe-connect.c:6181 fe-connect.c:6979 +#, c-format +msgid "invalid connection option \"%s\"" +msgstr "ogiltig anslutningsparameter \"%s\"" + +#: fe-connect.c:5560 fe-connect.c:6046 +#, c-format +msgid "unterminated quoted string in connection info string" +msgstr "icke terminerad sträng i uppkopplingsinformationen" + +#: fe-connect.c:5640 +#, c-format +msgid "definition of service \"%s\" not found" +msgstr "definition av service \"%s\" hittades inte" + +#: fe-connect.c:5666 +#, c-format +msgid "service file \"%s\" not found" +msgstr "servicefil \"%s\" hittades inte" + +#: fe-connect.c:5679 +#, c-format +msgid "line %d too long in service file \"%s\"" +msgstr "rad %d för lång i servicefil \"%s\"" + +#: fe-connect.c:5750 fe-connect.c:5793 +#, c-format +msgid "syntax error in service file \"%s\", line %d" +msgstr "syntaxfel i servicefel \"%s\", rad %d" + +#: fe-connect.c:5761 +#, c-format +msgid "nested service specifications not supported in service file \"%s\", line %d" +msgstr "nästlade servicespecifikationer stöds inte i servicefil \"%s\", rad %d" + +#: fe-connect.c:6500 +#, c-format +msgid "invalid URI propagated to internal parser routine: \"%s\"" +msgstr "ogiltig URI propagerad till intern parsningsrutin: \"%s\"" + +#: fe-connect.c:6577 +#, c-format +msgid "end of string reached when looking for matching \"]\" in IPv6 host address in URI: \"%s\"" +msgstr "nådde slutet på strängen när vi letade efter matchande \"]\" i IPv6-värdadress i URI: \"%s\"" + +#: fe-connect.c:6584 +#, c-format +msgid "IPv6 host address may not be empty in URI: \"%s\"" +msgstr "IPv6-värdadress får ej vara tom i URI: \"%s\"" + +#: fe-connect.c:6599 +#, c-format +msgid "unexpected character \"%c\" at position %d in URI (expected \":\" or \"/\"): \"%s\"" +msgstr "oväntat tecken \"%c\" vid position %d i URI (förväntade \":\" eller \"/\"): \"%s\"" + +#: fe-connect.c:6728 +#, c-format +msgid "extra key/value separator \"=\" in URI query parameter: \"%s\"" +msgstr "extra nyckel/värde-separator \"=\" i URI-frågeparameter: \"%s\"" + +#: fe-connect.c:6748 +#, c-format +msgid "missing key/value separator \"=\" in URI query parameter: \"%s\"" +msgstr "saknar nyckel/värde-separator \"=\" i URI-frågeparameter: \"%s\"" + +#: fe-connect.c:6800 +#, c-format +msgid "invalid URI query parameter: \"%s\"" +msgstr "ogiltig URI-frågeparameter: \"%s\"" + +#: fe-connect.c:6874 +#, c-format +msgid "invalid percent-encoded token: \"%s\"" +msgstr "ogiltigt procent-kodad symbol: \"%s\"" + +#: fe-connect.c:6884 +#, c-format +msgid "forbidden value %%00 in percent-encoded value: \"%s\"" +msgstr "förbjudet värde %%00 i procentkodat värde: \"%s\"" + +#: fe-connect.c:7248 +msgid "connection pointer is NULL\n" +msgstr "anslutningspekare är NULL\n" + +#: fe-connect.c:7256 fe-exec.c:710 fe-exec.c:970 fe-exec.c:3292 +#: fe-protocol3.c:974 fe-protocol3.c:1007 +msgid "out of memory\n" +msgstr "slut på minne\n" + +#: fe-connect.c:7547 +#, c-format +msgid "WARNING: password file \"%s\" is not a plain file\n" +msgstr "FEL: lösenordsfil \"%s\" är inte en vanlig fil\n" + +#: fe-connect.c:7556 +#, c-format +msgid "WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n" +msgstr "VARNING: lösenordsfilen \"%s\" har läsrättigheter för gruppen eller världen; rättigheten skall vara u=rw (0600) eller mindre\n" + +#: fe-connect.c:7663 +#, c-format +msgid "password retrieved from file \"%s\"" +msgstr "lösenord hämtat från fil \"%s\"" + +#: fe-exec.c:466 fe-exec.c:3366 +#, c-format +msgid "row number %d is out of range 0..%d" +msgstr "radnummer %d är utanför giltigt intervall 0..%d" + +#: fe-exec.c:528 fe-protocol3.c:1976 +#, c-format +msgid "%s" +msgstr "%s" + +#: fe-exec.c:831 +#, c-format +msgid "write to server failed" +msgstr "skrivning till servern misslyckades" + +#: fe-exec.c:869 +#, c-format +msgid "no error text available" +msgstr "inget feltext finns tillgänglig" + +#: fe-exec.c:958 +msgid "NOTICE" +msgstr "NOTIS" + +#: fe-exec.c:1016 +msgid "PGresult cannot support more than INT_MAX tuples" +msgstr "PGresult stöder inte mer än INT_MAX tupler" + +#: fe-exec.c:1028 +msgid "size_t overflow" +msgstr "size_t-överspill" + +#: fe-exec.c:1444 fe-exec.c:1513 fe-exec.c:1559 +#, c-format +msgid "command string is a null pointer" +msgstr "kommandosträngen är en null-pekare" + +#: fe-exec.c:1450 fe-exec.c:2888 +#, c-format +msgid "%s not allowed in pipeline mode" +msgstr "%s tillåts inte i pipeline-läge" + +#: fe-exec.c:1518 fe-exec.c:1564 fe-exec.c:1658 +#, c-format +msgid "number of parameters must be between 0 and %d" +msgstr "antal parametrar måste vara mellan 0 och %d" + +#: fe-exec.c:1554 fe-exec.c:1653 +#, c-format +msgid "statement name is a null pointer" +msgstr "satsens namn är en null-pekare" + +#: fe-exec.c:1695 fe-exec.c:3220 +#, c-format +msgid "no connection to the server" +msgstr "inte ansluten till servern" + +#: fe-exec.c:1703 fe-exec.c:3228 +#, c-format +msgid "another command is already in progress" +msgstr "ett annat kommando körs redan" + +#: fe-exec.c:1733 +#, c-format +msgid "cannot queue commands during COPY" +msgstr "kan inte köa kommandon när COPY körs" + +#: fe-exec.c:1850 +#, c-format +msgid "length must be given for binary parameter" +msgstr "längden måste anges för en binär parameter" + +#: fe-exec.c:2171 +#, c-format +msgid "unexpected asyncStatus: %d" +msgstr "oväntad asyncStatus: %d" + +#: fe-exec.c:2327 +#, c-format +msgid "synchronous command execution functions are not allowed in pipeline mode" +msgstr "synkrona kommandoexekveringsfunktioner tillåts inte i pipeline-läge" + +#: fe-exec.c:2344 +msgid "COPY terminated by new PQexec" +msgstr "COPY terminerad av ny PQexec" + +#: fe-exec.c:2360 +#, c-format +msgid "PQexec not allowed during COPY BOTH" +msgstr "PQexec tillåts inte under COPY BOTH" + +#: fe-exec.c:2586 fe-exec.c:2641 fe-exec.c:2709 fe-protocol3.c:1907 +#, c-format +msgid "no COPY in progress" +msgstr "ingen COPY körs" + +#: fe-exec.c:2895 +#, c-format +msgid "connection in wrong state" +msgstr "anslutning i felaktigt tillstånd" + +#: fe-exec.c:2938 +#, c-format +msgid "cannot enter pipeline mode, connection not idle" +msgstr "kan inte byta till pipeline-läge, anslutningen är inte inaktiv" + +#: fe-exec.c:2974 fe-exec.c:2995 +#, c-format +msgid "cannot exit pipeline mode with uncollected results" +msgstr "kan inte anvsluta pipeline-läge när alla svar inte tagits emot" + +#: fe-exec.c:2978 +#, c-format +msgid "cannot exit pipeline mode while busy" +msgstr "är upptagen och kan inte avsluta pipeline-läge" + +#: fe-exec.c:2989 +#, c-format +msgid "cannot exit pipeline mode while in COPY" +msgstr "kan inte avsluta pipeline-läge inne i en COPY" + +#: fe-exec.c:3154 +#, c-format +msgid "cannot send pipeline when not in pipeline mode" +msgstr "kan inte skicka en pipeline när vi inte är i pipeline-läge" + +#: fe-exec.c:3255 +msgid "invalid ExecStatusType code" +msgstr "ogiltig ExecStatusType-kod" + +#: fe-exec.c:3282 +msgid "PGresult is not an error result\n" +msgstr "PGresult är inte ett felresultat\n" + +#: fe-exec.c:3350 fe-exec.c:3373 +#, c-format +msgid "column number %d is out of range 0..%d" +msgstr "kolumnnummer %d är utanför giltigt intervall 0..%d" + +#: fe-exec.c:3388 +#, c-format +msgid "parameter number %d is out of range 0..%d" +msgstr "parameter nummer %d är utanför giltigt intervall 0..%d" + +#: fe-exec.c:3699 +#, c-format +msgid "could not interpret result from server: %s" +msgstr "kunde inte tolka svaret från servern: %s" + +#: fe-exec.c:3964 fe-exec.c:4054 +#, c-format +msgid "incomplete multibyte character" +msgstr "ofullständigt multibyte-tecken" + +#: fe-gssapi-common.c:122 +msgid "GSSAPI name import error" +msgstr "GSSAPI-fel vid import av namn" + +#: fe-lobj.c:144 fe-lobj.c:207 fe-lobj.c:397 fe-lobj.c:487 fe-lobj.c:560 +#: fe-lobj.c:956 fe-lobj.c:963 fe-lobj.c:970 fe-lobj.c:977 fe-lobj.c:984 +#: fe-lobj.c:991 fe-lobj.c:998 fe-lobj.c:1005 +#, c-format +msgid "cannot determine OID of function %s" +msgstr "kan inte härleda OID för funktionen %s" + +#: fe-lobj.c:160 +#, c-format +msgid "argument of lo_truncate exceeds integer range" +msgstr "argumentet till lo_truncate överskrider heltalsintervallet" + +#: fe-lobj.c:262 +#, c-format +msgid "argument of lo_read exceeds integer range" +msgstr "ett argument till lo_read överskriver heltalsintervallet" + +#: fe-lobj.c:313 +#, c-format +msgid "argument of lo_write exceeds integer range" +msgstr "ett argument till lo_write överskriver heltalsintervallet" + +#: fe-lobj.c:669 fe-lobj.c:780 +#, c-format +msgid "could not open file \"%s\": %s" +msgstr "kunde inte öppna fil \"%s\": %s" + +#: fe-lobj.c:725 +#, c-format +msgid "could not read from file \"%s\": %s" +msgstr "kunde inte läsa från fil \"%s\": %s" + +#: fe-lobj.c:801 fe-lobj.c:824 +#, c-format +msgid "could not write to file \"%s\": %s" +msgstr "kan inte skriva till fil \"%s\": %s" + +#: fe-lobj.c:908 +#, c-format +msgid "query to initialize large object functions did not return data" +msgstr "fråga för att initiera stort objekt-funktion returnerade ingen data" + +#: fe-misc.c:240 +#, c-format +msgid "integer of size %lu not supported by pqGetInt" +msgstr "heltal med storlek %lu stöds inte av pqGetInt" + +#: fe-misc.c:273 +#, c-format +msgid "integer of size %lu not supported by pqPutInt" +msgstr "heltal med storlek %lu stöds inte av pqPutInt" + +#: fe-misc.c:573 +#, c-format +msgid "connection not open" +msgstr "anslutningen är inte öppen" + +#: fe-misc.c:751 fe-secure-openssl.c:215 fe-secure-openssl.c:315 +#: fe-secure.c:257 fe-secure.c:419 +#, c-format +msgid "" +"server closed the connection unexpectedly\n" +"\tThis probably means the server terminated abnormally\n" +"\tbefore or while processing the request." +msgstr "" +"servern stängde oväntat ner uppkopplingen\n" +"\tTroligen så terminerade servern pga något fel antingen\n" +"\tinnan eller under tiden den bearbetade en förfrågan." + +#: fe-misc.c:818 +msgid "connection not open\n" +msgstr "anslutningen är inte öppen\n" + +#: fe-misc.c:1003 +#, c-format +msgid "timeout expired" +msgstr "timeout utgången" + +#: fe-misc.c:1047 +#, c-format +msgid "invalid socket" +msgstr "ogiltig socket" + +#: fe-misc.c:1069 +#, c-format +msgid "%s() failed: %s" +msgstr "%s() misslyckades: %s" + +#: fe-protocol3.c:182 +#, c-format +msgid "message type 0x%02x arrived from server while idle" +msgstr "meddelandetyp 0x%02x kom från server under viloperiod" + +#: fe-protocol3.c:385 +#, c-format +msgid "server sent data (\"D\" message) without prior row description (\"T\" message)" +msgstr "servern skickade data (meddelande \"D\") utan att först skicka en radbeskrivning (meddelande \"T\")" + +#: fe-protocol3.c:427 +#, c-format +msgid "unexpected response from server; first received character was \"%c\"" +msgstr "oväntat svar för servern; första mottagna tecknet var \"%c\"" + +#: fe-protocol3.c:450 +#, c-format +msgid "message contents do not agree with length in message type \"%c\"" +msgstr "meddelandeinnehåll stämmer inte med längden för meddelandetyp \"%c\"" + +#: fe-protocol3.c:468 +#, c-format +msgid "lost synchronization with server: got message type \"%c\", length %d" +msgstr "tappade synkronisering med servern: fick meddelandetyp \"%c\", längd %d" + +#: fe-protocol3.c:520 fe-protocol3.c:560 +msgid "insufficient data in \"T\" message" +msgstr "otillräckligt med data i \"T\"-meddelande" + +#: fe-protocol3.c:631 fe-protocol3.c:837 +msgid "out of memory for query result" +msgstr "slut på minnet för frågeresultat" + +#: fe-protocol3.c:700 +msgid "insufficient data in \"t\" message" +msgstr "otillräckligt med data i \"t\"-meddelande" + +#: fe-protocol3.c:759 fe-protocol3.c:791 fe-protocol3.c:809 +msgid "insufficient data in \"D\" message" +msgstr "otillräckligt med data i \"D\"-meddelande" + +#: fe-protocol3.c:765 +msgid "unexpected field count in \"D\" message" +msgstr "oväntat fältantal i \"D\"-meddelande" + +#: fe-protocol3.c:1020 +msgid "no error message available\n" +msgstr "inget felmeddelande finns tillgängligt\n" + +#. translator: %s represents a digit string +#: fe-protocol3.c:1068 fe-protocol3.c:1087 +#, c-format +msgid " at character %s" +msgstr " vid tecken %s" + +#: fe-protocol3.c:1100 +#, c-format +msgid "DETAIL: %s\n" +msgstr "DETALJ: %s\n" + +#: fe-protocol3.c:1103 +#, c-format +msgid "HINT: %s\n" +msgstr "TIPS: %s\n" + +#: fe-protocol3.c:1106 +#, c-format +msgid "QUERY: %s\n" +msgstr "FRÅGA: %s\n" + +#: fe-protocol3.c:1113 +#, c-format +msgid "CONTEXT: %s\n" +msgstr "KONTEXT: %s\n" + +#: fe-protocol3.c:1122 +#, c-format +msgid "SCHEMA NAME: %s\n" +msgstr "SCHEMANAMN: %s\n" + +#: fe-protocol3.c:1126 +#, c-format +msgid "TABLE NAME: %s\n" +msgstr "TABELLNAMN: %s\n" + +#: fe-protocol3.c:1130 +#, c-format +msgid "COLUMN NAME: %s\n" +msgstr "KOLUMNNAMN: %s\n" + +#: fe-protocol3.c:1134 +#, c-format +msgid "DATATYPE NAME: %s\n" +msgstr "DATATYPNAMN: %s\n" + +#: fe-protocol3.c:1138 +#, c-format +msgid "CONSTRAINT NAME: %s\n" +msgstr "VILLKORSNAMN: %s\n" + +#: fe-protocol3.c:1150 +msgid "LOCATION: " +msgstr "PLATS: " + +#: fe-protocol3.c:1152 +#, c-format +msgid "%s, " +msgstr "%s, " + +#: fe-protocol3.c:1154 +#, c-format +msgid "%s:%s" +msgstr "%s:%s" + +#: fe-protocol3.c:1349 +#, c-format +msgid "LINE %d: " +msgstr "RAD %d: " + +#: fe-protocol3.c:1423 +#, c-format +msgid "protocol version not supported by server: client uses %u.%u, server supports up to %u.%u" +msgstr "protokollversionen stöds inte av servern: klienten använder %u.%u, servern stöder upp till %u.%u" + +#: fe-protocol3.c:1429 +#, c-format +msgid "protocol extension not supported by server: %s" +msgid_plural "protocol extensions not supported by server: %s" +msgstr[0] "protokollutökning stöds inte av servern: %s" +msgstr[1] "protokollutökningar stöds inte av servern: %s" + +#: fe-protocol3.c:1437 +#, c-format +msgid "invalid %s message" +msgstr "ogiltig %s-meddelande" + +#: fe-protocol3.c:1802 +#, c-format +msgid "PQgetline: not doing text COPY OUT" +msgstr "PQgetline: utför inte text-COPY OUT" + +#: fe-protocol3.c:2176 +#, c-format +msgid "protocol error: no function result" +msgstr "protokollfel: inget funktionsresultat" + +#: fe-protocol3.c:2187 +#, c-format +msgid "protocol error: id=0x%x" +msgstr "protokollfel: id=0x%x" + +#: fe-secure-common.c:123 +#, c-format +msgid "SSL certificate's name contains embedded null" +msgstr "SSL-certifikatets namn innehåller null-värden" + +#: fe-secure-common.c:228 +#, c-format +msgid "certificate contains IP address with invalid length %zu" +msgstr "certifikater innehåller IP-adress med ogiltig längd %zu" + +#: fe-secure-common.c:237 +#, c-format +msgid "could not convert certificate's IP address to string: %s" +msgstr "kunde inte konvertera certifikatets IP-adress till sträng: %s" + +#: fe-secure-common.c:269 +#, c-format +msgid "host name must be specified for a verified SSL connection" +msgstr "värdnamn måste anges för en verifierad SSL-anslutning" + +#: fe-secure-common.c:286 +#, c-format +msgid "server certificate for \"%s\" (and %d other name) does not match host name \"%s\"" +msgid_plural "server certificate for \"%s\" (and %d other names) does not match host name \"%s\"" +msgstr[0] "servercertifikat för \"%s\" (och %d annat namn) matchar inte värdnamn \"%s\"" +msgstr[1] "servercertifikat för \"%s\" (och %d andra namn) matchar inte värdnamn \"%s\"" + +#: fe-secure-common.c:294 +#, c-format +msgid "server certificate for \"%s\" does not match host name \"%s\"" +msgstr "servercertifikat för \"%s\" matchar inte värdnamn \"%s\"" + +#: fe-secure-common.c:299 +#, c-format +msgid "could not get server's host name from server certificate" +msgstr "kan inte hämta ut serverns värdnamn från servercertifikatet" + +#: fe-secure-gssapi.c:201 +msgid "GSSAPI wrap error" +msgstr "GSSAPI-fel vid inpackning" + +#: fe-secure-gssapi.c:208 +#, c-format +msgid "outgoing GSSAPI message would not use confidentiality" +msgstr "utående GSSAPI-meddelande skulle inte använda sekretess" + +#: fe-secure-gssapi.c:215 +#, c-format +msgid "client tried to send oversize GSSAPI packet (%zu > %zu)" +msgstr "klienten försökte skicka för stort GSSAPI-paket (%zu > %zu)" + +#: fe-secure-gssapi.c:351 fe-secure-gssapi.c:593 +#, c-format +msgid "oversize GSSAPI packet sent by the server (%zu > %zu)" +msgstr "för stort GSSAPI-paket skickat av servern (%zu > %zu)" + +#: fe-secure-gssapi.c:390 +msgid "GSSAPI unwrap error" +msgstr "GSSAPI-fel vid uppackning" + +#: fe-secure-gssapi.c:399 +#, c-format +msgid "incoming GSSAPI message did not use confidentiality" +msgstr "inkommande GSSAPI-meddelande använde inte sekretess" + +#: fe-secure-gssapi.c:656 +msgid "could not initiate GSSAPI security context" +msgstr "kunde inte initiera GSSAPI-säkerhetskontext" + +#: fe-secure-gssapi.c:685 +msgid "GSSAPI size check error" +msgstr "GSSAPI-fel vid kontroll av storlek" + +#: fe-secure-gssapi.c:696 +msgid "GSSAPI context establishment error" +msgstr "GSSAPI-fel vid skapande av kontext" + +#: fe-secure-openssl.c:219 fe-secure-openssl.c:319 fe-secure-openssl.c:1531 +#, c-format +msgid "SSL SYSCALL error: %s" +msgstr "SSL SYSCALL fel: %s" + +#: fe-secure-openssl.c:225 fe-secure-openssl.c:325 fe-secure-openssl.c:1534 +#, c-format +msgid "SSL SYSCALL error: EOF detected" +msgstr "SSL SYSCALL-fel: EOF upptäckt" + +#: fe-secure-openssl.c:235 fe-secure-openssl.c:335 fe-secure-openssl.c:1542 +#, c-format +msgid "SSL error: %s" +msgstr "SSL-fel: %s" + +#: fe-secure-openssl.c:249 fe-secure-openssl.c:349 +#, c-format +msgid "SSL connection has been closed unexpectedly" +msgstr "SSL-anslutning har oväntat stängts" + +#: fe-secure-openssl.c:254 fe-secure-openssl.c:354 fe-secure-openssl.c:1589 +#, c-format +msgid "unrecognized SSL error code: %d" +msgstr "okänd SSL-felkod: %d" + +#: fe-secure-openssl.c:397 +#, c-format +msgid "could not determine server certificate signature algorithm" +msgstr "kunde inte bestämma serverns algoritm för certifikatsignering" + +#: fe-secure-openssl.c:417 +#, c-format +msgid "could not find digest for NID %s" +msgstr "kunde inte hitta kontrollsumma för NID %s" + +#: fe-secure-openssl.c:426 +#, c-format +msgid "could not generate peer certificate hash" +msgstr "kunde inte generera peer-certifikathash" + +#: fe-secure-openssl.c:509 +#, c-format +msgid "SSL certificate's name entry is missing" +msgstr "SSL-certifikatets namnpost saknas" + +#: fe-secure-openssl.c:543 +#, c-format +msgid "SSL certificate's address entry is missing" +msgstr "SSL-certifikatets adresspost saknas" + +#: fe-secure-openssl.c:960 +#, c-format +msgid "could not create SSL context: %s" +msgstr "kunde inte skapa SSL-kontext: %s" + +#: fe-secure-openssl.c:1002 +#, c-format +msgid "invalid value \"%s\" for minimum SSL protocol version" +msgstr "ogiltigt värde \"%s\" för minimal SSL-protokollversion" + +#: fe-secure-openssl.c:1012 +#, c-format +msgid "could not set minimum SSL protocol version: %s" +msgstr "kunde inte sätta minimal SSL-protokollversion: %s" + +#: fe-secure-openssl.c:1028 +#, c-format +msgid "invalid value \"%s\" for maximum SSL protocol version" +msgstr "ogiltigt värde \"%s\" för maximal SSL-protokollversion" + +#: fe-secure-openssl.c:1038 +#, c-format +msgid "could not set maximum SSL protocol version: %s" +msgstr "kunde inte sätta maximal SSL-protokollversion: %s" + +#: fe-secure-openssl.c:1076 +#, c-format +msgid "could not load system root certificate paths: %s" +msgstr "kunde inte ladda systemets root-certifikatsökvägar: %s" + +#: fe-secure-openssl.c:1093 +#, c-format +msgid "could not read root certificate file \"%s\": %s" +msgstr "kunde inte läsa root-certifikatfilen \"%s\": %s" + +#: fe-secure-openssl.c:1145 +#, c-format +msgid "" +"could not get home directory to locate root certificate file\n" +"Either provide the file, use the system's trusted roots with sslrootcert=system, or change sslmode to disable server certificate verification." +msgstr "" +"kunde inte hämta hemkatalogen för att lokalisera root-certifikatfilen\n" +"Antingen tillhandahåll filen, använd systemets betrodda root med sslrootcert=system eller ändra sslmode för att stänga av serverns certifikatverifiering." + +#: fe-secure-openssl.c:1148 +#, c-format +msgid "" +"root certificate file \"%s\" does not exist\n" +"Either provide the file, use the system's trusted roots with sslrootcert=system, or change sslmode to disable server certificate verification." +msgstr "" +"root-certifikatfilen \"%s\" finns inte\n" +"Antingen tillhandahåll filen, använd systemets betrodda root med sslrootcert=system eller ändra sslmode för att stänga av serverns certifikatverifiering." + +#: fe-secure-openssl.c:1183 +#, c-format +msgid "could not open certificate file \"%s\": %s" +msgstr "kunde inte öppna certifikatfil \"%s\": %s" + +#: fe-secure-openssl.c:1201 +#, c-format +msgid "could not read certificate file \"%s\": %s" +msgstr "kunde inte läsa certifikatfil \"%s\": %s" + +#: fe-secure-openssl.c:1225 +#, c-format +msgid "could not establish SSL connection: %s" +msgstr "kan inte skapa SSL-anslutning: %s" + +#: fe-secure-openssl.c:1257 +#, c-format +msgid "could not set SSL Server Name Indication (SNI): %s" +msgstr "kunde inte sätta SSL servernamnsindikering (SNI): %s" + +#: fe-secure-openssl.c:1300 +#, c-format +msgid "could not load SSL engine \"%s\": %s" +msgstr "kunde inte ladda SSL-motor \"%s\": %s" + +#: fe-secure-openssl.c:1311 +#, c-format +msgid "could not initialize SSL engine \"%s\": %s" +msgstr "kunde inte initiera SSL-motor \"%s\": %s" + +#: fe-secure-openssl.c:1326 +#, c-format +msgid "could not read private SSL key \"%s\" from engine \"%s\": %s" +msgstr "kunde inte läsa privat SSL-nyckel \"%s\" från motor \"%s\": %s" + +#: fe-secure-openssl.c:1339 +#, c-format +msgid "could not load private SSL key \"%s\" from engine \"%s\": %s" +msgstr "kunde inte ladda privat SSL-nyckel \"%s\" från motor \"%s\": %s" + +#: fe-secure-openssl.c:1376 +#, c-format +msgid "certificate present, but not private key file \"%s\"" +msgstr "certifikat tillgängligt, men inte den privata nyckelfilen \"%s\"" + +#: fe-secure-openssl.c:1379 +#, c-format +msgid "could not stat private key file \"%s\": %m" +msgstr "kunde inte köra stat() på privata nyckelfilen \"%s\": %m" + +#: fe-secure-openssl.c:1387 +#, c-format +msgid "private key file \"%s\" is not a regular file" +msgstr "privat nyckelfil \"%s\" är inte en vanlig fil" + +#: fe-secure-openssl.c:1420 +#, c-format +msgid "private key file \"%s\" has group or world access; file must have permissions u=rw (0600) or less if owned by the current user, or permissions u=rw,g=r (0640) or less if owned by root" +msgstr "privata nyckelfilen \"%s\" har grupp- eller världsrättigheter; filen måste ha rättigheterna u=rw (0600) eller mindre om den ägs av databasanvändaren eller rättigheterna u=rw,g=r (0640) eller mindre om den ägs av root." + +#: fe-secure-openssl.c:1444 +#, c-format +msgid "could not load private key file \"%s\": %s" +msgstr "kunde inte läsa in privata nyckelfilen \"%s\": %s" + +#: fe-secure-openssl.c:1460 +#, c-format +msgid "certificate does not match private key file \"%s\": %s" +msgstr "certifikatet matchar inte den privata nyckelfilen \"%s\": %s" + +#: fe-secure-openssl.c:1528 +#, c-format +msgid "SSL error: certificate verify failed: %s" +msgstr "SSL-fel: verifiering av certifikat misslyckades: %s" + +#: fe-secure-openssl.c:1573 +#, c-format +msgid "This may indicate that the server does not support any SSL protocol version between %s and %s." +msgstr "Detta kan tyda på att servern inte stöder någon SSL-protokolversion mellan %s oc %s." + +#: fe-secure-openssl.c:1606 +#, c-format +msgid "certificate could not be obtained: %s" +msgstr "certifikatet kunde inte hämtas: %s" + +#: fe-secure-openssl.c:1711 +#, c-format +msgid "no SSL error reported" +msgstr "inget SSL-fel rapporterat" + +#: fe-secure-openssl.c:1720 +#, c-format +msgid "SSL error code %lu" +msgstr "SSL-felkod %lu" + +#: fe-secure-openssl.c:1986 +#, c-format +msgid "WARNING: sslpassword truncated\n" +msgstr "VARNING: sslpassword trunkerat\n" + +#: fe-secure.c:263 +#, c-format +msgid "could not receive data from server: %s" +msgstr "kunde inte ta emot data från servern: %s" + +#: fe-secure.c:434 +#, c-format +msgid "could not send data to server: %s" +msgstr "kunde inte skicka data till servern: %s" + +#: win32.c:310 +#, c-format +msgid "unrecognized socket error: 0x%08X/%d" +msgstr "okänt socket-fel: 0x%08X/%d" + +#, c-format +#~ msgid "%s(%s) failed: error code %d\n" +#~ msgstr "%s(%s) misslyckades: felkod %d\n" + +#~ msgid "SCM_CRED authentication method not supported\n" +#~ msgstr "autentiseringsmetoden SCM_CRED stöds ej\n" + +#, c-format +#~ msgid "SSL error: %s\n" +#~ msgstr "SSL-fel: %s\n" + +#, c-format +#~ msgid "Unix-domain socket path \"%s\" is too long (maximum %d bytes)\n" +#~ msgstr "Sökväg till unixdomänuttag \"%s\" är för lång (maximalt %d byte)\n" + +#, c-format +#~ msgid "could not create SSL context: %s\n" +#~ msgstr "kan inte skapa SSL-omgivning: %s\n" + +#, c-format +#~ msgid "could not load private key file \"%s\": %s\n" +#~ msgstr "kunde inte ladda privata nyckelfilen \"%s\": %s\n" + +#, c-format +#~ msgid "could not open file \"%s\": %s\n" +#~ msgstr "kan inte öppna fil \"%s\": %s\n" + +#~ msgid "incoming GSSAPI message did not use confidentiality\n" +#~ msgstr "inkommande GSSAPI-meddelande använde inte sekretess\n" + +#~ msgid "outgoing GSSAPI message would not use confidentiality\n" +#~ msgstr "utgående GSSAPI-meddelande skulle inte använda sekretess\n" + +#, c-format +#~ msgid "private key file \"%s\" is not a regular file\n" +#~ msgstr "privat nyckelfilen \"%s\" är inte en vanlig fil\n" + +#, c-format +#~ msgid "unrecognized SSL error code: %d\n" +#~ msgstr "okänd SSL-felkod: %d\n" + +#, c-format +#~ msgid "user name lookup failure: error code %lu\n" +#~ msgstr "misslyckad sökning efter användarnamn: felkod %lu\n" diff --git a/src/interfaces/libpq/po/tr.po b/src/interfaces/libpq/po/tr.po new file mode 100644 index 0000000..855dad7 --- /dev/null +++ b/src/interfaces/libpq/po/tr.po @@ -0,0 +1,1247 @@ +# translation of libpq.po to Turkish +# Devrim GUNDUZ <devrim@CommandPrompt.com> 2004, 2005, 2006, 2007. +# Nicolai TUFAR <ntufar@gmail.com> 2004, 2005, 2006, 2007. +# Abdullah GÜLNER <agulner@gmail.com> 2017, 2018. +# +msgid "" +msgstr "" +"Project-Id-Version: libpq-tr\n" +"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" +"POT-Creation-Date: 2019-05-05 21:38+0000\n" +"PO-Revision-Date: 2019-06-14 10:49+0300\n" +"Last-Translator: Abdullah GÜLNER\n" +"Language-Team: Turkish <ceviri@postgresql.org.tr>\n" +"Language: tr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.8.7.1\n" +"X-Poedit-Basepath: /home/ntufar/pg/pgsql/src/interfaces/libpq\n" +"X-Poedit-SearchPath-0: /home/ntufar/pg/pgsql/src/interfaces/libpq\n" + +#: fe-auth-scram.c:183 +msgid "malformed SCRAM message (empty message)\n" +msgstr "hatalı SCRAM mesajı (boş mesaj)\n" + +#: fe-auth-scram.c:189 +msgid "malformed SCRAM message (length mismatch)\n" +msgstr "hatalı SCRAM mesajı (uzunluk uyuşmazlığı)\n" + +#: fe-auth-scram.c:238 +msgid "incorrect server signature\n" +msgstr "sunucu imzası yanlış\n" + +#: fe-auth-scram.c:247 +msgid "invalid SCRAM exchange state\n" +msgstr "geçersiz SCRAM değişim durumu\n" + +#: fe-auth-scram.c:270 +#, c-format +msgid "malformed SCRAM message (attribute \"%c\" expected)\n" +msgstr "hatalı SCRAM mesajı (\"%c\" niteliği bekleniyor)\n" + +#: fe-auth-scram.c:279 +#, c-format +msgid "malformed SCRAM message (expected character \"=\" for attribute \"%c\")\n" +msgstr "hatalı SCRAM mesajı (\"%c\" niteliği için \"=\" karakteri bekleniyor)\n" + +#: fe-auth-scram.c:320 +msgid "could not generate nonce\n" +msgstr "nonce oluşturulamadı\n" + +#: fe-auth-scram.c:328 fe-auth-scram.c:395 fe-auth-scram.c:517 +#: fe-auth-scram.c:537 fe-auth-scram.c:563 fe-auth-scram.c:577 +#: fe-auth-scram.c:619 fe-auth.c:290 fe-auth.c:360 fe-auth.c:395 fe-auth.c:581 +#: fe-auth.c:740 fe-auth.c:1052 fe-auth.c:1200 fe-connect.c:858 +#: fe-connect.c:1320 fe-connect.c:1496 fe-connect.c:2085 fe-connect.c:2108 +#: fe-connect.c:2830 fe-connect.c:4512 fe-connect.c:4764 fe-connect.c:4883 +#: fe-connect.c:5133 fe-connect.c:5213 fe-connect.c:5312 fe-connect.c:5568 +#: fe-connect.c:5597 fe-connect.c:5669 fe-connect.c:5693 fe-connect.c:5711 +#: fe-connect.c:5812 fe-connect.c:5821 fe-connect.c:6177 fe-connect.c:6327 +#: fe-exec.c:2748 fe-exec.c:3495 fe-exec.c:3660 fe-lobj.c:895 +#: fe-protocol2.c:1213 fe-protocol3.c:999 fe-protocol3.c:1703 +#: fe-secure-common.c:110 fe-secure-openssl.c:438 fe-secure-openssl.c:1025 +msgid "out of memory\n" +msgstr "yetersiz bellek\n" + +#: fe-auth-scram.c:555 +msgid "invalid SCRAM response (nonce mismatch)\n" +msgstr "geçersiz SCRAM cevabı (nonce uyuşmazlığı)\n" + +#: fe-auth-scram.c:594 +msgid "malformed SCRAM message (invalid iteration count)\n" +msgstr "hatalı SCRAM mesajı (geçersiz iterasyon sayısı)\n" + +#: fe-auth-scram.c:600 +msgid "malformed SCRAM message (garbage at end of server-first-message)\n" +msgstr "hatalı SCRAM mesajı (sunucu-ilk-mesajı sonunda anlamsız değer)\n" + +#: fe-auth-scram.c:630 +#, c-format +msgid "error received from server in SCRAM exchange: %s\n" +msgstr "SCRAM değişimi işleminde sunucudan hata alındı: %s\n" + +#: fe-auth-scram.c:646 +msgid "malformed SCRAM message (garbage at end of server-final-message)\n" +msgstr "hatalı SCRAM mesajı (sunucu-son-mesajı sonunda anlamsız değer)\n" + +#: fe-auth-scram.c:654 +msgid "malformed SCRAM message (invalid server signature)\n" +msgstr "hatalı SCRAM mesajı (geçersiz sunucu imzası)\n" + +#: fe-auth.c:77 +#, c-format +msgid "out of memory allocating GSSAPI buffer (%d)\n" +msgstr "GSSAPI tamponu ayrılırken yetersiz bellek hatası (%d)\n" + +#: fe-auth.c:132 +msgid "GSSAPI continuation error" +msgstr "GSSAPI devam hatası" + +#: fe-auth.c:159 fe-auth.c:389 fe-secure-common.c:98 +msgid "host name must be specified\n" +msgstr "sunucu adı belirtilmelidir\n" + +#: fe-auth.c:166 +msgid "duplicate GSS authentication request\n" +msgstr "çift GSS yetkilendirme isteği\n" + +#: fe-auth.c:231 +#, c-format +msgid "out of memory allocating SSPI buffer (%d)\n" +msgstr "GSSAPI tamponu ayrılırken yetersiz bellek hatası (%d)\n" + +#: fe-auth.c:279 +msgid "SSPI continuation error" +msgstr "SSPI devam hatası" + +#: fe-auth.c:350 +msgid "duplicate SSPI authentication request\n" +msgstr "çift SSPI yetkilendirme isteği\n" + +#: fe-auth.c:375 +msgid "could not acquire SSPI credentials" +msgstr "SSPI kimlik bilgileri alınamadı" + +#: fe-auth.c:429 +msgid "duplicate SASL authentication request\n" +msgstr "çift SASL yetkilendirme isteği\n" + +#: fe-auth.c:487 +msgid "server offered SCRAM-SHA-256-PLUS authentication over a non-SSL connection\n" +msgstr "" +"sunucu SSL'li olmayan bir bağlantı üzerinde SCRAM-SHA-256-PLUS kimlik doğrulaması önerdi\n" +" \n" + +#: fe-auth.c:499 +msgid "none of the server's SASL authentication mechanisms are supported\n" +msgstr "sunucunun SASL yetkilendirme mekanizmalarından hiçbiri desteklenmiyor\n" + +#: fe-auth.c:605 +#, c-format +msgid "out of memory allocating SASL buffer (%d)\n" +msgstr "SASL tamponu ayrılırken yetersiz bellek hatası (%d)\n" + +#: fe-auth.c:630 +msgid "AuthenticationSASLFinal received from server, but SASL authentication was not completed\n" +msgstr "sunucudan AuthenticationSASLFinal alındı, fakat SASL yetkilendirmesi tamamlanmadı\n" + +#: fe-auth.c:707 +msgid "SCM_CRED authentication method not supported\n" +msgstr "SCM_CRED yetkilendirme yöntemi desteklenmiyor.\n" + +#: fe-auth.c:798 +msgid "Kerberos 4 authentication not supported\n" +msgstr "Kerberos 4 yetkilendirmesi desteklenmiyor\n" + +#: fe-auth.c:803 +msgid "Kerberos 5 authentication not supported\n" +msgstr "Kerberos 5 yetkilendirmesi desteklenmiyor\n" + +#: fe-auth.c:874 +msgid "GSSAPI authentication not supported\n" +msgstr "GSSAPI yetkilendirmesi desteklenmiyor\n" + +#: fe-auth.c:906 +msgid "SSPI authentication not supported\n" +msgstr "SSPI yetkilendirmesi desteklenmiyor\n" + +#: fe-auth.c:914 +msgid "Crypt authentication not supported\n" +msgstr "Crypt yetkilendirmesi desteklenmiyor\n" + +#: fe-auth.c:980 +#, c-format +msgid "authentication method %u not supported\n" +msgstr "%u yetkilendirme sistemi desteklenmiyor\n" + +#: fe-auth.c:1027 +#, c-format +msgid "user name lookup failure: error code %lu\n" +msgstr "kullanıcı adı arama başarısız: hata kodu %lu\n" + +#: fe-auth.c:1037 fe-connect.c:2717 +#, c-format +msgid "could not look up local user ID %d: %s\n" +msgstr "yerel kullanıcı ID %d bulunamadı: %s\n" + +#: fe-auth.c:1042 fe-connect.c:2722 +#, c-format +msgid "local user with ID %d does not exist\n" +msgstr "yerel kullanıcı ID %d mevcut değildir\n" + +#: fe-auth.c:1144 +msgid "unexpected shape of result set returned for SHOW\n" +msgstr "SHOW için döndürülen sonuç kümesi beklenmeyen şekilde \n" + +#: fe-auth.c:1153 +msgid "password_encryption value too long\n" +msgstr "parola şifreleme (password_encryption) değeri çok uzun\n" + +#: fe-auth.c:1193 +#, c-format +msgid "unrecognized password encryption algorithm \"%s\"\n" +msgstr "bilinmeyen parola şifreleme algoritması \"%s\"\n" + +#: fe-connect.c:1041 +#, c-format +msgid "could not match %d host names to %d hostaddr values\n" +msgstr "%d sunucu adları %d sunucu adresleriyle eşleştirilemedi\n" + +#: fe-connect.c:1117 +#, c-format +msgid "could not match %d port numbers to %d hosts\n" +msgstr "%d kapı (port) numaraları %d sunucuları ile eşleştirilemedi\n" + +#: fe-connect.c:1213 +#, c-format +msgid "invalid sslmode value: \"%s\"\n" +msgstr "geçersiz sslmode değeri: \"%s\"\n" + +#: fe-connect.c:1234 +#, c-format +msgid "sslmode value \"%s\" invalid when SSL support is not compiled in\n" +msgstr "\"%s\" sslmode değeri, SSL desteği derlenmeyince geçersizdir\n" + +#: fe-connect.c:1258 +#, c-format +msgid "invalid gssencmode value: \"%s\"\n" +msgstr "geçersiz gssencmode değeri: \"%s\"\n" + +#: fe-connect.c:1268 +msgid "no GSSAPI support; cannot require GSSAPI\n" +msgstr "GSSAPI desteği yok; GSSAPI gerektiremez\n" + +#: fe-connect.c:1302 +#, c-format +msgid "invalid target_session_attrs value: \"%s\"\n" +msgstr "geçersiz target_session_attrs değeri: \"%s\"\n" + +#: fe-connect.c:1520 +#, c-format +msgid "could not set socket to TCP no delay mode: %s\n" +msgstr "soket TCP no delay moduna ayarlanamadı: %s\n" + +#: fe-connect.c:1583 +#, c-format +msgid "" +"could not connect to server: %s\n" +"\tIs the server running locally and accepting\n" +"\tconnections on Unix domain socket \"%s\"?\n" +msgstr "" +"sunucuya bağlanılamadı: %s\n" +"\tSunucu yerelde çalışıyor ve \"%s\" Unix domain\n" +"\tsoketi üzerinden bağlantılara izin veriyor mu?\n" + +#: fe-connect.c:1620 +#, c-format +msgid "" +"could not connect to server: %s\n" +"\tIs the server running on host \"%s\" (%s) and accepting\n" +"\tTCP/IP connections on port %s?\n" +msgstr "" +"sunucuya bağlanılamadı: %s\n" +"\tSunucu \"%s\" (%s) makinasında çalışıyor ve\n" +"\t %s portundan TCP/IP bağlantılarına izin veriyor mu?\n" + +#: fe-connect.c:1628 +#, c-format +msgid "" +"could not connect to server: %s\n" +"\tIs the server running on host \"%s\" and accepting\n" +"\tTCP/IP connections on port %s?\n" +msgstr "" +"sunucuya bağlanılamadı: %s\n" +"\tSunucu \"%s\" makiansında çalışıyor ve\n" +"\t %s portundan TCP/IP bağlantılarına izin veriyor mu?\n" + +#: fe-connect.c:1679 +#, c-format +msgid "invalid integer value \"%s\" for keyword \"%s\"\n" +msgstr "\"%2$s\" anahtar kelimesi için geçersiz tamsayı değeri \"%1$s\"\n" + +#: fe-connect.c:1709 fe-connect.c:1743 fe-connect.c:1778 fe-connect.c:1865 +#: fe-connect.c:2507 +#, c-format +msgid "setsockopt(%s) failed: %s\n" +msgstr "setsockopt(%s) başarısız oldu: %s\n" + +#: fe-connect.c:1831 +#, c-format +msgid "WSAIoctl(SIO_KEEPALIVE_VALS) failed: %ui\n" +msgstr "WSAIoctl(SIO_KEEPALIVE_VALS) başarısız oldu: %ui\n" + +#: fe-connect.c:2199 +msgid "invalid connection state, probably indicative of memory corruption\n" +msgstr "geçersiz bağlantı durumu, hafızanın zarar görmüş olmasının işareti olabilir\n" + +#: fe-connect.c:2267 +#, c-format +msgid "invalid port number: \"%s\"\n" +msgstr "geçersiz port numarası: \"%s\"\n" + +#: fe-connect.c:2283 +#, c-format +msgid "could not translate host name \"%s\" to address: %s\n" +msgstr "\"%s\" makine adı bir adrese çevirilemedi: %s\n" + +#: fe-connect.c:2296 +#, c-format +msgid "could not parse network address \"%s\": %s\n" +msgstr "ağ adresi \"%s\" ayrıştırılamadı: %s\n" + +#: fe-connect.c:2309 +#, c-format +msgid "Unix-domain socket path \"%s\" is too long (maximum %d bytes)\n" +msgstr "Unix-domain soket yolu \"%s\" çok uzun (azami %d bayt)\n" + +#: fe-connect.c:2324 +#, c-format +msgid "could not translate Unix-domain socket path \"%s\" to address: %s\n" +msgstr "\"%s\" Unix domain soket yolu adrese çevirilemedi: %s\n" + +#: fe-connect.c:2444 +#, c-format +msgid "could not create socket: %s\n" +msgstr "soket oluşturulamadı: %s\n" + +#: fe-connect.c:2466 +#, c-format +msgid "could not set socket to nonblocking mode: %s\n" +msgstr "soket bloklamasız ( non-blocking ) moda ayarlanamadı: %s\n" + +#: fe-connect.c:2476 +#, c-format +msgid "could not set socket to close-on-exec mode: %s\n" +msgstr "soket close-on-exec moduna ayarlanamadı: %s\n" + +#: fe-connect.c:2494 +msgid "keepalives parameter must be an integer\n" +msgstr "keepalives parametresi tamsayı olmalıdır\n" + +#: fe-connect.c:2634 +#, c-format +msgid "could not get socket error status: %s\n" +msgstr "soket hata durumu alınamadı: %s\n" + +#: fe-connect.c:2662 +#, c-format +msgid "could not get client address from socket: %s\n" +msgstr "soketten istemci adresi alınamadı: %s\n" + +#: fe-connect.c:2704 +msgid "requirepeer parameter is not supported on this platform\n" +msgstr "bu platformda requirepeer parametresi desteklenmiyor \n" + +#: fe-connect.c:2707 +#, c-format +msgid "could not get peer credentials: %s\n" +msgstr "karşı tarafın kimlik bilgileri alınamadı: %s \n" + +#: fe-connect.c:2730 +#, c-format +msgid "requirepeer specifies \"%s\", but actual peer user name is \"%s\"\n" +msgstr "requirepeer \"%s\" belirtiyor, ancak gerçek karşı taraf (peer) kullanıcı adı \"%s\"\n" + +#: fe-connect.c:2765 +#, c-format +msgid "could not send GSSAPI negotiation packet: %s\n" +msgstr "GSSAPI anlaşma (negotiation) paketi gönderilemedi: %s\n" + +#: fe-connect.c:2777 +msgid "GSSAPI encryption required, but was impossible (possibly no ccache, no server support, or using a local socket)\n" +msgstr "GSSAPI şifrelemesi gerekli, fakat mümkün değil (muhtemelen ccache yok, sunucu desteği yok ya da yerel soket kullanılıyor)\n" + +#: fe-connect.c:2804 +#, c-format +msgid "could not send SSL negotiation packet: %s\n" +msgstr "SSL anlaşma (negotiation) paketi gönderilemedi: %s\n" + +#: fe-connect.c:2843 +#, c-format +msgid "could not send startup packet: %s\n" +msgstr "başlangıç paketi gönderilemedi: %s\n" + +#: fe-connect.c:2913 +msgid "server does not support SSL, but SSL was required\n" +msgstr "sunucu SSL desteklemiyor, ama SSL gerekli idi\n" + +#: fe-connect.c:2939 +#, c-format +msgid "received invalid response to SSL negotiation: %c\n" +msgstr "ssl görüşmesine geçersiz yanıt alındı: %c\n" + +#: fe-connect.c:3029 +msgid "server doesn't support GSSAPI encryption, but it was required\n" +msgstr "sunucu GSSAPI şifrelemesi desteklemiyor, ama gerekli idi\n" + +#: fe-connect.c:3040 +#, c-format +msgid "received invalid response to GSSAPI negotiation: %c\n" +msgstr "GSSAPI görüşmesine geçersiz yanıt alındı: %c\n" + +#: fe-connect.c:3108 fe-connect.c:3141 +#, c-format +msgid "expected authentication request from server, but received %c\n" +msgstr "sunucudan yetkilendirme isteği beklendi ancak %c alındı\n" + +#: fe-connect.c:3388 +msgid "unexpected message from server during startup\n" +msgstr "başlangıç sırasında sunucudan beklenmeyen bir mesaj alındı\n" + +#: fe-connect.c:3615 +#, c-format +msgid "could not make a writable connection to server \"%s:%s\"\n" +msgstr "sunucuya yazılabilir (writable) bağlantı sağlanamadı \"%s:%s\"\n" + +#: fe-connect.c:3661 +#, c-format +msgid "test \"SHOW transaction_read_only\" failed on server \"%s:%s\"\n" +msgstr "\"SHOW transaction_read_only\" testi sunucuda başarısız oldu \"%s:%s\"\n" + +#: fe-connect.c:3676 +#, c-format +msgid "invalid connection state %d, probably indicative of memory corruption\n" +msgstr "%d - geçersiz bağlantı durumu, bellekteki veri zarar görmüş olabilir\n" + +#: fe-connect.c:4118 fe-connect.c:4178 +#, c-format +msgid "PGEventProc \"%s\" failed during PGEVT_CONNRESET event\n" +msgstr "PGEventProc \"%s\" işlemi PGEVT_CONNRESET işlemi sırasında başarısız oldu\n" + +#: fe-connect.c:4525 +#, c-format +msgid "invalid LDAP URL \"%s\": scheme must be ldap://\n" +msgstr "geçersiz LDAP URL \"%s\": şema, ldap:// ile başlamalıdir\n" + +#: fe-connect.c:4540 +#, c-format +msgid "invalid LDAP URL \"%s\": missing distinguished name\n" +msgstr "geçersiz LDAP URL \"%s\": distinguished isim eksik\n" + +#: fe-connect.c:4551 fe-connect.c:4604 +#, c-format +msgid "invalid LDAP URL \"%s\": must have exactly one attribute\n" +msgstr "geçersiz LDAP URL \"%s\": tam olarak bir nitelik (attribute) içermelidir\n" + +#: fe-connect.c:4561 fe-connect.c:4618 +#, c-format +msgid "invalid LDAP URL \"%s\": must have search scope (base/one/sub)\n" +msgstr "geçersiz LDAP URL \"%s\": arama kapsamı içermelidir (base/one/sub)\n" + +#: fe-connect.c:4572 +#, c-format +msgid "invalid LDAP URL \"%s\": no filter\n" +msgstr "geçersiz LDAP URL \"%s\": filtre eksik\n" + +#: fe-connect.c:4593 +#, c-format +msgid "invalid LDAP URL \"%s\": invalid port number\n" +msgstr "geçersiz LDAP URL \"%s\": geçersiz port numarası\n" + +#: fe-connect.c:4627 +msgid "could not create LDAP structure\n" +msgstr "LDAP yapısı oluşturma hatası\n" + +#: fe-connect.c:4703 +#, c-format +msgid "lookup on LDAP server failed: %s\n" +msgstr "LDAP sonucunda sorgulama hatası: %s\n" + +#: fe-connect.c:4714 +msgid "more than one entry found on LDAP lookup\n" +msgstr "LDAP sorgusu sonucunda birden fazla giriş bulundu\n" + +#: fe-connect.c:4715 fe-connect.c:4727 +msgid "no entry found on LDAP lookup\n" +msgstr "LDAP sorgusu sonucunda hiçbir giriş bulunamadı\n" + +#: fe-connect.c:4738 fe-connect.c:4751 +msgid "attribute has no values on LDAP lookup\n" +msgstr "LDAP sorgusu sonucunda bulunan attribute, hiçbir değer içermiyor\n" + +#: fe-connect.c:4803 fe-connect.c:4822 fe-connect.c:5351 +#, c-format +msgid "missing \"=\" after \"%s\" in connection info string\n" +msgstr "bağlantı bilgi katarında \"%s\" bilgisinden sonra \"=\" işareti eksik\n" + +#: fe-connect.c:4895 fe-connect.c:5536 fe-connect.c:6310 +#, c-format +msgid "invalid connection option \"%s\"\n" +msgstr "geçersiz bağlantı seçeneği \"%s\"\n" + +#: fe-connect.c:4911 fe-connect.c:5400 +msgid "unterminated quoted string in connection info string\n" +msgstr "bağlantı bilgi katarında sonlandırılmamış tırnaklı katar\n" + +#: fe-connect.c:4994 +#, c-format +msgid "definition of service \"%s\" not found\n" +msgstr "\"%s\" servisinin tanımı bulunamadı\n" + +#: fe-connect.c:5017 +#, c-format +msgid "service file \"%s\" not found\n" +msgstr "\"%s\" servis dosyası bulunamadı\n" + +#: fe-connect.c:5030 +#, c-format +msgid "line %d too long in service file \"%s\"\n" +msgstr "\"%2$s\" servis dosyasında %1$d no'lu satır çok uzun \n" + +#: fe-connect.c:5101 fe-connect.c:5145 +#, c-format +msgid "syntax error in service file \"%s\", line %d\n" +msgstr "\"%s\" servis dosyasında yazım hatası, satır no %d\n" + +#: fe-connect.c:5112 +#, c-format +msgid "nested service specifications not supported in service file \"%s\", line %d\n" +msgstr "\"%s\" servis dosyası satır no %d , desteklenmeyen içiçe servis tanımlamaları\n" + +#: fe-connect.c:5832 +#, c-format +msgid "invalid URI propagated to internal parser routine: \"%s\"\n" +msgstr "dahili çözümleyici yordamına aktarılan geçersiz URI: \"%s\"\n" + +#: fe-connect.c:5909 +#, c-format +msgid "end of string reached when looking for matching \"]\" in IPv6 host address in URI: \"%s\"\n" +msgstr "URI içinde IPv6 sunucu adresinde eşleşen \"]\" aranırken dize sonuna ulaşıldı: \"%s\"\n" + +#: fe-connect.c:5916 +#, c-format +msgid "IPv6 host address may not be empty in URI: \"%s\"\n" +msgstr "URI içinde IPv6 sunuu adresi boş olamaz: \"%s\"\n" + +#: fe-connect.c:5931 +#, c-format +msgid "unexpected character \"%c\" at position %d in URI (expected \":\" or \"/\"): \"%s\"\n" +msgstr "URI içinde %2$d pozisyonunda beklenmeyen karakter \"%1$c\" (\":\" veya \"/\" bekleniyordu): \"%3$s\"\n" + +#: fe-connect.c:6060 +#, c-format +msgid "extra key/value separator \"=\" in URI query parameter: \"%s\"\n" +msgstr "URI sorgu parametresinde fazla anahtar/değer ayıracı \"=\": \"%s\"\n" + +#: fe-connect.c:6080 +#, c-format +msgid "missing key/value separator \"=\" in URI query parameter: \"%s\"\n" +msgstr "URI sorgu parametresinde eksik anahtar/değer ayıracı \"=\": \"%s\"\n" + +#: fe-connect.c:6131 +#, c-format +msgid "invalid URI query parameter: \"%s\"\n" +msgstr "geçersiz URI sorgu parametresi: \"%s\"\n" + +#: fe-connect.c:6205 +#, c-format +msgid "invalid percent-encoded token: \"%s\"\n" +msgstr "geçersiz percent-encoded andacı (token)\"%s\"\n" + +#: fe-connect.c:6215 +#, c-format +msgid "forbidden value %%00 in percent-encoded value: \"%s\"\n" +msgstr "percent-encoded değeri içinde yasak değer %%00: \"%s\"\n" + +#: fe-connect.c:6580 +msgid "connection pointer is NULL\n" +msgstr "bağlantı belirteci NULL'dur\n" + +#: fe-connect.c:6878 +#, c-format +msgid "WARNING: password file \"%s\" is not a plain file\n" +msgstr "UYARI: \"%s\" password dosyası düz metin dosyası değildir\n" + +#: fe-connect.c:6887 +#, c-format +msgid "WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n" +msgstr "UYARI: \"%s\" şifre dosyası herkes ya da grup tarafından erişilebilir durumda; dosyanın izinleri u=rw (0600) ya da daha az olmalı\n" + +#: fe-connect.c:6981 +#, c-format +msgid "password retrieved from file \"%s\"\n" +msgstr "\"%s\" dosyasından parola okundu\n" + +#: fe-exec.c:445 fe-exec.c:2822 +#, c-format +msgid "row number %d is out of range 0..%d" +msgstr "%d satır numarası, 0..%d sınırının dışında" + +#: fe-exec.c:506 fe-protocol2.c:502 fe-protocol2.c:537 fe-protocol2.c:1056 +#: fe-protocol3.c:208 fe-protocol3.c:235 fe-protocol3.c:252 fe-protocol3.c:332 +#: fe-protocol3.c:727 fe-protocol3.c:958 +msgid "out of memory" +msgstr "yetersiz bellek" + +#: fe-exec.c:507 fe-protocol2.c:1402 fe-protocol3.c:1911 +#, c-format +msgid "%s" +msgstr "%s" + +#: fe-exec.c:816 +msgid "write to server failed\n" +msgstr "sunucuya yazma başarısız oldu\n" + +#: fe-exec.c:897 +msgid "NOTICE" +msgstr "BİLGİ" + +#: fe-exec.c:955 +msgid "PGresult cannot support more than INT_MAX tuples" +msgstr "PGresult INT_MAX değerinden daha fazla satır (Tuple) destekleyemez" + +#: fe-exec.c:967 +msgid "size_t overflow" +msgstr "size_t taşması" + +#: fe-exec.c:1244 fe-exec.c:1302 fe-exec.c:1348 +msgid "command string is a null pointer\n" +msgstr "komut katarı null belirteçtir\n" + +#: fe-exec.c:1308 fe-exec.c:1354 fe-exec.c:1449 +msgid "number of parameters must be between 0 and 65535\n" +msgstr "parametrelerin sayısı 0 ve 65535 arasında olmalı\n" + +#: fe-exec.c:1342 fe-exec.c:1443 +msgid "statement name is a null pointer\n" +msgstr "durum adı null belirteçtir\n" + +#: fe-exec.c:1362 fe-exec.c:1525 fe-exec.c:2234 fe-exec.c:2436 +msgid "function requires at least protocol version 3.0\n" +msgstr "fonksiyon en az 3.0 prokolüne gereksinim duyuyor.\n" + +#: fe-exec.c:1480 +msgid "no connection to the server\n" +msgstr "sunucuya bağlantı yok\n" + +#: fe-exec.c:1487 +msgid "another command is already in progress\n" +msgstr "şu anda işlenen başka bir komut var\n" + +#: fe-exec.c:1601 +msgid "length must be given for binary parameter\n" +msgstr "binary parametresinin uzunluğu belirtilmelidir\n" + +#: fe-exec.c:1864 +#, c-format +msgid "unexpected asyncStatus: %d\n" +msgstr "beklenmeyen asyncStatus: %d\n" + +#: fe-exec.c:1884 +#, c-format +msgid "PGEventProc \"%s\" failed during PGEVT_RESULTCREATE event\n" +msgstr "PGEventProc \"%s\" işlemi PGEVT_RESULTCREATE işlemi sırasında başarısız oldu\n" + +#: fe-exec.c:2044 +msgid "COPY terminated by new PQexec" +msgstr "COPY, yeni PQexec tarafından sonlandırıldı" + +#: fe-exec.c:2052 +msgid "COPY IN state must be terminated first\n" +msgstr "Öncelikle COPY IN durumu sonlandırılmalıdır\n" + +#: fe-exec.c:2072 +msgid "COPY OUT state must be terminated first\n" +msgstr "Öncelikle COPY OUT durumu sonlandırılmalıdır\n" + +#: fe-exec.c:2080 +msgid "PQexec not allowed during COPY BOTH\n" +msgstr "PQexec için COPY BOTH sırasında izin verilmiyor\n" + +#: fe-exec.c:2326 fe-exec.c:2393 fe-exec.c:2483 fe-protocol2.c:1359 +#: fe-protocol3.c:1842 +msgid "no COPY in progress\n" +msgstr "çalışan COPY süreci yok\n" + +#: fe-exec.c:2673 +msgid "connection in wrong state\n" +msgstr "bağlantı yanlış durumda\n" + +#: fe-exec.c:2704 +msgid "invalid ExecStatusType code" +msgstr "geçersiz ExecStatusType kodu" + +#: fe-exec.c:2731 +msgid "PGresult is not an error result\n" +msgstr "PGresult bir hata sonucu değildir\n" + +#: fe-exec.c:2806 fe-exec.c:2829 +#, c-format +msgid "column number %d is out of range 0..%d" +msgstr "%d kolon numarası, 0..%d aralığının dışında" + +#: fe-exec.c:2844 +#, c-format +msgid "parameter number %d is out of range 0..%d" +msgstr "%d sayılı parametre aralık dışında: 0..%d" + +#: fe-exec.c:3154 +#, c-format +msgid "could not interpret result from server: %s" +msgstr "sunucudan gelen yanıt yorumlanamadı: %s" + +#: fe-exec.c:3393 fe-exec.c:3477 +msgid "incomplete multibyte character\n" +msgstr "tamamlanmamış çoklu bayt karakteri\n" + +#: fe-lobj.c:154 +msgid "cannot determine OID of function lo_truncate\n" +msgstr "lo_truncate fonksiyonunun OID'i belirlenemiyor\n" + +#: fe-lobj.c:170 +msgid "argument of lo_truncate exceeds integer range\n" +msgstr "lo_truncate argümanı tamsayı aralığını aşıyor\n" + +#: fe-lobj.c:221 +msgid "cannot determine OID of function lo_truncate64\n" +msgstr "lo_truncate64 fonksiyonunun OID'i belirlenemiyor\n" + +#: fe-lobj.c:279 +msgid "argument of lo_read exceeds integer range\n" +msgstr "lo_read argümanı tamsayı aralığını aşıyor\n" + +#: fe-lobj.c:334 +msgid "argument of lo_write exceeds integer range\n" +msgstr "lo_write argümanı tamsayı aralığını aşıyor\n" + +#: fe-lobj.c:425 +msgid "cannot determine OID of function lo_lseek64\n" +msgstr "lo_lseek64 fonksiyonunun OID'i belirlenemiyor\n" + +#: fe-lobj.c:521 +msgid "cannot determine OID of function lo_create\n" +msgstr "lo_create fonksiyonunun OID'i belirlenemiyor\n" + +#: fe-lobj.c:600 +msgid "cannot determine OID of function lo_tell64\n" +msgstr "lo_tell64 fonksiyonunun OID'i belirlenemiyor\n" + +#: fe-lobj.c:706 fe-lobj.c:815 +#, c-format +msgid "could not open file \"%s\": %s\n" +msgstr "\"%s\" dosyası açılamadı: %s\n" + +#: fe-lobj.c:761 +#, c-format +msgid "could not read from file \"%s\": %s\n" +msgstr "\"%s\" dosyasından okuma hatası: %s\n" + +#: fe-lobj.c:835 fe-lobj.c:859 +#, c-format +msgid "could not write to file \"%s\": %s\n" +msgstr "\"%s\" dosyasına yazılamadı: %s\n" + +#: fe-lobj.c:946 +msgid "query to initialize large object functions did not return data\n" +msgstr "large object fonksiyonlarını ilklendirecek sorgu veri döndürmedi\n" + +#: fe-lobj.c:995 +msgid "cannot determine OID of function lo_open\n" +msgstr "lo_open fonksiyonunun OID'i belirlenemiyor\n" + +#: fe-lobj.c:1002 +msgid "cannot determine OID of function lo_close\n" +msgstr "lo_close fonksiyonunun OID'i belirlenemiyor\n" + +#: fe-lobj.c:1009 +msgid "cannot determine OID of function lo_creat\n" +msgstr "lo_create fonksiyonunun OID'i belirlenemiyor\n" + +#: fe-lobj.c:1016 +msgid "cannot determine OID of function lo_unlink\n" +msgstr "lo_unlink fonksiyonunun OID'i belirlenemiyor\n" + +#: fe-lobj.c:1023 +msgid "cannot determine OID of function lo_lseek\n" +msgstr "lo_lseek fonksiyonunun OID'i belirlenemiyor\n" + +#: fe-lobj.c:1030 +msgid "cannot determine OID of function lo_tell\n" +msgstr "lo_tell fonksiyonunun OID'i belirlenemiyor\n" + +#: fe-lobj.c:1037 +msgid "cannot determine OID of function loread\n" +msgstr "loread fonksiyonunun OID'i belirlenemiyor\n" + +#: fe-lobj.c:1044 +msgid "cannot determine OID of function lowrite\n" +msgstr "lowrite fonksiyonunun OID'i belirlenemiyor\n" + +#: fe-misc.c:290 +#, c-format +msgid "integer of size %lu not supported by pqGetInt" +msgstr "%lu büyüklüğündeki tamsayılar pqGetInt tarafından desteklenmez" + +#: fe-misc.c:326 +#, c-format +msgid "integer of size %lu not supported by pqPutInt" +msgstr "%lu büyüklüğündeki tamsayılar pqPutInt tarafından desteklenmez" + +#: fe-misc.c:637 fe-misc.c:859 +msgid "connection not open\n" +msgstr "bağlantı açık değil\n" + +#: fe-misc.c:807 fe-secure-openssl.c:206 fe-secure-openssl.c:314 +#: fe-secure.c:268 fe-secure.c:385 +msgid "" +"server closed the connection unexpectedly\n" +"\tThis probably means the server terminated abnormally\n" +"\tbefore or while processing the request.\n" +msgstr "" +"sunucu bağlantıyı beklenmedik şekilde kapattı\n" +"\tBu muhtemelen sunucunun isteği işlemeden önce ya da \n" +"\tisteği işlerken anormal olarak kapandığı anlamına gelir.\n" + +#: fe-misc.c:1046 +msgid "timeout expired\n" +msgstr "zamanaşımı süresi sona derdi\n" + +#: fe-misc.c:1091 +msgid "invalid socket\n" +msgstr "geçersiz soket\n" + +#: fe-misc.c:1114 +#, c-format +msgid "select() failed: %s\n" +msgstr "select() başarısız oldu: %s\n" + +#: fe-protocol2.c:90 +#, c-format +msgid "invalid setenv state %c, probably indicative of memory corruption\n" +msgstr "geçersiz setenv durumu %c, belleğin zarar görmesinin bir işareti olabilir\n" + +#: fe-protocol2.c:389 +#, c-format +msgid "invalid state %c, probably indicative of memory corruption\n" +msgstr "geçersiz %c durumu, belleğin zarar görmesinin bir işareti olabilir\n" + +#: fe-protocol2.c:478 fe-protocol3.c:185 +#, c-format +msgid "message type 0x%02x arrived from server while idle" +msgstr "sunucu boş durumdayken sunucudan 0x%02x ileti tipi geldi" + +#: fe-protocol2.c:528 +#, c-format +msgid "unexpected character %c following empty query response (\"I\" message)" +msgstr "boş sorgu yanıtını takip eden geçersiz karakter:%c (\"I\" mesajı)" + +#: fe-protocol2.c:594 +#, c-format +msgid "server sent data (\"D\" message) without prior row description (\"T\" message)" +msgstr "sunucu önceki satır tanımı (\"T\" mesajı) olmadan veri (\"D\" mesajı) gönderdi" + +#: fe-protocol2.c:612 +#, c-format +msgid "server sent binary data (\"B\" message) without prior row description (\"T\" message)" +msgstr "sunucu önceki satır tanımı (\"T\" mesajı) olmadan ikili veri (\"B\" mesajı) gönderdi" + +#: fe-protocol2.c:632 fe-protocol3.c:411 +#, c-format +msgid "unexpected response from server; first received character was \"%c\"\n" +msgstr "sunucudan beklenmeyen bir yanıt alındı; alınan ilk karakter\"%c\" idi\n" + +#: fe-protocol2.c:761 fe-protocol2.c:936 fe-protocol3.c:626 fe-protocol3.c:853 +msgid "out of memory for query result" +msgstr "sorgu sonucu için yetersiz bellek" + +#: fe-protocol2.c:1414 +#, c-format +msgid "lost synchronization with server, resetting connection" +msgstr "sunucu ile eşzamanlama kayboldu, bağlantı yeniden açılıyor" + +#: fe-protocol2.c:1536 fe-protocol2.c:1568 fe-protocol3.c:2099 +#, c-format +msgid "protocol error: id=0x%x\n" +msgstr "protokol hatası: id=0x%x\n" + +#: fe-protocol3.c:367 +msgid "server sent data (\"D\" message) without prior row description (\"T\" message)\n" +msgstr "" +"sunucu, önceki satır tanımı (\"T\" mesajı) olmadan veri (\"D\" mesajı) gönderdi\n" +"\n" + +#: fe-protocol3.c:432 +#, c-format +msgid "message contents do not agree with length in message type \"%c\"\n" +msgstr "ileti içeriği,\"%c\" ileti tipinin içindeki uzunlukla aynı değil\n" + +#: fe-protocol3.c:453 +#, c-format +msgid "lost synchronization with server: got message type \"%c\", length %d\n" +msgstr "sunucu ile eşzamanlılık kayboldu: \"%c\" ileti tipi alındı, uzunluğu %d\n" + +#: fe-protocol3.c:504 fe-protocol3.c:544 +msgid "insufficient data in \"T\" message" +msgstr "\"T\" mesajında yetersiz veri" + +#: fe-protocol3.c:577 +msgid "extraneous data in \"T\" message" +msgstr "\"T\" mesajında ilgisiz veri" + +#: fe-protocol3.c:690 +msgid "extraneous data in \"t\" message" +msgstr "\"t\" mesajında ilgisiz veri" + +#: fe-protocol3.c:761 fe-protocol3.c:793 fe-protocol3.c:811 +msgid "insufficient data in \"D\" message" +msgstr "\"D\" mesajında yetersiz veri" + +#: fe-protocol3.c:767 +msgid "unexpected field count in \"D\" message" +msgstr "\"D\" mesajında beklenmeyen alan sayısı" + +#: fe-protocol3.c:820 +msgid "extraneous data in \"D\" message" +msgstr "\"D\" mesajında ilgisiz veri" + +#: fe-protocol3.c:1012 +msgid "no error message available\n" +msgstr "hata mesajı bulunmuyor\n" + +#. translator: %s represents a digit string +#: fe-protocol3.c:1060 fe-protocol3.c:1079 +#, c-format +msgid " at character %s" +msgstr " %s. karakterde" + +#: fe-protocol3.c:1092 +#, c-format +msgid "DETAIL: %s\n" +msgstr "AYRINTI: %s\n" + +#: fe-protocol3.c:1095 +#, c-format +msgid "HINT: %s\n" +msgstr "İPUCU: %s\n" + +#: fe-protocol3.c:1098 +#, c-format +msgid "QUERY: %s\n" +msgstr "SORGU: %s\n" + +#: fe-protocol3.c:1105 +#, c-format +msgid "CONTEXT: %s\n" +msgstr "BAĞLAM: %s\n" + +#: fe-protocol3.c:1114 +#, c-format +msgid "SCHEMA NAME: %s\n" +msgstr "ŞEMA ADI: %s\n" + +#: fe-protocol3.c:1118 +#, c-format +msgid "TABLE NAME: %s\n" +msgstr "TABLO ADI: %s\n" + +#: fe-protocol3.c:1122 +#, c-format +msgid "COLUMN NAME: %s\n" +msgstr "SÜTUN ADI: %s\n" + +#: fe-protocol3.c:1126 +#, c-format +msgid "DATATYPE NAME: %s\n" +msgstr "VERİ TİPİ ADI: %s\n" + +#: fe-protocol3.c:1130 +#, c-format +msgid "CONSTRAINT NAME: %s\n" +msgstr "KISITLAMA ADI: %s\n" + +#: fe-protocol3.c:1142 +msgid "LOCATION: " +msgstr "YER: " + +#: fe-protocol3.c:1144 +#, c-format +msgid "%s, " +msgstr "%s, " + +#: fe-protocol3.c:1146 +#, c-format +msgid "%s:%s" +msgstr "%s:%s" + +#: fe-protocol3.c:1341 +#, c-format +msgid "LINE %d: " +msgstr "SATIR %d: " + +#: fe-protocol3.c:1736 +msgid "PQgetline: not doing text COPY OUT\n" +msgstr "PQgetline: COPY OUT metnini yapmıyor\n" + +#: fe-secure-common.c:124 +msgid "SSL certificate's name contains embedded null\n" +msgstr "SSL sertifikasının ismi gömülü olarak null içeriyor\n" + +#: fe-secure-common.c:171 +msgid "host name must be specified for a verified SSL connection\n" +msgstr "doğrulanmış bir SSL bağlantısı için makina adı belirtilmelidir\n" + +#: fe-secure-common.c:196 +#, c-format +msgid "server certificate for \"%s\" does not match host name \"%s\"\n" +msgstr "\"%s\" için olan sunucu sertifikası \"%s\" olan makina adı ile eşleşmiyor\n" + +#: fe-secure-common.c:202 +msgid "could not get server's host name from server certificate\n" +msgstr "sunucunun makina adı sunucu sertifikasından alınamadı\n" + +#: fe-secure-openssl.c:211 fe-secure-openssl.c:319 fe-secure-openssl.c:1219 +#, c-format +msgid "SSL SYSCALL error: %s\n" +msgstr "SSL SYSCALL hatası: %s\n" + +#: fe-secure-openssl.c:218 fe-secure-openssl.c:326 fe-secure-openssl.c:1223 +msgid "SSL SYSCALL error: EOF detected\n" +msgstr "SSL SYSCALL hatası: EOF bulundu\n" + +#: fe-secure-openssl.c:229 fe-secure-openssl.c:337 fe-secure-openssl.c:1232 +#, c-format +msgid "SSL error: %s\n" +msgstr "SSL hatası: %s\n" + +#: fe-secure-openssl.c:244 fe-secure-openssl.c:352 +msgid "SSL connection has been closed unexpectedly\n" +msgstr "SSL bağlantısı beklenmeyen şekilde sonlandırıldı\n" + +#: fe-secure-openssl.c:250 fe-secure-openssl.c:358 fe-secure-openssl.c:1241 +#, c-format +msgid "unrecognized SSL error code: %d\n" +msgstr "tanımlanamayan SSL hata kodu: %d\n" + +#: fe-secure-openssl.c:398 +msgid "could not determine server certificate signature algorithm\n" +msgstr "" +"sunucu sertifika imza algoritması belirlenemedi\n" +"\n" + +#: fe-secure-openssl.c:419 +#, c-format +msgid "could not find digest for NID %s\n" +msgstr "NID %s için özet (digest) bulunamadı\n" + +#: fe-secure-openssl.c:429 +msgid "could not generate peer certificate hash\n" +msgstr "karşı tarafın sertifika hash'i oluşturulamadı\n" + +#: fe-secure-openssl.c:486 +msgid "SSL certificate's name entry is missing\n" +msgstr "" +"SSL sertifikasının isim girişi eksik\n" +"\n" + +#: fe-secure-openssl.c:815 +#, c-format +msgid "could not create SSL context: %s\n" +msgstr "SSL bağlamı oluşturulamadı: %s\n" + +#: fe-secure-openssl.c:852 +#, c-format +msgid "could not read root certificate file \"%s\": %s\n" +msgstr "\"%s\"kök sertifika dosyası okunamadı: %s\n" + +#: fe-secure-openssl.c:880 +#, c-format +msgid "SSL library does not support CRL certificates (file \"%s\")\n" +msgstr "kurulu SSL kütüphanesi CRL sertifikalarını desteklemiyor (dosya adı \"%s\")\n" + +#: fe-secure-openssl.c:908 +msgid "" +"could not get home directory to locate root certificate file\n" +"Either provide the file or change sslmode to disable server certificate verification.\n" +msgstr "" +"kök sertifika dosyasının ev dizini bulunamadı\n" +"Ya bir dosya adı belirtin, ya da sunucu sertifika doğrulamasını kapatmak için sslmode ayarını değiştirin.\n" + +#: fe-secure-openssl.c:912 +#, c-format +msgid "" +"root certificate file \"%s\" does not exist\n" +"Either provide the file or change sslmode to disable server certificate verification.\n" +msgstr "" +"\"%s\" kök sertifika dosyası mevcut değil\n" +"Ya bu dosyayı oluşturun ya da sslmode ayarını sunucu sertifika doğrulamasını kapatmak için değiştirin.\n" + +#: fe-secure-openssl.c:943 +#, c-format +msgid "could not open certificate file \"%s\": %s\n" +msgstr "\"%s\" sertifikası açılamadı: %s\n" + +#: fe-secure-openssl.c:962 +#, c-format +msgid "could not read certificate file \"%s\": %s\n" +msgstr "\"%s\" sertifikası okunamadı: %s\n" + +#: fe-secure-openssl.c:987 +#, c-format +msgid "could not establish SSL connection: %s\n" +msgstr "SSL bağlantısı sağlanamadı: %s\n" + +#: fe-secure-openssl.c:1041 +#, c-format +msgid "could not load SSL engine \"%s\": %s\n" +msgstr "\"%s\" SSL motoru yüklenemedi: %s\n" + +#: fe-secure-openssl.c:1053 +#, c-format +msgid "could not initialize SSL engine \"%s\": %s\n" +msgstr "\"%s\" SSL motoru ilklendirilemedi: %s\n" + +#: fe-secure-openssl.c:1069 +#, c-format +msgid "could not read private SSL key \"%s\" from engine \"%s\": %s\n" +msgstr "\"%2$s\" motorundan \"%1$s\" özel SSL anahtarı okunamadı: %3$s\n" + +#: fe-secure-openssl.c:1083 +#, c-format +msgid "could not load private SSL key \"%s\" from engine \"%s\": %s\n" +msgstr "\"%2$s\" motorundan \"%1$s\" özel SSL anahtarı yüklenemedi: %3$s\n" + +#: fe-secure-openssl.c:1120 +#, c-format +msgid "certificate present, but not private key file \"%s\"\n" +msgstr "sertifika mevcut ancak özel anahtar (private key) mevcut değil \"%s\"\n" + +#: fe-secure-openssl.c:1128 +#, c-format +msgid "private key file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n" +msgstr "\"%s\" özel anahtar (private key) dosyası herkes ya da grup tarafından erişilebilir durumda; dosyanın izinleri u=rw (0600) ya da daha az olmalı\n" + +#: fe-secure-openssl.c:1139 +#, c-format +msgid "could not load private key file \"%s\": %s\n" +msgstr "özel anahtar (private key) dosyası \"%s\" okunamıyor: %s\n" + +#: fe-secure-openssl.c:1153 +#, c-format +msgid "certificate does not match private key file \"%s\": %s\n" +msgstr "sertifika, \"%s\" özel anahtar (private key) dosyası ile uyuşmuyor: %s\n" + +#: fe-secure-openssl.c:1262 +#, c-format +msgid "certificate could not be obtained: %s\n" +msgstr "sertifika elde edilemedi: %s\n" + +#: fe-secure-openssl.c:1351 +#, c-format +msgid "no SSL error reported" +msgstr "SSL hatası raporlanmadı" + +#: fe-secure-openssl.c:1360 +#, c-format +msgid "SSL error code %lu" +msgstr "SSL hata kodu: %lu" + +#: fe-secure.c:276 +#, c-format +msgid "could not receive data from server: %s\n" +msgstr "sunucudan veri alınamadı: %s\n" + +#: fe-secure.c:392 +#, c-format +msgid "could not send data to server: %s\n" +msgstr "sunucuya veri gönderilemedi: %s\n" + +#: win32.c:317 +#, c-format +msgid "unrecognized socket error: 0x%08X/%d" +msgstr "bilinmeyen soket hatası: 0x%08X/%d" + +#~ msgid "certificate could not be validated: %s\n" +#~ msgstr "sertifika doğrulanamadı: %s\n" + +#~ msgid "private key file \"%s\" has wrong permissions\n" +#~ msgstr "\"%s\" özel anahtarı yanlış izinlere sahip\n" + +#~ msgid "invalid value of PGSSLKEY environment variable\n" +#~ msgstr "PGSSLKEY ortam değişkeni için geçersiz değer\n" + +#~ msgid "could not get user information\n" +#~ msgstr "kullanıcı bilgisi alınamadı\n" + +#~ msgid "server common name \"%s\" does not resolve to %ld.%ld.%ld.%ld\n" +#~ msgstr "Sunucu ortak adı olan \"%s\" %ld.%ld.%ld.%ld adresine çözülemiyor\n" + +#~ msgid "unsupported protocol\n" +#~ msgstr "desteklenmeyen protokol\n" + +#~ msgid "could not get information about host \"%s\": %s\n" +#~ msgstr "\"%s\" sunucusu hakkında bilgi alınamadı: %s\n" + +#~ msgid "error querying socket: %s\n" +#~ msgstr "soketi sorgularken hata oluştu: %s\n" + +#~ msgid "root certificate file \"%s\" does not exist" +#~ msgstr "kök sertifika dosyası \"%s\" mevcut değildir" + +#~ msgid "invalid sslverify value: \"%s\"\n" +#~ msgstr "geçersiz sslverify değeri: \"%s\"\n" + +#~ msgid "could not read private key file \"%s\": %s\n" +#~ msgstr "\"%s\" özel anahtar dosyası okunamadı: %s\n" + +#~ msgid "private key file \"%s\" changed during execution\n" +#~ msgstr "\"%s\" özel anahtar dosyası çalışma anında açılamadı\n" + +#~ msgid "could not open private key file \"%s\": %s\n" +#~ msgstr "\"%s\" özel anahtar dosyası açılamadı: %s\n" + +#~ msgid "verified SSL connections are only supported when connecting to a host name" +#~ msgstr "Onaylanmış SSL bağlantıları sadece bir sunucu adına bağlanıldığı zaman geçerlidir" + +#~ msgid "could not get home directory to locate client certificate files\n" +#~ msgstr "İstemci sertifika dosyalarının olduğu ev dizini bulunamadı\n" + +#~ msgid "socket not open\n" +#~ msgstr "soket açık değil\n" + +#~ msgid "could not get home directory to locate service definition file" +#~ msgstr "servis dosyasının olduğu ev dizini bulunamadı" + +#~ msgid "setsockopt(SO_KEEPALIVE) failed: %s\n" +#~ msgstr "setsockopt(SO_KEEPALIVE) başarısız oldu: %s\n" + +#~ msgid "setsockopt(TCP_KEEPINTVL) failed: %s\n" +#~ msgstr "setsockopt(TCP_KEEPINTVL) başarısız oldu: %s\n" + +#~ msgid "setsockopt(TCP_KEEPALIVE) failed: %s\n" +#~ msgstr "setsockopt(SO_REUSEADDR) başarısız oldu: %s\n" + +#~ msgid "setsockopt(TCP_KEEPIDLE) failed: %s\n" +#~ msgstr "setsockopt(TCP_KEEPIDLE) başarısız oldu: %s\n" + +#~ msgid "could not restore non-blocking mode on socket: %s\n" +#~ msgstr "could not restore non-blocking mode on socket: %s\n" + +#~ msgid "Kerberos 5 authentication rejected: %*s\n" +#~ msgstr "Kerberos 5 yetkilendirmesi kabul edilmedi: %*s\n" + +#~ msgid "could not set socket to blocking mode: %s\n" +#~ msgstr "soket engelleme moduna ayarlanamadı: %s\n" + +#~ msgid "GSSAPI name import error" +#~ msgstr "GSSAPI ad aktarma hatası" diff --git a/src/interfaces/libpq/po/uk.po b/src/interfaces/libpq/po/uk.po new file mode 100644 index 0000000..de5d8f2 --- /dev/null +++ b/src/interfaces/libpq/po/uk.po @@ -0,0 +1,1199 @@ +msgid "" +msgstr "" +"Project-Id-Version: postgresql\n" +"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" +"POT-Creation-Date: 2021-08-17 08:39+0000\n" +"PO-Revision-Date: 2021-08-17 11:25\n" +"Last-Translator: \n" +"Language-Team: Ukrainian\n" +"Language: uk_UA\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=((n%10==1 && n%100!=11) ? 0 : ((n%10 >= 2 && n%10 <=4 && (n%100 < 12 || n%100 > 14)) ? 1 : ((n%10 == 0 || (n%10 >= 5 && n%10 <=9)) || (n%100 >= 11 && n%100 <= 14)) ? 2 : 3));\n" +"X-Crowdin-Project: postgresql\n" +"X-Crowdin-Project-ID: 324573\n" +"X-Crowdin-Language: uk\n" +"X-Crowdin-File: /REL_14_DEV/libpq.pot\n" +"X-Crowdin-File-ID: 774\n" + +#: fe-auth-scram.c:213 +msgid "malformed SCRAM message (empty message)\n" +msgstr "неправильне повідомлення SCRAM (пусте повідомлення)\n" + +#: fe-auth-scram.c:219 +msgid "malformed SCRAM message (length mismatch)\n" +msgstr "неправильне повідомлення SCRAM (невідповідність довжини)\n" + +#: fe-auth-scram.c:263 +msgid "could not verify server signature\n" +msgstr "не вдалося перевірити підпис сервера\n" + +#: fe-auth-scram.c:270 +msgid "incorrect server signature\n" +msgstr "невірний підпис сервера\n" + +#: fe-auth-scram.c:279 +msgid "invalid SCRAM exchange state\n" +msgstr "неприпустимий стан обміну SCRAM\n" + +#: fe-auth-scram.c:306 +#, c-format +msgid "malformed SCRAM message (attribute \"%c\" expected)\n" +msgstr "неправильне повідомлення SCRAM (очікувався атрибут \"%c\")\n" + +#: fe-auth-scram.c:315 +#, c-format +msgid "malformed SCRAM message (expected character \"=\" for attribute \"%c\")\n" +msgstr "неправильне повідомлення SCRAM (очікувався символ \"=\" для атрибута \"%c\")\n" + +#: fe-auth-scram.c:356 +msgid "could not generate nonce\n" +msgstr "не вдалося згенерувати одноразовий ідентифікатор\n" + +#: fe-auth-scram.c:366 fe-auth-scram.c:441 fe-auth-scram.c:595 +#: fe-auth-scram.c:616 fe-auth-scram.c:642 fe-auth-scram.c:657 +#: fe-auth-scram.c:707 fe-auth-scram.c:746 fe-auth.c:290 fe-auth.c:362 +#: fe-auth.c:398 fe-auth.c:615 fe-auth.c:774 fe-auth.c:1132 fe-auth.c:1282 +#: fe-connect.c:911 fe-connect.c:1455 fe-connect.c:1624 fe-connect.c:2976 +#: fe-connect.c:4657 fe-connect.c:4918 fe-connect.c:5037 fe-connect.c:5289 +#: fe-connect.c:5370 fe-connect.c:5469 fe-connect.c:5725 fe-connect.c:5754 +#: fe-connect.c:5826 fe-connect.c:5850 fe-connect.c:5868 fe-connect.c:5969 +#: fe-connect.c:5978 fe-connect.c:6336 fe-connect.c:6486 fe-connect.c:6752 +#: fe-exec.c:686 fe-exec.c:876 fe-exec.c:1223 fe-exec.c:3043 fe-exec.c:3226 +#: fe-exec.c:3999 fe-exec.c:4164 fe-gssapi-common.c:111 fe-lobj.c:881 +#: fe-protocol3.c:975 fe-protocol3.c:990 fe-protocol3.c:1023 +#: fe-protocol3.c:1731 fe-secure-common.c:110 fe-secure-gssapi.c:504 +#: fe-secure-openssl.c:440 fe-secure-openssl.c:1133 +msgid "out of memory\n" +msgstr "недостатньо пам'яті\n" + +#: fe-auth-scram.c:374 +msgid "could not encode nonce\n" +msgstr "не вдалося закодувати одноразовий ідентифікатор\n" + +#: fe-auth-scram.c:563 +msgid "could not calculate client proof\n" +msgstr "не вдалося обчислити підтвердження клієнта\n" + +#: fe-auth-scram.c:579 +msgid "could not encode client proof\n" +msgstr "не вдалося закодувати підтвердження клієнта\n" + +#: fe-auth-scram.c:634 +msgid "invalid SCRAM response (nonce mismatch)\n" +msgstr "неприпустима відповідь SCRAM (невідповідність одноразового ідентифікатора)\n" + +#: fe-auth-scram.c:667 +msgid "malformed SCRAM message (invalid salt)\n" +msgstr "неправильне повідомлення SCRAM (неприпустима сіль)\n" + +#: fe-auth-scram.c:681 +msgid "malformed SCRAM message (invalid iteration count)\n" +msgstr "неправильне повідомлення SCRAM (неприпустима кількість ітерацій)\n" + +#: fe-auth-scram.c:687 +msgid "malformed SCRAM message (garbage at end of server-first-message)\n" +msgstr "неправильне повідомлення SCRAM (сміття в кінці першого повідомлення сервера)\n" + +#: fe-auth-scram.c:723 +#, c-format +msgid "error received from server in SCRAM exchange: %s\n" +msgstr "отримано помилку від сервера під час обміну SCRAM: %s\n" + +#: fe-auth-scram.c:739 +msgid "malformed SCRAM message (garbage at end of server-final-message)\n" +msgstr "неправильне повідомлення SCRAM (сміття в кінці останнього повідомлення сервера)\n" + +#: fe-auth-scram.c:758 +msgid "malformed SCRAM message (invalid server signature)\n" +msgstr "неправильне повідомлення SCRAM (неприпустимий підпис сервера)\n" + +#: fe-auth.c:76 +#, c-format +msgid "out of memory allocating GSSAPI buffer (%d)\n" +msgstr "недостатньо пам'яті для буфера GSSAPI (%d)\n" + +#: fe-auth.c:131 +msgid "GSSAPI continuation error" +msgstr "Помилка продовження у GSSAPI" + +#: fe-auth.c:158 fe-auth.c:391 fe-gssapi-common.c:98 fe-secure-common.c:98 +msgid "host name must be specified\n" +msgstr "потрібно вказати ім’я хоста\n" + +#: fe-auth.c:165 +msgid "duplicate GSS authentication request\n" +msgstr "дублікат запиту автентифікації GSS\n" + +#: fe-auth.c:230 +#, c-format +msgid "out of memory allocating SSPI buffer (%d)\n" +msgstr "недостатньо пам'яті для буфера SSPI (%d)\n" + +#: fe-auth.c:278 +msgid "SSPI continuation error" +msgstr "Помилка продовження SSPI" + +#: fe-auth.c:351 +msgid "duplicate SSPI authentication request\n" +msgstr "дублікат запиту автентифікації SSPI\n" + +#: fe-auth.c:377 +msgid "could not acquire SSPI credentials" +msgstr "не вдалось отримати облікові дані SSPI" + +#: fe-auth.c:433 +msgid "channel binding required, but SSL not in use\n" +msgstr "необхідно зв’язування каналів, але SSL не використовується\n" + +#: fe-auth.c:440 +msgid "duplicate SASL authentication request\n" +msgstr "дублікат запиту автентифікації SASL\n" + +#: fe-auth.c:496 +msgid "channel binding is required, but client does not support it\n" +msgstr "потрібно зв'язування каналів, але клієнт не підтримує його\n" + +#: fe-auth.c:513 +msgid "server offered SCRAM-SHA-256-PLUS authentication over a non-SSL connection\n" +msgstr "сервер запропонував автентифікацію SCRAM-SHA-256-PLUS через підключення без SSL\n" + +#: fe-auth.c:525 +msgid "none of the server's SASL authentication mechanisms are supported\n" +msgstr "жоден з серверних механізмів автентифікації SASL не підтримується\n" + +#: fe-auth.c:533 +msgid "channel binding is required, but server did not offer an authentication method that supports channel binding\n" +msgstr "потрібно зв'язування каналів, але сервер не запропонував метод аутентифікації, який підтримує зв’язування каналів\n" + +#: fe-auth.c:639 +#, c-format +msgid "out of memory allocating SASL buffer (%d)\n" +msgstr "недостатньо пам'яті для буфера SASL (%d)\n" + +#: fe-auth.c:664 +msgid "AuthenticationSASLFinal received from server, but SASL authentication was not completed\n" +msgstr "Від сервера отримано AuthenticationSASLFinal, але автентифікація SASL не була завершена\n" + +#: fe-auth.c:741 +msgid "SCM_CRED authentication method not supported\n" +msgstr "Спосіб автентифікації SCM_CRED не підтримується\n" + +#: fe-auth.c:836 +msgid "channel binding required, but server authenticated client without channel binding\n" +msgstr "потрібно зв'язування каналів, але сервер автентифікував клієнта без зв’язування каналів\n" + +#: fe-auth.c:842 +msgid "channel binding required but not supported by server's authentication request\n" +msgstr "потрібно зв'язування каналів, але не підтримується запитом на аутентифікацію сервера\n" + +#: fe-auth.c:877 +msgid "Kerberos 4 authentication not supported\n" +msgstr "Автентифікація Kerberos 4 не підтримується\n" + +#: fe-auth.c:882 +msgid "Kerberos 5 authentication not supported\n" +msgstr "Автентифікація Kerberos 5 не підтримується\n" + +#: fe-auth.c:953 +msgid "GSSAPI authentication not supported\n" +msgstr "Автентифікація GSSAPI не підтримується\n" + +#: fe-auth.c:985 +msgid "SSPI authentication not supported\n" +msgstr "Автентифікація SSPI не підтримується\n" + +#: fe-auth.c:993 +msgid "Crypt authentication not supported\n" +msgstr "Автентифікація Crypt не підтримується\n" + +#: fe-auth.c:1060 +#, c-format +msgid "authentication method %u not supported\n" +msgstr "спосіб автентифікації %u не підтримується\n" + +#: fe-auth.c:1107 +#, c-format +msgid "user name lookup failure: error code %lu\n" +msgstr "невдала підстановка імені користувача: код помилки %lu\n" + +#: fe-auth.c:1117 fe-connect.c:2851 +#, c-format +msgid "could not look up local user ID %d: %s\n" +msgstr "не вдалося знайти локального користувача за ідентифікатором: %d: %s\n" + +#: fe-auth.c:1122 fe-connect.c:2856 +#, c-format +msgid "local user with ID %d does not exist\n" +msgstr "локального користувача з ідентифікатором %d не існує\n" + +#: fe-auth.c:1226 +msgid "unexpected shape of result set returned for SHOW\n" +msgstr "неочікувану форму набору результатів повернуто для SHOW\n" + +#: fe-auth.c:1235 +msgid "password_encryption value too long\n" +msgstr "занадто довге значення password_encryption \n" + +#: fe-auth.c:1275 +#, c-format +msgid "unrecognized password encryption algorithm \"%s\"\n" +msgstr "нерозпізнаний алгоритм шифрування пароля \"%s\"\n" + +#: fe-connect.c:1094 +#, c-format +msgid "could not match %d host names to %d hostaddr values\n" +msgstr "не вдалося зіставити %d імен хостів зі %d значеннями hostaddr\n" + +#: fe-connect.c:1175 +#, c-format +msgid "could not match %d port numbers to %d hosts\n" +msgstr "не вдалося зіставити %d номерів портів з %d хостами\n" + +#: fe-connect.c:1268 fe-connect.c:1294 fe-connect.c:1336 fe-connect.c:1345 +#: fe-connect.c:1378 fe-connect.c:1422 +#, c-format +msgid "invalid %s value: \"%s\"\n" +msgstr "неприпустиме значення %s : \"%s\"\n" + +#: fe-connect.c:1315 +#, c-format +msgid "sslmode value \"%s\" invalid when SSL support is not compiled in\n" +msgstr "значення sslmode \"%s\" неприпустиме, якщо підтримку протоколу SSL не скомпільовано\n" + +#: fe-connect.c:1363 +msgid "invalid SSL protocol version range\n" +msgstr "неприпустимий діапазон версії протоколу SSL\n" + +#: fe-connect.c:1388 +#, c-format +msgid "gssencmode value \"%s\" invalid when GSSAPI support is not compiled in\n" +msgstr "значення gssencmode \"%s\" неприпустиме, якщо підтримку протоколу GSSAPI не скомпільовано\n" + +#: fe-connect.c:1648 +#, c-format +msgid "could not set socket to TCP no delay mode: %s\n" +msgstr "не вдалося встановити сокет у TCP-режим без затримки: %s\n" + +#: fe-connect.c:1710 +#, c-format +msgid "connection to server on socket \"%s\" failed: " +msgstr "помилка при з'єднанні з сервером через сокет \"%s\": " + +#: fe-connect.c:1737 +#, c-format +msgid "connection to server at \"%s\" (%s), port %s failed: " +msgstr "підключення до серверу \"%s\" (%s), порт %s провалено: " + +#: fe-connect.c:1742 +#, c-format +msgid "connection to server at \"%s\", port %s failed: " +msgstr "підключення до серверу \"%s\", порт %s провалено: " + +#: fe-connect.c:1767 +msgid "\tIs the server running locally and accepting connections on that socket?\n" +msgstr "\tЧи працює сервер локально і приймає підключення до цього сокету?\n" + +#: fe-connect.c:1771 +msgid "\tIs the server running on that host and accepting TCP/IP connections?\n" +msgstr "\tЧи працює сервер на цьому хості і приймає TCP/IP підключення?\n" + +#: fe-connect.c:1835 +#, c-format +msgid "invalid integer value \"%s\" for connection option \"%s\"\n" +msgstr "неприпустиме ціле значення \"%s\" для параметра з'єднання \"%s\"\n" + +#: fe-connect.c:1865 fe-connect.c:1900 fe-connect.c:1936 fe-connect.c:2025 +#: fe-connect.c:2639 +#, c-format +msgid "%s(%s) failed: %s\n" +msgstr "%s(%s) помилка: %s\n" + +#: fe-connect.c:1990 +#, c-format +msgid "%s(%s) failed: error code %d\n" +msgstr "%s(%s) помилка: код помилки %d\n" + +#: fe-connect.c:2305 +msgid "invalid connection state, probably indicative of memory corruption\n" +msgstr "неприпустимий стан підключення, можливо, пошкоджена пам'ять\n" + +#: fe-connect.c:2384 +#, c-format +msgid "invalid port number: \"%s\"\n" +msgstr "неприпустимий номер порту: \"%s\"\n" + +#: fe-connect.c:2400 +#, c-format +msgid "could not translate host name \"%s\" to address: %s\n" +msgstr "не вдалося перекласти ім’я хоста \"%s\" в адресу: %s\n" + +#: fe-connect.c:2413 +#, c-format +msgid "could not parse network address \"%s\": %s\n" +msgstr "не вдалося проаналізувати адресу мережі \"%s\": %s\n" + +#: fe-connect.c:2426 +#, c-format +msgid "Unix-domain socket path \"%s\" is too long (maximum %d bytes)\n" +msgstr "Шлях Unix-сокету \"%s\" занадто довгий (максимум %d байтів)\n" + +#: fe-connect.c:2441 +#, c-format +msgid "could not translate Unix-domain socket path \"%s\" to address: %s\n" +msgstr "не вдалося перекласти шлях Unix-сокету \"%s\" в адресу: %s\n" + +#: fe-connect.c:2567 +#, c-format +msgid "could not create socket: %s\n" +msgstr "не вдалося створити сокет: %s\n" + +#: fe-connect.c:2598 +#, c-format +msgid "could not set socket to nonblocking mode: %s\n" +msgstr "не вдалося встановити сокет у режим без блокування: %s\n" + +#: fe-connect.c:2608 +#, c-format +msgid "could not set socket to close-on-exec mode: %s\n" +msgstr "не вдалося встановити сокет у режим закриття по виконанню: %s\n" + +#: fe-connect.c:2626 +msgid "keepalives parameter must be an integer\n" +msgstr "параметр keepalives має бути цілим числом\n" + +#: fe-connect.c:2767 +#, c-format +msgid "could not get socket error status: %s\n" +msgstr "не вдалося отримати статус помилки сокету: %s\n" + +#: fe-connect.c:2795 +#, c-format +msgid "could not get client address from socket: %s\n" +msgstr "не вдалося отримати адресу клієнта з сокету: %s\n" + +#: fe-connect.c:2837 +msgid "requirepeer parameter is not supported on this platform\n" +msgstr "параметр requirepeer не підтримується на цій платформі\n" + +#: fe-connect.c:2840 +#, c-format +msgid "could not get peer credentials: %s\n" +msgstr "не вдалося отримати облікові дані сервера: %s\n" + +#: fe-connect.c:2864 +#, c-format +msgid "requirepeer specifies \"%s\", but actual peer user name is \"%s\"\n" +msgstr "requirepeer вказує на \"%s\", але фактичне ім'я вузла \"%s\"\n" + +#: fe-connect.c:2904 +#, c-format +msgid "could not send GSSAPI negotiation packet: %s\n" +msgstr "не вдалося передати пакет узгодження протоколу GSSAPI: %s\n" + +#: fe-connect.c:2916 +msgid "GSSAPI encryption required but was impossible (possibly no credential cache, no server support, or using a local socket)\n" +msgstr "вимагалося шифрування GSSAPI, але не було неможливим (можливо, без кешу облікових даних, підтримки сервера, або використання локального сокета)\n" + +#: fe-connect.c:2958 +#, c-format +msgid "could not send SSL negotiation packet: %s\n" +msgstr "не вдалося передати пакет узгодження протоколу SSL: %s\n" + +#: fe-connect.c:2989 +#, c-format +msgid "could not send startup packet: %s\n" +msgstr "не вдалося передати стартовий пакет: %s\n" + +#: fe-connect.c:3065 +msgid "server does not support SSL, but SSL was required\n" +msgstr "сервер не підтримує протокол SSL, але протокол SSL вимагається\n" + +#: fe-connect.c:3092 +#, c-format +msgid "received invalid response to SSL negotiation: %c\n" +msgstr "отримано неприпустиму відповідь на узгодження SSL: %c\n" + +#: fe-connect.c:3181 +msgid "server doesn't support GSSAPI encryption, but it was required\n" +msgstr "сервер не підтримує шифрування GSSAPI, але це було необхідно\n" + +#: fe-connect.c:3193 +#, c-format +msgid "received invalid response to GSSAPI negotiation: %c\n" +msgstr "отримано неприпустиму відповідь на узгодження GSSAPI: %c\n" + +#: fe-connect.c:3259 fe-connect.c:3284 +#, c-format +msgid "expected authentication request from server, but received %c\n" +msgstr "очікувався запит автентифікації від сервера, але отримано %c\n" + +#: fe-connect.c:3491 +msgid "unexpected message from server during startup\n" +msgstr "неочікуване повідомлення від сервера під час запуску\n" + +#: fe-connect.c:3583 +msgid "session is read-only\n" +msgstr "сесія доступна тільки для читання\n" + +#: fe-connect.c:3586 +msgid "session is not read-only\n" +msgstr "сесія доступна не лише для читання\n" + +#: fe-connect.c:3640 +msgid "server is in hot standby mode\n" +msgstr "сервер знаходиться у режимі hot standby\n" + +#: fe-connect.c:3643 +msgid "server is not in hot standby mode\n" +msgstr "сервер не в режимі hot standby\n" + +#: fe-connect.c:3754 fe-connect.c:3806 +#, c-format +msgid "\"%s\" failed\n" +msgstr "\"%s\" помилка\n" + +#: fe-connect.c:3820 +#, c-format +msgid "invalid connection state %d, probably indicative of memory corruption\n" +msgstr "неприпустимий стан підключення %d, можливо, пошкоджена пам'ять\n" + +#: fe-connect.c:4266 fe-connect.c:4326 +#, c-format +msgid "PGEventProc \"%s\" failed during PGEVT_CONNRESET event\n" +msgstr "Помилка у PGEventProc \"%s\" під час події PGEVT_CONNRESET\n" + +#: fe-connect.c:4670 +#, c-format +msgid "invalid LDAP URL \"%s\": scheme must be ldap://\n" +msgstr "неприпустима URL-адреса протоколу LDAP \"%s\": схема має бути ldap://\n" + +#: fe-connect.c:4685 +#, c-format +msgid "invalid LDAP URL \"%s\": missing distinguished name\n" +msgstr "неприпустима URL-адреса протоколу LDAP \"%s\": відсутнє унікальне ім'я\n" + +#: fe-connect.c:4697 fe-connect.c:4755 +#, c-format +msgid "invalid LDAP URL \"%s\": must have exactly one attribute\n" +msgstr "неприпустима URL-адреса протоколу LDAP \"%s\": має бути лише один атрибут\n" + +#: fe-connect.c:4709 fe-connect.c:4771 +#, c-format +msgid "invalid LDAP URL \"%s\": must have search scope (base/one/sub)\n" +msgstr "неприпустима URL-адреса протоколу LDAP \"%s\": відсутня область пошуку (base/one/sub)\n" + +#: fe-connect.c:4721 +#, c-format +msgid "invalid LDAP URL \"%s\": no filter\n" +msgstr "неприпустима URL-адреса протоколу LDAP \"%s\": відсутній фільтр\n" + +#: fe-connect.c:4743 +#, c-format +msgid "invalid LDAP URL \"%s\": invalid port number\n" +msgstr "неприпустима URL-адреса протоколу LDAP \"%s\": неприпустимий номер порту\n" + +#: fe-connect.c:4781 +msgid "could not create LDAP structure\n" +msgstr "не вдалося створити структуру протоколу LDAP\n" + +#: fe-connect.c:4857 +#, c-format +msgid "lookup on LDAP server failed: %s\n" +msgstr "помилка підстановки на сервері протоколу LDAP: %s\n" + +#: fe-connect.c:4868 +msgid "more than one entry found on LDAP lookup\n" +msgstr "знайдено більше одного входження при підстановці протоколу LDAP\n" + +#: fe-connect.c:4869 fe-connect.c:4881 +msgid "no entry found on LDAP lookup\n" +msgstr "не знайдено входження при підстановці протоколу LDAP\n" + +#: fe-connect.c:4892 fe-connect.c:4905 +msgid "attribute has no values on LDAP lookup\n" +msgstr "атрибут не має значення при підстановці протоколу LDAP\n" + +#: fe-connect.c:4957 fe-connect.c:4976 fe-connect.c:5508 +#, c-format +msgid "missing \"=\" after \"%s\" in connection info string\n" +msgstr "відсутній \"=\" після \"%s\" у рядку інформації про підключення\n" + +#: fe-connect.c:5049 fe-connect.c:5693 fe-connect.c:6469 +#, c-format +msgid "invalid connection option \"%s\"\n" +msgstr "неприпустимий параметр підключення \"%s\"\n" + +#: fe-connect.c:5065 fe-connect.c:5557 +msgid "unterminated quoted string in connection info string\n" +msgstr "відкриті лапки у рядку інформації про підключення\n" + +#: fe-connect.c:5146 +#, c-format +msgid "definition of service \"%s\" not found\n" +msgstr "не знайдено визначення сервера \"%s\"\n" + +#: fe-connect.c:5172 +#, c-format +msgid "service file \"%s\" not found\n" +msgstr "не знайдено сервісний файл \"%s\"\n" + +#: fe-connect.c:5186 +#, c-format +msgid "line %d too long in service file \"%s\"\n" +msgstr "рядок %d занадто довгий у сервісному файлі \"%s\"\n" + +#: fe-connect.c:5257 fe-connect.c:5301 +#, c-format +msgid "syntax error in service file \"%s\", line %d\n" +msgstr "синтаксична помилка у сервісному файлі \"%s\", рядок %d\n" + +#: fe-connect.c:5268 +#, c-format +msgid "nested service specifications not supported in service file \"%s\", line %d\n" +msgstr "вкладені сервісні специфікації не підтримуються у сервісному файлі \"%s\", рядок %d\n" + +#: fe-connect.c:5989 +#, c-format +msgid "invalid URI propagated to internal parser routine: \"%s\"\n" +msgstr "у внутрішню процедуру аналізу рядка передано помилковий URI: \"%s\"\n" + +#: fe-connect.c:6066 +#, c-format +msgid "end of string reached when looking for matching \"]\" in IPv6 host address in URI: \"%s\"\n" +msgstr "досягнуто кінця рядка під час пошуку відповідного \"]\" в адресі IPv6 URI: \"%s\"\n" + +#: fe-connect.c:6073 +#, c-format +msgid "IPv6 host address may not be empty in URI: \"%s\"\n" +msgstr "IPv6, що знаходиться в URI, не може бути пустим: \"%s\"\n" + +#: fe-connect.c:6088 +#, c-format +msgid "unexpected character \"%c\" at position %d in URI (expected \":\" or \"/\"): \"%s\"\n" +msgstr "неочікуваний символ \"%c\" на позиції %d в URI (очікувалося \":\" або \"/\"): \"%s\"\n" + +#: fe-connect.c:6218 +#, c-format +msgid "extra key/value separator \"=\" in URI query parameter: \"%s\"\n" +msgstr "зайвий розділювач ключа/значення \"=\" в параметрі запиту URI: \"%s\"\n" + +#: fe-connect.c:6238 +#, c-format +msgid "missing key/value separator \"=\" in URI query parameter: \"%s\"\n" +msgstr "відсутній розділювач ключа/значення \"=\" у параметрі запиту URI: \"%s\"\n" + +#: fe-connect.c:6290 +#, c-format +msgid "invalid URI query parameter: \"%s\"\n" +msgstr "неприпустимий параметр запиту URI: \"%s\"\n" + +#: fe-connect.c:6364 +#, c-format +msgid "invalid percent-encoded token: \"%s\"\n" +msgstr "неприпустимий токен, закодований відсотками: \"%s\"\n" + +#: fe-connect.c:6374 +#, c-format +msgid "forbidden value %%00 in percent-encoded value: \"%s\"\n" +msgstr "неприпустиме значення %%00 для значення, закодованого відсотками: \"%s\"\n" + +#: fe-connect.c:6744 +msgid "connection pointer is NULL\n" +msgstr "нульове значення вказівника підключення \n" + +#: fe-connect.c:7032 +#, c-format +msgid "WARNING: password file \"%s\" is not a plain file\n" +msgstr "ПОПЕРЕДЖЕННЯ: файл паролів \"%s\" не є простим файлом\n" + +#: fe-connect.c:7041 +#, c-format +msgid "WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n" +msgstr "ПОПЕРЕДЖЕННЯ: до файлу паролів \"%s\" мають доступ група або всі; дозволи мають бути u=rw (0600) або менше\n" + +#: fe-connect.c:7149 +#, c-format +msgid "password retrieved from file \"%s\"\n" +msgstr "пароль отримано з файлу \"%s\"\n" + +#: fe-exec.c:449 fe-exec.c:3300 +#, c-format +msgid "row number %d is out of range 0..%d" +msgstr "число рядків %d поза діапазоном 0..%d" + +#: fe-exec.c:510 fe-protocol3.c:219 fe-protocol3.c:244 fe-protocol3.c:273 +#: fe-protocol3.c:291 fe-protocol3.c:371 fe-protocol3.c:743 +msgid "out of memory" +msgstr "недостатньо пам'яті" + +#: fe-exec.c:511 fe-protocol3.c:1939 +#, c-format +msgid "%s" +msgstr "%s" + +#: fe-exec.c:792 +msgid "write to server failed\n" +msgstr "записати на сервер не вдалося\n" + +#: fe-exec.c:864 +msgid "NOTICE" +msgstr "ПОВІДОМЛЕННЯ" + +#: fe-exec.c:922 +msgid "PGresult cannot support more than INT_MAX tuples" +msgstr "PGresult не може підтримувати більше ніж INT_MAX кортежів" + +#: fe-exec.c:934 +msgid "size_t overflow" +msgstr "переповнення size_t" + +#: fe-exec.c:1349 fe-exec.c:1454 fe-exec.c:1503 +msgid "command string is a null pointer\n" +msgstr "рядок команди є нульовим вказівником\n" + +#: fe-exec.c:1460 fe-exec.c:1509 fe-exec.c:1605 +#, c-format +msgid "number of parameters must be between 0 and %d\n" +msgstr "кількість параметрів має бути між 0 і %d\n" + +#: fe-exec.c:1497 fe-exec.c:1599 +msgid "statement name is a null pointer\n" +msgstr "ім’я оператора є пустим вказівником\n" + +#: fe-exec.c:1641 fe-exec.c:3153 +msgid "no connection to the server\n" +msgstr "немає підключення до сервера\n" + +#: fe-exec.c:1650 fe-exec.c:3162 +msgid "another command is already in progress\n" +msgstr "інша команда уже в прогресі\n" + +#: fe-exec.c:1679 +msgid "cannot queue commands during COPY\n" +msgstr "не можна поставити в чергу команди під час COPY\n" + +#: fe-exec.c:1797 +msgid "length must be given for binary parameter\n" +msgstr "для бінарного параметра має бути надана довжина\n" + +#: fe-exec.c:2117 +#, c-format +msgid "unexpected asyncStatus: %d\n" +msgstr "неочікуваний asyncStatus: %d\n" + +#: fe-exec.c:2137 +#, c-format +msgid "PGEventProc \"%s\" failed during PGEVT_RESULTCREATE event\n" +msgstr "Помилка у PGEventProc \"%s\" під час події PGEVT_RESULTCREAT\n" + +#: fe-exec.c:2285 +msgid "synchronous command execution functions are not allowed in pipeline mode\n" +msgstr "функції синхронного виконання команд заборонені в режимі конвеєра\n" + +#: fe-exec.c:2307 +msgid "COPY terminated by new PQexec" +msgstr "COPY завершено новим PQexec" + +#: fe-exec.c:2324 +msgid "PQexec not allowed during COPY BOTH\n" +msgstr "PQexec не дозволяється під час COPY BOTH\n" + +#: fe-exec.c:2552 fe-exec.c:2608 fe-exec.c:2677 fe-protocol3.c:1870 +msgid "no COPY in progress\n" +msgstr "Немає COPY у процесі\n" + +#: fe-exec.c:2854 +msgid "PQfn not allowed in pipeline mode\n" +msgstr "PQfn заборонено в режимі конвеєра\n" + +#: fe-exec.c:2862 +msgid "connection in wrong state\n" +msgstr "підключення у неправильному стані\n" + +#: fe-exec.c:2906 +msgid "cannot enter pipeline mode, connection not idle\n" +msgstr "не можна увійти в режим конвеєра, підключення не в очікуванні\n" + +#: fe-exec.c:2940 fe-exec.c:2957 +msgid "cannot exit pipeline mode with uncollected results\n" +msgstr "не можна вийти з режиму конвеєра з незібраними результатами\n" + +#: fe-exec.c:2945 +msgid "cannot exit pipeline mode while busy\n" +msgstr "не можна вийти з режиму конвеєра, коли зайнято\n" + +#: fe-exec.c:3087 +msgid "cannot send pipeline when not in pipeline mode\n" +msgstr "неможливо скористатися конвеєром не у режимі конвеєра\n" + +#: fe-exec.c:3189 +msgid "invalid ExecStatusType code" +msgstr "неприпустимий код ExecStatusType" + +#: fe-exec.c:3216 +msgid "PGresult is not an error result\n" +msgstr "PGresult не є помилковим результатом\n" + +#: fe-exec.c:3284 fe-exec.c:3307 +#, c-format +msgid "column number %d is out of range 0..%d" +msgstr "число стовпців %d поза діапазоном 0..%d" + +#: fe-exec.c:3322 +#, c-format +msgid "parameter number %d is out of range 0..%d" +msgstr "число параметрів %d поза діапазоном 0..%d" + +#: fe-exec.c:3632 +#, c-format +msgid "could not interpret result from server: %s" +msgstr "не вдалося інтерпретувати результат від сервера: %s" + +#: fe-exec.c:3892 fe-exec.c:3981 +msgid "incomplete multibyte character\n" +msgstr "неповний мультибайтний символ\n" + +#: fe-gssapi-common.c:124 +msgid "GSSAPI name import error" +msgstr "Помилка імпорту імені у GSSAPI" + +#: fe-lobj.c:145 fe-lobj.c:210 fe-lobj.c:403 fe-lobj.c:494 fe-lobj.c:568 +#: fe-lobj.c:969 fe-lobj.c:977 fe-lobj.c:985 fe-lobj.c:993 fe-lobj.c:1001 +#: fe-lobj.c:1009 fe-lobj.c:1017 fe-lobj.c:1025 +#, c-format +msgid "cannot determine OID of function %s\n" +msgstr "неможливо визначити ідентифікатор OID функції %s\n" + +#: fe-lobj.c:162 +msgid "argument of lo_truncate exceeds integer range\n" +msgstr "аргумент lo_truncate перевищує діапазон цілого числа\n" + +#: fe-lobj.c:266 +msgid "argument of lo_read exceeds integer range\n" +msgstr "аргумент lo_read перевищує діапазон цілого числа\n" + +#: fe-lobj.c:318 +msgid "argument of lo_write exceeds integer range\n" +msgstr "аргумент lo_write перевищує діапазон цілого числа\n" + +#: fe-lobj.c:678 fe-lobj.c:789 +#, c-format +msgid "could not open file \"%s\": %s\n" +msgstr "не вдалося відкрити файл \"%s\": %s\n" + +#: fe-lobj.c:734 +#, c-format +msgid "could not read from file \"%s\": %s\n" +msgstr "не вдалося прочитати з файлу \"%s\": %s\n" + +#: fe-lobj.c:810 fe-lobj.c:834 +#, c-format +msgid "could not write to file \"%s\": %s\n" +msgstr "не вдалося записати у файл \"%s\": %s\n" + +#: fe-lobj.c:920 +msgid "query to initialize large object functions did not return data\n" +msgstr "запит на ініціалізацію функцій для великих об’єктів не повернув дані\n" + +#: fe-misc.c:242 +#, c-format +msgid "integer of size %lu not supported by pqGetInt" +msgstr "pqGetInt не підтримує ціле число розміром %lu" + +#: fe-misc.c:275 +#, c-format +msgid "integer of size %lu not supported by pqPutInt" +msgstr "pqPutInt не підтримує ціле число розміром %lu" + +#: fe-misc.c:576 fe-misc.c:822 +msgid "connection not open\n" +msgstr "підключення не відкрито\n" + +#: fe-misc.c:755 fe-secure-openssl.c:209 fe-secure-openssl.c:316 +#: fe-secure.c:260 fe-secure.c:373 +msgid "server closed the connection unexpectedly\n" +"\tThis probably means the server terminated abnormally\n" +"\tbefore or while processing the request.\n" +msgstr "сервер неочікувано закрив підключення\n" +" Це може означати, що сервер завершив роботу ненормально до або під час обробки запиту.\n" + +#: fe-misc.c:1015 +msgid "timeout expired\n" +msgstr "тайм-аут минув\n" + +#: fe-misc.c:1060 +msgid "invalid socket\n" +msgstr "неприпустимий сокет\n" + +#: fe-misc.c:1083 +#, c-format +msgid "%s() failed: %s\n" +msgstr "%s() помилка: %s\n" + +#: fe-protocol3.c:196 +#, c-format +msgid "message type 0x%02x arrived from server while idle" +msgstr "отримано тип повідомлення 0x%02x від сервера під час бездіяльності" + +#: fe-protocol3.c:403 +msgid "server sent data (\"D\" message) without prior row description (\"T\" message)\n" +msgstr "сервер передав дані (повідомлення \"D\") без попереднього опису рядка (повідомлення \"T\")\n" + +#: fe-protocol3.c:446 +#, c-format +msgid "unexpected response from server; first received character was \"%c\"\n" +msgstr "неочікувана відповідь від сервера; перший отриманий символ був \"%c\"\n" + +#: fe-protocol3.c:471 +#, c-format +msgid "message contents do not agree with length in message type \"%c\"\n" +msgstr "вміст повідомлення не відповідає довжині у типі повідомлення \"%c\"\n" + +#: fe-protocol3.c:491 +#, c-format +msgid "lost synchronization with server: got message type \"%c\", length %d\n" +msgstr "втрачено синхронізацію з сервером: отримано тип повідомлення \"%c\", довжина %d\n" + +#: fe-protocol3.c:543 fe-protocol3.c:583 +msgid "insufficient data in \"T\" message" +msgstr "недостатньо даних у повідомленні \"T\"" + +#: fe-protocol3.c:654 fe-protocol3.c:860 +msgid "out of memory for query result" +msgstr "недостатньо пам'яті для результату запиту" + +#: fe-protocol3.c:723 +msgid "insufficient data in \"t\" message" +msgstr "недостатньо даних у повідомленні \"t\"" + +#: fe-protocol3.c:782 fe-protocol3.c:814 fe-protocol3.c:832 +msgid "insufficient data in \"D\" message" +msgstr "зайві дані у повідомленні \"D\"" + +#: fe-protocol3.c:788 +msgid "unexpected field count in \"D\" message" +msgstr "неочікувана кількість полів у повідомленні \"D\"" + +#: fe-protocol3.c:1036 +msgid "no error message available\n" +msgstr "немає доступного повідомлення про помилку\n" + +#. translator: %s represents a digit string +#: fe-protocol3.c:1084 fe-protocol3.c:1103 +#, c-format +msgid " at character %s" +msgstr " в символі %s" + +#: fe-protocol3.c:1116 +#, c-format +msgid "DETAIL: %s\n" +msgstr "ДЕТАЛІ: %s\n" + +#: fe-protocol3.c:1119 +#, c-format +msgid "HINT: %s\n" +msgstr "ПІДКАЗКА: %s\n" + +#: fe-protocol3.c:1122 +#, c-format +msgid "QUERY: %s\n" +msgstr "ЗАПИТ: %s\n" + +#: fe-protocol3.c:1129 +#, c-format +msgid "CONTEXT: %s\n" +msgstr "КОНТЕКСТ: %s\n" + +#: fe-protocol3.c:1138 +#, c-format +msgid "SCHEMA NAME: %s\n" +msgstr "ІМ'Я СХЕМИ: %s\n" + +#: fe-protocol3.c:1142 +#, c-format +msgid "TABLE NAME: %s\n" +msgstr "ІМ'Я ТАБЛИЦІ: %s\n" + +#: fe-protocol3.c:1146 +#, c-format +msgid "COLUMN NAME: %s\n" +msgstr "ІМ'Я СТОВПЦЯ: %s\n" + +#: fe-protocol3.c:1150 +#, c-format +msgid "DATATYPE NAME: %s\n" +msgstr "ІМ'Я ТИПУ ДАНИХ: %s\n" + +#: fe-protocol3.c:1154 +#, c-format +msgid "CONSTRAINT NAME: %s\n" +msgstr "ІМ'Я ОБМЕЖЕННЯ: %s\n" + +#: fe-protocol3.c:1166 +msgid "LOCATION: " +msgstr "РОЗТАШУВАННЯ: " + +#: fe-protocol3.c:1168 +#, c-format +msgid "%s, " +msgstr "%s, " + +#: fe-protocol3.c:1170 +#, c-format +msgid "%s:%s" +msgstr "%s:%s" + +#: fe-protocol3.c:1365 +#, c-format +msgid "LINE %d: " +msgstr "РЯДОК %d: " + +#: fe-protocol3.c:1764 +msgid "PQgetline: not doing text COPY OUT\n" +msgstr "PQgetline можна викликати лише під час COPY OUT\n" + +#: fe-protocol3.c:2130 +#, c-format +msgid "protocol error: id=0x%x\n" +msgstr "помилка протоколу: id=0x%x\n" + +#: fe-secure-common.c:124 +msgid "SSL certificate's name contains embedded null\n" +msgstr "Ім'я сертифікату SSL містить вбудоване Null-значення\n" + +#: fe-secure-common.c:171 +msgid "host name must be specified for a verified SSL connection\n" +msgstr "має бути вказано ім'я хосту для перевіреного SSL підключення\n" + +#: fe-secure-common.c:196 +#, c-format +msgid "server certificate for \"%s\" does not match host name \"%s\"\n" +msgstr "серверний сертифікат \"%s\" не співпадає з іменем хосту \"%s\"\n" + +#: fe-secure-common.c:202 +msgid "could not get server's host name from server certificate\n" +msgstr "не вдалося отримати ім'я хосту від серверного сертифікату\n" + +#: fe-secure-gssapi.c:201 +msgid "GSSAPI wrap error" +msgstr "помилка при згортанні GSSAPI" + +#: fe-secure-gssapi.c:209 +msgid "outgoing GSSAPI message would not use confidentiality\n" +msgstr "вихідне повідомлення GSSAPI не буде використовувати конфіденційність\n" + +#: fe-secure-gssapi.c:217 +#, c-format +msgid "client tried to send oversize GSSAPI packet (%zu > %zu)\n" +msgstr "клієнт намагався відправити переповнений пакет GSSAPI: (%zu > %zu)\n" + +#: fe-secure-gssapi.c:354 fe-secure-gssapi.c:596 +#, c-format +msgid "oversize GSSAPI packet sent by the server (%zu > %zu)\n" +msgstr "переповнений пакет GSSAPI відправлений сервером: (%zu > %zu)\n" + +#: fe-secure-gssapi.c:393 +msgid "GSSAPI unwrap error" +msgstr "помилка при розгортанні GSSAPI" + +#: fe-secure-gssapi.c:403 +msgid "incoming GSSAPI message did not use confidentiality\n" +msgstr "вхідне повідомлення GSSAPI не використовувало конфіденційність\n" + +#: fe-secure-gssapi.c:642 +msgid "could not initiate GSSAPI security context" +msgstr "не вдалося ініціювати контекст безпеки GSSAPI" + +#: fe-secure-gssapi.c:670 +msgid "GSSAPI size check error" +msgstr "помилка перевірки розміру GSSAPI" + +#: fe-secure-gssapi.c:681 +msgid "GSSAPI context establishment error" +msgstr "помилка встановлення контексту GSSAPI" + +#: fe-secure-openssl.c:214 fe-secure-openssl.c:321 fe-secure-openssl.c:1333 +#, c-format +msgid "SSL SYSCALL error: %s\n" +msgstr "Помилка SSL SYSCALL: %s\n" + +#: fe-secure-openssl.c:221 fe-secure-openssl.c:328 fe-secure-openssl.c:1337 +msgid "SSL SYSCALL error: EOF detected\n" +msgstr "Помилка SSL SYSCALL: виявлено EOF\n" + +#: fe-secure-openssl.c:232 fe-secure-openssl.c:339 fe-secure-openssl.c:1346 +#, c-format +msgid "SSL error: %s\n" +msgstr "Помилка SSL: %s\n" + +#: fe-secure-openssl.c:247 fe-secure-openssl.c:354 +msgid "SSL connection has been closed unexpectedly\n" +msgstr "SSL підключення було неочікувано перервано\n" + +#: fe-secure-openssl.c:253 fe-secure-openssl.c:360 fe-secure-openssl.c:1396 +#, c-format +msgid "unrecognized SSL error code: %d\n" +msgstr "нерозпізнаний код помилки SSL: %d\n" + +#: fe-secure-openssl.c:400 +msgid "could not determine server certificate signature algorithm\n" +msgstr "не вдалося визначити алгоритм підпису серверного сертифікату\n" + +#: fe-secure-openssl.c:421 +#, c-format +msgid "could not find digest for NID %s\n" +msgstr "не вдалося знайти дайджест для NID %s\n" + +#: fe-secure-openssl.c:431 +msgid "could not generate peer certificate hash\n" +msgstr "не вдалося згенерувати хеш сертифікату вузла\n" + +#: fe-secure-openssl.c:488 +msgid "SSL certificate's name entry is missing\n" +msgstr "Відсутня ім'я в сертифікаті SSL\n" + +#: fe-secure-openssl.c:822 +#, c-format +msgid "could not create SSL context: %s\n" +msgstr "не вдалося створити контекст SSL: %s\n" + +#: fe-secure-openssl.c:861 +#, c-format +msgid "invalid value \"%s\" for minimum SSL protocol version\n" +msgstr "неприпустиме значення \"%s\" для мінімальної версії протоколу SSL\n" + +#: fe-secure-openssl.c:872 +#, c-format +msgid "could not set minimum SSL protocol version: %s\n" +msgstr "не вдалося встановити мінімальну версію протоколу SSL: %s\n" + +#: fe-secure-openssl.c:890 +#, c-format +msgid "invalid value \"%s\" for maximum SSL protocol version\n" +msgstr "неприпустиме значення \"%s\" для максимальної версії протоколу SSL\n" + +#: fe-secure-openssl.c:901 +#, c-format +msgid "could not set maximum SSL protocol version: %s\n" +msgstr "не вдалося встановити максимальну версію протоколу SSL: %s\n" + +#: fe-secure-openssl.c:937 +#, c-format +msgid "could not read root certificate file \"%s\": %s\n" +msgstr "не вдалося прочитати файл кореневого сертифікату \"%s\": %s\n" + +#: fe-secure-openssl.c:990 +msgid "could not get home directory to locate root certificate file\n" +"Either provide the file or change sslmode to disable server certificate verification.\n" +msgstr "не вдалося отримати домашній каталог, щоб знайти файл кореневого сертифікату\n" +"Надайте файл або змініть sslmode, щоб вимкнути перевірку серверного сертифікату.\n" + +#: fe-secure-openssl.c:994 +#, c-format +msgid "root certificate file \"%s\" does not exist\n" +"Either provide the file or change sslmode to disable server certificate verification.\n" +msgstr "файлу кореневого сертифікату \"%s\" не існує\n" +"Вкажіть повний шлях до файлу або вимкніть перевірку сертифікату сервера, змінивши sslmode.\n" + +#: fe-secure-openssl.c:1025 +#, c-format +msgid "could not open certificate file \"%s\": %s\n" +msgstr "не вдалося відкрити файл сертифікату \"%s\": %s\n" + +#: fe-secure-openssl.c:1044 +#, c-format +msgid "could not read certificate file \"%s\": %s\n" +msgstr "не вдалося прочитати файл сертифікату \"%s\": %s\n" + +#: fe-secure-openssl.c:1069 +#, c-format +msgid "could not establish SSL connection: %s\n" +msgstr "не вдалося встановити SSL-підключення: %s\n" + +#: fe-secure-openssl.c:1103 +#, c-format +msgid "could not set SSL Server Name Indication (SNI): %s\n" +msgstr "не вдалося встановити Індикацію Імені Сервера протокол SSL (SNI): %s\n" + +#: fe-secure-openssl.c:1149 +#, c-format +msgid "could not load SSL engine \"%s\": %s\n" +msgstr "не вдалося завантажити модуль SSL \"%s\": %s\n" + +#: fe-secure-openssl.c:1161 +#, c-format +msgid "could not initialize SSL engine \"%s\": %s\n" +msgstr "не вдалося ініціалізувати модуль SSL \"%s\": %s\n" + +#: fe-secure-openssl.c:1177 +#, c-format +msgid "could not read private SSL key \"%s\" from engine \"%s\": %s\n" +msgstr "не вдалося прочитати закритий ключ SSL \"%s\" з модуля \"%s\": %s\n" + +#: fe-secure-openssl.c:1191 +#, c-format +msgid "could not load private SSL key \"%s\" from engine \"%s\": %s\n" +msgstr "не вдалося завантажити закритий ключ SSL \"%s\" з модуля \"%s\": %s\n" + +#: fe-secure-openssl.c:1228 +#, c-format +msgid "certificate present, but not private key file \"%s\"\n" +msgstr "сертифікат присутній, але файл закритого ключа \"%s\" ні\n" + +#: fe-secure-openssl.c:1236 +#, c-format +msgid "private key file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n" +msgstr "файл закритого ключа \"%s\" має груповий або всесвітній доступ; права повинні бути u=rw (0600) або більш обмежені\n" + +#: fe-secure-openssl.c:1261 +#, c-format +msgid "could not load private key file \"%s\": %s\n" +msgstr "не вдалося завантажити файл закритого ключа \"%s\": %s\n" + +#: fe-secure-openssl.c:1279 +#, c-format +msgid "certificate does not match private key file \"%s\": %s\n" +msgstr "сертифікат не відповідає файлу закритого ключа \"%s\": %s\n" + +#: fe-secure-openssl.c:1379 +#, c-format +msgid "This may indicate that the server does not support any SSL protocol version between %s and %s.\n" +msgstr "Це може вказувати, що сервер не підтримує жодної версії протоколу SSL між %s і %s.\n" + +#: fe-secure-openssl.c:1415 +#, c-format +msgid "certificate could not be obtained: %s\n" +msgstr "не вдалося отримати сертифікат: %s\n" + +#: fe-secure-openssl.c:1521 +#, c-format +msgid "no SSL error reported" +msgstr "немає повідомлення про помилку SSL" + +#: fe-secure-openssl.c:1530 +#, c-format +msgid "SSL error code %lu" +msgstr "Код помилки SSL %lu" + +#: fe-secure-openssl.c:1777 +#, c-format +msgid "WARNING: sslpassword truncated\n" +msgstr "ПОПЕРЕДЖЕННЯ: sslpassword скорочено\n" + +#: fe-secure.c:267 +#, c-format +msgid "could not receive data from server: %s\n" +msgstr "не вдалося отримати дані з серверу: %s\n" + +#: fe-secure.c:380 +#, c-format +msgid "could not send data to server: %s\n" +msgstr "не вдалося передати дані серверу: %s\n" + +#: win32.c:314 +#, c-format +msgid "unrecognized socket error: 0x%08X/%d" +msgstr "нерозпізнана помилка сокету: 0x%08X/%d" + diff --git a/src/interfaces/libpq/po/zh_CN.po b/src/interfaces/libpq/po/zh_CN.po new file mode 100644 index 0000000..34a34a8 --- /dev/null +++ b/src/interfaces/libpq/po/zh_CN.po @@ -0,0 +1,1193 @@ +# simplified Chinese translation file for libpq +# Bao Wei <weibao@forevertek.com>, 2002 +# +msgid "" +msgstr "" +"Project-Id-Version: libpq (PostgreSQL) 14\n" +"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" +"POT-Creation-Date: 2021-08-14 05:40+0000\n" +"PO-Revision-Date: 2021-08-15 16:25+0800\n" +"Last-Translator: Jie Zhang <zhangjie2@fujitsu.com>\n" +"Language-Team: Chinese (Simplified) <zhangjie2@fujitsu.com>\n" +"Language: zh_CN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.5.7\n" + +#: fe-auth-scram.c:213 +msgid "malformed SCRAM message (empty message)\n" +msgstr "错误的SCRAM消息(空消息)\n" + +#: fe-auth-scram.c:219 +msgid "malformed SCRAM message (length mismatch)\n" +msgstr "错误的SCRAM消息(长度不匹配)\n" + +#: fe-auth-scram.c:263 +msgid "could not verify server signature\n" +msgstr "无法验证服务器签名\n" + +#: fe-auth-scram.c:270 +msgid "incorrect server signature\n" +msgstr "服务器签名不正确\n" + +#: fe-auth-scram.c:279 +msgid "invalid SCRAM exchange state\n" +msgstr "SCRAM交换状态无效\n" + +#: fe-auth-scram.c:306 +#, c-format +msgid "malformed SCRAM message (attribute \"%c\" expected)\n" +msgstr "错误的SCRAM消息(应为属性\"%c\")\n" + +#: fe-auth-scram.c:315 +#, c-format +msgid "malformed SCRAM message (expected character \"=\" for attribute \"%c\")\n" +msgstr "错误的SCRAM消息(属性\"%c\"需要字符\"=\")\n" + +#: fe-auth-scram.c:356 +msgid "could not generate nonce\n" +msgstr "无法生成nonce\n" + +#: fe-auth-scram.c:366 fe-auth-scram.c:441 fe-auth-scram.c:595 +#: fe-auth-scram.c:616 fe-auth-scram.c:642 fe-auth-scram.c:657 +#: fe-auth-scram.c:707 fe-auth-scram.c:746 fe-auth.c:290 fe-auth.c:362 +#: fe-auth.c:398 fe-auth.c:615 fe-auth.c:774 fe-auth.c:1132 fe-auth.c:1282 +#: fe-connect.c:911 fe-connect.c:1455 fe-connect.c:1624 fe-connect.c:2976 +#: fe-connect.c:4657 fe-connect.c:4918 fe-connect.c:5037 fe-connect.c:5289 +#: fe-connect.c:5370 fe-connect.c:5469 fe-connect.c:5725 fe-connect.c:5754 +#: fe-connect.c:5826 fe-connect.c:5850 fe-connect.c:5868 fe-connect.c:5969 +#: fe-connect.c:5978 fe-connect.c:6336 fe-connect.c:6486 fe-connect.c:6752 +#: fe-exec.c:686 fe-exec.c:876 fe-exec.c:1223 fe-exec.c:3043 fe-exec.c:3226 +#: fe-exec.c:3999 fe-exec.c:4164 fe-gssapi-common.c:111 fe-lobj.c:881 +#: fe-protocol3.c:975 fe-protocol3.c:990 fe-protocol3.c:1023 +#: fe-protocol3.c:1731 fe-secure-common.c:110 fe-secure-gssapi.c:504 +#: fe-secure-openssl.c:440 fe-secure-openssl.c:1133 +msgid "out of memory\n" +msgstr "内存不足\n" + +#: fe-auth-scram.c:374 +msgid "could not encode nonce\n" +msgstr "无法编码nonce\n" + +#: fe-auth-scram.c:563 +msgid "could not calculate client proof\n" +msgstr "无法计算客户端证明\n" + +#: fe-auth-scram.c:579 +msgid "could not encode client proof\n" +msgstr "无法对客户端证明进行编码\n" + +#: fe-auth-scram.c:634 +msgid "invalid SCRAM response (nonce mismatch)\n" +msgstr "SCRAM响应无效(非匹配)\n" + +#: fe-auth-scram.c:667 +msgid "malformed SCRAM message (invalid salt)\n" +msgstr "错误的SCRAM消息 (无效的salt)\n" + +#: fe-auth-scram.c:681 +msgid "malformed SCRAM message (invalid iteration count)\n" +msgstr "错误的SCRAM消息(迭代计数无效)\n" + +#: fe-auth-scram.c:687 +msgid "malformed SCRAM message (garbage at end of server-first-message)\n" +msgstr "错误的SCRAM消息 (服务器第一条消息结束时为垃圾消息)\n" + +#: fe-auth-scram.c:723 +#, c-format +msgid "error received from server in SCRAM exchange: %s\n" +msgstr "在SCRAM交换中从服务器接收到错误: %s\n" + +#: fe-auth-scram.c:739 +msgid "malformed SCRAM message (garbage at end of server-final-message)\n" +msgstr "错误的SCRAM消息 (服务器最后一条消息结束时为垃圾消息)\n" + +#: fe-auth-scram.c:758 +msgid "malformed SCRAM message (invalid server signature)\n" +msgstr "错误的SCRAM消息 (服务器签名无效)\n" + +#: fe-auth.c:76 +#, c-format +msgid "out of memory allocating GSSAPI buffer (%d)\n" +msgstr "在分配GSSAPI缓冲区(%d)时内存用尽\n" + +#: fe-auth.c:131 +msgid "GSSAPI continuation error" +msgstr "GSSAPI连续出现错误" + +#: fe-auth.c:158 fe-auth.c:391 fe-gssapi-common.c:98 fe-secure-common.c:98 +msgid "host name must be specified\n" +msgstr "必须指定主机名\n" + +#: fe-auth.c:165 +msgid "duplicate GSS authentication request\n" +msgstr "重复的GSS认证请求\n" + +#: fe-auth.c:230 +#, c-format +msgid "out of memory allocating SSPI buffer (%d)\n" +msgstr "在分配SSPI缓冲区(%d)时内存用尽\n" + +#: fe-auth.c:278 +msgid "SSPI continuation error" +msgstr "SSPI连续出现错误" + +#: fe-auth.c:351 +msgid "duplicate SSPI authentication request\n" +msgstr "重复的SSPI认证请求\n" + +#: fe-auth.c:377 +msgid "could not acquire SSPI credentials" +msgstr "无法获得SSPI证书" + +#: fe-auth.c:433 +msgid "channel binding required, but SSL not in use\n" +msgstr "需要通道绑定,但未使用SSL\n" + +#: fe-auth.c:440 +msgid "duplicate SASL authentication request\n" +msgstr "重复的SASL认证请求\n" + +#: fe-auth.c:496 +msgid "channel binding is required, but client does not support it\n" +msgstr "通道绑定是必需的,但客户端不支持它\n" + +#: fe-auth.c:513 +msgid "server offered SCRAM-SHA-256-PLUS authentication over a non-SSL connection\n" +msgstr "服务器通过非SSL连接提供了SCRAM-SHA-256-PLUS身份验证\n" + +#: fe-auth.c:525 +msgid "none of the server's SASL authentication mechanisms are supported\n" +msgstr "不支持服务器的SASL身份验证机制\n" + +#: fe-auth.c:533 +msgid "channel binding is required, but server did not offer an authentication method that supports channel binding\n" +msgstr "需要通道绑定,但服务器未提供支持通道绑定的身份验证方法\n" + +#: fe-auth.c:639 +#, c-format +msgid "out of memory allocating SASL buffer (%d)\n" +msgstr "在分配SASL缓冲区(%d)时内存用尽\n" + +#: fe-auth.c:664 +msgid "AuthenticationSASLFinal received from server, but SASL authentication was not completed\n" +msgstr "从服务器接收到AuthenticationSASLFinal,但未完成SASL身份验证\n" + +#: fe-auth.c:741 +msgid "SCM_CRED authentication method not supported\n" +msgstr "不支持 SCM_CRED 认证方式\n" + +#: fe-auth.c:836 +msgid "channel binding required, but server authenticated client without channel binding\n" +msgstr "需要通道绑定,但服务器验证的客户端没有通道绑定\n" + +#: fe-auth.c:842 +msgid "channel binding required but not supported by server's authentication request\n" +msgstr "服务器的身份验证请求需要但不支持通道绑定\n" + +#: fe-auth.c:877 +msgid "Kerberos 4 authentication not supported\n" +msgstr "不支持 Kerberos 4 认证\n" + +#: fe-auth.c:882 +msgid "Kerberos 5 authentication not supported\n" +msgstr "不支持 Kerberos 5 认证\n" + +#: fe-auth.c:953 +msgid "GSSAPI authentication not supported\n" +msgstr "不支持GSSAPI认证\n" + +#: fe-auth.c:985 +msgid "SSPI authentication not supported\n" +msgstr "不支持SSPI认证\n" + +#: fe-auth.c:993 +msgid "Crypt authentication not supported\n" +msgstr "不支持Crypt认证\n" + +#: fe-auth.c:1060 +#, c-format +msgid "authentication method %u not supported\n" +msgstr "不支持 %u 认证方式\n" + +#: fe-auth.c:1107 +#, c-format +msgid "user name lookup failure: error code %lu\n" +msgstr "用户名查找失败:错误代码%lu\n" + +#: fe-auth.c:1117 fe-connect.c:2851 +#, c-format +msgid "could not look up local user ID %d: %s\n" +msgstr "无法查找本地用户ID %d: %s\n" + +#: fe-auth.c:1122 fe-connect.c:2856 +#, c-format +msgid "local user with ID %d does not exist\n" +msgstr "ID 为 %d 的本地用户不存在\n" + +#: fe-auth.c:1226 +msgid "unexpected shape of result set returned for SHOW\n" +msgstr "SHOW出现意外的结果状态\n" + +#: fe-auth.c:1235 +msgid "password_encryption value too long\n" +msgstr "密码_加密值太长\n" + +#: fe-auth.c:1275 +#, c-format +msgid "unrecognized password encryption algorithm \"%s\"\n" +msgstr "无法识别的密码加密算法 \"%s\"\n" + +#: fe-connect.c:1094 +#, c-format +msgid "could not match %d host names to %d hostaddr values\n" +msgstr "无法将主机名 %d 与主机地址 %d匹配\n" + +#: fe-connect.c:1175 +#, c-format +msgid "could not match %d port numbers to %d hosts\n" +msgstr "无法将端口号 %d与主机%d匹配\n" + +#: fe-connect.c:1268 fe-connect.c:1294 fe-connect.c:1336 fe-connect.c:1345 +#: fe-connect.c:1378 fe-connect.c:1422 +msgid "invalid %s value: \"%s\"\n" +msgstr "无效的 %s值: \"%s\"\n" + +#: fe-connect.c:1315 +#, c-format +msgid "sslmode value \"%s\" invalid when SSL support is not compiled in\n" +msgstr "无效的 sslmode 值 \"%s\" 当没有把 SSL 支持编译进来时\n" + +#: fe-connect.c:1363 +msgid "invalid SSL protocol version range\n" +msgstr "无效的SSL协议版本范围\n" + +#: fe-connect.c:1388 +#, c-format +msgid "gssencmode value \"%s\" invalid when GSSAPI support is not compiled in\n" +msgstr "无效的 gssencmode 值 \"%s\" 当没有把 GSSAPI 支持编译进来时\n" + +#: fe-connect.c:1648 +#, c-format +msgid "could not set socket to TCP no delay mode: %s\n" +msgstr "无法将套接字设置为 TCP 无延迟模式: %s\n" + +#: fe-connect.c:1710 +msgid "connection to server on socket \"%s\" failed: " +msgstr "连接到套接字\"%s\"上的服务器失败:" + +#: fe-connect.c:1737 +msgid "connection to server at \"%s\" (%s), port %s failed: " +msgstr "连接到\"%s\" (%s)上的服务器,端口%s失败:" + +#: fe-connect.c:1742 +msgid "connection to server at \"%s\", port %s failed: " +msgstr "连接到\"%s\"上的服务器,端口%s失败:" + +#: fe-connect.c:1767 +msgid "\tIs the server running locally and accepting connections on that socket?\n" +msgstr "\t服务器是否在本地运行并接受该套接字上的连接?\n" + +#: fe-connect.c:1771 +msgid "\tIs the server running on that host and accepting TCP/IP connections?\n" +msgstr "\t服务器是否在该主机上运行并接受TCP/IP连接?\n" + +#: fe-connect.c:1835 +#, c-format +msgid "invalid integer value \"%s\" for connection option \"%s\"\n" +msgstr "连接选项\"%2$s\"的整数值\"%1$s\"无效\n" + +#: fe-connect.c:1865 fe-connect.c:1900 fe-connect.c:1936 fe-connect.c:2025 +#: fe-connect.c:2639 +msgid "%s(%s) failed: %s\n" +msgstr "%s(%s)失败: %s\n" + +#: fe-connect.c:1990 +msgid "%s(%s) failed: error code %d\n" +msgstr "%s(%s) 失败: 错误码为 %d\n" + +#: fe-connect.c:2305 +msgid "invalid connection state, probably indicative of memory corruption\n" +msgstr "无效的联接状态, 可能是存储器数据被破坏的标志\n" + +#: fe-connect.c:2384 +#, c-format +msgid "invalid port number: \"%s\"\n" +msgstr "无效端口号: \"%s\"\n" + +#: fe-connect.c:2400 +#, c-format +msgid "could not translate host name \"%s\" to address: %s\n" +msgstr "无法解释主机名 \"%s\" 到地址: %s\n" + +#: fe-connect.c:2413 +#, c-format +msgid "could not parse network address \"%s\": %s\n" +msgstr "无法分析网络地址\"%s\": %s\n" + +#: fe-connect.c:2426 +#, c-format +msgid "Unix-domain socket path \"%s\" is too long (maximum %d bytes)\n" +msgstr "Unix域的套接字路径\"%s\"超长(最大为%d字节)\n" + +#: fe-connect.c:2441 +#, c-format +msgid "could not translate Unix-domain socket path \"%s\" to address: %s\n" +msgstr "无法解释 Unix-domian 套接字路径 \"%s\" 到地址: %s\n" + +#: fe-connect.c:2567 +#, c-format +msgid "could not create socket: %s\n" +msgstr "无法创建套接字: %s\n" + +#: fe-connect.c:2598 +#, c-format +msgid "could not set socket to nonblocking mode: %s\n" +msgstr "无法设置套接字为非阻塞模式: %s\n" + +#: fe-connect.c:2608 +#, c-format +msgid "could not set socket to close-on-exec mode: %s\n" +msgstr "无法将套接字设置为执行时关闭 (close-on-exec) 模式: %s\n" + +#: fe-connect.c:2626 +msgid "keepalives parameter must be an integer\n" +msgstr "参数keepalives必须是一个整数\n" + +#: fe-connect.c:2767 +#, c-format +msgid "could not get socket error status: %s\n" +msgstr "无法获取套接字错误状态: %s\n" + +#: fe-connect.c:2795 +#, c-format +msgid "could not get client address from socket: %s\n" +msgstr "无法从套接字获取客户端地址: %s\n" + +#: fe-connect.c:2837 +msgid "requirepeer parameter is not supported on this platform\n" +msgstr "在此平台上不支持requirepeer参数\n" + +#: fe-connect.c:2840 +#, c-format +msgid "could not get peer credentials: %s\n" +msgstr "无法获得对等(peer)证书:%s\n" + +#: fe-connect.c:2864 +#, c-format +msgid "requirepeer specifies \"%s\", but actual peer user name is \"%s\"\n" +msgstr "期望对方用户指定值为 \"%s\", 但实际的对方用户名为 \"%s\"\n" + +#: fe-connect.c:2904 +#, c-format +msgid "could not send GSSAPI negotiation packet: %s\n" +msgstr "无法发送 GSSAPI 握手包: %s\n" + +#: fe-connect.c:2916 +msgid "GSSAPI encryption required but was impossible (possibly no credential cache, no server support, or using a local socket)\n" +msgstr "需要GSSAPI加密,但不可能(可能没有凭据缓存、服务器不支持或使用本地套接字)\n" + +#: fe-connect.c:2958 +#, c-format +msgid "could not send SSL negotiation packet: %s\n" +msgstr "无法发送 SSL 握手包: %s\n" + +#: fe-connect.c:2989 +#, c-format +msgid "could not send startup packet: %s\n" +msgstr "无法发送启动包: %s\n" + +#: fe-connect.c:3065 +msgid "server does not support SSL, but SSL was required\n" +msgstr "服务器不支持 SSL, 但是要求使用 SSL\n" + +#: fe-connect.c:3092 +#, c-format +msgid "received invalid response to SSL negotiation: %c\n" +msgstr "收到对 SSL 握手的无效响应: %c\n" + +#: fe-connect.c:3181 +msgid "server doesn't support GSSAPI encryption, but it was required\n" +msgstr "服务器不支持 GSSAPI, 但这是必须的\n" + +#: fe-connect.c:3193 +#, c-format +msgid "received invalid response to GSSAPI negotiation: %c\n" +msgstr "收到对 GSSAPI 握手的无效响应: %c\n" + +#: fe-connect.c:3259 fe-connect.c:3284 +#, c-format +msgid "expected authentication request from server, but received %c\n" +msgstr "期待来自服务器的认证请求, 却收到 %c\n" + +#: fe-connect.c:3491 +msgid "unexpected message from server during startup\n" +msgstr "启动过程中收到来自服务器的非预期信息\n" + +#: fe-connect.c:3583 +msgid "session is read-only\n" +msgstr "会话是只读的\n" + +#: fe-connect.c:3586 +msgid "session is not read-only\n" +msgstr "会话不是只读的\n" + +#: fe-connect.c:3640 +msgid "server is in hot standby mode\n" +msgstr "服务器处于热备份模式\n" + +#: fe-connect.c:3643 +msgid "server is not in hot standby mode\n" +msgstr "服务器不处于热备份模式\n" + +#: fe-connect.c:3754 fe-connect.c:3806 +msgid "\"%s\" failed\n" +msgstr "\"%s\" 失败\n" + +#: fe-connect.c:3820 +#, c-format +msgid "invalid connection state %d, probably indicative of memory corruption\n" +msgstr "无效的连接状态 %d, 这可能表示内存出现问题\n" + +#: fe-connect.c:4266 fe-connect.c:4326 +#, c-format +msgid "PGEventProc \"%s\" failed during PGEVT_CONNRESET event\n" +msgstr "在PGEVT_CONNRESET事件触发期间执行PGEventProc \"%s\"错误\n" + +#: fe-connect.c:4670 +#, c-format +msgid "invalid LDAP URL \"%s\": scheme must be ldap://\n" +msgstr "无效LDAP URL\"%s\": 模式必须是ldap://\n" + +#: fe-connect.c:4685 +#, c-format +msgid "invalid LDAP URL \"%s\": missing distinguished name\n" +msgstr "无效LDAP URL \"%s\": 丢失可区分的名称\n" + +#: fe-connect.c:4697 fe-connect.c:4755 +#, c-format +msgid "invalid LDAP URL \"%s\": must have exactly one attribute\n" +msgstr "无效LDAP URL \"%s\": 只能有一个属性\n" + +#: fe-connect.c:4709 fe-connect.c:4771 +#, c-format +msgid "invalid LDAP URL \"%s\": must have search scope (base/one/sub)\n" +msgstr "无效LDAP URL \"%s\": 必须有搜索范围(base/one/sub)\n" + +#: fe-connect.c:4721 +#, c-format +msgid "invalid LDAP URL \"%s\": no filter\n" +msgstr "无效的 LDAP URL \"%s\": 没有过滤器\n" + +#: fe-connect.c:4743 +#, c-format +msgid "invalid LDAP URL \"%s\": invalid port number\n" +msgstr "无效LDAP URL \"%s\": 无效端口号\n" + +#: fe-connect.c:4781 +msgid "could not create LDAP structure\n" +msgstr "无法创建LDAP结构\n" + +#: fe-connect.c:4857 +#, c-format +msgid "lookup on LDAP server failed: %s\n" +msgstr "在LDAP服务器上的查找失败: %s\n" + +#: fe-connect.c:4868 +msgid "more than one entry found on LDAP lookup\n" +msgstr "在LDAP搜索上找到多个入口\n" + +#: fe-connect.c:4869 fe-connect.c:4881 +msgid "no entry found on LDAP lookup\n" +msgstr "在LDAP查找上没有发现入口\n" + +#: fe-connect.c:4892 fe-connect.c:4905 +msgid "attribute has no values on LDAP lookup\n" +msgstr "在LDAP查找上的属性没有值\n" + +#: fe-connect.c:4957 fe-connect.c:4976 fe-connect.c:5508 +#, c-format +msgid "missing \"=\" after \"%s\" in connection info string\n" +msgstr "在联接信息字串里的 \"%s\" 后面缺少 \"=\"\n" + +#: fe-connect.c:5049 fe-connect.c:5693 fe-connect.c:6469 +#, c-format +msgid "invalid connection option \"%s\"\n" +msgstr "非法联接选项 \"%s\"\n" + +#: fe-connect.c:5065 fe-connect.c:5557 +msgid "unterminated quoted string in connection info string\n" +msgstr "联接信息字串中未结束的引号字串\n" + +#: fe-connect.c:5146 +#, c-format +msgid "definition of service \"%s\" not found\n" +msgstr "错误:没有找到服务\"%s\"的定义\n" + +#: fe-connect.c:5172 +#, c-format +msgid "service file \"%s\" not found\n" +msgstr "错误:没有找到服务文件\"%s\"\n" + +#: fe-connect.c:5186 +#, c-format +msgid "line %d too long in service file \"%s\"\n" +msgstr "在服务文件\"%2$s\"中的第%1$d行的长度太长\n" + +#: fe-connect.c:5257 fe-connect.c:5301 +#, c-format +msgid "syntax error in service file \"%s\", line %d\n" +msgstr "在服务文件\"%s\"的第%d行出现语法错误\n" + +#: fe-connect.c:5268 +#, c-format +msgid "nested service specifications not supported in service file \"%s\", line %d\n" +msgstr "在服务文件\"%s\"的第%d行出现不支持的嵌套服务说明\n" + +#: fe-connect.c:5989 +#, c-format +msgid "invalid URI propagated to internal parser routine: \"%s\"\n" +msgstr "无效的URI传入内部解析器处理程序: \"%s\"\n" + +#: fe-connect.c:6066 +#, c-format +msgid "end of string reached when looking for matching \"]\" in IPv6 host address in URI: \"%s\"\n" +msgstr "在 URI: \"%s\"中的IPv6主机地址里查找匹配符\"]\"时遇到了字符串结束符\n" + +#: fe-connect.c:6073 +#, c-format +msgid "IPv6 host address may not be empty in URI: \"%s\"\n" +msgstr "URI:\"%s\"中的IPv6主机地址可能不为空\n" + +#: fe-connect.c:6088 +#, c-format +msgid "unexpected character \"%c\" at position %d in URI (expected \":\" or \"/\"): \"%s\"\n" +msgstr "非预期的字符\"%c\"出现在在位置%d, URI (expected \":\" or \"/\"):\"%s\"\n" + +#: fe-connect.c:6218 +#, c-format +msgid "extra key/value separator \"=\" in URI query parameter: \"%s\"\n" +msgstr "遇到多余的键/值分隔符\"=\"在URI查询参数里: \"%s\"\n" + +#: fe-connect.c:6238 +#, c-format +msgid "missing key/value separator \"=\" in URI query parameter: \"%s\"\n" +msgstr "缺少相应的键/值分隔符\"=\"在URI查询参数里: \"%s\"\n" + +#: fe-connect.c:6290 +#, c-format +msgid "invalid URI query parameter: \"%s\"\n" +msgstr "无效的URI查询参数: \"%s\"\n" + +#: fe-connect.c:6364 +#, c-format +msgid "invalid percent-encoded token: \"%s\"\n" +msgstr "无效的百分号编码令牌: \"%s\"\n" + +#: fe-connect.c:6374 +#, c-format +msgid "forbidden value %%00 in percent-encoded value: \"%s\"\n" +msgstr "在百分值编码的值: \"%s\"里禁止使用 %%00\n" + +#: fe-connect.c:6744 +msgid "connection pointer is NULL\n" +msgstr "联接指针是 NULL\n" + +#: fe-connect.c:7032 +#, c-format +msgid "WARNING: password file \"%s\" is not a plain file\n" +msgstr "警告: 口令文件\"%s\"不是普通文本文件\n" + +#: fe-connect.c:7041 +#, c-format +msgid "WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n" +msgstr "警告: 口令文件\"%s\"的访问权限过大; 权限应设置 为 u=rw (0600)或更少\n" + +#: fe-connect.c:7149 +#, c-format +msgid "password retrieved from file \"%s\"\n" +msgstr "从文件\"%s\"中获取口令\n" + +#: fe-exec.c:449 fe-exec.c:3300 +#, c-format +msgid "row number %d is out of range 0..%d" +msgstr "行号码 %d 超出了范围 0..%d" + +#: fe-exec.c:510 fe-protocol3.c:219 fe-protocol3.c:244 fe-protocol3.c:273 +#: fe-protocol3.c:291 fe-protocol3.c:371 fe-protocol3.c:743 +msgid "out of memory" +msgstr "内存不足" + +#: fe-exec.c:511 fe-protocol3.c:1939 +#, c-format +msgid "%s" +msgstr "%s" + +#: fe-exec.c:792 +msgid "write to server failed\n" +msgstr "写入服务器失败\n" + +#: fe-exec.c:864 +msgid "NOTICE" +msgstr "注意" + +#: fe-exec.c:922 +msgid "PGresult cannot support more than INT_MAX tuples" +msgstr "PGresult不能支持超过INT_MAX元组" + +#: fe-exec.c:934 +msgid "size_t overflow" +msgstr "size_t溢出" + +#: fe-exec.c:1349 fe-exec.c:1454 fe-exec.c:1503 +msgid "command string is a null pointer\n" +msgstr "命令字串是一个空指针\n" + +#: fe-exec.c:1460 fe-exec.c:1509 fe-exec.c:1605 +msgid "number of parameters must be between 0 and %d\n" +msgstr "参数的个数必须介于0到%d之间\n" + +#: fe-exec.c:1497 fe-exec.c:1599 +msgid "statement name is a null pointer\n" +msgstr "声明名字是一个空指针\n" + +#: fe-exec.c:1641 fe-exec.c:3153 +msgid "no connection to the server\n" +msgstr "没有到服务器的联接\n" + +#: fe-exec.c:1650 fe-exec.c:3162 +msgid "another command is already in progress\n" +msgstr "已经有另外一条命令在处理\n" + +#: fe-exec.c:1679 +msgid "cannot queue commands during COPY\n" +msgstr "复制期间无法对命令排队\n" + +#: fe-exec.c:1797 +msgid "length must be given for binary parameter\n" +msgstr "对于2进制参数必须指定长度\n" + +#: fe-exec.c:2117 +#, c-format +msgid "unexpected asyncStatus: %d\n" +msgstr "意外的 asyncStatus(异步状态): %d\n" + +#: fe-exec.c:2137 +#, c-format +msgid "PGEventProc \"%s\" failed during PGEVT_RESULTCREATE event\n" +msgstr "在PGEVT_CONNRESET事件触发期间执行PGEventProc \"%s\"错误\n" + +#: fe-exec.c:2285 +msgid "synchronous command execution functions are not allowed in pipeline mode\n" +msgstr "管道模式下不允许使用同步命令执行函数\n" + +#: fe-exec.c:2307 +msgid "COPY terminated by new PQexec" +msgstr "COPY 被一个新的 PQexec 终止" + +#: fe-exec.c:2324 +msgid "PQexec not allowed during COPY BOTH\n" +msgstr "在 COPY BOTH时不允许调用PQexec\n" + +#: fe-exec.c:2552 fe-exec.c:2608 fe-exec.c:2677 fe-protocol3.c:1870 +msgid "no COPY in progress\n" +msgstr "没有正在处理的 COPY\n" + +#: fe-exec.c:2854 +msgid "PQfn not allowed in pipeline mode\n" +msgstr "管道模式下不允许使用PQfn\n" + +#: fe-exec.c:2862 +msgid "connection in wrong state\n" +msgstr "联接处于错误状态\n" + +#: fe-exec.c:2906 +msgid "cannot enter pipeline mode, connection not idle\n" +msgstr "无法进入管道模式,连接未空闲\n" + +#: fe-exec.c:2940 fe-exec.c:2957 +msgid "cannot exit pipeline mode with uncollected results\n" +msgstr "无法退出具有未收集结果的管道模式\n" + +#: fe-exec.c:2945 +msgid "cannot exit pipeline mode while busy\n" +msgstr "忙时无法退出管道模式\n" + +#: fe-exec.c:3087 +msgid "cannot send pipeline when not in pipeline mode\n" +msgstr "不处于管道模式时无法发送管道\n" + +#: fe-exec.c:3189 +msgid "invalid ExecStatusType code" +msgstr "非法 ExecStatusType 代码" + +#: fe-exec.c:3216 +msgid "PGresult is not an error result\n" +msgstr "PGresult不是错误的结果\n" + +#: fe-exec.c:3284 fe-exec.c:3307 +#, c-format +msgid "column number %d is out of range 0..%d" +msgstr "列号码 %d 超出了范围 0..%d" + +#: fe-exec.c:3322 +#, c-format +msgid "parameter number %d is out of range 0..%d" +msgstr "参数号%d超出了范围 0..%d" + +#: fe-exec.c:3632 +#, c-format +msgid "could not interpret result from server: %s" +msgstr "无法解释来自服务器的结果: %s" + +#: fe-exec.c:3892 fe-exec.c:3981 +msgid "incomplete multibyte character\n" +msgstr "无效的多字节字符\n" + +#: fe-gssapi-common.c:124 +msgid "GSSAPI name import error" +msgstr "GSSAPI名称导入错误" + +#: fe-lobj.c:145 fe-lobj.c:210 fe-lobj.c:403 fe-lobj.c:494 fe-lobj.c:568 +#: fe-lobj.c:969 fe-lobj.c:977 fe-lobj.c:985 fe-lobj.c:993 fe-lobj.c:1001 +#: fe-lobj.c:1009 fe-lobj.c:1017 fe-lobj.c:1025 +msgid "cannot determine OID of function %s\n" +msgstr "无法判断函数%s的 OID\n" + +#: fe-lobj.c:162 +msgid "argument of lo_truncate exceeds integer range\n" +msgstr "lo_truncate的参数超出整数范围\n" + +#: fe-lobj.c:266 +msgid "argument of lo_read exceeds integer range\n" +msgstr "lo_read的参数值已超出整数范围\n" + +#: fe-lobj.c:318 +msgid "argument of lo_write exceeds integer range\n" +msgstr "lo_write的参数值已超出整数范围\n" + +#: fe-lobj.c:678 fe-lobj.c:789 +#, c-format +msgid "could not open file \"%s\": %s\n" +msgstr "无法打开文件 \"%s\": %s\n" + +#: fe-lobj.c:734 +#, c-format +msgid "could not read from file \"%s\": %s\n" +msgstr "无法读取文件 \"%s\": %s\n" + +#: fe-lobj.c:810 fe-lobj.c:834 +#, c-format +msgid "could not write to file \"%s\": %s\n" +msgstr "无法写入文件 \"%s\": %s\n" + +#: fe-lobj.c:920 +msgid "query to initialize large object functions did not return data\n" +msgstr "初始化大对象函数的查询没有返回数据\n" + +#: fe-misc.c:242 +#, c-format +msgid "integer of size %lu not supported by pqGetInt" +msgstr "pqGetInt 不支持大小为 %lu 的整数" + +#: fe-misc.c:275 +#, c-format +msgid "integer of size %lu not supported by pqPutInt" +msgstr "pqPutInt 不支持大小为 %lu 的整数" + +#: fe-misc.c:576 fe-misc.c:822 +msgid "connection not open\n" +msgstr "联接未打开\n" + +#: fe-misc.c:755 fe-secure-openssl.c:209 fe-secure-openssl.c:316 +#: fe-secure.c:260 fe-secure.c:373 +msgid "" +"server closed the connection unexpectedly\n" +"\tThis probably means the server terminated abnormally\n" +"\tbefore or while processing the request.\n" +msgstr "" +"服务器意外地关闭了联接\n" +"\t这种现象通常意味着服务器在处理请求之前\n" +"或者正在处理请求的时候意外中止\n" + +#: fe-misc.c:1015 +msgid "timeout expired\n" +msgstr "超时满\n" + +#: fe-misc.c:1060 +msgid "invalid socket\n" +msgstr "无效套接字\n" + +#: fe-misc.c:1083 +msgid "%s() failed: %s\n" +msgstr "%s()失败: %s\n" + +#: fe-protocol3.c:196 +#, c-format +msgid "message type 0x%02x arrived from server while idle" +msgstr "当空闲时收到服务起发送过来的消息类型 0x%02x" + +#: fe-protocol3.c:403 +msgid "server sent data (\"D\" message) without prior row description (\"T\" message)\n" +msgstr "server sent data (\"D\" message) without prior row description (\"T\" message)\n" + +#: fe-protocol3.c:446 +#, c-format +msgid "unexpected response from server; first received character was \"%c\"\n" +msgstr "来自服务器意外的回执, 第一个收到的字符是 \"%c\"\n" + +#: fe-protocol3.c:471 +#, c-format +msgid "message contents do not agree with length in message type \"%c\"\n" +msgstr "在消息类型 \"%c\" 中, 消息内容与长度不匹配\n" + +#: fe-protocol3.c:491 +#, c-format +msgid "lost synchronization with server: got message type \"%c\", length %d\n" +msgstr "失去与服务器同步: 获取到消息类型 \"%c\", 长度 %d\n" + +#: fe-protocol3.c:543 fe-protocol3.c:583 +msgid "insufficient data in \"T\" message" +msgstr "\"T\"消息中剩下的数据不够" + +#: fe-protocol3.c:654 fe-protocol3.c:860 +msgid "out of memory for query result" +msgstr "查询结果时内存耗尽" + +#: fe-protocol3.c:723 +msgid "insufficient data in \"t\" message" +msgstr "\"t\"消息中剩下的数据不够" + +#: fe-protocol3.c:782 fe-protocol3.c:814 fe-protocol3.c:832 +msgid "insufficient data in \"D\" message" +msgstr "\"D\"消息中剩下的数据不够" + +#: fe-protocol3.c:788 +msgid "unexpected field count in \"D\" message" +msgstr "在 \"D\" 消息中, 意外的字段个数" + +#: fe-protocol3.c:1036 +msgid "no error message available\n" +msgstr "没有可用的错误消息\n" + +#. translator: %s represents a digit string +#: fe-protocol3.c:1084 fe-protocol3.c:1103 +#, c-format +msgid " at character %s" +msgstr " 在字符 %s" + +#: fe-protocol3.c:1116 +#, c-format +msgid "DETAIL: %s\n" +msgstr "描述: %s\n" + +#: fe-protocol3.c:1119 +#, c-format +msgid "HINT: %s\n" +msgstr "提示: %s\n" + +#: fe-protocol3.c:1122 +#, c-format +msgid "QUERY: %s\n" +msgstr "查询: %s\n" + +#: fe-protocol3.c:1129 +#, c-format +msgid "CONTEXT: %s\n" +msgstr "背景: %s\n" + +#: fe-protocol3.c:1138 +#, c-format +msgid "SCHEMA NAME: %s\n" +msgstr "方案名: %s\n" + +#: fe-protocol3.c:1142 +#, c-format +msgid "TABLE NAME: %s\n" +msgstr "表名: %s\n" + +#: fe-protocol3.c:1146 +#, c-format +msgid "COLUMN NAME: %s\n" +msgstr "列名: %s\n" + +#: fe-protocol3.c:1150 +#, c-format +msgid "DATATYPE NAME: %s\n" +msgstr "数据类型名: %s\n" + +#: fe-protocol3.c:1154 +#, c-format +msgid "CONSTRAINT NAME: %s\n" +msgstr "约束名: %s\n" + +#: fe-protocol3.c:1166 +msgid "LOCATION: " +msgstr "位置: " + +#: fe-protocol3.c:1168 +#, c-format +msgid "%s, " +msgstr "%s, " + +#: fe-protocol3.c:1170 +#, c-format +msgid "%s:%s" +msgstr "%s:%s" + +#: fe-protocol3.c:1365 +#, c-format +msgid "LINE %d: " +msgstr "第%d行" + +#: fe-protocol3.c:1764 +msgid "PQgetline: not doing text COPY OUT\n" +msgstr "PQgetline: not doing text COPY OUT\n" + +#: fe-protocol3.c:2130 +#, c-format +msgid "protocol error: id=0x%x\n" +msgstr "协议错误: id=0x%x\n" + +#: fe-secure-common.c:124 +msgid "SSL certificate's name contains embedded null\n" +msgstr "SSL证书的名称包含嵌入的空值\n" + +#: fe-secure-common.c:171 +msgid "host name must be specified for a verified SSL connection\n" +msgstr "必须为一个已验证的SSL连接指定主机名\n" + +#: fe-secure-common.c:196 +#, c-format +msgid "server certificate for \"%s\" does not match host name \"%s\"\n" +msgstr "\"%s\"的服务器证书与主机名不匹配\"%s\"\n" + +#: fe-secure-common.c:202 +msgid "could not get server's host name from server certificate\n" +msgstr "无法从服务器证书得到服务器的主机名\n" + +#: fe-secure-gssapi.c:201 +msgid "GSSAPI wrap error" +msgstr "GSSAPI包装错误" + +#: fe-secure-gssapi.c:209 +msgid "outgoing GSSAPI message would not use confidentiality\n" +msgstr "传出的GSSAPI消息将不使用机密性\n" + +#: fe-secure-gssapi.c:217 +#, c-format +msgid "client tried to send oversize GSSAPI packet (%zu > %zu)\n" +msgstr "客户端试图发送过大的GSSAPI数据包 (%zu > %zu)\n" + +#: fe-secure-gssapi.c:354 fe-secure-gssapi.c:596 +#, c-format +msgid "oversize GSSAPI packet sent by the server (%zu > %zu)\n" +msgstr "服务器端发送的超大GSSAPI数据包(%zu > %zu)\n" + +#: fe-secure-gssapi.c:393 +msgid "GSSAPI unwrap error" +msgstr "GSSAPI展开错误" + +#: fe-secure-gssapi.c:403 +msgid "incoming GSSAPI message did not use confidentiality\n" +msgstr "传入的GSSAPI消息未使用机密性\n" + +#: fe-secure-gssapi.c:642 +msgid "could not initiate GSSAPI security context" +msgstr "无法初始化GSSAPI安全上下文" + +#: fe-secure-gssapi.c:670 +msgid "GSSAPI size check error" +msgstr "GSSAPI大小检查错误" + +#: fe-secure-gssapi.c:681 +msgid "GSSAPI context establishment error" +msgstr "GSSAPI上下文创建错误" + +#: fe-secure-openssl.c:214 fe-secure-openssl.c:321 fe-secure-openssl.c:1333 +#, c-format +msgid "SSL SYSCALL error: %s\n" +msgstr "SSL SYSCALL 错误: %s\n" + +#: fe-secure-openssl.c:221 fe-secure-openssl.c:328 fe-secure-openssl.c:1337 +msgid "SSL SYSCALL error: EOF detected\n" +msgstr "SSL SYSCALL 错误: 发现结束符\n" + +#: fe-secure-openssl.c:232 fe-secure-openssl.c:339 fe-secure-openssl.c:1346 +#, c-format +msgid "SSL error: %s\n" +msgstr "SSL 错误: %s\n" + +#: fe-secure-openssl.c:247 fe-secure-openssl.c:354 +msgid "SSL connection has been closed unexpectedly\n" +msgstr "SSL连接异常关闭\n" + +#: fe-secure-openssl.c:253 fe-secure-openssl.c:360 fe-secure-openssl.c:1396 +#, c-format +msgid "unrecognized SSL error code: %d\n" +msgstr "未知的 SSL 错误码: %d\n" + +#: fe-secure-openssl.c:400 +msgid "could not determine server certificate signature algorithm\n" +msgstr "无法确定服务器证书签名算法\n" + +#: fe-secure-openssl.c:421 +#, c-format +msgid "could not find digest for NID %s\n" +msgstr "找不到NID %s的摘要\n" + +#: fe-secure-openssl.c:431 +msgid "could not generate peer certificate hash\n" +msgstr "无法生成对等证书哈希\n" + +#: fe-secure-openssl.c:488 +msgid "SSL certificate's name entry is missing\n" +msgstr "SSL证书的名称项缺失\n" + +#: fe-secure-openssl.c:822 +#, c-format +msgid "could not create SSL context: %s\n" +msgstr "无法创建 SSL 环境: %s\n" + +#: fe-secure-openssl.c:861 +#, c-format +msgid "invalid value \"%s\" for minimum SSL protocol version\n" +msgstr "最小SSL协议版本的值\"%s\"无效\n" + +#: fe-secure-openssl.c:872 +#, c-format +msgid "could not set minimum SSL protocol version: %s\n" +msgstr "无法设置最低SSL协议版本: %s\n" + +#: fe-secure-openssl.c:890 +#, c-format +msgid "invalid value \"%s\" for maximum SSL protocol version\n" +msgstr "最大SSL协议版本的值\"%s\"无效\n" + +#: fe-secure-openssl.c:901 +#, c-format +msgid "could not set maximum SSL protocol version: %s\n" +msgstr "无法设置最大SSL协议版本: %s\n" + +#: fe-secure-openssl.c:937 +#, c-format +msgid "could not read root certificate file \"%s\": %s\n" +msgstr "无法读取根证书文件 \"%s\": %s\n" + +#: fe-secure-openssl.c:990 +msgid "" +"could not get home directory to locate root certificate file\n" +"Either provide the file or change sslmode to disable server certificate verification.\n" +msgstr "" +"无法获取home目录以定位根认证文件\n" +"可以提供该文件或者将sslmode改为禁用服务器证书认证.\n" + +#: fe-secure-openssl.c:994 +#, c-format +msgid "" +"root certificate file \"%s\" does not exist\n" +"Either provide the file or change sslmode to disable server certificate verification.\n" +msgstr "" +"根认证文件\"%s\"不存在\n" +"可以提供这个文件或者将sslmode改为禁用服务器认证检验.\n" + +#: fe-secure-openssl.c:1025 +#, c-format +msgid "could not open certificate file \"%s\": %s\n" +msgstr "无法打开证书文件 \"%s\": %s\n" + +#: fe-secure-openssl.c:1044 +#, c-format +msgid "could not read certificate file \"%s\": %s\n" +msgstr "无法读取证书文件 \"%s\": %s\n" + +#: fe-secure-openssl.c:1069 +#, c-format +msgid "could not establish SSL connection: %s\n" +msgstr "无法建立 SSL 联接: %s\n" + +#: fe-secure-openssl.c:1103 +msgid "could not set SSL Server Name Indication (SNI): %s\n" +msgstr "无法设置SSL服务器名称指示(SNI): %s\n" + +#: fe-secure-openssl.c:1149 +#, c-format +msgid "could not load SSL engine \"%s\": %s\n" +msgstr "无法加载SSL引擎 \"%s\": %s\n" + +#: fe-secure-openssl.c:1161 +#, c-format +msgid "could not initialize SSL engine \"%s\": %s\n" +msgstr "无法初始化SSL引擎\"%s\": %s\n" + +#: fe-secure-openssl.c:1177 +#, c-format +msgid "could not read private SSL key \"%s\" from engine \"%s\": %s\n" +msgstr "无法从引擎\"%2$s\"读取私有SSL钥\"%1$s\": %3$s\n" + +#: fe-secure-openssl.c:1191 +#, c-format +msgid "could not load private SSL key \"%s\" from engine \"%s\": %s\n" +msgstr "无法从引擎\"%2$s\"读取私有SSL钥\"%1$s\": %3$s\n" + +#: fe-secure-openssl.c:1228 +#, c-format +msgid "certificate present, but not private key file \"%s\"\n" +msgstr "有证书, 但不是私钥文件 \"%s\"\n" + +#: fe-secure-openssl.c:1236 +#, c-format +msgid "private key file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n" +msgstr "警告: 私钥文件 \"%s\"的访问权限过大; 权限应设置 为 u=rw (0600)或更小\n" + +#: fe-secure-openssl.c:1261 +#, c-format +msgid "could not load private key file \"%s\": %s\n" +msgstr "无法装载私钥文件 \"%s\": %s\n" + +#: fe-secure-openssl.c:1279 +#, c-format +msgid "certificate does not match private key file \"%s\": %s\n" +msgstr "证书不匹配私钥文件 \"%s\": %s\n" + +#: fe-secure-openssl.c:1379 +#, c-format +msgid "This may indicate that the server does not support any SSL protocol version between %s and %s.\n" +msgstr "这可能表示服务器不支持%s和%s之间的任何SSL协议版本.\n" + +#: fe-secure-openssl.c:1415 +#, c-format +msgid "certificate could not be obtained: %s\n" +msgstr "无法获得证书: %s\n" + +#: fe-secure-openssl.c:1521 +#, c-format +msgid "no SSL error reported" +msgstr "没有报告SSL错误" + +#: fe-secure-openssl.c:1530 +#, c-format +msgid "SSL error code %lu" +msgstr "SSL错误代码 %lu" + +#: fe-secure-openssl.c:1777 +#, c-format +msgid "WARNING: sslpassword truncated\n" +msgstr "警告:ssl密码被截断\n" + +#: fe-secure.c:267 +#, c-format +msgid "could not receive data from server: %s\n" +msgstr "无法从服务器接收数据: %s\n" + +#: fe-secure.c:380 +#, c-format +msgid "could not send data to server: %s\n" +msgstr "无法向服务器发送数据: %s\n" + +#: win32.c:314 +#, c-format +msgid "unrecognized socket error: 0x%08X/%d" +msgstr "不可识别的套接字错误: 0x%08X/%d" + diff --git a/src/interfaces/libpq/po/zh_TW.po b/src/interfaces/libpq/po/zh_TW.po new file mode 100644 index 0000000..ae43bad --- /dev/null +++ b/src/interfaces/libpq/po/zh_TW.po @@ -0,0 +1,1952 @@ +# Traditional Chinese message translation file for libpq +# Copyright (C) 2023 PostgreSQL Global Development Group +# This file is distributed under the same license as the libpq (PostgreSQL) package. +# 2004-11-11 Zhenbang Wei <znbang@gmail.com> +# +msgid "" +msgstr "" +"Project-Id-Version: libpq (PostgreSQL) 16\n" +"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" +"POT-Creation-Date: 2023-09-11 20:40+0000\n" +"PO-Revision-Date: 2023-11-06 08:49+0800\n" +"Last-Translator: Zhenbang Wei <znbang@gmail.com>\n" +"Language-Team: \n" +"Language: zh_TW\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Poedit 3.4.1\n" + +# utils/fmgr/dfmgr.c:145 +#: ../../port/thread.c:50 ../../port/thread.c:86 +#, c-format +msgid "could not look up local user ID %d: %s" +msgstr "無法查詢本地使用者ID %d: %s" + +# libpq/hba.c:1481 libpq/hba.c:1512 libpq/hba.c:1582 +#: ../../port/thread.c:55 ../../port/thread.c:91 +#, c-format +msgid "local user with ID %d does not exist" +msgstr "本地使用者ID %d 不存在" + +#: fe-auth-scram.c:227 +#, c-format +msgid "malformed SCRAM message (empty message)" +msgstr "SCRAM訊息格式錯誤(空訊息)" + +#: fe-auth-scram.c:232 +#, c-format +msgid "malformed SCRAM message (length mismatch)" +msgstr "SCRAM訊息格式錯誤(長度不一致)" + +#: fe-auth-scram.c:275 +#, c-format +msgid "could not verify server signature: %s" +msgstr "無法驗證伺服器簽名: %s" + +#: fe-auth-scram.c:281 +#, c-format +msgid "incorrect server signature" +msgstr "伺服器簽名錯誤" + +# tcop/postgres.c:3105 +#: fe-auth-scram.c:290 +#, c-format +msgid "invalid SCRAM exchange state" +msgstr "SCRAM交換狀態無效" + +#: fe-auth-scram.c:317 +#, c-format +msgid "malformed SCRAM message (attribute \"%c\" expected)" +msgstr "SCRAM訊息格式錯誤(預期屬性 \"%c\")" + +#: fe-auth-scram.c:326 +#, c-format +msgid "malformed SCRAM message (expected character \"=\" for attribute \"%c\")" +msgstr "SCRAM訊息格式錯誤(屬性 \"%c\" 的預期字元是 \"=\" )" + +# access/transam/xlog.c:4111 +#: fe-auth-scram.c:366 +#, c-format +msgid "could not generate nonce" +msgstr "無法產生nonce" + +# commands/sequence.c:798 executor/execGrouping.c:328 +# executor/execGrouping.c:388 executor/nodeIndexscan.c:1051 lib/dllist.c:43 +# lib/dllist.c:88 libpq/auth.c:637 postmaster/pgstat.c:1006 +# postmaster/pgstat.c:1023 postmaster/pgstat.c:2452 postmaster/pgstat.c:2527 +# postmaster/pgstat.c:2572 postmaster/pgstat.c:2623 +# postmaster/postmaster.c:755 postmaster/postmaster.c:1625 +# postmaster/postmaster.c:2344 storage/buffer/localbuf.c:139 +# storage/file/fd.c:587 storage/file/fd.c:620 storage/file/fd.c:766 +# storage/ipc/sinval.c:789 storage/lmgr/lock.c:497 storage/smgr/md.c:138 +# storage/smgr/md.c:848 storage/smgr/smgr.c:213 utils/adt/cash.c:297 +# utils/adt/cash.c:312 utils/adt/oracle_compat.c:73 +# utils/adt/oracle_compat.c:124 utils/adt/regexp.c:191 +# utils/adt/ri_triggers.c:3471 utils/cache/relcache.c:164 +# utils/cache/relcache.c:178 utils/cache/relcache.c:1130 +# utils/cache/typcache.c:165 utils/cache/typcache.c:487 +# utils/fmgr/dfmgr.c:127 utils/fmgr/fmgr.c:521 utils/fmgr/fmgr.c:532 +# utils/init/miscinit.c:213 utils/init/miscinit.c:234 +# utils/init/miscinit.c:244 utils/misc/guc.c:1898 utils/misc/guc.c:1911 +# utils/misc/guc.c:1924 utils/mmgr/aset.c:337 utils/mmgr/aset.c:503 +# utils/mmgr/aset.c:700 utils/mmgr/aset.c:893 utils/mmgr/portalmem.c:75 +#: fe-auth-scram.c:375 fe-auth-scram.c:448 fe-auth-scram.c:600 +#: fe-auth-scram.c:620 fe-auth-scram.c:644 fe-auth-scram.c:658 +#: fe-auth-scram.c:704 fe-auth-scram.c:740 fe-auth-scram.c:914 fe-auth.c:296 +#: fe-auth.c:369 fe-auth.c:403 fe-auth.c:618 fe-auth.c:729 fe-auth.c:1210 +#: fe-auth.c:1375 fe-connect.c:925 fe-connect.c:1759 fe-connect.c:1921 +#: fe-connect.c:3291 fe-connect.c:4496 fe-connect.c:5161 fe-connect.c:5416 +#: fe-connect.c:5534 fe-connect.c:5781 fe-connect.c:5861 fe-connect.c:5959 +#: fe-connect.c:6210 fe-connect.c:6237 fe-connect.c:6313 fe-connect.c:6336 +#: fe-connect.c:6360 fe-connect.c:6395 fe-connect.c:6481 fe-connect.c:6489 +#: fe-connect.c:6846 fe-connect.c:6996 fe-exec.c:527 fe-exec.c:1321 +#: fe-exec.c:3111 fe-exec.c:4071 fe-exec.c:4235 fe-gssapi-common.c:109 +#: fe-lobj.c:870 fe-protocol3.c:204 fe-protocol3.c:228 fe-protocol3.c:256 +#: fe-protocol3.c:273 fe-protocol3.c:353 fe-protocol3.c:720 fe-protocol3.c:959 +#: fe-protocol3.c:1770 fe-protocol3.c:2170 fe-secure-common.c:110 +#: fe-secure-gssapi.c:500 fe-secure-openssl.c:434 fe-secure-openssl.c:1285 +#, c-format +msgid "out of memory" +msgstr "記憶體不足" + +#: fe-auth-scram.c:382 +#, c-format +msgid "could not encode nonce" +msgstr "無法編碼nonce" + +# fe-connect.c:1197 +#: fe-auth-scram.c:570 +#, c-format +msgid "could not calculate client proof: %s" +msgstr "無法計算客戶端證明: %s" + +# libpq/pqcomm.c:1001 +#: fe-auth-scram.c:585 +#, c-format +msgid "could not encode client proof" +msgstr "無法編碼客戶端證明" + +#: fe-auth-scram.c:637 +#, c-format +msgid "invalid SCRAM response (nonce mismatch)" +msgstr "SCRAM回應無效(nonce不一致)" + +#: fe-auth-scram.c:667 +#, c-format +msgid "malformed SCRAM message (invalid salt)" +msgstr "SCRAM訊息格式錯誤(salt無效)" + +#: fe-auth-scram.c:680 +#, c-format +msgid "malformed SCRAM message (invalid iteration count)" +msgstr "SCRAM訊息格式錯誤(迭代次數無效)" + +#: fe-auth-scram.c:685 +#, c-format +msgid "malformed SCRAM message (garbage at end of server-first-message)" +msgstr "SCRAM訊息格式錯誤(伺服器首次訊息結尾有垃圾資料)" + +# libpq/auth.c:585 +#: fe-auth-scram.c:719 +#, c-format +msgid "error received from server in SCRAM exchange: %s" +msgstr "SCRAM交換時從伺服器收到錯誤: %s" + +#: fe-auth-scram.c:734 +#, c-format +msgid "malformed SCRAM message (garbage at end of server-final-message)" +msgstr "SCRAM訊息格式錯誤(伺服器最終訊息結尾有垃圾資料)" + +#: fe-auth-scram.c:751 +#, c-format +msgid "malformed SCRAM message (invalid server signature)" +msgstr "SCRAM訊息格式錯誤(伺服器簽名無效)" + +# access/transam/xlog.c:4111 +#: fe-auth-scram.c:923 +msgid "could not generate random salt" +msgstr "無法產生隨機salt" + +#: fe-auth.c:77 +#, c-format +msgid "out of memory allocating GSSAPI buffer (%d)" +msgstr "配置GSSAPI緩衝區時記憶體不足(%d)" + +#: fe-auth.c:138 +msgid "GSSAPI continuation error" +msgstr "GSSAPI continuation錯誤" + +# commands/aggregatecmds.c:111 +#: fe-auth.c:168 fe-auth.c:397 fe-gssapi-common.c:97 fe-secure-common.c:99 +#: fe-secure-common.c:173 +#, c-format +msgid "host name must be specified" +msgstr "必須指定主機名稱" + +#: fe-auth.c:174 +#, c-format +msgid "duplicate GSS authentication request" +msgstr "重複的GSS驗證請求" + +#: fe-auth.c:238 +#, c-format +msgid "out of memory allocating SSPI buffer (%d)" +msgstr "配置SSPI緩衝區時記憶體不足(%d)" + +#: fe-auth.c:285 +msgid "SSPI continuation error" +msgstr "SSPI continuation錯誤" + +#: fe-auth.c:359 +#, c-format +msgid "duplicate SSPI authentication request" +msgstr "重複的SSPI驗證請求" + +# libpq/be-secure.c:807 +#: fe-auth.c:384 +msgid "could not acquire SSPI credentials" +msgstr "無法取得SSPI憑證" + +#: fe-auth.c:437 +#, c-format +msgid "channel binding required, but SSL not in use" +msgstr "需要通道綁定,但未使用SSL" + +#: fe-auth.c:443 +#, c-format +msgid "duplicate SASL authentication request" +msgstr "重複的SASL驗證請求" + +#: fe-auth.c:501 +#, c-format +msgid "channel binding is required, but client does not support it" +msgstr "需要通道綁定,但客戶端不支援" + +#: fe-auth.c:517 +#, c-format +msgid "server offered SCRAM-SHA-256-PLUS authentication over a non-SSL connection" +msgstr "伺服器在非SSL連線提供SCRAM-SHA-256-PLUS身份驗證" + +# fe-auth.c:608 +#: fe-auth.c:531 +#, c-format +msgid "none of the server's SASL authentication mechanisms are supported" +msgstr "沒有支援伺服器的任何SASL身份驗證機制" + +#: fe-auth.c:538 +#, c-format +msgid "channel binding is required, but server did not offer an authentication method that supports channel binding" +msgstr "需要通道綁定,但伺服器未提供支援通道綁定的身份驗證方法" + +#: fe-auth.c:641 +#, c-format +msgid "out of memory allocating SASL buffer (%d)" +msgstr "配置SASL緩衝區時記憶體不足(%d)" + +# libpq/auth.c:391 +#: fe-auth.c:665 +#, c-format +msgid "AuthenticationSASLFinal received from server, but SASL authentication was not completed" +msgstr "從伺服器收到AuthenticationSASLFinal,但SASL身份驗證未完成" + +#: fe-auth.c:675 +#, c-format +msgid "no client response found after SASL exchange success" +msgstr "SASL交換成功後找不到客戶端回應" + +#: fe-auth.c:738 fe-auth.c:745 fe-auth.c:1358 fe-auth.c:1369 +#, c-format +msgid "could not encrypt password: %s" +msgstr "無法加密密碼: %s" + +#: fe-auth.c:773 +msgid "server requested a cleartext password" +msgstr "伺服器要求明文密碼" + +#: fe-auth.c:775 +msgid "server requested a hashed password" +msgstr "伺服器要求密碼雜湊" + +#: fe-auth.c:778 +msgid "server requested GSSAPI authentication" +msgstr "伺服器要求GSSAPI身份驗證" + +#: fe-auth.c:780 +msgid "server requested SSPI authentication" +msgstr "伺服器要求SSPI身份驗證" + +#: fe-auth.c:784 +msgid "server requested SASL authentication" +msgstr "伺服器要求SASL身份驗證" + +#: fe-auth.c:787 +msgid "server requested an unknown authentication type" +msgstr "伺服器要求未知的身份驗證類型" + +#: fe-auth.c:820 +#, c-format +msgid "server did not request an SSL certificate" +msgstr "伺服器未要求SSL憑證" + +#: fe-auth.c:825 +#, c-format +msgid "server accepted connection without a valid SSL certificate" +msgstr "伺服器接受一個沒有有效SSL憑證的連線" + +#: fe-auth.c:879 +msgid "server did not complete authentication" +msgstr "伺服器未完成身份驗證" + +# fe-auth.c:655 +#: fe-auth.c:913 +#, c-format +msgid "authentication method requirement \"%s\" failed: %s" +msgstr "身份驗證方法需求\"%s\"失敗: %s" + +#: fe-auth.c:936 +#, c-format +msgid "channel binding required, but server authenticated client without channel binding" +msgstr "需要通道綁定,但伺服器在未進行通道綁定的情況下對客戶端進行了身份驗證" + +#: fe-auth.c:941 +#, c-format +msgid "channel binding required but not supported by server's authentication request" +msgstr "需要通道綁定,但伺服器的身份驗證請求不支援此功能" + +# fe-auth.c:608 +#: fe-auth.c:975 +#, c-format +msgid "Kerberos 4 authentication not supported" +msgstr "不支援Kerberos 4身份驗證" + +# fe-auth.c:627 +#: fe-auth.c:979 +#, c-format +msgid "Kerberos 5 authentication not supported" +msgstr "不支援Kerberos 5身份驗證" + +# fe-auth.c:608 +#: fe-auth.c:1049 +#, c-format +msgid "GSSAPI authentication not supported" +msgstr "不支援GSSAPI身份驗證" + +# fe-auth.c:608 +#: fe-auth.c:1080 +#, c-format +msgid "SSPI authentication not supported" +msgstr "不支援SSPI身份驗證" + +# fe-auth.c:608 +#: fe-auth.c:1087 +#, c-format +msgid "Crypt authentication not supported" +msgstr "不支援Crypt身份驗證" + +# fe-auth.c:655 +#: fe-auth.c:1151 +#, c-format +msgid "authentication method %u not supported" +msgstr "不支援身份驗證方法 %u" + +# port/win32/security.c:39 +#: fe-auth.c:1197 +#, c-format +msgid "user name lookup failure: error code %lu" +msgstr "使用者名稱查找失敗: 錯誤碼 %lu" + +#: fe-auth.c:1321 +#, c-format +msgid "unexpected shape of result set returned for SHOW" +msgstr "SHOW 回傳的結果集格式與預期不符" + +#: fe-auth.c:1329 +#, c-format +msgid "password_encryption value too long" +msgstr "password_encryption值過長" + +# access/transam/xlog.c:3720 +#: fe-auth.c:1379 +#, c-format +msgid "unrecognized password encryption algorithm \"%s\"" +msgstr "無法識別的密碼加密演算法 \"%s\"" + +# fe-connect.c:946 +#: fe-connect.c:1132 +#, c-format +msgid "could not match %d host names to %d hostaddr values" +msgstr "無法將 %d 主機名稱對應到 %d hostaddr值" + +#: fe-connect.c:1212 +#, c-format +msgid "could not match %d port numbers to %d hosts" +msgstr "無法將 %d 連接埠對應到 %d 主機" + +#: fe-connect.c:1337 +#, c-format +msgid "negative require_auth method \"%s\" cannot be mixed with non-negative methods" +msgstr "" + +#: fe-connect.c:1350 +#, c-format +msgid "require_auth method \"%s\" cannot be mixed with negative methods" +msgstr "" + +# utils/adt/network.c:105 +#: fe-connect.c:1410 fe-connect.c:1461 fe-connect.c:1503 fe-connect.c:1559 +#: fe-connect.c:1567 fe-connect.c:1598 fe-connect.c:1644 fe-connect.c:1684 +#: fe-connect.c:1705 +#, c-format +msgid "invalid %s value: \"%s\"" +msgstr "無效的 %s 值: %s" + +# commands/copy.c:2716 parser/parse_target.c:648 parser/parse_target.c:658 +#: fe-connect.c:1443 +#, c-format +msgid "require_auth method \"%s\" is specified more than once" +msgstr "require_auth方式\"%s\"被多次指定" + +# fe-connect.c:472 +#: fe-connect.c:1484 fe-connect.c:1523 fe-connect.c:1606 +#, c-format +msgid "%s value \"%s\" invalid when SSL support is not compiled in" +msgstr "編譯未加上SSL支援時,%s 值 \"%s\" 無效" + +#: fe-connect.c:1546 +#, c-format +msgid "weak sslmode \"%s\" may not be used with sslrootcert=system (use \"verify-full\")" +msgstr "弱SSL模式\"%s\"不能與sslrootcert=system一起使用(用\"verify-full\")" + +#: fe-connect.c:1584 +#, c-format +msgid "invalid SSL protocol version range" +msgstr "SSL協議版本範圍無效" + +# catalog/aclchk.c:758 commands/comment.c:1001 commands/functioncmds.c:451 +# commands/proclang.c:202 commands/proclang.c:257 utils/adt/acl.c:2079 +#: fe-connect.c:1621 +#, c-format +msgid "%s value \"%s\" is not supported (check OpenSSL version)" +msgstr "不支援%s值\"%s\"(請檢查OpenSSL版本)" + +# fe-connect.c:472 +#: fe-connect.c:1651 +#, c-format +msgid "gssencmode value \"%s\" invalid when GSSAPI support is not compiled in" +msgstr "編譯未加上GSSAPI支援時,gssencmode值\"%s\"無效" + +# fe-connect.c:810 +#: fe-connect.c:1944 +#, c-format +msgid "could not set socket to TCP no delay mode: %s" +msgstr "無法將socket設定為TCP無延遲模式: %s" + +#: fe-connect.c:2003 +#, c-format +msgid "connection to server on socket \"%s\" failed: " +msgstr "透過 socket \"%s\" 連線至資料庫失敗: " + +#: fe-connect.c:2029 +#, c-format +msgid "connection to server at \"%s\" (%s), port %s failed: " +msgstr "連線至資料庫 \"%s\"(%s),連接埠 %s 失敗: " + +#: fe-connect.c:2034 +#, c-format +msgid "connection to server at \"%s\", port %s failed: " +msgstr "連線至資料庫 \"%s\",連接埠 %s 失敗: " + +# fe-connect.c:841 +#: fe-connect.c:2057 +#, c-format +msgid "\tIs the server running locally and accepting connections on that socket?" +msgstr "\t伺服器是否在本地執行並接受socket連線?" + +# fe-connect.c:853 +#: fe-connect.c:2059 +#, c-format +msgid "\tIs the server running on that host and accepting TCP/IP connections?" +msgstr "\t伺服器是否在該主機上執行並接受TCP/IP連線?" + +# utils/adt/formatting.c:2044 +#: fe-connect.c:2122 +#, c-format +msgid "invalid integer value \"%s\" for connection option \"%s\"" +msgstr "連接選項 \"%s\" 的整數值 \"%s\" 無效" + +# fe-misc.c:991 +#: fe-connect.c:2151 fe-connect.c:2185 fe-connect.c:2220 fe-connect.c:2318 +#: fe-connect.c:2973 +#, c-format +msgid "%s(%s) failed: %s" +msgstr "%s(%s) 失敗: %s" + +#: fe-connect.c:2284 +#, c-format +msgid "%s(%s) failed: error code %d" +msgstr "%s(%s) 失敗: 錯誤碼 %d" + +# fe-connect.c:1154 +#: fe-connect.c:2597 +#, c-format +msgid "invalid connection state, probably indicative of memory corruption" +msgstr "連線狀態無效,可能是記憶體損壞" + +# commands/user.c:240 commands/user.c:371 +#: fe-connect.c:2676 +#, c-format +msgid "invalid port number: \"%s\"" +msgstr "連接埠無效: \"%s\"" + +# fe-connect.c:946 +#: fe-connect.c:2690 +#, c-format +msgid "could not translate host name \"%s\" to address: %s" +msgstr "無法將主機名稱 \"%s\" 轉譯成位址: %s" + +# libpq/hba.c:1380 +#: fe-connect.c:2702 +#, c-format +msgid "could not parse network address \"%s\": %s" +msgstr "無法解析網路位址 \"%s\": %s" + +#: fe-connect.c:2713 +#, c-format +msgid "Unix-domain socket path \"%s\" is too long (maximum %d bytes)" +msgstr "Unix-domain socket路徑\"%s\"太長(最多 %d 個位元組)" + +# fe-connect.c:950 +#: fe-connect.c:2727 +#, c-format +msgid "could not translate Unix-domain socket path \"%s\" to address: %s" +msgstr "無法將Unix-domain socket 路徑 \"%s\" 轉譯成位址: %s" + +# fe-connect.c:1197 +#: fe-connect.c:2901 +#, c-format +msgid "could not create socket: %s" +msgstr "無法建立socket: %s" + +# fe-connect.c:783 +#: fe-connect.c:2932 +#, c-format +msgid "could not set socket to nonblocking mode: %s" +msgstr "無法將socket設成非阻擋模式: %s" + +# fe-auth.c:394 +#: fe-connect.c:2943 +#, c-format +msgid "could not set socket to close-on-exec mode: %s" +msgstr "無法將socket設成close-on-exec模式: %s" + +#: fe-connect.c:2961 +#, c-format +msgid "keepalives parameter must be an integer" +msgstr "keepalive參數必須是整數" + +# fe-connect.c:1308 +#: fe-connect.c:3100 +#, c-format +msgid "could not get socket error status: %s" +msgstr "無法取得spclet錯誤狀態: %s" + +# fe-connect.c:1347 +#: fe-connect.c:3127 +#, c-format +msgid "could not get client address from socket: %s" +msgstr "無法從socket取得客戶端位址: %s" + +# commands/tablespace.c:386 commands/tablespace.c:483 +#: fe-connect.c:3165 +#, c-format +msgid "requirepeer parameter is not supported on this platform" +msgstr "此平臺不支援requirepeer參數" + +# libpq/hba.c:1472 libpq/hba.c:1503 libpq/hba.c:1571 +#: fe-connect.c:3167 +#, c-format +msgid "could not get peer credentials: %s" +msgstr "無法取得對等憑證: %s" + +#: fe-connect.c:3180 +#, c-format +msgid "requirepeer specifies \"%s\", but actual peer user name is \"%s\"" +msgstr "requirepeer指定為\"%s\",但實際對等使用者名稱是\"%s\"" + +# fe-connect.c:1392 +#: fe-connect.c:3221 +#, c-format +msgid "could not send GSSAPI negotiation packet: %s" +msgstr "無法傳送GSSAPI協商封包: %s" + +#: fe-connect.c:3233 +#, c-format +msgid "GSSAPI encryption required but was impossible (possibly no credential cache, no server support, or using a local socket)" +msgstr "需要GSSAPI加密但無法達成(可能沒有憑證快取、沒有伺服器支援或使用本機socket)" + +# fe-connect.c:1392 +#: fe-connect.c:3274 +#, c-format +msgid "could not send SSL negotiation packet: %s" +msgstr "無法傳送SSL協商封包: %s" + +# fe-connect.c:1427 +#: fe-connect.c:3303 +#, c-format +msgid "could not send startup packet: %s" +msgstr "無法傳送啟動封包: %s" + +# fe-connect.c:1486 +# fe-connect.c:1503 +#: fe-connect.c:3378 +#, c-format +msgid "server does not support SSL, but SSL was required" +msgstr "伺服器不支援 SSL,但 SSL 是必要的" + +# fe-connect.c:1519 +#: fe-connect.c:3404 +#, c-format +msgid "received invalid response to SSL negotiation: %c" +msgstr "收到無效的SSL協商回應: %c" + +#: fe-connect.c:3424 +#, c-format +msgid "received unencrypted data after SSL response" +msgstr "在SSL回應後收到未加密的資料" + +# fe-connect.c:1486 +# fe-connect.c:1503 +#: fe-connect.c:3504 +#, c-format +msgid "server doesn't support GSSAPI encryption, but it was required" +msgstr "伺服器不支援GSSAPI加密,但這是必要條件" + +# fe-connect.c:1519 +#: fe-connect.c:3515 +#, c-format +msgid "received invalid response to GSSAPI negotiation: %c" +msgstr "收到對GSSAPI協商的無效回應: %c" + +#: fe-connect.c:3533 +#, c-format +msgid "received unencrypted data after GSSAPI encryption response" +msgstr "在GSSAPI加密回應後收到未加密的資料" + +# fe-connect.c:1576 +# fe-connect.c:1608 +#: fe-connect.c:3598 +#, c-format +msgid "expected authentication request from server, but received %c" +msgstr "預期從伺服器收到身份驗證請求,但收到%c" + +#: fe-connect.c:3625 fe-connect.c:3794 +#, c-format +msgid "received invalid authentication request" +msgstr "收到無效的身份驗證請求" + +# fe-connect.c:1519 +#: fe-connect.c:3630 fe-connect.c:3779 +#, c-format +msgid "received invalid protocol negotiation message" +msgstr "收到無效的協定協商訊息" + +# libpq/pqformat.c:671 +#: fe-connect.c:3648 fe-connect.c:3702 +#, c-format +msgid "received invalid error message" +msgstr "收到無效的錯誤訊息" + +# fe-connect.c:1844 +#: fe-connect.c:3865 +#, c-format +msgid "unexpected message from server during startup" +msgstr "啟動過程中從自伺服器收到非預期訊息" + +# commands/copy.c:905 executor/execMain.c:443 tcop/utility.c:323 +#: fe-connect.c:3956 +#, c-format +msgid "session is read-only" +msgstr "工作階段是唯讀模式" + +# commands/copy.c:905 executor/execMain.c:443 tcop/utility.c:323 +#: fe-connect.c:3958 +#, c-format +msgid "session is not read-only" +msgstr "工作階段不是唯讀模式" + +#: fe-connect.c:4011 +#, c-format +msgid "server is in hot standby mode" +msgstr "伺服器處於熱備援模式" + +#: fe-connect.c:4013 +#, c-format +msgid "server is not in hot standby mode" +msgstr "伺服器未處於熱備援模式" + +#: fe-connect.c:4129 fe-connect.c:4179 +#, c-format +msgid "\"%s\" failed" +msgstr "\"%s\"失敗" + +# fe-connect.c:1914 +#: fe-connect.c:4193 +#, c-format +msgid "invalid connection state %d, probably indicative of memory corruption" +msgstr "無效的連線狀態 %d,可能指示記憶體損壞" + +#: fe-connect.c:5174 +#, c-format +msgid "invalid LDAP URL \"%s\": scheme must be ldap://" +msgstr "無效的LDAP URL \"%s\": scheme必須是 ldap://" + +#: fe-connect.c:5189 +#, c-format +msgid "invalid LDAP URL \"%s\": missing distinguished name" +msgstr "無效的LDAP URL \"%s\": 缺少識別名稱" + +#: fe-connect.c:5201 fe-connect.c:5259 +#, c-format +msgid "invalid LDAP URL \"%s\": must have exactly one attribute" +msgstr "無效的LDAP URL \"%s\": 只能有一個屬性" + +#: fe-connect.c:5213 fe-connect.c:5275 +#, c-format +msgid "invalid LDAP URL \"%s\": must have search scope (base/one/sub)" +msgstr "無效的LDAP URL \"%s\": 必須有搜尋範圍(base/one/sub)" + +#: fe-connect.c:5225 +#, c-format +msgid "invalid LDAP URL \"%s\": no filter" +msgstr "無效的LDAP URL \"%s\": 沒有過濾條件" + +#: fe-connect.c:5247 +#, c-format +msgid "invalid LDAP URL \"%s\": invalid port number" +msgstr "無效的LDAP URL \"%s\": 連接埠無效" + +# fe-secure.c:932 +#: fe-connect.c:5284 +#, c-format +msgid "could not create LDAP structure" +msgstr "無法建立LDAP結構" + +#: fe-connect.c:5359 +#, c-format +msgid "lookup on LDAP server failed: %s" +msgstr "在LDAP伺服器上查找失敗: %s" + +#: fe-connect.c:5369 +#, c-format +msgid "more than one entry found on LDAP lookup" +msgstr "LDAP 查找時找到多個項目" + +#: fe-connect.c:5371 fe-connect.c:5382 +#, c-format +msgid "no entry found on LDAP lookup" +msgstr "LDAP 查找時找不到項目" + +#: fe-connect.c:5392 fe-connect.c:5404 +#, c-format +msgid "attribute has no values on LDAP lookup" +msgstr "LDAP 查找時屬性沒有值" + +# fe-connect.c:2592 +#: fe-connect.c:5455 fe-connect.c:5474 fe-connect.c:5998 +#, c-format +msgid "missing \"=\" after \"%s\" in connection info string" +msgstr "連線字串裡的 \"%s\" 後面缺少 \"=\"" + +# fe-connect.c:2675 +#: fe-connect.c:5545 fe-connect.c:6181 fe-connect.c:6979 +#, c-format +msgid "invalid connection option \"%s\"" +msgstr "無效的連線選項 \"%s\"" + +# fe-connect.c:2641 +#: fe-connect.c:5560 fe-connect.c:6046 +#, c-format +msgid "unterminated quoted string in connection info string" +msgstr "連接字串中的引號未結束" + +#: fe-connect.c:5640 +#, c-format +msgid "definition of service \"%s\" not found" +msgstr "找不到服務 \"%s\" 的定義" + +#: fe-connect.c:5666 +#, c-format +msgid "service file \"%s\" not found" +msgstr "找不到服務檔 \"%s\"" + +#: fe-connect.c:5679 +#, c-format +msgid "line %d too long in service file \"%s\"" +msgstr "服務檔 \"%2$s\" 第 %1$d 行太長" + +# guc-file.l:267 +#: fe-connect.c:5750 fe-connect.c:5793 +#, c-format +msgid "syntax error in service file \"%s\", line %d" +msgstr "服務檔 \"%s\" 第 %d 行語法錯誤" + +# guc-file.l:267 +#: fe-connect.c:5761 +#, c-format +msgid "nested service specifications not supported in service file \"%s\", line %d" +msgstr "服務檔 \"%s\" 第 %d 行不支援巢狀服務規格" + +#: fe-connect.c:6500 +#, c-format +msgid "invalid URI propagated to internal parser routine: \"%s\"" +msgstr "無效的 URI 被傳到內部解析器routine: \"%s\"" + +#: fe-connect.c:6577 +#, c-format +msgid "end of string reached when looking for matching \"]\" in IPv6 host address in URI: \"%s\"" +msgstr "尋找 URI 中 IPv6 主機位址的對應 \"]\" 時到達字串結尾: \"%s\"" + +#: fe-connect.c:6584 +#, c-format +msgid "IPv6 host address may not be empty in URI: \"%s\"" +msgstr "URI 中 IPv6 主機位址不得為空: \"%s\"" + +#: fe-connect.c:6599 +#, c-format +msgid "unexpected character \"%c\" at position %d in URI (expected \":\" or \"/\"): \"%s\"" +msgstr "URI 的位置 %2$d 發現非預期字元 \"%1$c\"(預期為 \":\" 或 \"/\"): \"%3$s\"" + +#: fe-connect.c:6728 +#, c-format +msgid "extra key/value separator \"=\" in URI query parameter: \"%s\"" +msgstr "URI 查詢參數有多餘的鍵/值分隔符號 \"=\": \"%s\"" + +#: fe-connect.c:6748 +#, c-format +msgid "missing key/value separator \"=\" in URI query parameter: \"%s\"" +msgstr "URI 查詢參數缺少鍵/值分隔符號 \"=\": \"%s\"" + +# utils/misc/guc.c:3792 +#: fe-connect.c:6800 +#, c-format +msgid "invalid URI query parameter: \"%s\"" +msgstr "無效的 URI 查詢參數: \"%s\"" + +# utils/mb/mbutils.c:326 +#: fe-connect.c:6874 +#, c-format +msgid "invalid percent-encoded token: \"%s\"" +msgstr "無效的百分比編碼標記: \"%s\"" + +#: fe-connect.c:6884 +#, c-format +msgid "forbidden value %%00 in percent-encoded value: \"%s\"" +msgstr "百分比編碼值中禁止使用 %%00: \"%s\"" + +# fe-connect.c:2897 +#: fe-connect.c:7248 +msgid "connection pointer is NULL\n" +msgstr "連線指標是 NULL\n" + +# fe-connect.c:1414 +# fe-connect.c:2544 +# fe-connect.c:2553 +# fe-connect.c:3132 +# fe-lobj.c:556 +# fe-protocol2.c:1007 +# fe-protocol3.c:958 +#: fe-connect.c:7256 fe-exec.c:710 fe-exec.c:970 fe-exec.c:3292 +#: fe-protocol3.c:974 fe-protocol3.c:1007 +msgid "out of memory\n" +msgstr "記憶體不足\n" + +#: fe-connect.c:7547 +#, c-format +msgid "WARNING: password file \"%s\" is not a plain file\n" +msgstr "警告: 密碼檔 \"%s\" 不是純文字檔\n" + +# fe-connect.c:3154 +#: fe-connect.c:7556 +#, c-format +msgid "WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n" +msgstr "警告: 密碼檔 \"%s\" 有群組或全域存取權限,權限應為 u=rw (0600) 或更低的權限\n" + +# utils/init/miscinit.c:792 utils/misc/guc.c:5074 +#: fe-connect.c:7663 +#, c-format +msgid "password retrieved from file \"%s\"" +msgstr "從檔案 \"%s\" 取得密碼" + +# fe-exec.c:1922 +#: fe-exec.c:466 fe-exec.c:3366 +#, c-format +msgid "row number %d is out of range 0..%d" +msgstr "列號 %d 超出範圍 0..%d" + +# commands/vacuum.c:2258 commands/vacuumlazy.c:489 commands/vacuumlazy.c:770 +# nodes/print.c:86 storage/lmgr/deadlock.c:888 tcop/postgres.c:3285 +#: fe-exec.c:528 fe-protocol3.c:1976 +#, c-format +msgid "%s" +msgstr "%s" + +#: fe-exec.c:831 +#, c-format +msgid "write to server failed" +msgstr "寫入伺服器失敗" + +# storage/buffer/localbuf.c:103 +#: fe-exec.c:869 +#, c-format +msgid "no error text available" +msgstr "無錯誤文字可用" + +# fe-exec.c:484 +#: fe-exec.c:958 +msgid "NOTICE" +msgstr "注意" + +#: fe-exec.c:1016 +msgid "PGresult cannot support more than INT_MAX tuples" +msgstr "PGresult 不能支援超過 INT_MAX 個 tuple" + +#: fe-exec.c:1028 +msgid "size_t overflow" +msgstr "size_t 溢位" + +# fe-exec.c:653 +# fe-exec.c:705 +# fe-exec.c:745 +#: fe-exec.c:1444 fe-exec.c:1513 fe-exec.c:1559 +#, c-format +msgid "command string is a null pointer" +msgstr "命令字串是空指標" + +# translator: %s is a SQL statement name +# executor/functions.c:124 executor/spi.c:1396 +#: fe-exec.c:1450 fe-exec.c:2888 +#, c-format +msgid "%s not allowed in pipeline mode" +msgstr "管道模式不允許 %s" + +# utils/adt/timestamp.c:882 +#: fe-exec.c:1518 fe-exec.c:1564 fe-exec.c:1658 +#, c-format +msgid "number of parameters must be between 0 and %d" +msgstr "參數數量必須在 0 和 %d 之間" + +# fe-exec.c:738 +# fe-exec.c:828 +#: fe-exec.c:1554 fe-exec.c:1653 +#, c-format +msgid "statement name is a null pointer" +msgstr "陳述式名稱是空指標" + +# fe-exec.c:859 +#: fe-exec.c:1695 fe-exec.c:3220 +#, c-format +msgid "no connection to the server" +msgstr "未連接到伺服器" + +# fe-exec.c:866 +#: fe-exec.c:1703 fe-exec.c:3228 +#, c-format +msgid "another command is already in progress" +msgstr "另一個命令正在執行中" + +#: fe-exec.c:1733 +#, c-format +msgid "cannot queue commands during COPY" +msgstr "COPY 過程中無法排隊等候命令" + +#: fe-exec.c:1850 +#, c-format +msgid "length must be given for binary parameter" +msgstr "必須提供長度給binary參數" + +# fe-exec.c:1204 +#: fe-exec.c:2171 +#, c-format +msgid "unexpected asyncStatus: %d" +msgstr "非預期的 asyncStatus: %d" + +#: fe-exec.c:2327 +#, c-format +msgid "synchronous command execution functions are not allowed in pipeline mode" +msgstr "管道模式中不允許同步命令執行函數" + +# fe-exec.c:1331 +#: fe-exec.c:2344 +msgid "COPY terminated by new PQexec" +msgstr "COPY 被新的 PQexec 終止" + +# fe-protocol3.c:1000 +#: fe-exec.c:2360 +#, c-format +msgid "PQexec not allowed during COPY BOTH" +msgstr "COPY BOTH 過程中不允許 PQexec" + +# fe-exec.c:1469 +# fe-exec.c:1534 +# fe-exec.c:1619 +# fe-protocol2.c:1153 +# fe-protocol3.c:1115 +#: fe-exec.c:2586 fe-exec.c:2641 fe-exec.c:2709 fe-protocol3.c:1907 +#, c-format +msgid "no COPY in progress" +msgstr "沒有進行中的 COPY" + +# fe-exec.c:1811 +#: fe-exec.c:2895 +#, c-format +msgid "connection in wrong state" +msgstr "連線處於錯誤狀態" + +# fe-lobj.c:674 +#: fe-exec.c:2938 +#, c-format +msgid "cannot enter pipeline mode, connection not idle" +msgstr "無法進入管道模式,連線未處於閒置狀態" + +#: fe-exec.c:2974 fe-exec.c:2995 +#, c-format +msgid "cannot exit pipeline mode with uncollected results" +msgstr "無法退出管道模式,尚有未收集的結果" + +#: fe-exec.c:2978 +#, c-format +msgid "cannot exit pipeline mode while busy" +msgstr "忙碌時無法退出管道模式" + +#: fe-exec.c:2989 +#, c-format +msgid "cannot exit pipeline mode while in COPY" +msgstr "進行 COPY 時無法退出管道模式" + +#: fe-exec.c:3154 +#, c-format +msgid "cannot send pipeline when not in pipeline mode" +msgstr "不在管道模式下無法傳送管道" + +# fe-exec.c:1842 +#: fe-exec.c:3255 +msgid "invalid ExecStatusType code" +msgstr "無效的 ExecStatusType 碼" + +# utils/adt/float.c:1508 utils/adt/float.c:1538 +#: fe-exec.c:3282 +msgid "PGresult is not an error result\n" +msgstr "PGresult 不是錯誤結果\n" + +# fe-exec.c:1906 +# fe-exec.c:1929 +#: fe-exec.c:3350 fe-exec.c:3373 +#, c-format +msgid "column number %d is out of range 0..%d" +msgstr "欄號 %d 超出範圍 0..%d" + +# fe-exec.c:1922 +#: fe-exec.c:3388 +#, c-format +msgid "parameter number %d is out of range 0..%d" +msgstr "參數編號 %d 超出範圍 0..%d" + +# fe-exec.c:2204 +#: fe-exec.c:3699 +#, c-format +msgid "could not interpret result from server: %s" +msgstr "無法解釋來自伺服器的結果: %s" + +# postmaster/postmaster.c:1256 postmaster/postmaster.c:1287 +#: fe-exec.c:3964 fe-exec.c:4054 +#, c-format +msgid "incomplete multibyte character" +msgstr "不完整的多位元組字元" + +#: fe-gssapi-common.c:122 +msgid "GSSAPI name import error" +msgstr "GSSAPI 名稱匯入錯誤" + +# fe-lobj.c:646 +#: fe-lobj.c:144 fe-lobj.c:207 fe-lobj.c:397 fe-lobj.c:487 fe-lobj.c:560 +#: fe-lobj.c:956 fe-lobj.c:963 fe-lobj.c:970 fe-lobj.c:977 fe-lobj.c:984 +#: fe-lobj.c:991 fe-lobj.c:998 fe-lobj.c:1005 +#, c-format +msgid "cannot determine OID of function %s" +msgstr "無法確定函數 %s 的 OID" + +#: fe-lobj.c:160 +#, c-format +msgid "argument of lo_truncate exceeds integer range" +msgstr "lo_truncate 的參數超出整數範圍" + +#: fe-lobj.c:262 +#, c-format +msgid "argument of lo_read exceeds integer range" +msgstr "lo_read 的參數超出整數範圍" + +#: fe-lobj.c:313 +#, c-format +msgid "argument of lo_write exceeds integer range" +msgstr "lo_write 的參數超出整數範圍" + +# fe-lobj.c:410 +# fe-lobj.c:495 +#: fe-lobj.c:669 fe-lobj.c:780 +#, c-format +msgid "could not open file \"%s\": %s" +msgstr "無法開啟檔案 \"%s\":%s" + +# utils/init/miscinit.c:792 utils/misc/guc.c:5074 +#: fe-lobj.c:725 +#, c-format +msgid "could not read from file \"%s\": %s" +msgstr "無法從檔案 %s 讀取: %s" + +# access/transam/xlog.c:1555 access/transam/xlog.c:1679 +# access/transam/xlog.c:2964 access/transam/xlog.c:3002 commands/copy.c:1117 +# commands/tablespace.c:668 commands/tablespace.c:674 +# postmaster/postmaster.c:3430 utils/init/miscinit.c:832 +# utils/init/miscinit.c:841 utils/misc/guc.c:4934 utils/misc/guc.c:4998 +#: fe-lobj.c:801 fe-lobj.c:824 +#, c-format +msgid "could not write to file \"%s\": %s" +msgstr "無法寫入檔案 \"%s\": %s" + +# fe-lobj.c:601 +#: fe-lobj.c:908 +#, c-format +msgid "query to initialize large object functions did not return data" +msgstr "初始化大物件函數的查詢沒有回傳資料" + +# fe-misc.c:228 +#: fe-misc.c:240 +#, c-format +msgid "integer of size %lu not supported by pqGetInt" +msgstr "pqGetInt 不支援大小為 %lu 的整數" + +# fe-misc.c:264 +#: fe-misc.c:273 +#, c-format +msgid "integer of size %lu not supported by pqPutInt" +msgstr "pqPutInt 不支援大小為 %lu 的整數" + +# fe-misc.c:544 +# fe-misc.c:748 +#: fe-misc.c:573 +#, c-format +msgid "connection not open" +msgstr "連線未開啟" + +# fe-misc.c:718 +# fe-misc.c:786 +#: fe-misc.c:751 fe-secure-openssl.c:215 fe-secure-openssl.c:315 +#: fe-secure.c:257 fe-secure.c:419 +#, c-format +msgid "" +"server closed the connection unexpectedly\n" +"\tThis probably means the server terminated abnormally\n" +"\tbefore or while processing the request." +msgstr "" +"伺服器意外關閉連線\n" +"\t這可能表示伺服器在處理請求之前或期間異常中止。" + +# fe-misc.c:544 +# fe-misc.c:748 +#: fe-misc.c:818 +msgid "connection not open\n" +msgstr "連線未開啟\n" + +# fe-misc.c:923 +#: fe-misc.c:1003 +#, c-format +msgid "timeout expired" +msgstr "逾時過期" + +# utils/adt/encode.c:307 +#: fe-misc.c:1047 +#, c-format +msgid "invalid socket" +msgstr "無效的 socket" + +# fe-misc.c:991 +#: fe-misc.c:1069 +#, c-format +msgid "%s() failed: %s" +msgstr "%s() 失敗: %s" + +# fe-protocol2.c:423 +# fe-protocol3.c:183 +#: fe-protocol3.c:182 +#, c-format +msgid "message type 0x%02x arrived from server while idle" +msgstr "閒置時收到伺服器送來類型為 0x%02x 的訊息" + +# fe-protocol2.c:517 +#: fe-protocol3.c:385 +#, c-format +msgid "server sent data (\"D\" message) without prior row description (\"T\" message)" +msgstr "伺服器在先前未傳送列描述(\"T\" 訊息)的情況下傳送資料(\"D\" 訊息)" + +# fe-protocol2.c:548 +# fe-protocol3.c:344 +#: fe-protocol3.c:427 +#, c-format +msgid "unexpected response from server; first received character was \"%c\"" +msgstr "非預期的伺服器回應,第一個收到的字元是 \"%c\"" + +# fe-protocol3.c:365 +#: fe-protocol3.c:450 +#, c-format +msgid "message contents do not agree with length in message type \"%c\"" +msgstr "訊息內容與訊息類型 \"%c\" 中的長度不一致" + +# fe-protocol3.c:386 +#: fe-protocol3.c:468 +#, c-format +msgid "lost synchronization with server: got message type \"%c\", length %d" +msgstr "與伺服器失去同步: 收到訊息類型 \"%c\",長度 %d" + +# libpq/pqformat.c:591 libpq/pqformat.c:609 libpq/pqformat.c:630 +# utils/adt/arrayfuncs.c:1277 utils/adt/rowtypes.c:523 +#: fe-protocol3.c:520 fe-protocol3.c:560 +msgid "insufficient data in \"T\" message" +msgstr "\"T\" 訊息中的資料不足" + +# fe-protocol2.c:760 +# fe-protocol3.c:577 +#: fe-protocol3.c:631 fe-protocol3.c:837 +msgid "out of memory for query result" +msgstr "查詢結果記憶體不足" + +# libpq/pqformat.c:591 libpq/pqformat.c:609 libpq/pqformat.c:630 +# utils/adt/arrayfuncs.c:1277 utils/adt/rowtypes.c:523 +#: fe-protocol3.c:700 +msgid "insufficient data in \"t\" message" +msgstr "\"t\" 訊息中的資料不足" + +# libpq/pqformat.c:591 libpq/pqformat.c:609 libpq/pqformat.c:630 +# utils/adt/arrayfuncs.c:1277 utils/adt/rowtypes.c:523 +#: fe-protocol3.c:759 fe-protocol3.c:791 fe-protocol3.c:809 +msgid "insufficient data in \"D\" message" +msgstr "\"D\" 訊息中的資料不足" + +# fe-protocol3.c:522 +#: fe-protocol3.c:765 +msgid "unexpected field count in \"D\" message" +msgstr "\"D\" 訊息的欄位數與預期不同" + +#: fe-protocol3.c:1020 +msgid "no error message available\n" +msgstr "無法提供錯誤訊息\n" + +# translator: %s represents a digit string +# fe-protocol3.c:651 +# fe-protocol3.c:659 +#. translator: %s represents a digit string +#: fe-protocol3.c:1068 fe-protocol3.c:1087 +#, c-format +msgid " at character %s" +msgstr " 於字元 %s" + +# fe-protocol3.c:668 +#: fe-protocol3.c:1100 +#, c-format +msgid "DETAIL: %s\n" +msgstr "詳細資料: %s\n" + +# fe-protocol3.c:671 +#: fe-protocol3.c:1103 +#, c-format +msgid "HINT: %s\n" +msgstr "提示: %s\n" + +# fe-protocol3.c:674 +#: fe-protocol3.c:1106 +#, c-format +msgid "QUERY: %s\n" +msgstr "查詢: %s\n" + +# fe-protocol3.c:677 +#: fe-protocol3.c:1113 +#, c-format +msgid "CONTEXT: %s\n" +msgstr "CONTEXT: %s\n" + +# fe-protocol3.c:677 +#: fe-protocol3.c:1122 +#, c-format +#| msgid "CONTEXT: %s\n" +msgid "SCHEMA NAME: %s\n" +msgstr "SCHEMA 名稱: %s\n" + +# utils/error/elog.c:1555 +#: fe-protocol3.c:1126 +#, c-format +#| msgid "STATEMENT: %s" +msgid "TABLE NAME: %s\n" +msgstr "資料表名稱: %s\n" + +# fe-protocol3.c:677 +#: fe-protocol3.c:1130 +#, c-format +msgid "COLUMN NAME: %s\n" +msgstr "欄位名稱: %s\n" + +# utils/error/elog.c:1555 +#: fe-protocol3.c:1134 +#, c-format +msgid "DATATYPE NAME: %s\n" +msgstr "資料型別名稱: %s\n" + +# fe-protocol3.c:677 +#: fe-protocol3.c:1138 +#, c-format +msgid "CONSTRAINT NAME: %s\n" +msgstr "約束名稱: %s\n" + +# fe-protocol3.c:689 +#: fe-protocol3.c:1150 +msgid "LOCATION: " +msgstr "位置: " + +# fe-protocol3.c:691 +#: fe-protocol3.c:1152 +#, c-format +msgid "%s, " +msgstr "%s, " + +# fe-protocol3.c:693 +#: fe-protocol3.c:1154 +#, c-format +msgid "%s:%s" +msgstr "%s:%s" + +#: fe-protocol3.c:1349 +#, c-format +msgid "LINE %d: " +msgstr "行 %d: " + +# postmaster/postmaster.c:1349 +#: fe-protocol3.c:1423 +#, c-format +msgid "protocol version not supported by server: client uses %u.%u, server supports up to %u.%u" +msgstr "伺服器不支援的通訊協定版本: 客戶端使用 %u.%u,伺服器支援最高到 %u.%u" + +# catalog/pg_proc.c:487 +#: fe-protocol3.c:1429 +#, c-format +msgid "protocol extension not supported by server: %s" +msgid_plural "protocol extensions not supported by server: %s" +msgstr[0] "伺服器不支援的通訊協定擴展: %s" + +# libpq/pqformat.c:671 +#: fe-protocol3.c:1437 +#, c-format +msgid "invalid %s message" +msgstr "無效的 %s 訊息" + +# fe-protocol3.c:1000 +#: fe-protocol3.c:1802 +#, c-format +msgid "PQgetline: not doing text COPY OUT" +msgstr "PQgetline: 不執行文字 COPY OUT" + +#: fe-protocol3.c:2176 +#, c-format +msgid "protocol error: no function result" +msgstr "通訊協定錯誤: 無函數結果" + +# fe-protocol2.c:1343 +# fe-protocol2.c:1375 +# fe-protocol3.c:1387 +#: fe-protocol3.c:2187 +#, c-format +msgid "protocol error: id=0x%x" +msgstr "通訊協定錯誤: ID=0x%x" + +#: fe-secure-common.c:123 +#, c-format +msgid "SSL certificate's name contains embedded null" +msgstr "SSL 憑證的名稱包含嵌入的空字符" + +#: fe-secure-common.c:228 +#, c-format +msgid "certificate contains IP address with invalid length %zu" +msgstr "憑證包含具有無效長度 %zu 的IP位址" + +# libpq/be-secure.c:659 +#: fe-secure-common.c:237 +#, c-format +msgid "could not convert certificate's IP address to string: %s" +msgstr "無法將憑證的IP位址轉成字串: %s" + +# commands/aggregatecmds.c:111 +#: fe-secure-common.c:269 +#, c-format +msgid "host name must be specified for a verified SSL connection" +msgstr "必須為已驗證的SSL連線指定主機名稱" + +# fe-secure.c:580 +#: fe-secure-common.c:286 +#, c-format +msgid "server certificate for \"%s\" (and %d other name) does not match host name \"%s\"" +msgid_plural "server certificate for \"%s\" (and %d other names) does not match host name \"%s\"" +msgstr[0] "伺服器憑證的名稱 \"%s\"(以及其他 %d 個名稱)與主機名稱 \"%s\" 不一致" + +# fe-secure.c:580 +#: fe-secure-common.c:294 +#, c-format +msgid "server certificate for \"%s\" does not match host name \"%s\"" +msgstr "伺服器憑證的名稱 \"%s\" 與主機名稱 \"%s\" 不一致" + +# fe-misc.c:610 +# fe-misc.c:701 +#: fe-secure-common.c:299 +#, c-format +msgid "could not get server's host name from server certificate" +msgstr "無法從伺服器憑證取得伺服器的主機名稱" + +#: fe-secure-gssapi.c:201 +msgid "GSSAPI wrap error" +msgstr "GSSAPI 封裝錯誤" + +#: fe-secure-gssapi.c:208 +#, c-format +msgid "outgoing GSSAPI message would not use confidentiality" +msgstr "傳出的 GSSAPI 訊息將不使用機密性" + +#: fe-secure-gssapi.c:215 +#, c-format +msgid "client tried to send oversize GSSAPI packet (%zu > %zu)" +msgstr "客戶端嘗試發送過大的 GSSAPI 封包(%zu > %zu)" + +#: fe-secure-gssapi.c:351 fe-secure-gssapi.c:593 +#, c-format +msgid "oversize GSSAPI packet sent by the server (%zu > %zu)" +msgstr "伺服器發送的 GSSAPI 封包過大(%zu > %zu)" + +#: fe-secure-gssapi.c:390 +msgid "GSSAPI unwrap error" +msgstr "GSSAPI 解封錯誤" + +#: fe-secure-gssapi.c:399 +#, c-format +msgid "incoming GSSAPI message did not use confidentiality" +msgstr "傳入的 GSSAPI 訊息未使用機密性" + +# libpq/be-secure.c:649 +#: fe-secure-gssapi.c:656 +msgid "could not initiate GSSAPI security context" +msgstr "無法初始化 SSPI 安全性 context" + +#: fe-secure-gssapi.c:685 +msgid "GSSAPI size check error" +msgstr "GSSAPI 大小檢查錯誤" + +#: fe-secure-gssapi.c:696 +msgid "GSSAPI context establishment error" +msgstr "GSSAPI 建立 context 錯誤" + +# fe-secure.c:330 +# fe-secure.c:415 +# fe-secure.c:1038 +#: fe-secure-openssl.c:219 fe-secure-openssl.c:319 fe-secure-openssl.c:1531 +#, c-format +msgid "SSL SYSCALL error: %s" +msgstr "SSL SYSCALL 錯誤: %s" + +# libpq/be-secure.c:286 libpq/be-secure.c:379 +#: fe-secure-openssl.c:225 fe-secure-openssl.c:325 fe-secure-openssl.c:1534 +#, c-format +msgid "SSL SYSCALL error: EOF detected" +msgstr "SSL SYSCALL 錯誤: 偵測到 EOF" + +# libpq/be-secure.c:294 libpq/be-secure.c:387 +#: fe-secure-openssl.c:235 fe-secure-openssl.c:335 fe-secure-openssl.c:1542 +#, c-format +msgid "SSL error: %s" +msgstr "SSL 錯誤: %s" + +#: fe-secure-openssl.c:249 fe-secure-openssl.c:349 +#, c-format +msgid "SSL connection has been closed unexpectedly" +msgstr "SSL 連線意外關閉" + +# libpq/be-secure.c:303 libpq/be-secure.c:396 +#: fe-secure-openssl.c:254 fe-secure-openssl.c:354 fe-secure-openssl.c:1589 +#, c-format +msgid "unrecognized SSL error code: %d" +msgstr "無法識別的 SSL 錯誤碼: %d" + +# libpq/be-secure.c:659 +#: fe-secure-openssl.c:397 +#, c-format +msgid "could not determine server certificate signature algorithm" +msgstr "無法確定伺服器憑證的簽名演算法" + +#: fe-secure-openssl.c:417 +#, c-format +msgid "could not find digest for NID %s" +msgstr "找不到 NID %s 的摘要" + +# libpq/hba.c:1472 libpq/hba.c:1503 libpq/hba.c:1571 +#: fe-secure-openssl.c:426 +#, c-format +msgid "could not generate peer certificate hash" +msgstr "無法生成對等憑證的雜湊值" + +#: fe-secure-openssl.c:509 +#, c-format +msgid "SSL certificate's name entry is missing" +msgstr "SSL 憑證缺少名稱項目" + +#: fe-secure-openssl.c:543 +#, c-format +msgid "SSL certificate's address entry is missing" +msgstr "SSL 憑證缺少位址項目" + +# libpq/be-secure.c:649 +#: fe-secure-openssl.c:960 +#, c-format +msgid "could not create SSL context: %s" +msgstr "無法建立 SSL context: %s" + +# utils/adt/formatting.c:2044 +#: fe-secure-openssl.c:1002 +#, c-format +msgid "invalid value \"%s\" for minimum SSL protocol version" +msgstr "無效的最小 SSL 通訊協定版本值 \"%s\"" + +# port/win32/security.c:39 +#: fe-secure-openssl.c:1012 +#, c-format +msgid "could not set minimum SSL protocol version: %s" +msgstr "無法設定最小 SSL 通訊協定版本: %s" + +# utils/adt/formatting.c:2044 +#: fe-secure-openssl.c:1028 +#, c-format +msgid "invalid value \"%s\" for maximum SSL protocol version" +msgstr "無效的最大 SSL 通訊協定版本值 \"%s\"" + +# port/win32/security.c:39 +#: fe-secure-openssl.c:1038 +#, c-format +msgid "could not set maximum SSL protocol version: %s" +msgstr "無法設定最大 SSL 通訊協定版本: %s" + +# libpq/be-secure.c:714 +#: fe-secure-openssl.c:1076 +#, c-format +msgid "could not load system root certificate paths: %s" +msgstr "無法載入系統根憑證路徑: %s" + +# fe-secure.c:977 +#: fe-secure-openssl.c:1093 +#, c-format +msgid "could not read root certificate file \"%s\": %s" +msgstr "無法讀取根憑證檔案 \"%s\": %s" + +#: fe-secure-openssl.c:1145 +#, c-format +msgid "" +"could not get home directory to locate root certificate file\n" +"Either provide the file, use the system's trusted roots with sslrootcert=system, or change sslmode to disable server certificate verification." +msgstr "" +"無法取得家目錄以找到根憑證檔\n" +"可以選擇提供檔案、用 sslrootcert=system 使用系統的信任根憑證,或將 sslmode 改為停用伺服器憑證驗證。" + +#: fe-secure-openssl.c:1148 +#, c-format +msgid "" +"root certificate file \"%s\" does not exist\n" +"Either provide the file, use the system's trusted roots with sslrootcert=system, or change sslmode to disable server certificate verification." +msgstr "" +"根憑證檔 \"%s\" 不存在\n" +"可以選擇提供檔案、用 sslrootcert=system 使用系統的信任根憑證,或將 sslmode 改為停用伺服器憑證驗證。" + +# fe-secure.c:775 +#: fe-secure-openssl.c:1183 +#, c-format +msgid "could not open certificate file \"%s\": %s" +msgstr "無法開啟憑證檔 \"%s\": %s" + +# fe-secure.c:784 +#: fe-secure-openssl.c:1201 +#, c-format +msgid "could not read certificate file \"%s\": %s" +msgstr "無法讀取憑證檔 \"%s\": %s" + +# fe-secure.c:264 +#: fe-secure-openssl.c:1225 +#, c-format +msgid "could not establish SSL connection: %s" +msgstr "無法建立 SSL 連線: %s" + +# libpq/be-secure.c:807 +#: fe-secure-openssl.c:1257 +#, c-format +msgid "could not set SSL Server Name Indication (SNI): %s" +msgstr "無法設定 SSL Server Name Indication (SNI): %s" + +# fe-lobj.c:410 +# fe-lobj.c:495 +#: fe-secure-openssl.c:1300 +#, c-format +msgid "could not load SSL engine \"%s\": %s" +msgstr "無法載入 SSL 引擎 \"%s\": %s" + +# libpq/be-secure.c:789 +#: fe-secure-openssl.c:1311 +#, c-format +msgid "could not initialize SSL engine \"%s\": %s" +msgstr "無法初始化 SSL 引擎 \"%s\": %s" + +# fe-secure.c:833 +#: fe-secure-openssl.c:1326 +#, c-format +msgid "could not read private SSL key \"%s\" from engine \"%s\": %s" +msgstr "無法從引擎 \"%2$s\" 讀取私有 SSL 金鑰 \"%1$s\": %3$s" + +# fe-secure.c:833 +#: fe-secure-openssl.c:1339 +#, c-format +msgid "could not load private SSL key \"%s\" from engine \"%s\": %s" +msgstr "無法從引擎 \"%2$s\" 載入私有 SSL 金鑰 \"%1$s\": %3$s" + +# fe-secure.c:798 +#: fe-secure-openssl.c:1376 +#, c-format +msgid "certificate present, but not private key file \"%s\"" +msgstr "憑證存在,但沒有私鑰檔 \"%s\"" + +# libpq/be-secure.c:666 +#: fe-secure-openssl.c:1379 +#, c-format +msgid "could not stat private key file \"%s\": %m" +msgstr "無法取得私鑰檔 \"%s\" 的狀態: %m" + +#: fe-secure-openssl.c:1387 +#, c-format +msgid "private key file \"%s\" is not a regular file" +msgstr "私鑰檔 \"%s\" 不是一般檔案" + +# fe-connect.c:3154 +#: fe-secure-openssl.c:1420 +#, c-format +msgid "private key file \"%s\" has group or world access; file must have permissions u=rw (0600) or less if owned by the current user, or permissions u=rw,g=r (0640) or less if owned by root" +msgstr "私鑰檔 \"%s\" 有群組或全域存取權限,如果檔案由目前使用者擁有,權限應為 u=rw (0600) 或更低的權限,如果由 root 擁有,權限應為 u=rw,g=r (0640) 或更低的權限" + +# libpq/be-secure.c:689 +#: fe-secure-openssl.c:1444 +#, c-format +msgid "could not load private key file \"%s\": %s" +msgstr "無法載入私鑰檔\"%s\": %s" + +# fe-secure.c:848 +#: fe-secure-openssl.c:1460 +#, c-format +msgid "certificate does not match private key file \"%s\": %s" +msgstr "憑證與私鑰檔 \"%s\" 不一致: %s" + +# libpq/be-secure.c:694 +#: fe-secure-openssl.c:1528 +#, c-format +msgid "SSL error: certificate verify failed: %s" +msgstr "SSL 錯誤: 憑證驗證失敗: %s" + +#: fe-secure-openssl.c:1573 +#, c-format +msgid "This may indicate that the server does not support any SSL protocol version between %s and %s." +msgstr "這可能表示伺服器不支援介於 %s 和 %s 之間的任何 SSL 協定版本。" + +# fe-secure.c:1093 +#: fe-secure-openssl.c:1606 +#, c-format +msgid "certificate could not be obtained: %s" +msgstr "無法取得憑證: %s" + +# libpq/be-secure.c:303 libpq/be-secure.c:396 +#: fe-secure-openssl.c:1711 +#, c-format +msgid "no SSL error reported" +msgstr "未回報 SSL 錯誤" + +# libpq/be-secure.c:294 libpq/be-secure.c:387 +#: fe-secure-openssl.c:1720 +#, c-format +msgid "SSL error code %lu" +msgstr "SSL 錯誤碼 %lu" + +#: fe-secure-openssl.c:1986 +#, c-format +msgid "WARNING: sslpassword truncated\n" +msgstr "警告: sslpassword 被截斷\n" + +# fe-misc.c:610 +# fe-misc.c:701 +#: fe-secure.c:263 +#, c-format +msgid "could not receive data from server: %s" +msgstr "無法從伺服器接收資料: %s" + +# fe-misc.c:803 +#: fe-secure.c:434 +#, c-format +msgid "could not send data to server: %s" +msgstr "無法傳送資料至伺服器: %s" + +# libpq/be-secure.c:303 libpq/be-secure.c:396 +#: win32.c:310 +#, c-format +msgid "unrecognized socket error: 0x%08X/%d" +msgstr "無法識別的 socket 錯誤: 0x%08X/%d" + +# fe-exec.c:1339 +#~ msgid "COPY IN state must be terminated first\n" +#~ msgstr "必須先結束 COPY IN 狀態\n" + +# fe-exec.c:1359 +#~ msgid "COPY OUT state must be terminated first\n" +#~ msgstr "必須先結束 COPY OUT 狀態\n" + +# fe-auth.c:411 +# fe-auth.c:415 +#, c-format +#~ msgid "Kerberos 5 authentication rejected: %*s\n" +#~ msgstr "kerberos 5 認證被拒絕: %*s\n" + +#, c-format +#~ msgid "PGEventProc \"%s\" failed during PGEVT_CONNRESET event\n" +#~ msgstr "PGEVT_CONNRESET 事件期間 PGEventProc \"%s\" 失敗\n" + +#, c-format +#~ msgid "PGEventProc \"%s\" failed during PGEVT_RESULTCREATE event\n" +#~ msgstr "PGEVT_RESULTCREATE 事件期間 PGEventProc \"%s\" 失敗\n" + +# fe-auth.c:508 +#~ msgid "SCM_CRED authentication method not supported\n" +#~ msgstr "不支援 SCM_CRED 驗證\n" + +# fe-secure.c:335 +# fe-secure.c:420 +# fe-secure.c:1042 +#~ msgid "SSL SYSCALL error: EOF detected\n" +#~ msgstr "SSL SYSCALL 錯誤: 發現EOF\n" + +#~ msgid "SSL certificate's common name contains embedded null\n" +#~ msgstr "SSL 憑證的一般名稱包含內嵌的 Null\n" + +# fe-secure.c:347 +# fe-secure.c:431 +# fe-secure.c:1051 +#, c-format +#~ msgid "SSL error: %s\n" +#~ msgstr "SSL 錯誤: %s\n" + +# fe-secure.c:775 +#, c-format +#~ msgid "SSL library does not support CRL certificates (file \"%s\")\n" +#~ msgstr "SSL 程式庫不支援 CRL 憑證 (檔案 \"%s\")\n" + +#, c-format +#~ msgid "WSAIoctl(SIO_KEEPALIVE_VALS) failed: %ui\n" +#~ msgstr "WSAIoctl(SIO_KEEPALIVE_VALS) 失敗: %ui\n" + +# fe-lobj.c:653 +#~ msgid "cannot determine OID of function lo_creat\n" +#~ msgstr "無法判斷函式 lo_creat 的 OID\n" + +# fe-lobj.c:653 +#~ msgid "cannot determine OID of function lo_create\n" +#~ msgstr "無法判斷函式 lo_create 的 OID\n" + +# fe-lobj.c:667 +#~ msgid "cannot determine OID of function lo_lseek\n" +#~ msgstr "無法判斷函式 lo_lseek 的 OID\n" + +# fe-lobj.c:639 +#~ msgid "cannot determine OID of function lo_open\n" +#~ msgstr "無法判斷函式 lo_open 的 OID\n" + +# fe-lobj.c:653 +#~ msgid "cannot determine OID of function lo_truncate\n" +#~ msgstr "無法判斷函式 lo_truncate 的 OID\n" + +# fe-lobj.c:660 +#~ msgid "cannot determine OID of function lo_unlink\n" +#~ msgstr "無法判斷函式 lo_unlink 的 OID\n" + +# fe-lobj.c:681 +#~ msgid "cannot determine OID of function loread\n" +#~ msgstr "無法判斷函式 loread 的 OID\n" + +# fe-lobj.c:688 +#~ msgid "cannot determine OID of function lowrite\n" +#~ msgstr "無法判斷函式 lowrite 的 OID\n" + +# fe-secure.c:932 +#, c-format +#~ msgid "could not create SSL context: %s\n" +#~ msgstr "無法建立 SSL context: %s\n" + +# libpq/pqcomm.c:702 +#, c-format +#~ msgid "could not get effective UID from peer credentials: %s\n" +#~ msgstr "無法從對點認證取得有效 UID: %s\n" + +# libpq/be-secure.c:714 +#~ msgid "could not get home directory to locate client certificate files" +#~ msgstr "無法取得用來找出用戶端憑證檔的主目錄" + +# libpq/be-secure.c:714 +#~ msgid "could not get home directory to locate service definition file" +#~ msgstr "無法取得用來尋找服務定義檔的家目錄" + +# libpq/be-secure.c:689 +#, c-format +#~ msgid "could not load private key file \"%s\": %s\n" +#~ msgstr "無法載入私鑰檔 \"%s\": %s\n" + +# fe-lobj.c:410 +# fe-lobj.c:495 +#, c-format +#~ msgid "could not open file \"%s\": %s\n" +#~ msgstr "無法開啟檔案 \"%s\": %s\n" + +# fe-secure.c:815 +#~ msgid "could not open private key file \"%s\": %s\n" +#~ msgstr "無法開啟私鑰檔\"%s\":%s\n" + +# fe-secure.c:833 +#~ msgid "could not read private key file \"%s\": %s\n" +#~ msgstr "無法讀取私鑰檔\"%s\":%s\n" + +# fe-auth.c:441 +#, c-format +#~ msgid "could not restore non-blocking mode on socket: %s\n" +#~ msgstr "無法將 socket 還原為非阻擋模式: %s\n" + +# fe-auth.c:394 +#, c-format +#~ msgid "could not set socket to blocking mode: %s\n" +#~ msgstr "無法將 socket 設為阻擋模式: %s\n" + +# fe-connect.c:946 +#, c-format +#~ msgid "could not translate host name \"%s\" to address: %s\n" +#~ msgstr "無法將主機名稱 \"%s\" 轉換成位址: %s\n" + +# fe-secure.c:504 +#~ msgid "error querying socket: %s\n" +#~ msgstr "詢問socket發生錯誤:%s\n" + +# fe-lobj.c:447 +#~ msgid "error while reading file \"%s\"\n" +#~ msgstr "讀取檔案 \"%s\" 時發生錯誤\n" + +# fe-auth.c:764 +#~ msgid "fe_getauthname: invalid authentication system: %d\n" +#~ msgstr "fe_getauthname:無效的認證系統:%d\n" + +# fe-exec.c:753 +# fe-exec.c:902 +# fe-exec.c:1577 +#~ msgid "function requires at least protocol version 3.0\n" +#~ msgstr "函式需要 3.0 版以上的協定\n" + +# fe-auth.c:692 +#~ msgid "invalid authentication service name \"%s\", ignored\n" +#~ msgstr "忽略非法的認證服務名稱\"%s\"\n" + +# fe-protocol2.c:91 +#, c-format +#~ msgid "invalid setenv state %c, probably indicative of memory corruption\n" +#~ msgstr "無效的 setenv 狀態 %c,可能是記憶體中的資料被破壞\n" + +# fe-connect.c:452 +#, c-format +#~ msgid "invalid sslmode value: \"%s\"\n" +#~ msgstr "無效的 sslmode: \"%s\"\n" + +# fe-protocol2.c:333 +#, c-format +#~ msgid "invalid state %c, probably indicative of memory corruption\n" +#~ msgstr "無效的狀態 %c,可能是記憶體中的資料被破壞\n" + +# libpq/hba.c:1481 libpq/hba.c:1512 libpq/hba.c:1582 +#, c-format +#~ msgid "local user with ID %d does not exist\n" +#~ msgstr "本機使用者 ID %d 不存在\n" + +# fe-protocol2.c:1208 +#~ msgid "lost synchronization with server, resetting connection" +#~ msgstr "無法與伺服器協調,重置連線" + +# fe-secure.c:824 +#~ msgid "private key file \"%s\" changed during execution\n" +#~ msgstr "私鑰檔\"%s\"在執行過程中被改變\n" + +# fe-misc.c:991 +#, c-format +#~ msgid "select() failed: %s\n" +#~ msgstr "select()失敗: %s\n" + +# fe-protocol2.c:533 +#~ msgid "server sent binary data (\"B\" message) without prior row description (\"T\" message)" +#~ msgstr "伺服器傳送二元資料(\"B\" 訊息)而未提供資料行描述(\"T\" 訊息)" + +# fe-protocol3.c:306 +#~ msgid "server sent data (\"D\" message) without prior row description (\"T\" message)\n" +#~ msgstr "伺服器傳送資料(\"D\" 訊息)而未提供資料行描述(\"T\" 訊息)\n" + +# libpq/pqcomm.c:346 +#, c-format +#~ msgid "setsockopt(SO_KEEPALIVE) failed: %s\n" +#~ msgstr "setsockopt(SO_KEEPALIVE) 失敗: %s\n" + +# libpq/pqcomm.c:346 +#, c-format +#~ msgid "setsockopt(TCP_KEEPALIVE) failed: %s\n" +#~ msgstr "setsockopt(TCP_KEEPALIVE) 失敗: %s\n" + +# libpq/pqcomm.c:360 +#, c-format +#~ msgid "setsockopt(TCP_KEEPCNT) failed: %s\n" +#~ msgstr "setsockopt(TCP_KEEPCNT) 失敗: %s\n" + +# libpq/pqcomm.c:346 +#, c-format +#~ msgid "setsockopt(TCP_KEEPIDLE) failed: %s\n" +#~ msgstr "setsockopt(TCP_KEEPIDLE) 失敗: %s\n" + +# libpq/pqcomm.c:360 +#, c-format +#~ msgid "setsockopt(TCP_KEEPINTVL) failed: %s\n" +#~ msgstr "setsockopt(TCP_KEEPINTVL) 失敗: %s\n" + +# fe-misc.c:968 +#~ msgid "socket not open\n" +#~ msgstr "socket 未開啟\n" + +# fe-protocol2.c:462 +#, c-format +#~ msgid "unexpected character %c following empty query response (\"I\" message)" +#~ msgstr "空的查詢回應(\"I\" 訊息)後跟隨非預期字元 %c" + +# fe-secure.c:357 +# fe-secure.c:441 +# fe-secure.c:1059 +#, c-format +#~ msgid "unrecognized SSL error code: %d\n" +#~ msgstr "無法識別的 SSL 錯誤碼: %d\n" + +# fe-secure.c:551 +#~ msgid "unsupported protocol\n" +#~ msgstr "不被支援的協定\n" + +#~ msgid "verified SSL connections are only supported when connecting to a host name" +#~ msgstr "只有在連線到主機名稱時,才支援經驗證的 SSL 連線" diff --git a/src/interfaces/libpq/pqexpbuffer.c b/src/interfaces/libpq/pqexpbuffer.c new file mode 100644 index 0000000..de7e032 --- /dev/null +++ b/src/interfaces/libpq/pqexpbuffer.c @@ -0,0 +1,412 @@ +/*------------------------------------------------------------------------- + * + * pqexpbuffer.c + * + * PQExpBuffer provides an indefinitely-extensible string data type. + * It can be used to buffer either ordinary C strings (null-terminated text) + * or arbitrary binary data. All storage is allocated with malloc(). + * + * This module is essentially the same as the backend's StringInfo data type, + * but it is intended for use in frontend libpq and client applications. + * Thus, it does not rely on palloc() nor elog(), nor psprintf.c which + * will exit() on error. + * + * It does rely on vsnprintf(); if configure finds that libc doesn't provide + * a usable vsnprintf(), then a copy of our own implementation of it will + * be linked into libpq. + * + * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/interfaces/libpq/pqexpbuffer.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres_fe.h" + +#include <limits.h> + +#include "pqexpbuffer.h" + +#ifdef WIN32 +#include "win32.h" +#endif + + +/* All "broken" PQExpBuffers point to this string. */ +static const char oom_buffer[1] = ""; + +/* Need a char * for unconstify() compatibility */ +static const char *oom_buffer_ptr = oom_buffer; + + +/* + * markPQExpBufferBroken + * + * Put a PQExpBuffer in "broken" state if it isn't already. + */ +static void +markPQExpBufferBroken(PQExpBuffer str) +{ + if (str->data != oom_buffer) + free(str->data); + + /* + * Casting away const here is a bit ugly, but it seems preferable to not + * marking oom_buffer const. We want to do that to encourage the compiler + * to put oom_buffer in read-only storage, so that anyone who tries to + * scribble on a broken PQExpBuffer will get a failure. + */ + str->data = unconstify(char *, oom_buffer_ptr); + str->len = 0; + str->maxlen = 0; +} + +/* + * createPQExpBuffer + * + * Create an empty 'PQExpBufferData' & return a pointer to it. + */ +PQExpBuffer +createPQExpBuffer(void) +{ + PQExpBuffer res; + + res = (PQExpBuffer) malloc(sizeof(PQExpBufferData)); + if (res != NULL) + initPQExpBuffer(res); + + return res; +} + +/* + * initPQExpBuffer + * + * Initialize a PQExpBufferData struct (with previously undefined contents) + * to describe an empty string. + */ +void +initPQExpBuffer(PQExpBuffer str) +{ + str->data = (char *) malloc(INITIAL_EXPBUFFER_SIZE); + if (str->data == NULL) + { + str->data = unconstify(char *, oom_buffer_ptr); /* see comment above */ + str->maxlen = 0; + str->len = 0; + } + else + { + str->maxlen = INITIAL_EXPBUFFER_SIZE; + str->len = 0; + str->data[0] = '\0'; + } +} + +/* + * destroyPQExpBuffer(str); + * + * free()s both the data buffer and the PQExpBufferData. + * This is the inverse of createPQExpBuffer(). + */ +void +destroyPQExpBuffer(PQExpBuffer str) +{ + if (str) + { + termPQExpBuffer(str); + free(str); + } +} + +/* + * termPQExpBuffer(str) + * free()s the data buffer but not the PQExpBufferData itself. + * This is the inverse of initPQExpBuffer(). + */ +void +termPQExpBuffer(PQExpBuffer str) +{ + if (str->data != oom_buffer) + free(str->data); + /* just for luck, make the buffer validly empty. */ + str->data = unconstify(char *, oom_buffer_ptr); /* see comment above */ + str->maxlen = 0; + str->len = 0; +} + +/* + * resetPQExpBuffer + * Reset a PQExpBuffer to empty + * + * Note: if possible, a "broken" PQExpBuffer is returned to normal. + */ +void +resetPQExpBuffer(PQExpBuffer str) +{ + if (str) + { + if (str->data != oom_buffer) + { + str->len = 0; + str->data[0] = '\0'; + } + else + { + /* try to reinitialize to valid state */ + initPQExpBuffer(str); + } + } +} + +/* + * enlargePQExpBuffer + * Make sure there is enough space for 'needed' more bytes in the buffer + * ('needed' does not include the terminating null). + * + * Returns 1 if OK, 0 if failed to enlarge buffer. (In the latter case + * the buffer is left in "broken" state.) + */ +int +enlargePQExpBuffer(PQExpBuffer str, size_t needed) +{ + size_t newlen; + char *newdata; + + if (PQExpBufferBroken(str)) + return 0; /* already failed */ + + /* + * Guard against ridiculous "needed" values, which can occur if we're fed + * bogus data. Without this, we can get an overflow or infinite loop in + * the following. + */ + if (needed >= ((size_t) INT_MAX - str->len)) + { + markPQExpBufferBroken(str); + return 0; + } + + needed += str->len + 1; /* total space required now */ + + /* Because of the above test, we now have needed <= INT_MAX */ + + if (needed <= str->maxlen) + return 1; /* got enough space already */ + + /* + * We don't want to allocate just a little more space with each append; + * for efficiency, double the buffer size each time it overflows. + * Actually, we might need to more than double it if 'needed' is big... + */ + newlen = (str->maxlen > 0) ? (2 * str->maxlen) : 64; + while (needed > newlen) + newlen = 2 * newlen; + + /* + * Clamp to INT_MAX in case we went past it. Note we are assuming here + * that INT_MAX <= UINT_MAX/2, else the above loop could overflow. We + * will still have newlen >= needed. + */ + if (newlen > (size_t) INT_MAX) + newlen = (size_t) INT_MAX; + + newdata = (char *) realloc(str->data, newlen); + if (newdata != NULL) + { + str->data = newdata; + str->maxlen = newlen; + return 1; + } + + markPQExpBufferBroken(str); + return 0; +} + +/* + * printfPQExpBuffer + * Format text data under the control of fmt (an sprintf-like format string) + * and insert it into str. More space is allocated to str if necessary. + * This is a convenience routine that does the same thing as + * resetPQExpBuffer() followed by appendPQExpBuffer(). + */ +void +printfPQExpBuffer(PQExpBuffer str, const char *fmt,...) +{ + int save_errno = errno; + va_list args; + bool done; + + resetPQExpBuffer(str); + + if (PQExpBufferBroken(str)) + return; /* already failed */ + + /* Loop in case we have to retry after enlarging the buffer. */ + do + { + errno = save_errno; + va_start(args, fmt); + done = appendPQExpBufferVA(str, fmt, args); + va_end(args); + } while (!done); +} + +/* + * appendPQExpBuffer + * + * Format text data under the control of fmt (an sprintf-like format string) + * and append it to whatever is already in str. More space is allocated + * to str if necessary. This is sort of like a combination of sprintf and + * strcat. + */ +void +appendPQExpBuffer(PQExpBuffer str, const char *fmt,...) +{ + int save_errno = errno; + va_list args; + bool done; + + if (PQExpBufferBroken(str)) + return; /* already failed */ + + /* Loop in case we have to retry after enlarging the buffer. */ + do + { + errno = save_errno; + va_start(args, fmt); + done = appendPQExpBufferVA(str, fmt, args); + va_end(args); + } while (!done); +} + +/* + * appendPQExpBufferVA + * Shared guts of printfPQExpBuffer/appendPQExpBuffer. + * Attempt to format data and append it to str. Returns true if done + * (either successful or hard failure), false if need to retry. + * + * Caution: callers must be sure to preserve their entry-time errno + * when looping, in case the fmt contains "%m". + */ +bool +appendPQExpBufferVA(PQExpBuffer str, const char *fmt, va_list args) +{ + size_t avail; + size_t needed; + int nprinted; + + /* + * Try to format the given string into the available space; but if there's + * hardly any space, don't bother trying, just enlarge the buffer first. + */ + if (str->maxlen > str->len + 16) + { + avail = str->maxlen - str->len; + + nprinted = vsnprintf(str->data + str->len, avail, fmt, args); + + /* + * If vsnprintf reports an error, fail (we assume this means there's + * something wrong with the format string). + */ + if (unlikely(nprinted < 0)) + { + markPQExpBufferBroken(str); + return true; + } + + if ((size_t) nprinted < avail) + { + /* Success. Note nprinted does not include trailing null. */ + str->len += nprinted; + return true; + } + + /* + * We assume a C99-compliant vsnprintf, so believe its estimate of the + * required space, and add one for the trailing null. (If it's wrong, + * the logic will still work, but we may loop multiple times.) + * + * Choke if the required space would exceed INT_MAX, since str->maxlen + * can't represent more than that. + */ + if (unlikely(nprinted > INT_MAX - 1)) + { + markPQExpBufferBroken(str); + return true; + } + needed = nprinted + 1; + } + else + { + /* + * We have to guess at how much to enlarge, since we're skipping the + * formatting work. Fortunately, because of enlargePQExpBuffer's + * preference for power-of-2 sizes, this number isn't very sensitive; + * the net effect is that we'll double the buffer size before trying + * to run vsnprintf, which seems sensible. + */ + needed = 32; + } + + /* Increase the buffer size and try again. */ + if (!enlargePQExpBuffer(str, needed)) + return true; /* oops, out of memory */ + + return false; +} + +/* + * appendPQExpBufferStr + * Append the given string to a PQExpBuffer, allocating more space + * if necessary. + */ +void +appendPQExpBufferStr(PQExpBuffer str, const char *data) +{ + appendBinaryPQExpBuffer(str, data, strlen(data)); +} + +/* + * appendPQExpBufferChar + * Append a single byte to str. + * Like appendPQExpBuffer(str, "%c", ch) but much faster. + */ +void +appendPQExpBufferChar(PQExpBuffer str, char ch) +{ + /* Make more room if needed */ + if (!enlargePQExpBuffer(str, 1)) + return; + + /* OK, append the character */ + str->data[str->len] = ch; + str->len++; + str->data[str->len] = '\0'; +} + +/* + * appendBinaryPQExpBuffer + * + * Append arbitrary binary data to a PQExpBuffer, allocating more space + * if necessary. + */ +void +appendBinaryPQExpBuffer(PQExpBuffer str, const char *data, size_t datalen) +{ + /* Make more room if needed */ + if (!enlargePQExpBuffer(str, datalen)) + return; + + /* OK, append the data */ + memcpy(str->data + str->len, data, datalen); + str->len += datalen; + + /* + * Keep a trailing null in place, even though it's probably useless for + * binary data... + */ + str->data[str->len] = '\0'; +} diff --git a/src/interfaces/libpq/pqexpbuffer.h b/src/interfaces/libpq/pqexpbuffer.h new file mode 100644 index 0000000..020e94e --- /dev/null +++ b/src/interfaces/libpq/pqexpbuffer.h @@ -0,0 +1,192 @@ +/*------------------------------------------------------------------------- + * + * pqexpbuffer.h + * Declarations/definitions for "PQExpBuffer" functions. + * + * PQExpBuffer provides an indefinitely-extensible string data type. + * It can be used to buffer either ordinary C strings (null-terminated text) + * or arbitrary binary data. All storage is allocated with malloc(). + * + * This module is essentially the same as the backend's StringInfo data type, + * but it is intended for use in frontend libpq and client applications. + * Thus, it does not rely on palloc() nor elog(). + * + * It does rely on vsnprintf(); if configure finds that libc doesn't provide + * a usable vsnprintf(), then a copy of our own implementation of it will + * be linked into libpq. + * + * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/interfaces/libpq/pqexpbuffer.h + * + *------------------------------------------------------------------------- + */ +#ifndef PQEXPBUFFER_H +#define PQEXPBUFFER_H + +/*------------------------- + * PQExpBufferData holds information about an extensible string. + * data is the current buffer for the string (allocated with malloc). + * len is the current string length. There is guaranteed to be + * a terminating '\0' at data[len], although this is not very + * useful when the string holds binary data rather than text. + * maxlen is the allocated size in bytes of 'data', i.e. the maximum + * string size (including the terminating '\0' char) that we can + * currently store in 'data' without having to reallocate + * more space. We must always have maxlen > len. + * + * An exception occurs if we failed to allocate enough memory for the string + * buffer. In that case data points to a statically allocated empty string, + * and len = maxlen = 0. + *------------------------- + */ +typedef struct PQExpBufferData +{ + char *data; + size_t len; + size_t maxlen; +} PQExpBufferData; + +typedef PQExpBufferData *PQExpBuffer; + +/*------------------------ + * Test for a broken (out of memory) PQExpBuffer. + * When a buffer is "broken", all operations except resetting or deleting it + * are no-ops. + *------------------------ + */ +#define PQExpBufferBroken(str) \ + ((str) == NULL || (str)->maxlen == 0) + +/*------------------------ + * Same, but for use when using a static or local PQExpBufferData struct. + * For that, a null-pointer test is useless and may draw compiler warnings. + *------------------------ + */ +#define PQExpBufferDataBroken(buf) \ + ((buf).maxlen == 0) + +/*------------------------ + * Initial size of the data buffer in a PQExpBuffer. + * NB: this must be large enough to hold error messages that might + * be returned by PQrequestCancel(). + *------------------------ + */ +#define INITIAL_EXPBUFFER_SIZE 256 + +/*------------------------ + * There are two ways to create a PQExpBuffer object initially: + * + * PQExpBuffer stringptr = createPQExpBuffer(); + * Both the PQExpBufferData and the data buffer are malloc'd. + * + * PQExpBufferData string; + * initPQExpBuffer(&string); + * The data buffer is malloc'd but the PQExpBufferData is presupplied. + * This is appropriate if the PQExpBufferData is a field of another + * struct. + *------------------------- + */ + +/*------------------------ + * createPQExpBuffer + * Create an empty 'PQExpBufferData' & return a pointer to it. + */ +extern PQExpBuffer createPQExpBuffer(void); + +/*------------------------ + * initPQExpBuffer + * Initialize a PQExpBufferData struct (with previously undefined contents) + * to describe an empty string. + */ +extern void initPQExpBuffer(PQExpBuffer str); + +/*------------------------ + * To destroy a PQExpBuffer, use either: + * + * destroyPQExpBuffer(str); + * free()s both the data buffer and the PQExpBufferData. + * This is the inverse of createPQExpBuffer(). + * + * termPQExpBuffer(str) + * free()s the data buffer but not the PQExpBufferData itself. + * This is the inverse of initPQExpBuffer(). + * + * NOTE: some routines build up a string using PQExpBuffer, and then + * release the PQExpBufferData but return the data string itself to their + * caller. At that point the data string looks like a plain malloc'd + * string. + */ +extern void destroyPQExpBuffer(PQExpBuffer str); +extern void termPQExpBuffer(PQExpBuffer str); + +/*------------------------ + * resetPQExpBuffer + * Reset a PQExpBuffer to empty + * + * Note: if possible, a "broken" PQExpBuffer is returned to normal. + */ +extern void resetPQExpBuffer(PQExpBuffer str); + +/*------------------------ + * enlargePQExpBuffer + * Make sure there is enough space for 'needed' more bytes in the buffer + * ('needed' does not include the terminating null). + * + * Returns 1 if OK, 0 if failed to enlarge buffer. (In the latter case + * the buffer is left in "broken" state.) + */ +extern int enlargePQExpBuffer(PQExpBuffer str, size_t needed); + +/*------------------------ + * printfPQExpBuffer + * Format text data under the control of fmt (an sprintf-like format string) + * and insert it into str. More space is allocated to str if necessary. + * This is a convenience routine that does the same thing as + * resetPQExpBuffer() followed by appendPQExpBuffer(). + */ +extern void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...) pg_attribute_printf(2, 3); + +/*------------------------ + * appendPQExpBuffer + * Format text data under the control of fmt (an sprintf-like format string) + * and append it to whatever is already in str. More space is allocated + * to str if necessary. This is sort of like a combination of sprintf and + * strcat. + */ +extern void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...) pg_attribute_printf(2, 3); + +/*------------------------ + * appendPQExpBufferVA + * Attempt to format data and append it to str. Returns true if done + * (either successful or hard failure), false if need to retry. + * + * Caution: callers must be sure to preserve their entry-time errno + * when looping, in case the fmt contains "%m". + */ +extern bool appendPQExpBufferVA(PQExpBuffer str, const char *fmt, va_list args) pg_attribute_printf(2, 0); + +/*------------------------ + * appendPQExpBufferStr + * Append the given string to a PQExpBuffer, allocating more space + * if necessary. + */ +extern void appendPQExpBufferStr(PQExpBuffer str, const char *data); + +/*------------------------ + * appendPQExpBufferChar + * Append a single byte to str. + * Like appendPQExpBuffer(str, "%c", ch) but much faster. + */ +extern void appendPQExpBufferChar(PQExpBuffer str, char ch); + +/*------------------------ + * appendBinaryPQExpBuffer + * Append arbitrary binary data to a PQExpBuffer, allocating more space + * if necessary. + */ +extern void appendBinaryPQExpBuffer(PQExpBuffer str, + const char *data, size_t datalen); + +#endif /* PQEXPBUFFER_H */ diff --git a/src/interfaces/libpq/pthread-win32.c b/src/interfaces/libpq/pthread-win32.c new file mode 100644 index 0000000..8e65637 --- /dev/null +++ b/src/interfaces/libpq/pthread-win32.c @@ -0,0 +1,60 @@ +/*------------------------------------------------------------------------- +* +* pthread-win32.c +* partial pthread implementation for win32 +* +* Copyright (c) 2004-2023, PostgreSQL Global Development Group +* IDENTIFICATION +* src/interfaces/libpq/pthread-win32.c +* +*------------------------------------------------------------------------- +*/ + +#include "postgres_fe.h" + +#include "pthread-win32.h" + +DWORD +pthread_self(void) +{ + return GetCurrentThreadId(); +} + +void +pthread_setspecific(pthread_key_t key, void *val) +{ +} + +void * +pthread_getspecific(pthread_key_t key) +{ + return NULL; +} + +int +pthread_mutex_init(pthread_mutex_t *mp, void *attr) +{ + *mp = (CRITICAL_SECTION *) malloc(sizeof(CRITICAL_SECTION)); + if (!*mp) + return 1; + InitializeCriticalSection(*mp); + return 0; +} + +int +pthread_mutex_lock(pthread_mutex_t *mp) +{ + if (!*mp) + return 1; + EnterCriticalSection(*mp); + return 0; +} + +int +pthread_mutex_unlock(pthread_mutex_t *mp) +{ + if (!*mp) + return 1; + LeaveCriticalSection(*mp); + return 0; +} diff --git a/src/interfaces/libpq/t/001_uri.pl b/src/interfaces/libpq/t/001_uri.pl new file mode 100644 index 0000000..fd062a9 --- /dev/null +++ b/src/interfaces/libpq/t/001_uri.pl @@ -0,0 +1,269 @@ +# Copyright (c) 2021-2023, PostgreSQL Global Development Group +use strict; +use warnings; + +use PostgreSQL::Test::Utils; +use Test::More; +use IPC::Run; + + +# List of URIs tests. For each test the first element is the input string, the +# second the expected stdout and the third the expected stderr. Optionally, +# additional arguments may specify key/value pairs which will override +# environment variables for the duration of the test. +my @tests = ( + [ + q{postgresql://uri-user:secret@host:12345/db}, + q{user='uri-user' password='secret' dbname='db' host='host' port='12345' (inet)}, + q{}, + ], + [ + q{postgresql://uri-user@host:12345/db}, + q{user='uri-user' dbname='db' host='host' port='12345' (inet)}, q{}, + ], + [ + q{postgresql://uri-user@host/db}, + q{user='uri-user' dbname='db' host='host' (inet)}, q{}, + ], + [ + q{postgresql://host:12345/db}, + q{dbname='db' host='host' port='12345' (inet)}, q{}, + ], + [ q{postgresql://host/db}, q{dbname='db' host='host' (inet)}, q{}, ], + [ + q{postgresql://uri-user@host:12345/}, + q{user='uri-user' host='host' port='12345' (inet)}, + q{}, + ], + [ + q{postgresql://uri-user@host/}, + q{user='uri-user' host='host' (inet)}, + q{}, + ], + [ q{postgresql://uri-user@}, q{user='uri-user' (local)}, q{}, ], + [ q{postgresql://host:12345/}, q{host='host' port='12345' (inet)}, q{}, ], + [ q{postgresql://host:12345}, q{host='host' port='12345' (inet)}, q{}, ], + [ q{postgresql://host/db}, q{dbname='db' host='host' (inet)}, q{}, ], + [ q{postgresql://host/}, q{host='host' (inet)}, q{}, ], + [ q{postgresql://host}, q{host='host' (inet)}, q{}, ], + [ q{postgresql://}, q{(local)}, q{}, ], + [ + q{postgresql://?hostaddr=127.0.0.1}, q{hostaddr='127.0.0.1' (inet)}, + q{}, + ], + [ + q{postgresql://example.com?hostaddr=63.1.2.4}, + q{host='example.com' hostaddr='63.1.2.4' (inet)}, + q{}, + ], + [ q{postgresql://%68ost/}, q{host='host' (inet)}, q{}, ], + [ + q{postgresql://host/db?user=uri-user}, + q{user='uri-user' dbname='db' host='host' (inet)}, + q{}, + ], + [ + q{postgresql://host/db?user=uri-user&port=12345}, + q{user='uri-user' dbname='db' host='host' port='12345' (inet)}, + q{}, + ], + [ + q{postgresql://host/db?u%73er=someotheruser&port=12345}, + q{user='someotheruser' dbname='db' host='host' port='12345' (inet)}, + q{}, + ], + [ + q{postgresql://host/db?u%7aer=someotheruser&port=12345}, q{}, + q{libpq_uri_regress: invalid URI query parameter: "uzer"}, + ], + [ + q{postgresql://host:12345?user=uri-user}, + q{user='uri-user' host='host' port='12345' (inet)}, + q{}, + ], + [ + q{postgresql://host?user=uri-user}, + q{user='uri-user' host='host' (inet)}, + q{}, + ], + [ q{postgresql://host?}, q{host='host' (inet)}, q{}, ], + [ + q{postgresql://[::1]:12345/db}, + q{dbname='db' host='::1' port='12345' (inet)}, + q{}, + ], + [ q{postgresql://[::1]/db}, q{dbname='db' host='::1' (inet)}, q{}, ], + [ + q{postgresql://[2001:db8::1234]/}, q{host='2001:db8::1234' (inet)}, + q{}, + ], + [ + q{postgresql://[200z:db8::1234]/}, q{host='200z:db8::1234' (inet)}, + q{}, + ], + [ q{postgresql://[::1]}, q{host='::1' (inet)}, q{}, ], + [ q{postgres://}, q{(local)}, q{}, ], + [ q{postgres:///}, q{(local)}, q{}, ], + [ q{postgres:///db}, q{dbname='db' (local)}, q{}, ], + [ + q{postgres://uri-user@/db}, q{user='uri-user' dbname='db' (local)}, + q{}, + ], + [ + q{postgres://?host=/path/to/socket/dir}, + q{host='/path/to/socket/dir' (local)}, + q{}, + ], + [ + q{postgresql://host?uzer=}, q{}, + q{libpq_uri_regress: invalid URI query parameter: "uzer"}, + ], + [ + q{postgre://}, + q{}, + q{libpq_uri_regress: missing "=" after "postgre://" in connection info string}, + ], + [ + q{postgres://[::1}, + q{}, + q{libpq_uri_regress: end of string reached when looking for matching "]" in IPv6 host address in URI: "postgres://[::1"}, + ], + [ + q{postgres://[]}, + q{}, + q{libpq_uri_regress: IPv6 host address may not be empty in URI: "postgres://[]"}, + ], + [ + q{postgres://[::1]z}, + q{}, + q{libpq_uri_regress: unexpected character "z" at position 17 in URI (expected ":" or "/"): "postgres://[::1]z"}, + ], + [ + q{postgresql://host?zzz}, + q{}, + q{libpq_uri_regress: missing key/value separator "=" in URI query parameter: "zzz"}, + ], + [ + q{postgresql://host?value1&value2}, + q{}, + q{libpq_uri_regress: missing key/value separator "=" in URI query parameter: "value1"}, + ], + [ + q{postgresql://host?key=key=value}, + q{}, + q{libpq_uri_regress: extra key/value separator "=" in URI query parameter: "key"}, + ], + [ + q{postgres://host?dbname=%XXfoo}, q{}, + q{libpq_uri_regress: invalid percent-encoded token: "%XXfoo"}, + ], + [ + q{postgresql://a%00b}, + q{}, + q{libpq_uri_regress: forbidden value %00 in percent-encoded value: "a%00b"}, + ], + [ + q{postgresql://%zz}, q{}, + q{libpq_uri_regress: invalid percent-encoded token: "%zz"}, + ], + [ + q{postgresql://%1}, q{}, + q{libpq_uri_regress: invalid percent-encoded token: "%1"}, + ], + [ + q{postgresql://%}, q{}, + q{libpq_uri_regress: invalid percent-encoded token: "%"}, + ], + [ q{postgres://@host}, q{host='host' (inet)}, q{}, ], + [ q{postgres://host:/}, q{host='host' (inet)}, q{}, ], + [ q{postgres://:12345/}, q{port='12345' (local)}, q{}, ], + [ + q{postgres://otheruser@?host=/no/such/directory}, + q{user='otheruser' host='/no/such/directory' (local)}, + q{}, + ], + [ + q{postgres://otheruser@/?host=/no/such/directory}, + q{user='otheruser' host='/no/such/directory' (local)}, + q{}, + ], + [ + q{postgres://otheruser@:12345?host=/no/such/socket/path}, + q{user='otheruser' host='/no/such/socket/path' port='12345' (local)}, + q{}, + ], + [ + q{postgres://otheruser@:12345/db?host=/path/to/socket}, + q{user='otheruser' dbname='db' host='/path/to/socket' port='12345' (local)}, + q{}, + ], + [ + q{postgres://:12345/db?host=/path/to/socket}, + q{dbname='db' host='/path/to/socket' port='12345' (local)}, + q{}, + ], + [ + q{postgres://:12345?host=/path/to/socket}, + q{host='/path/to/socket' port='12345' (local)}, + q{}, + ], + [ + q{postgres://%2Fvar%2Flib%2Fpostgresql/dbname}, + q{dbname='dbname' host='/var/lib/postgresql' (local)}, + q{}, + ], + # Usually the default sslmode is 'prefer' (for libraries with SSL) or + # 'disable' (for those without). This default changes to 'verify-full' if + # the system CA store is in use. + [ + q{postgresql://host?sslmode=disable}, + q{host='host' sslmode='disable' (inet)}, + q{}, + PGSSLROOTCERT => "system", + ], + [ + q{postgresql://host?sslmode=prefer}, + q{host='host' sslmode='prefer' (inet)}, + q{}, + PGSSLROOTCERT => "system", + ], + [ + q{postgresql://host?sslmode=verify-full}, + q{host='host' (inet)}, + q{}, PGSSLROOTCERT => "system", + ]); + +# test to run for each of the above test definitions +sub test_uri +{ + local $Test::Builder::Level = $Test::Builder::Level + 1; + local %ENV = %ENV; + + my $uri; + my %expect; + my %envvars; + my %result; + + ($uri, $expect{stdout}, $expect{stderr}, %envvars) = @$_; + + $expect{'exit'} = $expect{stderr} eq ''; + %ENV = (%ENV, %envvars); + + my $cmd = [ 'libpq_uri_regress', $uri ]; + $result{exit} = IPC::Run::run $cmd, '>', \$result{stdout}, '2>', + \$result{stderr}; + + chomp($result{stdout}); + chomp($result{stderr}); + + # use is_deeply so there's one test result for each test above, without + # losing the information whether stdout/stderr mismatched. + is_deeply(\%result, \%expect, $uri); +} + +foreach (@tests) +{ + test_uri($_); +} + +done_testing(); diff --git a/src/interfaces/libpq/t/002_api.pl b/src/interfaces/libpq/t/002_api.pl new file mode 100644 index 0000000..8b43a98 --- /dev/null +++ b/src/interfaces/libpq/t/002_api.pl @@ -0,0 +1,22 @@ +# Copyright (c) 2022-2023, PostgreSQL Global Development Group +use strict; +use warnings; + +use PostgreSQL::Test::Utils; +use Test::More; + +# Test PQsslAttribute(NULL, "library") +my ($out, $err) = run_command([ 'libpq_testclient', '--ssl' ]); + +if ($ENV{with_ssl} eq 'openssl') +{ + is($out, 'OpenSSL', 'PQsslAttribute(NULL, "library") returns "OpenSSL"'); +} +else +{ + is( $err, + 'SSL is not enabled', + 'PQsslAttribute(NULL, "library") returns NULL'); +} + +done_testing(); diff --git a/src/interfaces/libpq/t/003_load_balance_host_list.pl b/src/interfaces/libpq/t/003_load_balance_host_list.pl new file mode 100644 index 0000000..21c3b8d --- /dev/null +++ b/src/interfaces/libpq/t/003_load_balance_host_list.pl @@ -0,0 +1,91 @@ +# Copyright (c) 2023, PostgreSQL Global Development Group +use strict; +use warnings; +use Config; +use PostgreSQL::Test::Utils; +use PostgreSQL::Test::Cluster; +use Test::More; + +# This tests load balancing across the list of different hosts in the host +# parameter of the connection string. + +# Cluster setup which is shared for testing both load balancing methods +my $node1 = PostgreSQL::Test::Cluster->new('node1'); +my $node2 = PostgreSQL::Test::Cluster->new('node2', own_host => 1); +my $node3 = PostgreSQL::Test::Cluster->new('node3', own_host => 1); + +# Create a data directory with initdb +$node1->init(); +$node2->init(); +$node3->init(); + +# Start the PostgreSQL server +$node1->start(); +$node2->start(); +$node3->start(); + +# Start the tests for load balancing method 1 +my $hostlist = $node1->host . ',' . $node2->host . ',' . $node3->host; +my $portlist = $node1->port . ',' . $node2->port . ',' . $node3->port; + +$node1->connect_fails( + "host=$hostlist port=$portlist load_balance_hosts=doesnotexist", + "load_balance_hosts doesn't accept unknown values", + expected_stderr => qr/invalid load_balance_hosts value: "doesnotexist"/); + +# load_balance_hosts=disable should always choose the first one. +$node1->connect_ok( + "host=$hostlist port=$portlist load_balance_hosts=disable", + "load_balance_hosts=disable connects to the first node", + sql => "SELECT 'connect1'", + log_like => [qr/statement: SELECT 'connect1'/]); + +# Statistically the following loop with load_balance_hosts=random will almost +# certainly connect at least once to each of the nodes. The chance of that not +# happening is so small that it's negligible: (2/3)^50 = 1.56832855e-9 +foreach my $i (1 .. 50) +{ + $node1->connect_ok( + "host=$hostlist port=$portlist load_balance_hosts=random", + "repeated connections with random load balancing", + sql => "SELECT 'connect2'"); +} + +my $node1_occurences = () = + $node1->log_content() =~ /statement: SELECT 'connect2'/g; +my $node2_occurences = () = + $node2->log_content() =~ /statement: SELECT 'connect2'/g; +my $node3_occurences = () = + $node3->log_content() =~ /statement: SELECT 'connect2'/g; + +my $total_occurences = + $node1_occurences + $node2_occurences + $node3_occurences; + +ok($node1_occurences > 1, "received at least one connection on node1"); +ok($node2_occurences > 1, "received at least one connection on node2"); +ok($node3_occurences > 1, "received at least one connection on node3"); +ok($total_occurences == 50, "received 50 connections across all nodes"); + +$node1->stop(); +$node2->stop(); + +# load_balance_hosts=disable should continue trying hosts until it finds a +# working one. +$node3->connect_ok( + "host=$hostlist port=$portlist load_balance_hosts=disable", + "load_balance_hosts=disable continues until it connects to the a working node", + sql => "SELECT 'connect3'", + log_like => [qr/statement: SELECT 'connect3'/]); + +# Also with load_balance_hosts=random we continue to the next nodes if previous +# ones are down. Connect a few times to make sure it's not just lucky. +foreach my $i (1 .. 5) +{ + $node3->connect_ok( + "host=$hostlist port=$portlist load_balance_hosts=random", + "load_balance_hosts=random continues until it connects to the a working node", + sql => "SELECT 'connect4'", + log_like => [qr/statement: SELECT 'connect4'/]); +} + +done_testing(); diff --git a/src/interfaces/libpq/t/004_load_balance_dns.pl b/src/interfaces/libpq/t/004_load_balance_dns.pl new file mode 100644 index 0000000..875070e --- /dev/null +++ b/src/interfaces/libpq/t/004_load_balance_dns.pl @@ -0,0 +1,141 @@ +# Copyright (c) 2023, PostgreSQL Global Development Group +use strict; +use warnings; +use Config; +use PostgreSQL::Test::Utils; +use PostgreSQL::Test::Cluster; +use Test::More; + +if ($ENV{PG_TEST_EXTRA} !~ /\bload_balance\b/) +{ + plan skip_all => + 'Potentially unsafe test load_balance not enabled in PG_TEST_EXTRA'; +} + +# This tests loadbalancing based on a DNS entry that contains multiple records +# for different IPs. Since setting up a DNS server is more effort than we +# consider reasonable to run this test, this situation is instead imitated by +# using a hosts file where a single hostname maps to multiple different IP +# addresses. This test requires the administrator to add the following lines to +# the hosts file (if we detect that this hasn't happened we skip the test): +# +# 127.0.0.1 pg-loadbalancetest +# 127.0.0.2 pg-loadbalancetest +# 127.0.0.3 pg-loadbalancetest +# +# Windows or Linux are required to run this test because these OSes allow +# binding to 127.0.0.2 and 127.0.0.3 addresses by default, but other OSes +# don't. We need to bind to different IP addresses, so that we can use these +# different IP addresses in the hosts file. +# +# The hosts file needs to be prepared before running this test. We don't do it +# on the fly, because it requires root permissions to change the hosts file. In +# CI we set up the previously mentioned rules in the hosts file, so that this +# load balancing method is tested. + +# Cluster setup which is shared for testing both load balancing methods +my $can_bind_to_127_0_0_2 = + $Config{osname} eq 'linux' || $PostgreSQL::Test::Utils::windows_os; + +# Checks for the requirements for testing load balancing method 2 +if (!$can_bind_to_127_0_0_2) +{ + plan skip_all => 'load_balance test only supported on Linux and Windows'; +} + +my $hosts_path; +if ($windows_os) +{ + $hosts_path = 'c:\Windows\System32\Drivers\etc\hosts'; +} +else +{ + $hosts_path = '/etc/hosts'; +} + +my $hosts_content = PostgreSQL::Test::Utils::slurp_file($hosts_path); + +my $hosts_count = () = + $hosts_content =~ /127\.0\.0\.[1-3] pg-loadbalancetest/g; +if ($hosts_count != 3) +{ + # Host file is not prepared for this test + plan skip_all => "hosts file was not prepared for DNS load balance test"; +} + +$PostgreSQL::Test::Cluster::use_tcp = 1; +$PostgreSQL::Test::Cluster::test_pghost = '127.0.0.1'; +my $port = PostgreSQL::Test::Cluster::get_free_port(); +my $node1 = PostgreSQL::Test::Cluster->new('node1', port => $port); +my $node2 = + PostgreSQL::Test::Cluster->new('node2', port => $port, own_host => 1); +my $node3 = + PostgreSQL::Test::Cluster->new('node3', port => $port, own_host => 1); + +# Create a data directory with initdb +$node1->init(); +$node2->init(); +$node3->init(); + +# Start the PostgreSQL server +$node1->start(); +$node2->start(); +$node3->start(); + +# load_balance_hosts=disable should always choose the first one. +$node1->connect_ok( + "host=pg-loadbalancetest port=$port load_balance_hosts=disable", + "load_balance_hosts=disable connects to the first node", + sql => "SELECT 'connect1'", + log_like => [qr/statement: SELECT 'connect1'/]); + + +# Statistically the following loop with load_balance_hosts=random will almost +# certainly connect at least once to each of the nodes. The chance of that not +# happening is so small that it's negligible: (2/3)^50 = 1.56832855e-9 +foreach my $i (1 .. 50) +{ + $node1->connect_ok( + "host=pg-loadbalancetest port=$port load_balance_hosts=random", + "repeated connections with random load balancing", + sql => "SELECT 'connect2'"); +} + +my $node1_occurences = () = + $node1->log_content() =~ /statement: SELECT 'connect2'/g; +my $node2_occurences = () = + $node2->log_content() =~ /statement: SELECT 'connect2'/g; +my $node3_occurences = () = + $node3->log_content() =~ /statement: SELECT 'connect2'/g; + +my $total_occurences = + $node1_occurences + $node2_occurences + $node3_occurences; + +ok($node1_occurences > 1, "received at least one connection on node1"); +ok($node2_occurences > 1, "received at least one connection on node2"); +ok($node3_occurences > 1, "received at least one connection on node3"); +ok($total_occurences == 50, "received 50 connections across all nodes"); + +$node1->stop(); +$node2->stop(); + +# load_balance_hosts=disable should continue trying hosts until it finds a +# working one. +$node3->connect_ok( + "host=pg-loadbalancetest port=$port load_balance_hosts=disable", + "load_balance_hosts=disable continues until it connects to the a working node", + sql => "SELECT 'connect3'", + log_like => [qr/statement: SELECT 'connect3'/]); + +# Also with load_balance_hosts=random we continue to the next nodes if previous +# ones are down. Connect a few times to make sure it's not just lucky. +foreach my $i (1 .. 5) +{ + $node3->connect_ok( + "host=pg-loadbalancetest port=$port load_balance_hosts=random", + "load_balance_hosts=random continues until it connects to the a working node", + sql => "SELECT 'connect4'", + log_like => [qr/statement: SELECT 'connect4'/]); +} + +done_testing(); diff --git a/src/interfaces/libpq/test/.gitignore b/src/interfaces/libpq/test/.gitignore new file mode 100644 index 0000000..6ba78ad --- /dev/null +++ b/src/interfaces/libpq/test/.gitignore @@ -0,0 +1,2 @@ +/libpq_testclient +/libpq_uri_regress diff --git a/src/interfaces/libpq/test/Makefile b/src/interfaces/libpq/test/Makefile new file mode 100644 index 0000000..75ac08f --- /dev/null +++ b/src/interfaces/libpq/test/Makefile @@ -0,0 +1,24 @@ +# src/interfaces/libpq/test/Makefile + +PGFILEDESC = "libpq test program" +PGAPPICON = win32 + +subdir = src/interfaces/libpq/test +top_builddir = ../../../.. +include $(top_builddir)/src/Makefile.global + +ifeq ($(PORTNAME), win32) +LDFLAGS += -lws2_32 +endif + +override CPPFLAGS := -I$(libpq_srcdir) $(CPPFLAGS) +LDFLAGS_INTERNAL += $(libpq_pgport) + +PROGS = libpq_testclient libpq_uri_regress + +all: $(PROGS) + +$(PROGS): $(WIN32RES) + +clean distclean maintainer-clean: + rm -f $(PROGS) *.o diff --git a/src/interfaces/libpq/test/libpq_testclient.c b/src/interfaces/libpq/test/libpq_testclient.c new file mode 100644 index 0000000..4ed6679 --- /dev/null +++ b/src/interfaces/libpq/test/libpq_testclient.c @@ -0,0 +1,37 @@ +/* + * libpq_testclient.c + * A test program for the libpq public API + * + * Copyright (c) 2022-2023, PostgreSQL Global Development Group + * + * IDENTIFICATION + * src/interfaces/libpq/test/libpq_testclient.c + */ + +#include "postgres_fe.h" + +#include "libpq-fe.h" + +static void +print_ssl_library() +{ + const char *lib = PQsslAttribute(NULL, "library"); + + if (!lib) + fprintf(stderr, "SSL is not enabled\n"); + else + printf("%s\n", lib); +} + +int +main(int argc, char *argv[]) +{ + if ((argc > 1) && !strcmp(argv[1], "--ssl")) + { + print_ssl_library(); + return 0; + } + + printf("currently only --ssl is supported\n"); + return 1; +} diff --git a/src/interfaces/libpq/test/libpq_uri_regress.c b/src/interfaces/libpq/test/libpq_uri_regress.c new file mode 100644 index 0000000..53d4edb --- /dev/null +++ b/src/interfaces/libpq/test/libpq_uri_regress.c @@ -0,0 +1,84 @@ +/* + * libpq_uri_regress.c + * A test program for libpq URI format + * + * This is a helper for libpq conninfo regression testing. It takes a single + * conninfo string as a parameter, parses it using PQconninfoParse, and then + * prints out the values from the parsed PQconninfoOption struct that differ + * from the defaults (obtained from PQconndefaults). + * + * Portions Copyright (c) 2012-2023, PostgreSQL Global Development Group + * + * IDENTIFICATION + * src/interfaces/libpq/test/libpq_uri_regress.c + */ + +#include "postgres_fe.h" + +#include "libpq-fe.h" + +int +main(int argc, char *argv[]) +{ + PQconninfoOption *opts; + PQconninfoOption *defs; + PQconninfoOption *opt; + PQconninfoOption *def; + char *errmsg = NULL; + bool local = true; + + if (argc != 2) + return 1; + + opts = PQconninfoParse(argv[1], &errmsg); + if (opts == NULL) + { + fprintf(stderr, "libpq_uri_regress: %s", errmsg); + return 1; + } + + defs = PQconndefaults(); + if (defs == NULL) + { + fprintf(stderr, "libpq_uri_regress: cannot fetch default options\n"); + return 1; + } + + /* + * Loop on the options, and print the value of each if not the default. + * + * XXX this coding assumes that PQconninfoOption structs always have the + * keywords in the same order. + */ + for (opt = opts, def = defs; opt->keyword; ++opt, ++def) + { + if (opt->val != NULL) + { + if (def->val == NULL || strcmp(opt->val, def->val) != 0) + printf("%s='%s' ", opt->keyword, opt->val); + + /* + * Try to detect if this is a Unix-domain socket or inet. This is + * a bit grotty but it's the same thing that libpq itself does. + * + * Note that we directly test for '/' instead of using + * is_absolute_path, as that would be considerably more messy. + * This would fail on Windows, but that platform doesn't have + * Unix-domain sockets anyway. + */ + if (*opt->val && + (strcmp(opt->keyword, "hostaddr") == 0 || + (strcmp(opt->keyword, "host") == 0 && *opt->val != '/'))) + { + local = false; + } + } + } + + if (local) + printf("(local)\n"); + else + printf("(inet)\n"); + + return 0; +} diff --git a/src/interfaces/libpq/test/meson.build b/src/interfaces/libpq/test/meson.build new file mode 100644 index 0000000..d56b63e --- /dev/null +++ b/src/interfaces/libpq/test/meson.build @@ -0,0 +1,38 @@ +# Copyright (c) 2022-2023, PostgreSQL Global Development Group + +libpq_uri_regress_sources = files( + 'libpq_uri_regress.c', +) + +if host_system == 'windows' + libpq_uri_regress_sources += rc_bin_gen.process(win32ver_rc, extra_args: [ + '--NAME', 'libpq_uri_regress', + '--FILEDESC', 'libpq test program',]) +endif + +testprep_targets += executable('libpq_uri_regress', + libpq_uri_regress_sources, + dependencies: [frontend_code, libpq], + kwargs: default_bin_args + { + 'install': false, + } +) + + +libpq_testclient_sources = files( + 'libpq_testclient.c', +) + +if host_system == 'windows' + libpq_testclient_sources += rc_bin_gen.process(win32ver_rc, extra_args: [ + '--NAME', 'libpq_testclient', + '--FILEDESC', 'libpq test program',]) +endif + +testprep_targets += executable('libpq_testclient', + libpq_testclient_sources, + dependencies: [frontend_code, libpq], + kwargs: default_bin_args + { + 'install': false, + } +) diff --git a/src/interfaces/libpq/win32.c b/src/interfaces/libpq/win32.c new file mode 100644 index 0000000..e4d29ee --- /dev/null +++ b/src/interfaces/libpq/win32.c @@ -0,0 +1,320 @@ +/* + * src/interfaces/libpq/win32.c + * + * + * FILE + * win32.c + * + * DESCRIPTION + * Win32 support functions. + * + * Contains table and functions for looking up win32 socket error + * descriptions. But will/may contain other win32 helper functions + * for libpq. + * + * The error constants are taken from the Frambak Bakfram LGSOCKET + * library guys who in turn took them from the Winsock FAQ. + * + * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + */ + +/* Make stuff compile faster by excluding not used stuff */ + +#define VC_EXTRALEAN +#ifndef __MINGW32__ +#define NOGDI +#endif +#define NOCRYPT + +#include "postgres_fe.h" + +#include "win32.h" + +/* Declared here to avoid pulling in all includes, which causes name collisions */ +#ifdef ENABLE_NLS +extern char *libpq_gettext(const char *msgid) pg_attribute_format_arg(1); +#else +#define libpq_gettext(x) (x) +#endif + + +static struct WSErrorEntry +{ + DWORD error; + const char *description; +} WSErrors[] = + +{ + { + 0, "No error" + }, + { + WSAEINTR, "Interrupted system call" + }, + { + WSAEBADF, "Bad file number" + }, + { + WSAEACCES, "Permission denied" + }, + { + WSAEFAULT, "Bad address" + }, + { + WSAEINVAL, "Invalid argument" + }, + { + WSAEMFILE, "Too many open sockets" + }, + { + WSAEWOULDBLOCK, "Operation would block" + }, + { + WSAEINPROGRESS, "Operation now in progress" + }, + { + WSAEALREADY, "Operation already in progress" + }, + { + WSAENOTSOCK, "Socket operation on non-socket" + }, + { + WSAEDESTADDRREQ, "Destination address required" + }, + { + WSAEMSGSIZE, "Message too long" + }, + { + WSAEPROTOTYPE, "Protocol wrong type for socket" + }, + { + WSAENOPROTOOPT, "Bad protocol option" + }, + { + WSAEPROTONOSUPPORT, "Protocol not supported" + }, + { + WSAESOCKTNOSUPPORT, "Socket type not supported" + }, + { + WSAEOPNOTSUPP, "Operation not supported on socket" + }, + { + WSAEPFNOSUPPORT, "Protocol family not supported" + }, + { + WSAEAFNOSUPPORT, "Address family not supported" + }, + { + WSAEADDRINUSE, "Address already in use" + }, + { + WSAEADDRNOTAVAIL, "Cannot assign requested address" + }, + { + WSAENETDOWN, "Network is down" + }, + { + WSAENETUNREACH, "Network is unreachable" + }, + { + WSAENETRESET, "Net connection reset" + }, + { + WSAECONNABORTED, "Software caused connection abort" + }, + { + WSAECONNRESET, "Connection reset by peer" + }, + { + WSAENOBUFS, "No buffer space available" + }, + { + WSAEISCONN, "Socket is already connected" + }, + { + WSAENOTCONN, "Socket is not connected" + }, + { + WSAESHUTDOWN, "Cannot send after socket shutdown" + }, + { + WSAETOOMANYREFS, "Too many references, cannot splice" + }, + { + WSAETIMEDOUT, "Connection timed out" + }, + { + WSAECONNREFUSED, "Connection refused" + }, + { + WSAELOOP, "Too many levels of symbolic links" + }, + { + WSAENAMETOOLONG, "File name too long" + }, + { + WSAEHOSTDOWN, "Host is down" + }, + { + WSAEHOSTUNREACH, "No route to host" + }, + { + WSAENOTEMPTY, "Directory not empty" + }, + { + WSAEPROCLIM, "Too many processes" + }, + { + WSAEUSERS, "Too many users" + }, + { + WSAEDQUOT, "Disc quota exceeded" + }, + { + WSAESTALE, "Stale NFS file handle" + }, + { + WSAEREMOTE, "Too many levels of remote in path" + }, + { + WSASYSNOTREADY, "Network system is unavailable" + }, + { + WSAVERNOTSUPPORTED, "Winsock version out of range" + }, + { + WSANOTINITIALISED, "WSAStartup not yet called" + }, + { + WSAEDISCON, "Graceful shutdown in progress" + }, + { + WSAHOST_NOT_FOUND, "Host not found" + }, + { + WSATRY_AGAIN, "NA Host not found / SERVFAIL" + }, + { + WSANO_RECOVERY, "Non recoverable FORMERR||REFUSED||NOTIMP" + }, + { + WSANO_DATA, "No host data of that type was found" + }, + { + 0, 0 + } /* End of table */ +}; + + +/* + * Returns 0 if not found, linear but who cares, at this moment + * we're already in pain :) + */ + +static int +LookupWSErrorMessage(DWORD err, char *dest) +{ + struct WSErrorEntry *e; + + for (e = WSErrors; e->description; e++) + { + if (e->error == err) + { + strcpy(dest, e->description); + return 1; + } + } + return 0; +} + + +struct MessageDLL +{ + const char *dll_name; + void *handle; + int loaded; /* BOOL */ +} dlls[] = + +{ + { + "netmsg.dll", 0, 0 + }, + { + "winsock.dll", 0, 0 + }, + { + "ws2_32.dll", 0, 0 + }, + { + "wsock32n.dll", 0, 0 + }, + { + "mswsock.dll", 0, 0 + }, + { + "ws2help.dll", 0, 0 + }, + { + "ws2thk.dll", 0, 0 + }, + { + 0, 0, 1 + } /* Last one, no dll, always loaded */ +}; + +#define DLLS_SIZE (sizeof(dlls)/sizeof(struct MessageDLL)) + +/* + * Returns a description of the socket error by first trying + * to find it in the lookup table, and if that fails, tries + * to load any of the winsock dlls to find that message. + */ + +const char * +winsock_strerror(int err, char *strerrbuf, size_t buflen) +{ + unsigned long flags; + int offs, + i; + int success = LookupWSErrorMessage(err, strerrbuf); + + for (i = 0; !success && i < DLLS_SIZE; i++) + { + + if (!dlls[i].loaded) + { + dlls[i].loaded = 1; /* Only load once */ + dlls[i].handle = (void *) LoadLibraryEx(dlls[i].dll_name, + 0, + LOAD_LIBRARY_AS_DATAFILE); + } + + if (dlls[i].dll_name && !dlls[i].handle) + continue; /* Didn't load */ + + flags = FORMAT_MESSAGE_FROM_SYSTEM + | FORMAT_MESSAGE_IGNORE_INSERTS + | (dlls[i].handle ? FORMAT_MESSAGE_FROM_HMODULE : 0); + + success = 0 != FormatMessage(flags, + dlls[i].handle, err, + MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), + strerrbuf, buflen - 64, + 0); + } + + if (!success) + sprintf(strerrbuf, libpq_gettext("unrecognized socket error: 0x%08X/%d"), err, err); + else + { + strerrbuf[buflen - 1] = '\0'; + offs = strlen(strerrbuf); + if (offs > (int) buflen - 64) + offs = buflen - 64; + sprintf(strerrbuf + offs, " (0x%08X/%d)", err, err); + } + return strerrbuf; +} diff --git a/src/interfaces/libpq/win32.h b/src/interfaces/libpq/win32.h new file mode 100644 index 0000000..fcce1e0 --- /dev/null +++ b/src/interfaces/libpq/win32.h @@ -0,0 +1,23 @@ +/* + * src/interfaces/libpq/win32.h + */ +#ifndef __win32_h_included +#define __win32_h_included + +/* + * Some compatibility functions + */ + +/* open provided elsewhere */ +#define close(a) _close(a) +#define read(a,b,c) _read(a,b,c) +#define write(a,b,c) _write(a,b,c) + +#undef EAGAIN /* doesn't apply on sockets */ + +/* + * support for handling Windows Socket errors + */ +extern const char *winsock_strerror(int err, char *strerrbuf, size_t buflen); + +#endif |