PostgreSQL Source Code git master
Loading...
Searching...
No Matches
libpq-int.h File Reference
#include "libpq-events.h"
#include <netdb.h>
#include <sys/socket.h>
#include <time.h>
#include <pthread.h>
#include <signal.h>
#include "libpq/pqcomm.h"
#include "fe-auth-sasl.h"
#include "pqexpbuffer.h"
#include "libpq/pg-gssapi.h"
#include "common/pg_prng.h"
Include dependency graph for libpq-int.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

union  pgresult_data
 
struct  pgresParamDesc
 
struct  pgresAttValue
 
struct  pgMessageField
 
struct  PGNoticeHooks
 
struct  PGEvent
 
struct  pg_result
 
struct  PQEnvironmentOption
 
struct  pgParameterStatus
 
struct  pgLobjfuncs
 
struct  pgDataValue
 
struct  PGcmdQueueEntry
 
struct  pg_conn_host
 
struct  pg_conn
 

Macros

#define CMDSTATUS_LEN   64 /* should match COMPLETION_TAG_BUFSIZE */
 
#define NULL_LEN   (-1) /* pg_result len for NULL value */
 
#define ENC_ERROR   0
 
#define ENC_PLAINTEXT   0x01
 
#define ENC_GSSAPI   0x02
 
#define ENC_SSL   0x04
 
#define AUTH_RESPONSE_GSS   'G'
 
#define AUTH_RESPONSE_PASSWORD   'P'
 
#define AUTH_RESPONSE_SASL_INITIAL   'I'
 
#define AUTH_RESPONSE_SASL   'S'
 
#define pglock_thread()   pg_g_threadlock(true)
 
#define pgunlock_thread()   pg_g_threadlock(false)
 
#define pqClearConnErrorState(conn)
 
#define pgHavePendingResult(conn)    ((conn)->result != NULL || (conn)->error_result)
 
#define pqIsnonblocking(conn)   ((conn)->nonblocking)
 
#define OUTBUFFER_THRESHOLD   65536
 
#define libpq_gettext(x)   (x)
 
#define libpq_ngettext(s, p, n)   ((n) == 1 ? (s) : (p))
 
#define SOCK_ERRNO   errno
 
#define SOCK_STRERROR   strerror_r
 
#define SOCK_ERRNO_SET(e)   (errno = (e))
 

Typedefs

typedef union pgresult_data PGresult_data
 
typedef struct pgresParamDesc PGresParamDesc
 
typedef struct pgresAttValue PGresAttValue
 
typedef struct pgMessageField PGMessageField
 
typedef struct PGEvent PGEvent
 
typedef struct PQEnvironmentOption PQEnvironmentOption
 
typedef struct pgParameterStatus pgParameterStatus
 
typedef struct pgLobjfuncs PGlobjfuncs
 
typedef struct pgDataValue PGdataValue
 
typedef enum pg_conn_host_type pg_conn_host_type
 
typedef struct PGcmdQueueEntry PGcmdQueueEntry
 
typedef struct pg_conn_host pg_conn_host
 

Enumerations

enum  PGAsyncStatusType {
  PGASYNC_IDLE , PGASYNC_BUSY , PGASYNC_READY , PGASYNC_READY_MORE ,
  PGASYNC_COPY_IN , PGASYNC_COPY_OUT , PGASYNC_COPY_BOTH , PGASYNC_PIPELINE_IDLE
}
 
enum  PGTargetServerType {
  SERVER_TYPE_ANY = 0 , SERVER_TYPE_READ_WRITE , SERVER_TYPE_READ_ONLY , SERVER_TYPE_PRIMARY ,
  SERVER_TYPE_STANDBY , SERVER_TYPE_PREFER_STANDBY , SERVER_TYPE_PREFER_STANDBY_PASS2
}
 
enum  PGLoadBalanceType { LOAD_BALANCE_DISABLE = 0 , LOAD_BALANCE_RANDOM }
 
enum  PGTernaryBool { PG_BOOL_UNKNOWN = 0 , PG_BOOL_YES , PG_BOOL_NO }
 
enum  pg_conn_host_type { CHT_HOST_NAME , CHT_HOST_ADDRESS , CHT_UNIX_SOCKET }
 
enum  PGQueryClass {
  PGQUERY_SIMPLE , PGQUERY_EXTENDED , PGQUERY_PREPARE , PGQUERY_DESCRIBE ,
  PGQUERY_SYNC , PGQUERY_CLOSE
}
 

Functions

void pqDropConnection (PGconn *conn, bool flushInput)
 
bool pqConnectOptions2 (PGconn *conn)
 
int pqConnectDBStart (PGconn *conn)
 
int pqConnectDBComplete (PGconn *conn)
 
PGconnpqMakeEmptyPGconn (void)
 
void pqReleaseConnHosts (PGconn *conn)
 
void pqClosePGconn (PGconn *conn)
 
int pqPacketSend (PGconn *conn, char pack_type, const void *buf, size_t buf_len)
 
bool pqGetHomeDirectory (char *buf, int bufsize)
 
bool pqCopyPGconn (PGconn *srcConn, PGconn *dstConn)
 
bool pqParseIntParam (const char *value, int *result, PGconn *conn, const char *context)
 
void pqSetResultError (PGresult *res, PQExpBuffer errorMessage, int offset)
 
voidpqResultAlloc (PGresult *res, size_t nBytes, bool isBinary)
 
charpqResultStrdup (PGresult *res, const char *str)
 
void pqClearAsyncResult (PGconn *conn)
 
void pqSaveErrorResult (PGconn *conn)
 
PGresultpqPrepareAsyncResult (PGconn *conn)
 
void pqInternalNotice (const PGNoticeHooks *hooks, const char *fmt,...) pg_attribute_printf(2
 
void void pqSaveMessageField (PGresult *res, char code, const char *value)
 
int pqSaveParameterStatus (PGconn *conn, const char *name, const char *value)
 
int pqRowProcessor (PGconn *conn, const char **errmsgp)
 
void pqCommandQueueAdvance (PGconn *conn, bool isReadyForQuery, bool gotSync)
 
int PQsendQueryContinue (PGconn *conn, const char *query)
 
charpqBuildStartupPacket3 (PGconn *conn, int *packetlen, const PQEnvironmentOption *options)
 
void pqParseInput3 (PGconn *conn)
 
int pqGetErrorNotice3 (PGconn *conn, bool isError)
 
void pqBuildErrorMessage3 (PQExpBuffer msg, const PGresult *res, PGVerbosity verbosity, PGContextVisibility show_context)
 
int pqGetNegotiateProtocolVersion3 (PGconn *conn)
 
int pqGetCopyData3 (PGconn *conn, char **buffer, int async)
 
int pqGetline3 (PGconn *conn, char *s, int maxlen)
 
int pqGetlineAsync3 (PGconn *conn, char *buffer, int bufsize)
 
int pqEndcopy3 (PGconn *conn)
 
PGresultpqFunctionCall3 (PGconn *conn, Oid fnid, int *result_buf, int *actual_result_len, int result_is_int, const PQArgBlock *args, int nargs)
 
int PQsendCancelRequest (PGconn *cancelConn)
 
int pqCheckOutBufferSpace (size_t bytes_needed, PGconn *conn)
 
int pqCheckInBufferSpace (size_t bytes_needed, PGconn *conn)
 
void pqParseDone (PGconn *conn, int newInStart)
 
int pqGetc (char *result, PGconn *conn)
 
int pqPutc (char c, PGconn *conn)
 
int pqGets (PQExpBuffer buf, PGconn *conn)
 
int pqGets_append (PQExpBuffer buf, PGconn *conn)
 
int pqPuts (const char *s, PGconn *conn)
 
int pqGetnchar (void *s, size_t len, PGconn *conn)
 
int pqSkipnchar (size_t len, PGconn *conn)
 
int pqPutnchar (const void *s, size_t len, PGconn *conn)
 
int pqGetInt (int *result, size_t bytes, PGconn *conn)
 
int pqPutInt (int value, size_t bytes, PGconn *conn)
 
int pqPutMsgStart (char msg_type, PGconn *conn)
 
int pqPutMsgEnd (PGconn *conn)
 
int pqReadData (PGconn *conn)
 
int pqFlush (PGconn *conn)
 
int pqWait (int forRead, int forWrite, PGconn *conn)
 
int pqWaitTimed (int forRead, int forWrite, PGconn *conn, pg_usec_time_t end_time)
 
int pqReadReady (PGconn *conn)
 
int pqWriteReady (PGconn *conn)
 
PostgresPollingStatusType pqsecure_open_client (PGconn *)
 
void pqsecure_close (PGconn *)
 
ssize_t pqsecure_read (PGconn *, void *ptr, size_t len)
 
ssize_t pqsecure_write (PGconn *, const void *ptr, size_t len)
 
ssize_t pqsecure_raw_read (PGconn *, void *ptr, size_t len)
 
ssize_t pqsecure_raw_write (PGconn *, const void *ptr, size_t len)
 
int pq_block_sigpipe (sigset_t *osigset, bool *sigpipe_pending)
 
void pq_reset_sigpipe (sigset_t *osigset, bool sigpipe_pending, bool got_epipe)
 
PostgresPollingStatusType pgtls_open_client (PGconn *conn)
 
void pgtls_close (PGconn *conn)
 
ssize_t pgtls_read (PGconn *conn, void *ptr, size_t len)
 
bool pgtls_read_pending (PGconn *conn)
 
ssize_t pgtls_write (PGconn *conn, const void *ptr, size_t len)
 
charpgtls_get_peer_certificate_hash (PGconn *conn, size_t *len)
 
int pgtls_verify_peer_name_matches_certificate_guts (PGconn *conn, int *names_examined, char **first_name)
 
void pqTraceOutputMessage (PGconn *conn, const char *message, bool toServer)
 
void pqTraceOutputNoTypeByteMessage (PGconn *conn, const char *message)
 
void pqTraceOutputCharResponse (PGconn *conn, const char *responseType, char response)
 
void libpq_append_error (PQExpBuffer errorMessage, const char *fmt,...) pg_attribute_printf(2
 
void void libpq_append_conn_error (PGconn *conn, const char *fmt,...) pg_attribute_printf(2
 
void void void libpq_append_grease_info (PGconn *conn)
 

Variables

char *const pgresStatus []
 
pgthreadlock_t pg_g_threadlock
 

Macro Definition Documentation

◆ AUTH_RESPONSE_GSS

#define AUTH_RESPONSE_GSS   'G'

Definition at line 335 of file libpq-int.h.

◆ AUTH_RESPONSE_PASSWORD

#define AUTH_RESPONSE_PASSWORD   'P'

Definition at line 336 of file libpq-int.h.

◆ AUTH_RESPONSE_SASL

#define AUTH_RESPONSE_SASL   'S'

Definition at line 338 of file libpq-int.h.

◆ AUTH_RESPONSE_SASL_INITIAL

#define AUTH_RESPONSE_SASL_INITIAL   'I'

Definition at line 337 of file libpq-int.h.

◆ CMDSTATUS_LEN

#define CMDSTATUS_LEN   64 /* should match COMPLETION_TAG_BUFSIZE */

Definition at line 83 of file libpq-int.h.

◆ ENC_ERROR

#define ENC_ERROR   0

Definition at line 229 of file libpq-int.h.

◆ ENC_GSSAPI

#define ENC_GSSAPI   0x02

Definition at line 231 of file libpq-int.h.

◆ ENC_PLAINTEXT

#define ENC_PLAINTEXT   0x01

Definition at line 230 of file libpq-int.h.

◆ ENC_SSL

#define ENC_SSL   0x04

Definition at line 232 of file libpq-int.h.

◆ libpq_gettext

#define libpq_gettext (   x)    (x)

Definition at line 951 of file libpq-int.h.

◆ libpq_ngettext

#define libpq_ngettext (   s,
  p,
 
)    ((n) == 1 ? (s) : (p))

Definition at line 952 of file libpq-int.h.

◆ NULL_LEN

#define NULL_LEN   (-1) /* pg_result len for NULL value */

Definition at line 130 of file libpq-int.h.

◆ OUTBUFFER_THRESHOLD

#define OUTBUFFER_THRESHOLD   65536

Definition at line 945 of file libpq-int.h.

◆ pgHavePendingResult

#define pgHavePendingResult (   conn)     ((conn)->result != NULL || (conn)->error_result)

Definition at line 933 of file libpq-int.h.

951 : (p))
952#endif
953/*
954 * libpq code should use the above, not _(), since that would use the
955 * surrounding programs's message catalog.
956 */
957#undef _
958
959extern void libpq_append_error(PQExpBuffer errorMessage, const char *fmt,...) pg_attribute_printf(2, 3);
962
963/*
964 * These macros are needed to let error-handling code be portable between
965 * Unix and Windows. (ugh)
966 */
967#ifdef WIN32
968#define SOCK_ERRNO (WSAGetLastError())
969#define SOCK_STRERROR winsock_strerror
970#define SOCK_ERRNO_SET(e) WSASetLastError(e)
971#else
972#define SOCK_ERRNO errno
973#define SOCK_STRERROR strerror_r
974#define SOCK_ERRNO_SET(e) (errno = (e))
975#endif
976
977#endif /* LIBPQ_INT_H */
#define pg_attribute_printf(f, a)
Definition c.h:268
void libpq_append_error(PQExpBuffer errorMessage, const char *fmt,...) pg_attribute_printf(2
void void libpq_append_conn_error(PGconn *conn, const char *fmt,...) pg_attribute_printf(2
void void void libpq_append_grease_info(PGconn *conn)
Definition fe-misc.c:1432
static int fb(int x)
PGconn * conn
Definition streamutil.c:52

◆ pglock_thread

#define pglock_thread ( )    pg_g_threadlock(true)

Definition at line 745 of file libpq-int.h.

◆ pgunlock_thread

#define pgunlock_thread ( )    pg_g_threadlock(false)

Definition at line 746 of file libpq-int.h.

◆ pqClearConnErrorState

#define pqClearConnErrorState (   conn)
Value:
(resetPQExpBuffer(&(conn)->errorMessage), \
(conn)->errorReported = 0)
void resetPQExpBuffer(PQExpBuffer str)

Definition at line 924 of file libpq-int.h.

◆ pqIsnonblocking

#define pqIsnonblocking (   conn)    ((conn)->nonblocking)

Definition at line 940 of file libpq-int.h.

◆ SOCK_ERRNO

#define SOCK_ERRNO   errno

Definition at line 973 of file libpq-int.h.

◆ SOCK_ERRNO_SET

#define SOCK_ERRNO_SET (   e)    (errno = (e))

Definition at line 975 of file libpq-int.h.

◆ SOCK_STRERROR

#define SOCK_STRERROR   strerror_r

Definition at line 974 of file libpq-int.h.

Typedef Documentation

◆ pg_conn_host

◆ pg_conn_host_type

◆ PGcmdQueueEntry

◆ PGdataValue

◆ PGEvent

◆ PGlobjfuncs

◆ PGMessageField

◆ pgParameterStatus

◆ PGresAttValue

◆ PGresParamDesc

◆ PGresult_data

Definition at line 98 of file libpq-int.h.

◆ PQEnvironmentOption

Enumeration Type Documentation

◆ pg_conn_host_type

Enumerator
CHT_HOST_NAME 
CHT_HOST_ADDRESS 
CHT_UNIX_SOCKET 

Definition at line 307 of file libpq-int.h.

308{
pg_conn_host_type
Definition libpq-int.h:308
@ CHT_UNIX_SOCKET
Definition libpq-int.h:311
@ CHT_HOST_ADDRESS
Definition libpq-int.h:310
@ CHT_HOST_NAME
Definition libpq-int.h:309

◆ PGAsyncStatusType

Enumerator
PGASYNC_IDLE 
PGASYNC_BUSY 
PGASYNC_READY 
PGASYNC_READY_MORE 
PGASYNC_COPY_IN 
PGASYNC_COPY_OUT 
PGASYNC_COPY_BOTH 
PGASYNC_PIPELINE_IDLE 

Definition at line 213 of file libpq-int.h.

214{
215 PGASYNC_IDLE, /* nothing's happening, dude */
216 PGASYNC_BUSY, /* query in progress */
217 PGASYNC_READY, /* query done, waiting for client to fetch
218 * result */
219 PGASYNC_READY_MORE, /* query done, waiting for client to fetch
220 * result, more results expected from this
221 * query */
222 PGASYNC_COPY_IN, /* Copy In data transfer in progress */
223 PGASYNC_COPY_OUT, /* Copy Out data transfer in progress */
224 PGASYNC_COPY_BOTH, /* Copy In/Out data transfer in progress */
225 PGASYNC_PIPELINE_IDLE, /* "Idle" between commands in pipeline mode */
PGAsyncStatusType
Definition libpq-int.h:214
@ PGASYNC_COPY_OUT
Definition libpq-int.h:223
@ PGASYNC_READY_MORE
Definition libpq-int.h:219
@ PGASYNC_READY
Definition libpq-int.h:217
@ PGASYNC_COPY_BOTH
Definition libpq-int.h:224
@ PGASYNC_IDLE
Definition libpq-int.h:215
@ PGASYNC_COPY_IN
Definition libpq-int.h:222
@ PGASYNC_BUSY
Definition libpq-int.h:216
@ PGASYNC_PIPELINE_IDLE
Definition libpq-int.h:225

◆ PGLoadBalanceType

Enumerator
LOAD_BALANCE_DISABLE 
LOAD_BALANCE_RANDOM 

Definition at line 247 of file libpq-int.h.

248{
249 LOAD_BALANCE_DISABLE = 0, /* Use the existing host order (default) */
250 LOAD_BALANCE_RANDOM, /* Randomly shuffle the hosts */
PGLoadBalanceType
Definition libpq-int.h:248
@ LOAD_BALANCE_DISABLE
Definition libpq-int.h:249
@ LOAD_BALANCE_RANDOM
Definition libpq-int.h:250

◆ PGQueryClass

Enumerator
PGQUERY_SIMPLE 
PGQUERY_EXTENDED 
PGQUERY_PREPARE 
PGQUERY_DESCRIBE 
PGQUERY_SYNC 
PGQUERY_CLOSE 

Definition at line 318 of file libpq-int.h.

319{
320 PGQUERY_SIMPLE, /* simple Query protocol (PQexec) */
321 PGQUERY_EXTENDED, /* full Extended protocol (PQexecParams) */
322 PGQUERY_PREPARE, /* Parse only (PQprepare) */
323 PGQUERY_DESCRIBE, /* Describe Statement or Portal */
324 PGQUERY_SYNC, /* Sync (at end of a pipeline) */
325 PGQUERY_CLOSE /* Close Statement or Portal */
PGQueryClass
Definition libpq-int.h:319
@ PGQUERY_SIMPLE
Definition libpq-int.h:320
@ PGQUERY_SYNC
Definition libpq-int.h:324
@ PGQUERY_EXTENDED
Definition libpq-int.h:321
@ PGQUERY_DESCRIBE
Definition libpq-int.h:323
@ PGQUERY_CLOSE
Definition libpq-int.h:325
@ PGQUERY_PREPARE
Definition libpq-int.h:322

◆ PGTargetServerType

Enumerator
SERVER_TYPE_ANY 
SERVER_TYPE_READ_WRITE 
SERVER_TYPE_READ_ONLY 
SERVER_TYPE_PRIMARY 
SERVER_TYPE_STANDBY 
SERVER_TYPE_PREFER_STANDBY 
SERVER_TYPE_PREFER_STANDBY_PASS2 

Definition at line 235 of file libpq-int.h.

236{
237 SERVER_TYPE_ANY = 0, /* Any server (default) */
238 SERVER_TYPE_READ_WRITE, /* Read-write server */
239 SERVER_TYPE_READ_ONLY, /* Read-only server */
240 SERVER_TYPE_PRIMARY, /* Primary server */
241 SERVER_TYPE_STANDBY, /* Standby server */
242 SERVER_TYPE_PREFER_STANDBY, /* Prefer standby server */
243 SERVER_TYPE_PREFER_STANDBY_PASS2 /* second pass - behaves same as ANY */
PGTargetServerType
Definition libpq-int.h:236
@ SERVER_TYPE_STANDBY
Definition libpq-int.h:241
@ SERVER_TYPE_PRIMARY
Definition libpq-int.h:240
@ SERVER_TYPE_ANY
Definition libpq-int.h:237
@ SERVER_TYPE_READ_WRITE
Definition libpq-int.h:238
@ SERVER_TYPE_PREFER_STANDBY_PASS2
Definition libpq-int.h:243
@ SERVER_TYPE_PREFER_STANDBY
Definition libpq-int.h:242
@ SERVER_TYPE_READ_ONLY
Definition libpq-int.h:239

◆ PGTernaryBool

Enumerator
PG_BOOL_UNKNOWN 
PG_BOOL_YES 
PG_BOOL_NO 

Definition at line 254 of file libpq-int.h.

255{
256 PG_BOOL_UNKNOWN = 0, /* Currently unknown */
257 PG_BOOL_YES, /* Yes (true) */
258 PG_BOOL_NO /* No (false) */
PGTernaryBool
Definition libpq-int.h:255
@ PG_BOOL_YES
Definition libpq-int.h:257
@ PG_BOOL_NO
Definition libpq-int.h:258
@ PG_BOOL_UNKNOWN
Definition libpq-int.h:256

Function Documentation

◆ libpq_append_conn_error()

void void libpq_append_conn_error ( PGconn conn,
const char fmt,
  ... 
)
extern

◆ libpq_append_error()

void libpq_append_error ( PQExpBuffer  errorMessage,
const char fmt,
  ... 
)
extern

◆ libpq_append_grease_info()

void void void libpq_append_grease_info ( PGconn conn)
extern

Definition at line 1432 of file fe-misc.c.

1433{
1434 /* translator: %s is a URL */
1436 "\tThis indicates a bug in either the server being contacted\n"
1437 "\tor a proxy handling the connection. Please consider\n"
1438 "\treporting this to the maintainers of that software.\n"
1439 "\tFor more information, including instructions on how to\n"
1440 "\twork around this issue for now, visit\n"
1441 "\t\t%s",
1442 "https://www.postgresql.org/docs/devel/libpq-connect.html#LIBPQ-CONNECT-MAX-PROTOCOL-VERSION");
1443}
void libpq_append_conn_error(PGconn *conn, const char *fmt,...)
Definition fe-misc.c:1404

References conn, and libpq_append_conn_error().

Referenced by PQconnectPoll(), and pqGetNegotiateProtocolVersion3().

◆ pgtls_close()

void pgtls_close ( PGconn conn)
extern

Definition at line 1502 of file fe-secure-openssl.c.

1503{
1504 if (conn->ssl_in_use)
1505 {
1506 if (conn->ssl)
1507 {
1508 /*
1509 * We can't destroy everything SSL-related here due to the
1510 * possible later calls to OpenSSL routines which may need our
1511 * thread callbacks, so set a flag here and check at the end.
1512 */
1513
1514 SSL_shutdown(conn->ssl);
1515 SSL_free(conn->ssl);
1516 conn->ssl = NULL;
1517 conn->ssl_in_use = false;
1518 conn->ssl_handshake_started = false;
1519 }
1520
1521 if (conn->peer)
1522 {
1523 X509_free(conn->peer);
1524 conn->peer = NULL;
1525 }
1526
1527#ifdef USE_SSL_ENGINE
1528 if (conn->engine)
1529 {
1530 ENGINE_finish(conn->engine);
1531 ENGINE_free(conn->engine);
1532 conn->engine = NULL;
1533 }
1534#endif
1535 }
1536}
bool ssl_handshake_started
Definition libpq-int.h:622
bool ssl_in_use
Definition libpq-int.h:621

References conn, fb(), pg_conn::ssl_handshake_started, and pg_conn::ssl_in_use.

Referenced by open_client_SSL(), pgtls_open_client(), and pqsecure_close().

◆ pgtls_get_peer_certificate_hash()

char * pgtls_get_peer_certificate_hash ( PGconn conn,
size_t len 
)
extern

Definition at line 340 of file fe-secure-openssl.c.

341{
343 const EVP_MD *algo_type;
344 unsigned char hash[EVP_MAX_MD_SIZE]; /* size for SHA-512 */
345 unsigned int hash_size;
346 int algo_nid;
347 char *cert_hash;
348
349 *len = 0;
350
351 if (!conn->peer)
352 return NULL;
353
354 peer_cert = conn->peer;
355
356 /*
357 * Get the signature algorithm of the certificate to determine the hash
358 * algorithm to use for the result. Prefer X509_get_signature_info(),
359 * introduced in OpenSSL 1.1.1, which can handle RSA-PSS signatures.
360 */
361#if HAVE_X509_GET_SIGNATURE_INFO
363#else
365 &algo_nid, NULL))
366#endif
367 {
368 libpq_append_conn_error(conn, "could not determine server certificate signature algorithm");
369 return NULL;
370 }
371
372 /*
373 * The TLS server's certificate bytes need to be hashed with SHA-256 if
374 * its signature algorithm is MD5 or SHA-1 as per RFC 5929
375 * (https://tools.ietf.org/html/rfc5929#section-4.1). If something else
376 * is used, the same hash as the signature algorithm is used.
377 */
378 switch (algo_nid)
379 {
380 case NID_md5:
381 case NID_sha1:
383 break;
384 default:
386 if (algo_type == NULL)
387 {
388 libpq_append_conn_error(conn, "could not find digest for NID %s",
390 return NULL;
391 }
392 break;
393 }
394
396 {
397 libpq_append_conn_error(conn, "could not generate peer certificate hash");
398 return NULL;
399 }
400
401 /* save result */
403 if (cert_hash == NULL)
404 {
405 libpq_append_conn_error(conn, "out of memory");
406 return NULL;
407 }
409 *len = hash_size;
410
411 return cert_hash;
412}
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
const void size_t len
static unsigned hash(unsigned *uv, int n)
Definition rege_dfa.c:715
#define malloc(a)

References conn, fb(), hash(), len, libpq_append_conn_error(), malloc, and memcpy().

Referenced by build_client_final_message().

◆ pgtls_open_client()

PostgresPollingStatusType pgtls_open_client ( PGconn conn)
extern

Definition at line 96 of file fe-secure-openssl.c.

97{
98 /* First time through? */
99 if (conn->ssl == NULL)
100 {
101 /*
102 * Create a connection-specific SSL object, and load client
103 * certificate, private key, and trusted CA certs.
104 */
105 if (initialize_SSL(conn) != 0)
106 {
107 /* initialize_SSL already put a message in conn->errorMessage */
110 }
111 }
112
113 /* Begin or continue the actual handshake */
114 return open_client_SSL(conn);
115}
static int initialize_SSL(PGconn *conn)
static PostgresPollingStatusType open_client_SSL(PGconn *conn)
void pgtls_close(PGconn *conn)
@ PGRES_POLLING_FAILED
Definition libpq-fe.h:121

References conn, fb(), initialize_SSL(), open_client_SSL(), PGRES_POLLING_FAILED, and pgtls_close().

Referenced by pqsecure_open_client().

◆ pgtls_read()

ssize_t pgtls_read ( PGconn conn,
void ptr,
size_t  len 
)
extern

Definition at line 118 of file fe-secure-openssl.c.

119{
120 ssize_t n;
121 int result_errno = 0;
123 int err;
124 unsigned long ecode;
125
126rloop:
127
128 /*
129 * Prepare to call SSL_get_error() by clearing thread's OpenSSL error
130 * queue. In general, the current thread's error queue must be empty
131 * before the TLS/SSL I/O operation is attempted, or SSL_get_error() will
132 * not work reliably. Since the possibility exists that other OpenSSL
133 * clients running in the same thread but not under our control will fail
134 * to call ERR_get_error() themselves (after their own I/O operations),
135 * pro-actively clear the per-thread error queue now.
136 */
139 n = SSL_read(conn->ssl, ptr, len);
140 err = SSL_get_error(conn->ssl, n);
141
142 /*
143 * Other clients of OpenSSL may fail to call ERR_get_error(), but we
144 * always do, so as to not cause problems for OpenSSL clients that don't
145 * call ERR_clear_error() defensively. Be sure that this happens by
146 * calling now. SSL_get_error() relies on the OpenSSL per-thread error
147 * queue being intact, so this is the earliest possible point
148 * ERR_get_error() may be called.
149 */
150 ecode = (err != SSL_ERROR_NONE || n < 0) ? ERR_get_error() : 0;
151 switch (err)
152 {
153 case SSL_ERROR_NONE:
154 if (n < 0)
155 {
156 /* Not supposed to happen, so we don't translate the msg */
158 "SSL_read failed but did not provide error information\n");
159 /* assume the connection is broken */
161 }
162 break;
164 n = 0;
165 break;
167
168 /*
169 * Returning 0 here would cause caller to wait for read-ready,
170 * which is not correct since what SSL wants is wait for
171 * write-ready. The former could get us stuck in an infinite
172 * wait, so don't risk it; busy-loop instead.
173 */
174 goto rloop;
176 if (n < 0 && SOCK_ERRNO != 0)
177 {
179 if (result_errno == EPIPE ||
181 libpq_append_conn_error(conn, "server closed the connection unexpectedly\n"
182 "\tThis probably means the server terminated abnormally\n"
183 "\tbefore or while processing the request.");
184 else
185 libpq_append_conn_error(conn, "SSL SYSCALL error: %s",
187 sebuf, sizeof(sebuf)));
188 }
189 else
190 {
191 libpq_append_conn_error(conn, "SSL SYSCALL error: EOF detected");
192 /* assume the connection is broken */
194 n = -1;
195 }
196 break;
197 case SSL_ERROR_SSL:
198 {
199 char *errm = SSLerrmessage(ecode);
200
201 libpq_append_conn_error(conn, "SSL error: %s", errm);
203 /* assume the connection is broken */
205 n = -1;
206 break;
207 }
209
210 /*
211 * Per OpenSSL documentation, this error code is only returned for
212 * a clean connection closure, so we should not report it as a
213 * server crash.
214 */
215 libpq_append_conn_error(conn, "SSL connection has been closed unexpectedly");
217 n = -1;
218 break;
219 default:
220 libpq_append_conn_error(conn, "unrecognized SSL error code: %d", err);
221 /* assume the connection is broken */
223 n = -1;
224 break;
225 }
226
227 /* ensure we return the intended errno to caller */
229
230 return n;
231}
void err(int eval, const char *fmt,...)
Definition err.c:43
static void SSLerrfree(char *buf)
static char * SSLerrmessage(unsigned long ecode)
#define SOCK_STRERROR
Definition libpq-int.h:974
#define SOCK_ERRNO
Definition oauth-utils.c:86
#define SOCK_ERRNO_SET(e)
Definition oauth-utils.c:87
#define PG_STRERROR_R_BUFLEN
Definition port.h:278
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
PQExpBufferData errorMessage
Definition libpq-int.h:684
#define ECONNRESET
Definition win32_port.h:371

References appendPQExpBufferStr(), conn, ECONNRESET, err(), pg_conn::errorMessage, fb(), len, libpq_append_conn_error(), PG_STRERROR_R_BUFLEN, SOCK_ERRNO, SOCK_ERRNO_SET, SOCK_STRERROR, SSLerrfree(), and SSLerrmessage().

Referenced by pqsecure_read().

◆ pgtls_read_pending()

bool pgtls_read_pending ( PGconn conn)
extern

Definition at line 234 of file fe-secure-openssl.c.

235{
236 return SSL_pending(conn->ssl) > 0;
237}

References conn, and fb().

Referenced by pqSocketCheck().

◆ pgtls_verify_peer_name_matches_certificate_guts()

int pgtls_verify_peer_name_matches_certificate_guts ( PGconn conn,
int names_examined,
char **  first_name 
)
extern

Definition at line 544 of file fe-secure-openssl.c.

547{
549 int i;
550 int rc = 0;
551 char *host = conn->connhost[conn->whichhost].host;
552 int host_type;
553 bool check_cn = true;
554
555 Assert(host && host[0]); /* should be guaranteed by caller */
556
557 /*
558 * We try to match the NSS behavior here, which is a slight departure from
559 * the spec but seems to make more intuitive sense:
560 *
561 * If connhost contains a DNS name, and the certificate's SANs contain any
562 * dNSName entries, then we'll ignore the Subject Common Name entirely;
563 * otherwise, we fall back to checking the CN. (This behavior matches the
564 * RFC.)
565 *
566 * If connhost contains an IP address, and the SANs contain iPAddress
567 * entries, we again ignore the CN. Otherwise, we allow the CN to match,
568 * EVEN IF there is a dNSName in the SANs. (RFC 6125 prohibits this: "A
569 * client MUST NOT seek a match for a reference identifier of CN-ID if the
570 * presented identifiers include a DNS-ID, SRV-ID, URI-ID, or any
571 * application-specific identifier types supported by the client.")
572 *
573 * NOTE: Prior versions of libpq did not consider iPAddress entries at
574 * all, so this new behavior might break a certificate that has different
575 * IP addresses in the Subject CN and the SANs.
576 */
577 if (is_ip_address(host))
579 else
581
582 /*
583 * First, get the Subject Alternative Names (SANs) from the certificate,
584 * and compare them against the originally given hostname.
585 */
588
589 if (peer_san)
590 {
592
593 for (i = 0; i < san_len; i++)
594 {
596 char *alt_name = NULL;
597
598 if (name->type == host_type)
599 {
600 /*
601 * This SAN is of the same type (IP or DNS) as our host name,
602 * so don't allow a fallback check of the CN.
603 */
604 check_cn = false;
605 }
606
607 if (name->type == GEN_DNS)
608 {
609 (*names_examined)++;
611 name->d.dNSName,
612 &alt_name);
613 }
614 else if (name->type == GEN_IPADD)
615 {
616 (*names_examined)++;
618 name->d.iPAddress,
619 &alt_name);
620 }
621
622 if (alt_name)
623 {
624 if (!*first_name)
626 else
627 free(alt_name);
628 }
629
630 if (rc != 0)
631 {
632 /*
633 * Either we hit an error or a match, and either way we should
634 * not fall back to the CN.
635 */
636 check_cn = false;
637 break;
638 }
639 }
641 }
642
643 /*
644 * If there is no subjectAltName extension of the matching type, check the
645 * Common Name.
646 *
647 * (Per RFC 2818 and RFC 6125, if the subjectAltName extension of type
648 * dNSName is present, the CN must be ignored. We break this rule if host
649 * is an IP address; see the comment above.)
650 */
651 if (check_cn)
652 {
654
656 if (subject_name != NULL)
657 {
658 int cn_index;
659
661 NID_commonName, -1);
662 if (cn_index >= 0)
663 {
664 char *common_name = NULL;
665
666 (*names_examined)++;
669 &common_name);
670
671 if (common_name)
672 {
673 if (!*first_name)
675 else
677 }
678 }
679 }
680 }
681
682 return rc;
683}
#define Assert(condition)
Definition c.h:943
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 bool is_ip_address(const char *host)
int i
Definition isn.c:77
#define free(a)
char * host
Definition libpq-int.h:358
int whichhost
Definition libpq-int.h:482
pg_conn_host * connhost
Definition libpq-int.h:483
const char * name

References Assert, conn, pg_conn::connhost, fb(), free, pg_conn_host::host, i, is_ip_address(), name, openssl_verify_peer_name_matches_certificate_ip(), openssl_verify_peer_name_matches_certificate_name(), and pg_conn::whichhost.

Referenced by pq_verify_peer_name_matches_certificate().

◆ pgtls_write()

ssize_t pgtls_write ( PGconn conn,
const void ptr,
size_t  len 
)
extern

Definition at line 240 of file fe-secure-openssl.c.

241{
242 ssize_t n;
243 int result_errno = 0;
245 int err;
246 unsigned long ecode;
247
250 n = SSL_write(conn->ssl, ptr, len);
251 err = SSL_get_error(conn->ssl, n);
252 ecode = (err != SSL_ERROR_NONE || n < 0) ? ERR_get_error() : 0;
253 switch (err)
254 {
255 case SSL_ERROR_NONE:
256 if (n < 0)
257 {
258 /* Not supposed to happen, so we don't translate the msg */
260 "SSL_write failed but did not provide error information\n");
261 /* assume the connection is broken */
263 }
264 break;
266
267 /*
268 * Returning 0 here causes caller to wait for write-ready, which
269 * is not really the right thing, but it's the best we can do.
270 */
271 n = 0;
272 break;
274 n = 0;
275 break;
277
278 /*
279 * If errno is still zero then assume it's a read EOF situation,
280 * and report EOF. (This seems possible because SSL_write can
281 * also do reads.)
282 */
283 if (n < 0 && SOCK_ERRNO != 0)
284 {
287 libpq_append_conn_error(conn, "server closed the connection unexpectedly\n"
288 "\tThis probably means the server terminated abnormally\n"
289 "\tbefore or while processing the request.");
290 else
291 libpq_append_conn_error(conn, "SSL SYSCALL error: %s",
293 sebuf, sizeof(sebuf)));
294 }
295 else
296 {
297 libpq_append_conn_error(conn, "SSL SYSCALL error: EOF detected");
298 /* assume the connection is broken */
300 n = -1;
301 }
302 break;
303 case SSL_ERROR_SSL:
304 {
305 char *errm = SSLerrmessage(ecode);
306
307 libpq_append_conn_error(conn, "SSL error: %s", errm);
309 /* assume the connection is broken */
311 n = -1;
312 break;
313 }
315
316 /*
317 * Per OpenSSL documentation, this error code is only returned for
318 * a clean connection closure, so we should not report it as a
319 * server crash.
320 */
321 libpq_append_conn_error(conn, "SSL connection has been closed unexpectedly");
323 n = -1;
324 break;
325 default:
326 libpq_append_conn_error(conn, "unrecognized SSL error code: %d", err);
327 /* assume the connection is broken */
329 n = -1;
330 break;
331 }
332
333 /* ensure we return the intended errno to caller */
335
336 return n;
337}

References appendPQExpBufferStr(), conn, ECONNRESET, err(), pg_conn::errorMessage, fb(), len, libpq_append_conn_error(), PG_STRERROR_R_BUFLEN, SOCK_ERRNO, SOCK_ERRNO_SET, SOCK_STRERROR, SSLerrfree(), and SSLerrmessage().

Referenced by pqsecure_write().

◆ pq_block_sigpipe()

int pq_block_sigpipe ( sigset_t osigset,
bool sigpipe_pending 
)
extern

Definition at line 94 of file oauth-utils.c.

95{
98
101
102 /* Block SIGPIPE and save previous mask for later reset */
104 if (SOCK_ERRNO)
105 return -1;
106
107 /* We can have a pending SIGPIPE only if it was blocked before */
109 {
110 /* Is there a pending SIGPIPE? */
111 if (sigpending(&sigset) != 0)
112 return -1;
113
115 *sigpipe_pending = true;
116 else
117 *sigpipe_pending = false;
118 }
119 else
120 *sigpipe_pending = false;
121
122 return 0;
123}
#define SIGPIPE
Definition win32_port.h:163

References fb(), SIGPIPE, SOCK_ERRNO, and SOCK_ERRNO_SET.

Referenced by pg_fe_run_oauth_flow(), and PQprint().

◆ pq_reset_sigpipe()

void pq_reset_sigpipe ( sigset_t osigset,
bool  sigpipe_pending,
bool  got_epipe 
)
extern

Definition at line 130 of file oauth-utils.c.

131{
133 int signo;
135
136 /* Clear SIGPIPE only if none was pending */
137 if (got_epipe && !sigpipe_pending)
138 {
139 if (sigpending(&sigset) == 0 &&
141 {
143
146
148 }
149 }
150
151 /* Restore saved block mask */
153
155}

References fb(), SIGPIPE, SOCK_ERRNO, and SOCK_ERRNO_SET.

Referenced by pg_fe_run_oauth_flow(), and PQprint().

◆ pqBuildErrorMessage3()

void pqBuildErrorMessage3 ( PQExpBuffer  msg,
const PGresult res,
PGVerbosity  verbosity,
PGContextVisibility  show_context 
)
extern

Definition at line 1030 of file fe-protocol3.c.

1032{
1033 const char *val;
1034 const char *querytext = NULL;
1035 int querypos = 0;
1036
1037 /* If we couldn't allocate a PGresult, just say "out of memory" */
1038 if (res == NULL)
1039 {
1040 appendPQExpBufferStr(msg, libpq_gettext("out of memory\n"));
1041 return;
1042 }
1043
1044 /*
1045 * If we don't have any broken-down fields, just return the base message.
1046 * This mainly applies if we're given a libpq-generated error result.
1047 */
1048 if (res->errFields == NULL)
1049 {
1050 if (res->errMsg && res->errMsg[0])
1051 appendPQExpBufferStr(msg, res->errMsg);
1052 else
1053 appendPQExpBufferStr(msg, libpq_gettext("no error message available\n"));
1054 return;
1055 }
1056
1057 /* Else build error message from relevant fields */
1059 if (val)
1060 appendPQExpBuffer(msg, "%s: ", val);
1061
1062 if (verbosity == PQERRORS_SQLSTATE)
1063 {
1064 /*
1065 * If we have a SQLSTATE, print that and nothing else. If not (which
1066 * shouldn't happen for server-generated errors, but might possibly
1067 * happen for libpq-generated ones), fall back to TERSE format, as
1068 * that seems better than printing nothing at all.
1069 */
1071 if (val)
1072 {
1073 appendPQExpBuffer(msg, "%s\n", val);
1074 return;
1075 }
1076 verbosity = PQERRORS_TERSE;
1077 }
1078
1079 if (verbosity == PQERRORS_VERBOSE)
1080 {
1082 if (val)
1083 appendPQExpBuffer(msg, "%s: ", val);
1084 }
1086 if (val)
1089 if (val)
1090 {
1091 if (verbosity != PQERRORS_TERSE && res->errQuery != NULL)
1092 {
1093 /* emit position as a syntax cursor display */
1094 querytext = res->errQuery;
1095 querypos = atoi(val);
1096 }
1097 else
1098 {
1099 /* emit position as text addition to primary message */
1100 /* translator: %s represents a digit string */
1101 appendPQExpBuffer(msg, libpq_gettext(" at character %s"),
1102 val);
1103 }
1104 }
1105 else
1106 {
1108 if (val)
1109 {
1111 if (verbosity != PQERRORS_TERSE && querytext != NULL)
1112 {
1113 /* emit position as a syntax cursor display */
1114 querypos = atoi(val);
1115 }
1116 else
1117 {
1118 /* emit position as text addition to primary message */
1119 /* translator: %s represents a digit string */
1120 appendPQExpBuffer(msg, libpq_gettext(" at character %s"),
1121 val);
1122 }
1123 }
1124 }
1125 appendPQExpBufferChar(msg, '\n');
1126 if (verbosity != PQERRORS_TERSE)
1127 {
1128 if (querytext && querypos > 0)
1130 res->client_encoding);
1132 if (val)
1133 appendPQExpBuffer(msg, libpq_gettext("DETAIL: %s\n"), val);
1135 if (val)
1136 appendPQExpBuffer(msg, libpq_gettext("HINT: %s\n"), val);
1138 if (val)
1139 appendPQExpBuffer(msg, libpq_gettext("QUERY: %s\n"), val);
1140 if (show_context == PQSHOW_CONTEXT_ALWAYS ||
1141 (show_context == PQSHOW_CONTEXT_ERRORS &&
1143 {
1145 if (val)
1146 appendPQExpBuffer(msg, libpq_gettext("CONTEXT: %s\n"),
1147 val);
1148 }
1149 }
1150 if (verbosity == PQERRORS_VERBOSE)
1151 {
1153 if (val)
1155 libpq_gettext("SCHEMA NAME: %s\n"), val);
1157 if (val)
1159 libpq_gettext("TABLE NAME: %s\n"), val);
1161 if (val)
1163 libpq_gettext("COLUMN NAME: %s\n"), val);
1165 if (val)
1167 libpq_gettext("DATATYPE NAME: %s\n"), val);
1169 if (val)
1171 libpq_gettext("CONSTRAINT NAME: %s\n"), val);
1172 }
1173 if (verbosity == PQERRORS_VERBOSE)
1174 {
1175 const char *valf;
1176 const char *vall;
1177
1181 if (val || valf || vall)
1182 {
1183 appendPQExpBufferStr(msg, libpq_gettext("LOCATION: "));
1184 if (val)
1185 appendPQExpBuffer(msg, libpq_gettext("%s, "), val);
1186 if (valf && vall) /* unlikely we'd have just one */
1187 appendPQExpBuffer(msg, libpq_gettext("%s:%s"),
1188 valf, vall);
1189 appendPQExpBufferChar(msg, '\n');
1190 }
1191 }
1192}
static void reportErrorPosition(PQExpBuffer msg, const char *query, int loc, int encoding)
long val
Definition informix.c:689
#define PQresultErrorField
@ PGRES_FATAL_ERROR
Definition libpq-fe.h:142
@ PQSHOW_CONTEXT_ALWAYS
Definition libpq-fe.h:172
@ PQSHOW_CONTEXT_ERRORS
Definition libpq-fe.h:171
@ PQERRORS_VERBOSE
Definition libpq-fe.h:164
@ PQERRORS_TERSE
Definition libpq-fe.h:162
@ PQERRORS_SQLSTATE
Definition libpq-fe.h:165
#define libpq_gettext(x)
Definition oauth-utils.h:44
#define PG_DIAG_INTERNAL_QUERY
#define PG_DIAG_SCHEMA_NAME
#define PG_DIAG_CONSTRAINT_NAME
#define PG_DIAG_DATATYPE_NAME
#define PG_DIAG_SOURCE_LINE
#define PG_DIAG_STATEMENT_POSITION
#define PG_DIAG_SOURCE_FILE
#define PG_DIAG_MESSAGE_HINT
#define PG_DIAG_SQLSTATE
#define PG_DIAG_TABLE_NAME
#define PG_DIAG_MESSAGE_PRIMARY
#define PG_DIAG_COLUMN_NAME
#define PG_DIAG_MESSAGE_DETAIL
#define PG_DIAG_CONTEXT
#define PG_DIAG_SEVERITY
#define PG_DIAG_SOURCE_FUNCTION
#define PG_DIAG_INTERNAL_POSITION
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
void appendPQExpBufferChar(PQExpBuffer str, char ch)
char * errMsg
Definition libpq-int.h:193
PGMessageField * errFields
Definition libpq-int.h:194
ExecStatusType resultStatus
Definition libpq-int.h:174
char * errQuery
Definition libpq-int.h:195
int client_encoding
Definition libpq-int.h:186

References appendPQExpBuffer(), appendPQExpBufferChar(), appendPQExpBufferStr(), pg_result::client_encoding, pg_result::errFields, pg_result::errMsg, pg_result::errQuery, fb(), libpq_gettext, PG_DIAG_COLUMN_NAME, PG_DIAG_CONSTRAINT_NAME, PG_DIAG_CONTEXT, PG_DIAG_DATATYPE_NAME, PG_DIAG_INTERNAL_POSITION, PG_DIAG_INTERNAL_QUERY, PG_DIAG_MESSAGE_DETAIL, PG_DIAG_MESSAGE_HINT, PG_DIAG_MESSAGE_PRIMARY, PG_DIAG_SCHEMA_NAME, PG_DIAG_SEVERITY, PG_DIAG_SOURCE_FILE, PG_DIAG_SOURCE_FUNCTION, PG_DIAG_SOURCE_LINE, PG_DIAG_SQLSTATE, PG_DIAG_STATEMENT_POSITION, PG_DIAG_TABLE_NAME, PGRES_FATAL_ERROR, PQERRORS_SQLSTATE, PQERRORS_TERSE, PQERRORS_VERBOSE, PQresultErrorField, PQSHOW_CONTEXT_ALWAYS, PQSHOW_CONTEXT_ERRORS, reportErrorPosition(), pg_result::resultStatus, and val.

Referenced by pqGetErrorNotice3(), and PQresultVerboseErrorMessage().

◆ pqBuildStartupPacket3()

char * pqBuildStartupPacket3 ( PGconn conn,
int packetlen,
const PQEnvironmentOption options 
)
extern

Definition at line 2436 of file fe-protocol3.c.

2438{
2439 char *startpacket;
2440 size_t len;
2441
2443 if (len == 0 || len > INT_MAX)
2444 return NULL;
2445
2446 *packetlen = len;
2447 startpacket = (char *) malloc(*packetlen);
2448 if (!startpacket)
2449 return NULL;
2450
2452 Assert(*packetlen == len);
2453
2454 return startpacket;
2455}
static size_t build_startup_packet(const PGconn *conn, char *packet, const PQEnvironmentOption *options)

References Assert, build_startup_packet(), conn, fb(), len, and malloc.

Referenced by PQconnectPoll().

◆ pqCheckInBufferSpace()

int pqCheckInBufferSpace ( size_t  bytes_needed,
PGconn conn 
)
extern

Definition at line 351 of file fe-misc.c.

352{
353 int newsize = conn->inBufSize;
354 char *newbuf;
355
356 /* Quick exit if we have enough space */
357 if (bytes_needed <= (size_t) newsize)
358 return 0;
359
360 /*
361 * Before concluding that we need to enlarge the buffer, left-justify
362 * whatever is in it and recheck. The caller's value of bytes_needed
363 * includes any data to the left of inStart, but we can delete that in
364 * preference to enlarging the buffer. It's slightly ugly to have this
365 * function do this, but it's better than making callers worry about it.
366 */
368
369 if (conn->inStart < conn->inEnd)
370 {
371 if (conn->inStart > 0)
372 {
374 conn->inEnd - conn->inStart);
375 conn->inEnd -= conn->inStart;
377 conn->inStart = 0;
378 }
379 }
380 else
381 {
382 /* buffer is logically empty, reset it */
383 conn->inStart = conn->inCursor = conn->inEnd = 0;
384 }
385
386 /* Recheck whether we have enough space */
387 if (bytes_needed <= (size_t) newsize)
388 return 0;
389
390 /*
391 * If we need to enlarge the buffer, we first try to double it in size; if
392 * that doesn't work, enlarge in multiples of 8K. This avoids thrashing
393 * the malloc pool by repeated small enlargements.
394 *
395 * Note: tests for newsize > 0 are to catch integer overflow.
396 */
397 do
398 {
399 newsize *= 2;
400 } while (newsize > 0 && bytes_needed > (size_t) newsize);
401
402 if (newsize > 0 && bytes_needed <= (size_t) newsize)
403 {
405 if (newbuf)
406 {
407 /* realloc succeeded */
410 return 0;
411 }
412 }
413
415 do
416 {
417 newsize += 8192;
418 } while (newsize > 0 && bytes_needed > (size_t) newsize);
419
420 if (newsize > 0 && bytes_needed <= (size_t) newsize)
421 {
423 if (newbuf)
424 {
425 /* realloc succeeded */
428 return 0;
429 }
430 }
431
432 /* realloc failed. Probably out of memory */
434 "cannot allocate memory for input buffer\n");
435 return EOF;
436}
#define realloc(a, b)
char * inBuffer
Definition libpq-int.h:577
int inCursor
Definition libpq-int.h:580
int inEnd
Definition libpq-int.h:581
int inBufSize
Definition libpq-int.h:578
int inStart
Definition libpq-int.h:579

References appendPQExpBufferStr(), conn, pg_conn::errorMessage, fb(), pg_conn::inBuffer, pg_conn::inBufSize, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, and realloc.

Referenced by getCopyDataMessage(), PQconnectPoll(), pqFunctionCall3(), pqParseInput3(), and pqReadData().

◆ pqCheckOutBufferSpace()

int pqCheckOutBufferSpace ( size_t  bytes_needed,
PGconn conn 
)
extern

Definition at line 287 of file fe-misc.c.

288{
289 int newsize = conn->outBufSize;
290 char *newbuf;
291
292 /* Quick exit if we have enough space */
293 if (bytes_needed <= (size_t) newsize)
294 return 0;
295
296 /*
297 * If we need to enlarge the buffer, we first try to double it in size; if
298 * that doesn't work, enlarge in multiples of 8K. This avoids thrashing
299 * the malloc pool by repeated small enlargements.
300 *
301 * Note: tests for newsize > 0 are to catch integer overflow.
302 */
303 do
304 {
305 newsize *= 2;
306 } while (newsize > 0 && bytes_needed > (size_t) newsize);
307
308 if (newsize > 0 && bytes_needed <= (size_t) newsize)
309 {
311 if (newbuf)
312 {
313 /* realloc succeeded */
316 return 0;
317 }
318 }
319
321 do
322 {
323 newsize += 8192;
324 } while (newsize > 0 && bytes_needed > (size_t) newsize);
325
326 if (newsize > 0 && bytes_needed <= (size_t) newsize)
327 {
329 if (newbuf)
330 {
331 /* realloc succeeded */
334 return 0;
335 }
336 }
337
338 /* realloc failed. Probably out of memory */
340 "cannot allocate memory for output buffer\n");
341 return EOF;
342}
int outBufSize
Definition libpq-int.h:585
char * outBuffer
Definition libpq-int.h:584

References appendPQExpBufferStr(), conn, pg_conn::errorMessage, fb(), pg_conn::outBuffer, pg_conn::outBufSize, and realloc.

Referenced by PQputCopyData(), pqPutMsgBytes(), and pqPutMsgStart().

◆ pqClearAsyncResult()

void pqClearAsyncResult ( PGconn conn)
extern

◆ pqClosePGconn()

void pqClosePGconn ( PGconn conn)
extern

Definition at line 5307 of file fe-connect.c.

5308{
5309 /*
5310 * If possible, send Terminate message to close the connection politely.
5311 */
5313
5314 /*
5315 * Must reset the blocking status so a possible reconnect will work.
5316 *
5317 * Don't call PQsetnonblocking() because it will fail if it's unable to
5318 * flush the connection.
5319 */
5320 conn->nonblocking = false;
5321
5322 /*
5323 * Close the connection, reset all transient state, flush I/O buffers.
5324 * Note that this includes clearing conn's error state; we're no longer
5325 * interested in any failures associated with the old connection, and we
5326 * want a clean slate for any new connection attempt.
5327 */
5328 pqDropConnection(conn, true);
5329 conn->status = CONNECTION_BAD; /* Well, not really _bad_ - just absent */
5334 pqClearAsyncResult(conn); /* deallocate result */
5336
5337 /*
5338 * Release addrinfo, but since cancel requests never change their addrinfo
5339 * we don't do that. Otherwise we would have to rebuild it during a
5340 * PQcancelReset.
5341 */
5342 if (!conn->cancelRequest)
5344
5345 /* Reset all state obtained from server, too */
5347}
void pqClearOAuthToken(PGconn *conn)
void pqDropConnection(PGconn *conn, bool flushInput)
Definition fe-connect.c:537
static void sendTerminateConn(PGconn *conn)
static void release_conn_addrinfo(PGconn *conn)
static void pqDropServerData(PGconn *conn)
Definition fe-connect.c:663
void pqClearAsyncResult(PGconn *conn)
Definition fe-exec.c:785
@ CONNECTION_BAD
Definition libpq-fe.h:91
@ PQTRANS_IDLE
Definition libpq-fe.h:153
@ PQ_PIPELINE_OFF
Definition libpq-fe.h:193
#define pqClearConnErrorState(conn)
Definition libpq-int.h:924
PGTransactionStatusType xactStatus
Definition libpq-int.h:465
bool cancelRequest
Definition libpq-int.h:434
bool nonblocking
Definition libpq-int.h:468
PGAsyncStatusType asyncStatus
Definition libpq-int.h:464
PGpipelineStatus pipelineStatus
Definition libpq-int.h:470
ConnStatusType status
Definition libpq-int.h:463

References pg_conn::asyncStatus, pg_conn::cancelRequest, conn, CONNECTION_BAD, pg_conn::nonblocking, PGASYNC_IDLE, pg_conn::pipelineStatus, PQ_PIPELINE_OFF, pqClearAsyncResult(), pqClearConnErrorState, pqClearOAuthToken(), pqDropConnection(), pqDropServerData(), PQTRANS_IDLE, release_conn_addrinfo(), sendTerminateConn(), pg_conn::status, and pg_conn::xactStatus.

Referenced by PQcancelReset(), PQfinish(), PQreset(), and PQresetStart().

◆ pqCommandQueueAdvance()

void pqCommandQueueAdvance ( PGconn conn,
bool  isReadyForQuery,
bool  gotSync 
)
extern

Definition at line 3159 of file fe-exec.c.

3160{
3162
3163 if (conn->cmd_queue_head == NULL)
3164 return;
3165
3166 /*
3167 * If processing a query of simple query protocol, we only advance the
3168 * queue when we receive the ReadyForQuery message for it.
3169 */
3171 return;
3172
3173 /*
3174 * If we're waiting for a SYNC, don't advance the queue until we get one.
3175 */
3177 return;
3178
3179 /* delink element from queue */
3182
3183 /* If the queue is now empty, reset the tail too */
3184 if (conn->cmd_queue_head == NULL)
3186
3187 /* and make the queue element recyclable */
3188 prevquery->next = NULL;
3190}
static void pqRecycleCmdQueueEntry(PGconn *conn, PGcmdQueueEntry *entry)
Definition fe-exec.c:1403
PGQueryClass queryclass
Definition libpq-int.h:345
struct PGcmdQueueEntry * next
Definition libpq-int.h:347
PGcmdQueueEntry * cmd_queue_tail
Definition libpq-int.h:491
PGcmdQueueEntry * cmd_queue_head
Definition libpq-int.h:490

References pg_conn::cmd_queue_head, pg_conn::cmd_queue_tail, conn, fb(), PGcmdQueueEntry::next, PGQUERY_SIMPLE, PGQUERY_SYNC, pqRecycleCmdQueueEntry(), and PGcmdQueueEntry::queryclass.

Referenced by PQgetResult(), and pqParseInput3().

◆ pqConnectDBComplete()

int pqConnectDBComplete ( PGconn conn)
extern

Definition at line 2799 of file fe-connect.c.

2800{
2803 int timeout = 0;
2804 int last_whichhost = -2; /* certainly different from whichhost */
2805 int last_whichaddr = -2; /* certainly different from whichaddr */
2806
2807 if (conn == NULL || conn->status == CONNECTION_BAD)
2808 return 0;
2809
2810 /*
2811 * Set up a time limit, if connect_timeout is greater than zero.
2812 */
2813 if (conn->connect_timeout != NULL)
2814 {
2816 "connect_timeout"))
2817 {
2818 /* mark the connection as bad to report the parsing failure */
2820 return 0;
2821 }
2822 }
2823
2824 for (;;)
2825 {
2826 int ret = 0;
2827
2828 /*
2829 * (Re)start the connect_timeout timer if it's active and we are
2830 * considering a different host than we were last time through. If
2831 * we've already succeeded, though, needn't recalculate.
2832 */
2833 if (flag != PGRES_POLLING_OK &&
2834 timeout > 0 &&
2837 {
2841 }
2842
2843 /*
2844 * Wait, if necessary. Note that the initial state (just after
2845 * PQconnectStart) is to wait for the socket to select for writing.
2846 */
2847 switch (flag)
2848 {
2849 case PGRES_POLLING_OK:
2850 return 1; /* success! */
2851
2853 ret = pqWaitTimed(1, 0, conn, end_time);
2854 if (ret == -1)
2855 {
2856 /* hard failure, eg select() problem, aborts everything */
2858 return 0;
2859 }
2860 break;
2861
2863 ret = pqWaitTimed(0, 1, conn, end_time);
2864 if (ret == -1)
2865 {
2866 /* hard failure, eg select() problem, aborts everything */
2868 return 0;
2869 }
2870 break;
2871
2872 default:
2873 /* Just in case we failed to set it in PQconnectPoll */
2875 return 0;
2876 }
2877
2878 if (ret == 1) /* connect_timeout elapsed */
2879 {
2880 /*
2881 * Give up on current server/address, try the next one.
2882 */
2883 conn->try_next_addr = true;
2885 }
2886
2887 /*
2888 * Now try to advance the state machine.
2889 */
2890 if (conn->cancelRequest)
2892 else
2894 }
2895}
PostgresPollingStatusType PQcancelPoll(PGcancelConn *cancelConn)
Definition fe-cancel.c:226
PostgresPollingStatusType PQconnectPoll(PGconn *conn)
bool pqParseIntParam(const char *value, int *result, PGconn *conn, const char *context)
pg_usec_time_t PQgetCurrentTimeUSec(void)
Definition fe-misc.c:1235
int pqWaitTimed(int forRead, int forWrite, PGconn *conn, pg_usec_time_t end_time)
Definition fe-misc.c:1035
@ CONNECTION_NEEDED
Definition libpq-fe.h:106
int64_t pg_usec_time_t
Definition libpq-fe.h:246
PostgresPollingStatusType
Definition libpq-fe.h:120
@ PGRES_POLLING_OK
Definition libpq-fe.h:124
@ PGRES_POLLING_READING
Definition libpq-fe.h:122
@ PGRES_POLLING_WRITING
Definition libpq-fe.h:123
static int64 end_time
Definition pgbench.c:176
int whichaddr
Definition libpq-int.h:541
char * connect_timeout
Definition libpq-int.h:384
bool try_next_addr
Definition libpq-int.h:538
char * flag(int b)
Definition test-ctype.c:33

References pg_conn::cancelRequest, conn, pg_conn::connect_timeout, CONNECTION_BAD, CONNECTION_NEEDED, end_time, fb(), flag(), PGRES_POLLING_OK, PGRES_POLLING_READING, PGRES_POLLING_WRITING, PQcancelPoll(), PQconnectPoll(), PQgetCurrentTimeUSec(), pqParseIntParam(), pqWaitTimed(), pg_conn::status, pg_conn::try_next_addr, pg_conn::whichaddr, and pg_conn::whichhost.

Referenced by internal_ping(), PQcancelBlocking(), PQconnectdb(), PQconnectdbParams(), PQreset(), and PQsetdbLogin().

◆ pqConnectDBStart()

int pqConnectDBStart ( PGconn conn)
extern

Definition at line 2721 of file fe-connect.c.

2722{
2723 if (!conn)
2724 return 0;
2725
2726 if (!conn->options_valid)
2727 goto connect_errReturn;
2728
2729 /*
2730 * Check for bad linking to backend-internal versions of src/common
2731 * functions (see comments in link-canary.c for the reason we need this).
2732 * Nobody but developers should see this message, so we don't bother
2733 * translating it.
2734 */
2736 {
2738 "libpq is incorrectly linked to backend functions\n");
2739 goto connect_errReturn;
2740 }
2741
2742 /* Ensure our buffers are empty */
2743 conn->inStart = conn->inCursor = conn->inEnd = 0;
2744 conn->outCount = 0;
2745
2746 /*
2747 * Set up to try to connect to the first host. (Setting whichhost = -1 is
2748 * a bit of a cheat, but PQconnectPoll will advance it to 0 before
2749 * anything else looks at it.)
2750 *
2751 * Cancel requests are special though, they should only try one host and
2752 * address, and these fields have already been set up in PQcancelCreate,
2753 * so leave these fields alone for cancel requests.
2754 */
2755 if (!conn->cancelRequest)
2756 {
2757 conn->whichhost = -1;
2758 conn->try_next_host = true;
2759 conn->try_next_addr = false;
2760 }
2761
2763
2764 /* Also reset the target_server_type state if needed */
2767
2768 /*
2769 * The code for processing CONNECTION_NEEDED state is in PQconnectPoll(),
2770 * so that it can easily be re-executed if needed again during the
2771 * asynchronous startup process. However, we must run it once here,
2772 * because callers expect a success return from this routine to mean that
2773 * we are in PGRES_POLLING_WRITING connection state.
2774 */
2776 return 1;
2777
2779
2780 /*
2781 * If we managed to open a socket, close it immediately rather than
2782 * waiting till PQfinish. (The application cannot have gotten the socket
2783 * from PQsocket yet, so this doesn't risk breaking anything.)
2784 */
2785 pqDropConnection(conn, true);
2787 return 0;
2788}
bool try_next_host
Definition libpq-int.h:539
bool options_valid
Definition libpq-int.h:467
PGTargetServerType target_server_type
Definition libpq-int.h:535
int outCount
Definition libpq-int.h:586

References appendPQExpBufferStr(), pg_conn::cancelRequest, conn, CONNECTION_BAD, CONNECTION_NEEDED, pg_conn::errorMessage, fb(), pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, pg_conn::options_valid, pg_conn::outCount, pg_link_canary_is_frontend(), PGRES_POLLING_WRITING, PQconnectPoll(), pqDropConnection(), SERVER_TYPE_PREFER_STANDBY, SERVER_TYPE_PREFER_STANDBY_PASS2, pg_conn::status, pg_conn::target_server_type, pg_conn::try_next_addr, pg_conn::try_next_host, and pg_conn::whichhost.

Referenced by PQcancelStart(), PQconnectStart(), PQconnectStartParams(), PQreset(), PQresetStart(), and PQsetdbLogin().

◆ pqConnectOptions2()

bool pqConnectOptions2 ( PGconn conn)
extern

Definition at line 1257 of file fe-connect.c.

1258{
1259 int i;
1260
1261 /*
1262 * Allocate memory for details about each host to which we might possibly
1263 * try to connect. For that, count the number of elements in the hostaddr
1264 * or host options. If neither is given, assume one host.
1265 */
1266 conn->whichhost = 0;
1267 if (conn->pghostaddr && conn->pghostaddr[0] != '\0')
1269 else if (conn->pghost && conn->pghost[0] != '\0')
1271 else
1272 conn->nconnhost = 1;
1274 calloc(conn->nconnhost, sizeof(pg_conn_host));
1275 if (conn->connhost == NULL)
1276 goto oom_error;
1277
1278 /*
1279 * We now have one pg_conn_host structure per possible host. Fill in the
1280 * host and hostaddr fields for each, by splitting the parameter strings.
1281 */
1282 if (conn->pghostaddr != NULL && conn->pghostaddr[0] != '\0')
1283 {
1284 char *s = conn->pghostaddr;
1285 bool more = true;
1286
1287 for (i = 0; i < conn->nconnhost && more; i++)
1288 {
1290 if (conn->connhost[i].hostaddr == NULL)
1291 goto oom_error;
1292 }
1293
1294 /*
1295 * If hostaddr was given, the array was allocated according to the
1296 * number of elements in the hostaddr list, so it really should be the
1297 * right size.
1298 */
1299 Assert(!more);
1300 Assert(i == conn->nconnhost);
1301 }
1302
1303 if (conn->pghost != NULL && conn->pghost[0] != '\0')
1304 {
1305 char *s = conn->pghost;
1306 bool more = true;
1307
1308 for (i = 0; i < conn->nconnhost && more; i++)
1309 {
1311 if (conn->connhost[i].host == NULL)
1312 goto oom_error;
1313 }
1314
1315 /* Check for wrong number of host items. */
1316 if (more || i != conn->nconnhost)
1317 {
1319 libpq_append_conn_error(conn, "could not match %d host names to %d hostaddr values",
1321 return false;
1322 }
1323 }
1324
1325 /*
1326 * Now, for each host slot, identify the type of address spec, and fill in
1327 * the default address if nothing was given.
1328 */
1329 for (i = 0; i < conn->nconnhost; i++)
1330 {
1332
1333 if (ch->hostaddr != NULL && ch->hostaddr[0] != '\0')
1335 else if (ch->host != NULL && ch->host[0] != '\0')
1336 {
1337 ch->type = CHT_HOST_NAME;
1338 if (is_unixsock_path(ch->host))
1339 ch->type = CHT_UNIX_SOCKET;
1340 }
1341 else
1342 {
1343 free(ch->host);
1344
1345 /*
1346 * This bit selects the default host location. If you change
1347 * this, see also pg_regress.
1348 */
1349 if (DEFAULT_PGSOCKET_DIR[0])
1350 {
1352 ch->type = CHT_UNIX_SOCKET;
1353 }
1354 else
1355 {
1356 ch->host = strdup(DefaultHost);
1357 ch->type = CHT_HOST_NAME;
1358 }
1359 if (ch->host == NULL)
1360 goto oom_error;
1361 }
1362 }
1363
1364 /*
1365 * Next, work out the port number corresponding to each host name.
1366 *
1367 * Note: unlike the above for host names, this could leave the port fields
1368 * as null or empty strings. We will substitute DEF_PGPORT whenever we
1369 * read such a port field.
1370 */
1371 if (conn->pgport != NULL && conn->pgport[0] != '\0')
1372 {
1373 char *s = conn->pgport;
1374 bool more = true;
1375
1376 for (i = 0; i < conn->nconnhost && more; i++)
1377 {
1379 if (conn->connhost[i].port == NULL)
1380 goto oom_error;
1381 }
1382
1383 /*
1384 * If exactly one port was given, use it for every host. Otherwise,
1385 * there must be exactly as many ports as there were hosts.
1386 */
1387 if (i == 1 && !more)
1388 {
1389 for (i = 1; i < conn->nconnhost; i++)
1390 {
1392 if (conn->connhost[i].port == NULL)
1393 goto oom_error;
1394 }
1395 }
1396 else if (more || i != conn->nconnhost)
1397 {
1399 libpq_append_conn_error(conn, "could not match %d port numbers to %d hosts",
1401 return false;
1402 }
1403 }
1404
1405 /*
1406 * If user name was not given, fetch it. (Most likely, the fetch will
1407 * fail, since the only way we get here is if pg_fe_getauthname() failed
1408 * during conninfo_add_defaults(). But now we want an error message.)
1409 */
1410 if (conn->pguser == NULL || conn->pguser[0] == '\0')
1411 {
1412 free(conn->pguser);
1414 if (!conn->pguser)
1415 {
1417 return false;
1418 }
1419 }
1420
1421 /*
1422 * If database name was not given, default it to equal user name
1423 */
1424 if (conn->dbName == NULL || conn->dbName[0] == '\0')
1425 {
1426 free(conn->dbName);
1428 if (!conn->dbName)
1429 goto oom_error;
1430 }
1431
1432 /*
1433 * If password was not given, try to look it up in password file. Note
1434 * that the result might be different for each host/port pair.
1435 */
1436 if (conn->pgpass == NULL || conn->pgpass[0] == '\0')
1437 {
1438 /* If password file wasn't specified, use ~/PGPASSFILE */
1439 if (conn->pgpassfile == NULL || conn->pgpassfile[0] == '\0')
1440 {
1441 char homedir[MAXPGPATH];
1442
1443 if (pqGetHomeDirectory(homedir, sizeof(homedir)))
1444 {
1447 if (!conn->pgpassfile)
1448 goto oom_error;
1449 snprintf(conn->pgpassfile, MAXPGPATH, "%s/%s",
1451 }
1452 }
1453
1454 if (conn->pgpassfile != NULL && conn->pgpassfile[0] != '\0')
1455 {
1456 for (i = 0; i < conn->nconnhost; i++)
1457 {
1458 /*
1459 * Try to get a password for this host from file. We use host
1460 * for the hostname search key if given, else hostaddr (at
1461 * least one of them is guaranteed nonempty by now).
1462 */
1463 const char *pwhost = conn->connhost[i].host;
1464 const char *password_errmsg = NULL;
1465
1466 if (pwhost == NULL || pwhost[0] == '\0')
1468
1471 conn->connhost[i].port,
1472 conn->dbName,
1473 conn->pguser,
1476
1477 if (password_errmsg != NULL)
1478 {
1481 return false;
1482 }
1483 }
1484 }
1485 }
1486
1487 /*
1488 * parse and validate require_auth option
1489 */
1490 if (conn->require_auth && conn->require_auth[0])
1491 {
1492 char *s = conn->require_auth;
1493 bool first,
1494 more;
1495 bool negated = false;
1496
1497 /*
1498 * By default, start from an empty set of allowed methods and
1499 * mechanisms, and add to it.
1500 */
1501 conn->auth_required = true;
1504
1505 for (first = true, more = true; more; first = false)
1506 {
1507 char *method,
1508 *part;
1509 uint32 bits = 0;
1510 const pg_fe_sasl_mech *mech = NULL;
1511
1513 if (part == NULL)
1514 goto oom_error;
1515
1516 /*
1517 * Check for negation, e.g. '!password'. If one element is
1518 * negated, they all have to be.
1519 */
1520 method = part;
1521 if (*method == '!')
1522 {
1523 if (first)
1524 {
1525 /*
1526 * Switch to a permissive set of allowed methods and
1527 * mechanisms, and subtract from it.
1528 */
1529 conn->auth_required = false;
1532 }
1533 else if (!negated)
1534 {
1536 libpq_append_conn_error(conn, "negative require_auth method \"%s\" cannot be mixed with non-negative methods",
1537 method);
1538
1539 free(part);
1540 return false;
1541 }
1542
1543 negated = true;
1544 method++;
1545 }
1546 else if (negated)
1547 {
1549 libpq_append_conn_error(conn, "require_auth method \"%s\" cannot be mixed with negative methods",
1550 method);
1551
1552 free(part);
1553 return false;
1554 }
1555
1556 /*
1557 * First group: methods that can be handled solely with the
1558 * authentication request codes.
1559 */
1560 if (strcmp(method, "password") == 0)
1561 {
1562 bits = (1 << AUTH_REQ_PASSWORD);
1563 }
1564 else if (strcmp(method, "md5") == 0)
1565 {
1566 bits = (1 << AUTH_REQ_MD5);
1567 }
1568 else if (strcmp(method, "gss") == 0)
1569 {
1570 bits = (1 << AUTH_REQ_GSS);
1571 bits |= (1 << AUTH_REQ_GSS_CONT);
1572 }
1573 else if (strcmp(method, "sspi") == 0)
1574 {
1575 bits = (1 << AUTH_REQ_SSPI);
1576 bits |= (1 << AUTH_REQ_GSS_CONT);
1577 }
1578
1579 /*
1580 * Next group: SASL mechanisms. All of these use the same request
1581 * codes, so the list of allowed mechanisms is tracked separately.
1582 *
1583 * supported_sasl_mechs must contain all mechanisms handled here.
1584 */
1585 else if (strcmp(method, "scram-sha-256") == 0)
1586 {
1588 }
1589 else if (strcmp(method, "oauth") == 0)
1590 {
1592 }
1593
1594 /*
1595 * Final group: meta-options.
1596 */
1597 else if (strcmp(method, "none") == 0)
1598 {
1599 /*
1600 * Special case: let the user explicitly allow (or disallow)
1601 * connections where the server does not send an explicit
1602 * authentication challenge, such as "trust" and "cert" auth.
1603 */
1604 if (negated) /* "!none" */
1605 {
1606 if (conn->auth_required)
1607 goto duplicate;
1608
1609 conn->auth_required = true;
1610 }
1611 else /* "none" */
1612 {
1613 if (!conn->auth_required)
1614 goto duplicate;
1615
1616 conn->auth_required = false;
1617 }
1618
1619 free(part);
1620 continue; /* avoid the bitmask manipulation below */
1621 }
1622 else
1623 {
1625 libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1626 "require_auth", method);
1627
1628 free(part);
1629 return false;
1630 }
1631
1632 if (mech)
1633 {
1634 /*
1635 * Update the mechanism set only. The method bitmask will be
1636 * updated for SASL further down.
1637 */
1638 Assert(!bits);
1639
1640 if (negated)
1641 {
1642 /* Remove the existing mechanism from the list. */
1644 if (i < 0)
1645 goto duplicate;
1646
1648 }
1649 else
1650 {
1651 /*
1652 * Find a space to put the new mechanism (after making
1653 * sure it's not already there).
1654 */
1656 if (i >= 0)
1657 goto duplicate;
1658
1660 if (i < 0)
1661 {
1662 /* Should not happen; the pointer list is corrupted. */
1663 Assert(false);
1664
1667 "internal error: no space in allowed_sasl_mechs");
1668 free(part);
1669 return false;
1670 }
1671
1673 }
1674 }
1675 else
1676 {
1677 /* Update the method bitmask. */
1678 Assert(bits);
1679
1680 if (negated)
1681 {
1682 if ((conn->allowed_auth_methods & bits) == 0)
1683 goto duplicate;
1684
1686 }
1687 else
1688 {
1689 if ((conn->allowed_auth_methods & bits) == bits)
1690 goto duplicate;
1691
1692 conn->allowed_auth_methods |= bits;
1693 }
1694 }
1695
1696 free(part);
1697 continue;
1698
1699 duplicate:
1700
1701 /*
1702 * A duplicated method probably indicates a typo in a setting
1703 * where typos are extremely risky.
1704 */
1706 libpq_append_conn_error(conn, "require_auth method \"%s\" is specified more than once",
1707 part);
1708
1709 free(part);
1710 return false;
1711 }
1712
1713 /*
1714 * Finally, allow SASL authentication requests if (and only if) we've
1715 * allowed any mechanisms.
1716 */
1717 {
1718 bool allowed = false;
1719 const uint32 sasl_bits =
1720 (1 << AUTH_REQ_SASL)
1721 | (1 << AUTH_REQ_SASL_CONT)
1722 | (1 << AUTH_REQ_SASL_FIN);
1723
1724 for (i = 0; i < lengthof(conn->allowed_sasl_mechs); i++)
1725 {
1727 {
1728 allowed = true;
1729 break;
1730 }
1731 }
1732
1733 /*
1734 * For the standard case, add the SASL bits to the (default-empty)
1735 * set if needed. For the negated case, remove them.
1736 */
1737 if (!negated && allowed)
1739 else if (negated && !allowed)
1741 }
1742 }
1743
1744 /*
1745 * validate channel_binding option
1746 */
1747 if (conn->channel_binding)
1748 {
1749 if (strcmp(conn->channel_binding, "disable") != 0
1750 && strcmp(conn->channel_binding, "prefer") != 0
1751 && strcmp(conn->channel_binding, "require") != 0)
1752 {
1754 libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1755 "channel_binding", conn->channel_binding);
1756 return false;
1757 }
1758 }
1759 else
1760 {
1762 if (!conn->channel_binding)
1763 goto oom_error;
1764 }
1765
1766#ifndef USE_SSL
1767
1768 /*
1769 * sslrootcert=system is not supported. Since setting this changes the
1770 * default sslmode, check this _before_ we validate sslmode, to avoid
1771 * confusing the user with errors for an option they may not have set.
1772 */
1773 if (conn->sslrootcert
1774 && strcmp(conn->sslrootcert, "system") == 0)
1775 {
1777 libpq_append_conn_error(conn, "%s value \"%s\" invalid when SSL support is not compiled in",
1778 "sslrootcert", conn->sslrootcert);
1779 return false;
1780 }
1781#endif
1782
1783 /*
1784 * validate sslmode option
1785 */
1786 if (conn->sslmode)
1787 {
1788 if (strcmp(conn->sslmode, "disable") != 0
1789 && strcmp(conn->sslmode, "allow") != 0
1790 && strcmp(conn->sslmode, "prefer") != 0
1791 && strcmp(conn->sslmode, "require") != 0
1792 && strcmp(conn->sslmode, "verify-ca") != 0
1793 && strcmp(conn->sslmode, "verify-full") != 0)
1794 {
1796 libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1797 "sslmode", conn->sslmode);
1798 return false;
1799 }
1800
1801#ifndef USE_SSL
1802 switch (conn->sslmode[0])
1803 {
1804 case 'a': /* "allow" */
1805 case 'p': /* "prefer" */
1806
1807 /*
1808 * warn user that an SSL connection will never be negotiated
1809 * since SSL was not compiled in?
1810 */
1811 break;
1812
1813 case 'r': /* "require" */
1814 case 'v': /* "verify-ca" or "verify-full" */
1816 libpq_append_conn_error(conn, "%s value \"%s\" invalid when SSL support is not compiled in",
1817 "sslmode", conn->sslmode);
1818 return false;
1819 }
1820#endif
1821 }
1822 else
1823 {
1825 if (!conn->sslmode)
1826 goto oom_error;
1827 }
1828
1829 /*
1830 * validate sslnegotiation option, default is "postgres" for the postgres
1831 * style negotiated connection with an extra round trip but more options.
1832 */
1833 if (conn->sslnegotiation)
1834 {
1835 if (strcmp(conn->sslnegotiation, "postgres") != 0
1836 && strcmp(conn->sslnegotiation, "direct") != 0)
1837 {
1839 libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1840 "sslnegotiation", conn->sslnegotiation);
1841 return false;
1842 }
1843
1844#ifndef USE_SSL
1845 if (conn->sslnegotiation[0] != 'p')
1846 {
1848 libpq_append_conn_error(conn, "%s value \"%s\" invalid when SSL support is not compiled in",
1849 "sslnegotiation", conn->sslnegotiation);
1850 return false;
1851 }
1852#endif
1853
1854 /*
1855 * Don't allow direct SSL negotiation with sslmode='prefer', because
1856 * that poses a risk of unintentional fallback to plaintext connection
1857 * when connecting to a pre-v17 server that does not support direct
1858 * SSL connections. To keep things simple, don't allow it with
1859 * sslmode='allow' or sslmode='disable' either. If a user goes through
1860 * the trouble of setting sslnegotiation='direct', they probably
1861 * intend to use SSL, and sslmode=disable or allow is probably a user
1862 * mistake anyway.
1863 */
1864 if (conn->sslnegotiation[0] == 'd' &&
1865 conn->sslmode[0] != 'r' && conn->sslmode[0] != 'v')
1866 {
1868 libpq_append_conn_error(conn, "weak sslmode \"%s\" may not be used with sslnegotiation=direct (use \"require\", \"verify-ca\", or \"verify-full\")",
1869 conn->sslmode);
1870 return false;
1871 }
1872 }
1873 else
1874 {
1876 if (!conn->sslnegotiation)
1877 goto oom_error;
1878 }
1879
1880#ifdef USE_SSL
1881
1882 /*
1883 * If sslrootcert=system, make sure our chosen sslmode is compatible.
1884 */
1885 if (conn->sslrootcert
1886 && strcmp(conn->sslrootcert, "system") == 0
1887 && strcmp(conn->sslmode, "verify-full") != 0)
1888 {
1890 libpq_append_conn_error(conn, "weak sslmode \"%s\" may not be used with sslrootcert=system (use \"verify-full\")",
1891 conn->sslmode);
1892 return false;
1893 }
1894#endif
1895
1896 /*
1897 * Validate TLS protocol versions for ssl_min_protocol_version and
1898 * ssl_max_protocol_version.
1899 */
1901 {
1903 libpq_append_conn_error(conn, "invalid \"%s\" value: \"%s\"",
1904 "ssl_min_protocol_version",
1906 return false;
1907 }
1909 {
1911 libpq_append_conn_error(conn, "invalid \"%s\" value: \"%s\"",
1912 "ssl_max_protocol_version",
1914 return false;
1915 }
1916
1917 /*
1918 * Check if the range of SSL protocols defined is correct. This is done
1919 * at this early step because this is independent of the SSL
1920 * implementation used, and this avoids unnecessary cycles with an
1921 * already-built SSL context when the connection is being established, as
1922 * it would be doomed anyway.
1923 */
1926 {
1928 libpq_append_conn_error(conn, "invalid SSL protocol version range");
1929 return false;
1930 }
1931
1932 /*
1933 * validate sslcertmode option
1934 */
1935 if (conn->sslcertmode)
1936 {
1937 if (strcmp(conn->sslcertmode, "disable") != 0 &&
1938 strcmp(conn->sslcertmode, "allow") != 0 &&
1939 strcmp(conn->sslcertmode, "require") != 0)
1940 {
1942 libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1943 "sslcertmode", conn->sslcertmode);
1944 return false;
1945 }
1946#ifndef USE_SSL
1947 if (strcmp(conn->sslcertmode, "require") == 0)
1948 {
1950 libpq_append_conn_error(conn, "%s value \"%s\" invalid when SSL support is not compiled in",
1951 "sslcertmode", conn->sslcertmode);
1952 return false;
1953 }
1954#endif
1955#ifndef HAVE_SSL_CTX_SET_CERT_CB
1956
1957 /*
1958 * Without a certificate callback, the current implementation can't
1959 * figure out if a certificate was actually requested, so "require" is
1960 * useless.
1961 */
1962 if (strcmp(conn->sslcertmode, "require") == 0)
1963 {
1965 libpq_append_conn_error(conn, "%s value \"%s\" is not supported (check OpenSSL version)",
1966 "sslcertmode", conn->sslcertmode);
1967 return false;
1968 }
1969#endif
1970 }
1971 else
1972 {
1974 if (!conn->sslcertmode)
1975 goto oom_error;
1976 }
1977
1978 /*
1979 * validate gssencmode option
1980 */
1981 if (conn->gssencmode)
1982 {
1983 if (strcmp(conn->gssencmode, "disable") != 0 &&
1984 strcmp(conn->gssencmode, "prefer") != 0 &&
1985 strcmp(conn->gssencmode, "require") != 0)
1986 {
1988 libpq_append_conn_error(conn, "invalid %s value: \"%s\"", "gssencmode", conn->gssencmode);
1989 return false;
1990 }
1991#ifndef ENABLE_GSS
1992 if (strcmp(conn->gssencmode, "require") == 0)
1993 {
1995 libpq_append_conn_error(conn, "gssencmode value \"%s\" invalid when GSSAPI support is not compiled in",
1996 conn->gssencmode);
1997 return false;
1998 }
1999#endif
2000 }
2001 else
2002 {
2004 if (!conn->gssencmode)
2005 goto oom_error;
2006 }
2007
2008 /*
2009 * validate target_session_attrs option, and set target_server_type
2010 */
2012 {
2013 if (strcmp(conn->target_session_attrs, "any") == 0)
2015 else if (strcmp(conn->target_session_attrs, "read-write") == 0)
2017 else if (strcmp(conn->target_session_attrs, "read-only") == 0)
2019 else if (strcmp(conn->target_session_attrs, "primary") == 0)
2021 else if (strcmp(conn->target_session_attrs, "standby") == 0)
2023 else if (strcmp(conn->target_session_attrs, "prefer-standby") == 0)
2025 else
2026 {
2028 libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
2029 "target_session_attrs",
2031 return false;
2032 }
2033 }
2034 else
2036
2038 {
2039 int len;
2040
2044 goto oom_error;
2047 if (len < 0)
2048 {
2049 libpq_append_conn_error(conn, "invalid SCRAM client key");
2050 return false;
2051 }
2052 if (len != SCRAM_MAX_KEY_LEN)
2053 {
2054 libpq_append_conn_error(conn, "invalid SCRAM client key length: %d", len);
2055 return false;
2056 }
2058 }
2059
2061 {
2062 int len;
2063
2067 goto oom_error;
2070 if (len < 0)
2071 {
2072 libpq_append_conn_error(conn, "invalid SCRAM server key");
2073 return false;
2074 }
2075 if (len != SCRAM_MAX_KEY_LEN)
2076 {
2077 libpq_append_conn_error(conn, "invalid SCRAM server key length: %d", len);
2078 return false;
2079 }
2081 }
2082
2083 /*
2084 * validate load_balance_hosts option, and set load_balance_type
2085 */
2087 {
2088 if (strcmp(conn->load_balance_hosts, "disable") == 0)
2090 else if (strcmp(conn->load_balance_hosts, "random") == 0)
2092 else
2093 {
2095 libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
2096 "load_balance_hosts",
2098 return false;
2099 }
2100 }
2101 else
2103
2105 {
2107
2108 /*
2109 * This is the "inside-out" variant of the Fisher-Yates shuffle
2110 * algorithm. Notionally, we append each new value to the array and
2111 * then swap it with a randomly-chosen array element (possibly
2112 * including itself, else we fail to generate permutations with the
2113 * last integer last). The swap step can be optimized by combining it
2114 * with the insertion.
2115 */
2116 for (i = 1; i < conn->nconnhost; i++)
2117 {
2118 int j = pg_prng_uint64_range(&conn->prng_state, 0, i);
2120
2121 conn->connhost[j] = conn->connhost[i];
2122 conn->connhost[i] = temp;
2123 }
2124 }
2125
2127 {
2128 if (!pqParseProtocolVersion(conn->min_protocol_version, &conn->min_pversion, conn, "min_protocol_version"))
2129 {
2131 return false;
2132 }
2133 }
2134 else
2135 {
2137 }
2138
2140 {
2141 if (!pqParseProtocolVersion(conn->max_protocol_version, &conn->max_pversion, conn, "max_protocol_version"))
2142 {
2144 return false;
2145 }
2146 }
2147 else
2148 {
2149 /*
2150 * Default to PG_PROTOCOL_GREASE, which is larger than all real
2151 * versions, to test negotiation. The server should automatically
2152 * downgrade to a supported version.
2153 *
2154 * This behavior is for 19beta only. It will be reverted before RC1.
2155 */
2157 }
2158
2160 {
2162 libpq_append_conn_error(conn, "\"%s\" is greater than \"%s\"", "min_protocol_version", "max_protocol_version");
2163 return false;
2164 }
2165
2166 /*
2167 * Resolve special "auto" client_encoding from the locale
2168 */
2170 strcmp(conn->client_encoding_initial, "auto") == 0)
2171 {
2175 goto oom_error;
2176 }
2177
2178 /*
2179 * Only if we get this far is it appropriate to try to connect. (We need a
2180 * state flag, rather than just the boolean result of this function, in
2181 * case someone tries to PQreset() the PGconn.)
2182 */
2183 conn->options_valid = true;
2184
2185 return true;
2186
2187oom_error:
2189 libpq_append_conn_error(conn, "out of memory");
2190 return false;
2191}
int pg_b64_dec_len(int srclen)
Definition base64.c:239
int pg_b64_decode(const char *src, int len, uint8 *dst, int dstlen)
Definition base64.c:116
uint32_t uint32
Definition c.h:624
#define lengthof(array)
Definition c.h:873
const pg_fe_sasl_mech pg_oauth_mech
const pg_fe_sasl_mech pg_scram_mech
char * pg_fe_getauthname(PQExpBuffer errorMessage)
Definition fe-auth.c:1344
static bool pqParseProtocolVersion(const char *value, ProtocolVersion *result, PGconn *conn, const char *context)
#define DefaultHost
Definition fe-connect.c:121
static bool sslVerifyProtocolRange(const char *min, const char *max)
static void libpq_prng_init(PGconn *conn)
static char * passwordFromFile(const char *hostname, const char *port, const char *dbname, const char *username, const char *pgpassfile, const char **errmsg)
bool pqGetHomeDirectory(char *buf, int bufsize)
#define DefaultSSLMode
Definition fe-connect.c:134
#define DefaultGSSMode
Definition fe-connect.c:142
static int count_comma_separated_elems(const char *input)
static void clear_allowed_sasl_mechs(PGconn *conn)
static void fill_allowed_sasl_mechs(PGconn *conn)
#define DefaultChannelBinding
Definition fe-connect.c:126
static int index_of_allowed_sasl_mech(PGconn *conn, const pg_fe_sasl_mech *mech)
static bool sslVerifyProtocolVersion(const char *version)
#define DefaultSSLNegotiation
Definition fe-connect.c:137
#define PGPASSFILE
Definition fe-connect.c:79
#define DefaultSSLCertMode
Definition fe-connect.c:135
static char * parse_comma_separated_list(char **startptr, bool *more)
int j
Definition isn.c:78
#define MAXPGPATH
#define DEFAULT_PGSOCKET_DIR
uint64 pg_prng_uint64_range(pg_prng_state *state, uint64 rmin, uint64 rmax)
Definition pg_prng.c:144
#define pg_encoding_to_char
Definition pg_wchar.h:483
#define snprintf
Definition port.h:260
int pg_get_encoding_from_locale(const char *ctype, bool write_message)
Definition chklocale.c:301
#define PG_PROTOCOL_EARLIEST
Definition pqcomm.h:94
static bool is_unixsock_path(const char *path)
Definition pqcomm.h:66
#define PG_PROTOCOL_GREASE
Definition pqcomm.h:115
#define AUTH_REQ_SSPI
Definition protocol.h:105
#define AUTH_REQ_SASL_CONT
Definition protocol.h:107
#define AUTH_REQ_GSS
Definition protocol.h:103
#define AUTH_REQ_MD5
Definition protocol.h:101
#define AUTH_REQ_PASSWORD
Definition protocol.h:99
#define AUTH_REQ_GSS_CONT
Definition protocol.h:104
#define AUTH_REQ_SASL
Definition protocol.h:106
#define AUTH_REQ_SASL_FIN
Definition protocol.h:108
#define SCRAM_MAX_KEY_LEN
#define calloc(a, b)
char * password
Definition libpq-int.h:362
char * port
Definition libpq-int.h:360
char * hostaddr
Definition libpq-int.h:359
pg_conn_host_type type
Definition libpq-int.h:357
uint8 * scram_client_key_binary
Definition libpq-int.h:546
char * sslrootcert
Definition libpq-int.h:413
char * sslnegotiation
Definition libpq-int.h:407
int nconnhost
Definition libpq-int.h:481
char * require_auth
Definition libpq-int.h:428
char * channel_binding
Definition libpq-int.h:398
char * pghost
Definition libpq-int.h:374
size_t scram_client_key_len
Definition libpq-int.h:545
char * ssl_max_protocol_version
Definition libpq-int.h:426
uint8 * scram_server_key_binary
Definition libpq-int.h:548
char * pgpass
Definition libpq-int.h:396
ProtocolVersion min_pversion
Definition libpq-int.h:549
char * dbName
Definition libpq-int.h:390
char * sslcertmode
Definition libpq-int.h:412
uint32 allowed_auth_methods
Definition libpq-int.h:518
char * target_session_attrs
Definition libpq-int.h:427
bool auth_required
Definition libpq-int.h:516
char * max_protocol_version
Definition libpq-int.h:424
char * load_balance_hosts
Definition libpq-int.h:429
char * pguser
Definition libpq-int.h:395
char * min_protocol_version
Definition libpq-int.h:423
char * client_encoding_initial
Definition libpq-int.h:386
char * sslmode
Definition libpq-int.h:406
pg_prng_state prng_state
Definition libpq-int.h:564
char * ssl_min_protocol_version
Definition libpq-int.h:425
char * gssencmode
Definition libpq-int.h:418
char * scram_server_key
Definition libpq-int.h:431
char * pghostaddr
Definition libpq-int.h:378
char * scram_client_key
Definition libpq-int.h:430
ProtocolVersion max_pversion
Definition libpq-int.h:550
char * pgpassfile
Definition libpq-int.h:397
PGLoadBalanceType load_balance_type
Definition libpq-int.h:536
size_t scram_server_key_len
Definition libpq-int.h:547
char * pgport
Definition libpq-int.h:382
const pg_fe_sasl_mech * allowed_sasl_mechs[2]
Definition libpq-int.h:520

References pg_conn::allowed_auth_methods, pg_conn::allowed_sasl_mechs, Assert, AUTH_REQ_GSS, AUTH_REQ_GSS_CONT, AUTH_REQ_MD5, AUTH_REQ_PASSWORD, AUTH_REQ_SASL, AUTH_REQ_SASL_CONT, AUTH_REQ_SASL_FIN, AUTH_REQ_SSPI, pg_conn::auth_required, calloc, pg_conn::channel_binding, CHT_HOST_ADDRESS, CHT_HOST_NAME, CHT_UNIX_SOCKET, clear_allowed_sasl_mechs(), pg_conn::client_encoding_initial, conn, CONNECTION_BAD, pg_conn::connhost, count_comma_separated_elems(), pg_conn::dbName, DEFAULT_PGSOCKET_DIR, DefaultChannelBinding, DefaultGSSMode, DefaultHost, DefaultSSLCertMode, DefaultSSLMode, DefaultSSLNegotiation, pg_conn::errorMessage, fb(), fill_allowed_sasl_mechs(), free, pg_conn::gssencmode, pg_conn_host::host, pg_conn_host::hostaddr, i, index_of_allowed_sasl_mech(), is_unixsock_path(), j, len, lengthof, libpq_append_conn_error(), libpq_prng_init(), LOAD_BALANCE_DISABLE, pg_conn::load_balance_hosts, LOAD_BALANCE_RANDOM, pg_conn::load_balance_type, malloc, pg_conn::max_protocol_version, pg_conn::max_pversion, MAXPGPATH, pg_conn::min_protocol_version, pg_conn::min_pversion, pg_conn::nconnhost, pg_conn::options_valid, parse_comma_separated_list(), pg_conn_host::password, passwordFromFile(), pg_b64_dec_len(), pg_b64_decode(), pg_encoding_to_char, pg_fe_getauthname(), pg_get_encoding_from_locale(), pg_oauth_mech, pg_prng_uint64_range(), PG_PROTOCOL_EARLIEST, PG_PROTOCOL_GREASE, pg_scram_mech, pg_conn::pghost, pg_conn::pghostaddr, pg_conn::pgpass, PGPASSFILE, pg_conn::pgpassfile, pg_conn::pgport, pg_conn::pguser, pg_conn_host::port, pqGetHomeDirectory(), pqParseProtocolVersion(), pg_conn::prng_state, pg_conn::require_auth, pg_conn::scram_client_key, pg_conn::scram_client_key_binary, pg_conn::scram_client_key_len, SCRAM_MAX_KEY_LEN, pg_conn::scram_server_key, pg_conn::scram_server_key_binary, pg_conn::scram_server_key_len, SERVER_TYPE_ANY, SERVER_TYPE_PREFER_STANDBY, SERVER_TYPE_PRIMARY, SERVER_TYPE_READ_ONLY, SERVER_TYPE_READ_WRITE, SERVER_TYPE_STANDBY, snprintf, pg_conn::ssl_max_protocol_version, pg_conn::ssl_min_protocol_version, pg_conn::sslcertmode, pg_conn::sslmode, pg_conn::sslnegotiation, pg_conn::sslrootcert, sslVerifyProtocolRange(), sslVerifyProtocolVersion(), pg_conn::status, pg_conn::target_server_type, pg_conn::target_session_attrs, pg_conn_host::type, and pg_conn::whichhost.

Referenced by PQcancelCreate(), PQconnectStart(), PQconnectStartParams(), and PQsetdbLogin().

◆ pqCopyPGconn()

bool pqCopyPGconn ( PGconn srcConn,
PGconn dstConn 
)
extern

Definition at line 1042 of file fe-connect.c.

1043{
1045
1046 /* copy over connection options */
1047 for (option = PQconninfoOptions; option->keyword; option++)
1048 {
1049 if (option->connofs >= 0)
1050 {
1051 const char **tmp = (const char **) ((char *) srcConn + option->connofs);
1052
1053 if (*tmp)
1054 {
1055 char **dstConnmember = (char **) ((char *) dstConn + option->connofs);
1056
1057 if (*dstConnmember)
1059 *dstConnmember = strdup(*tmp);
1060 if (*dstConnmember == NULL)
1061 {
1062 libpq_append_conn_error(dstConn, "out of memory");
1063 return false;
1064 }
1065 }
1066 }
1067 }
1068 return true;
1069}
static const internalPQconninfoOption PQconninfoOptions[]
Definition fe-connect.c:201

References fb(), free, libpq_append_conn_error(), and PQconninfoOptions.

Referenced by PQcancelCreate().

◆ pqDropConnection()

void pqDropConnection ( PGconn conn,
bool  flushInput 
)
extern

Definition at line 537 of file fe-connect.c.

538{
539 /* Drop any SSL state */
541
542 /* Close the socket itself */
543 if (conn->sock != PGINVALID_SOCKET)
546
547 /* Optionally discard any unread data */
548 if (flushInput)
549 conn->inStart = conn->inCursor = conn->inEnd = 0;
550
551 /* Always discard any unsent data */
552 conn->outCount = 0;
553
554 /* Likewise, discard any pending pipelined commands */
559
560 /* Free authentication/encryption state */
562 {
563 /*
564 * Any in-progress async authentication should be torn down first so
565 * that cleanup_async_auth() can depend on the other authentication
566 * state if necessary.
567 */
570 }
572 /* cleanup_async_auth() should have done this, but make sure */
574#ifdef ENABLE_GSS
575 {
577
578 if (conn->gcred != GSS_C_NO_CREDENTIAL)
579 {
580 gss_release_cred(&min_s, &conn->gcred);
581 conn->gcred = GSS_C_NO_CREDENTIAL;
582 }
583 if (conn->gctx)
585 if (conn->gtarg_nam)
586 gss_release_name(&min_s, &conn->gtarg_nam);
587 if (conn->gss_SendBuffer)
588 {
589 free(conn->gss_SendBuffer);
590 conn->gss_SendBuffer = NULL;
591 }
592 if (conn->gss_RecvBuffer)
593 {
594 free(conn->gss_RecvBuffer);
595 conn->gss_RecvBuffer = NULL;
596 }
597 if (conn->gss_ResultBuffer)
598 {
599 free(conn->gss_ResultBuffer);
600 conn->gss_ResultBuffer = NULL;
601 }
602 conn->gssenc = false;
603 }
604#endif
605#ifdef ENABLE_SSPI
606 if (conn->sspitarget)
607 {
608 free(conn->sspitarget);
609 conn->sspitarget = NULL;
610 }
611 if (conn->sspicred)
612 {
613 FreeCredentialsHandle(conn->sspicred);
614 free(conn->sspicred);
615 conn->sspicred = NULL;
616 }
617 if (conn->sspictx)
618 {
619 DeleteSecurityContext(conn->sspictx);
620 free(conn->sspictx);
621 conn->sspictx = NULL;
622 }
623 conn->usesspi = 0;
624#endif
625 if (conn->sasl_state)
626 {
629 }
630}
static void pqFreeCommandQueue(PGcmdQueueEntry *queue)
Definition fe-connect.c:637
void pqsecure_close(PGconn *conn)
Definition fe-secure.c:152
#define PGINVALID_SOCKET
Definition port.h:31
#define closesocket
Definition port.h:397
pgsocket sock
Definition libpq-int.h:500
const pg_fe_sasl_mech * sasl
Definition libpq-int.h:612
void(* cleanup_async_auth)(PGconn *conn)
Definition libpq-int.h:530
PGcmdQueueEntry * cmd_queue_recycle
Definition libpq-int.h:497
pgsocket altsock
Definition libpq-int.h:531
PostgresPollingStatusType(* async_auth)(PGconn *conn)
Definition libpq-int.h:529
void * sasl_state
Definition libpq-int.h:613
void(* free)(void *state)

References pg_conn::altsock, pg_conn::async_auth, pg_conn::cleanup_async_auth, closesocket, pg_conn::cmd_queue_head, pg_conn::cmd_queue_recycle, pg_conn::cmd_queue_tail, conn, fb(), free, pg_fe_sasl_mech::free, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, pg_conn::outCount, PGINVALID_SOCKET, pqFreeCommandQueue(), pqsecure_close(), pg_conn::sasl, pg_conn::sasl_state, and pg_conn::sock.

Referenced by handleFatalError(), pqClosePGconn(), pqConnectDBStart(), PQconnectPoll(), and pqReadData().

◆ pqEndcopy3()

int pqEndcopy3 ( PGconn conn)
extern

Definition at line 2113 of file fe-protocol3.c.

2114{
2116
2120 {
2121 libpq_append_conn_error(conn, "no COPY in progress");
2122 return 1;
2123 }
2124
2125 /* Send the CopyDone message if needed */
2128 {
2129 if (pqPutMsgStart(PqMsg_CopyDone, conn) < 0 ||
2130 pqPutMsgEnd(conn) < 0)
2131 return 1;
2132
2133 /*
2134 * If we sent the COPY command in extended-query mode, we must issue a
2135 * Sync as well.
2136 */
2137 if (conn->cmd_queue_head &&
2139 {
2140 if (pqPutMsgStart(PqMsg_Sync, conn) < 0 ||
2141 pqPutMsgEnd(conn) < 0)
2142 return 1;
2143 }
2144 }
2145
2146 /*
2147 * make sure no data is waiting to be sent, abort if we are non-blocking
2148 * and the flush fails
2149 */
2151 return 1;
2152
2153 /* Return to active duty */
2155
2156 /*
2157 * Non blocking connections may have to abort at this point. If everyone
2158 * played the game there should be no problem, but in error scenarios the
2159 * expected messages may not have arrived yet. (We are assuming that the
2160 * backend's packetizing will ensure that CommandComplete arrives along
2161 * with the CopyDone; are there corner cases where that doesn't happen?)
2162 */
2164 return 1;
2165
2166 /* Wait for the completion response */
2168
2169 /* Expecting a successful result */
2170 if (result && result->resultStatus == PGRES_COMMAND_OK)
2171 {
2172 PQclear(result);
2173 return 0;
2174 }
2175
2176 /*
2177 * Trouble. For backwards-compatibility reasons, we issue the error
2178 * message as if it were a notice (would be nice to get rid of this
2179 * silliness, but too many apps probably don't handle errors from
2180 * PQendcopy reasonably). Note that the app can still obtain the error
2181 * status from the PGconn object.
2182 */
2183 if (conn->errorMessage.len > 0)
2184 {
2185 /* We have to strip the trailing newline ... pain in neck... */
2187
2188 if (svLast == '\n')
2189 conn->errorMessage.data[conn->errorMessage.len - 1] = '\0';
2192 }
2193
2194 PQclear(result);
2195
2196 return 1;
2197}
uint32 result
void pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt,...)
Definition fe-exec.c:944
int PQisBusy(PGconn *conn)
Definition fe-exec.c:2048
int pqFlush(PGconn *conn)
Definition fe-misc.c:994
int pqPutMsgStart(char msg_type, PGconn *conn)
Definition fe-misc.c:473
int pqPutMsgEnd(PGconn *conn)
Definition fe-misc.c:532
#define PQgetResult
@ PGRES_COMMAND_OK
Definition libpq-fe.h:131
#define pqIsnonblocking(conn)
Definition libpq-int.h:940
#define PqMsg_CopyDone
Definition protocol.h:64
#define PqMsg_Sync
Definition protocol.h:27
PGNoticeHooks noticeHooks
Definition libpq-int.h:455

References pg_conn::asyncStatus, pg_conn::cmd_queue_head, conn, PQExpBufferData::data, pg_conn::errorMessage, fb(), PQExpBufferData::len, libpq_append_conn_error(), pg_conn::noticeHooks, PGASYNC_BUSY, PGASYNC_COPY_BOTH, PGASYNC_COPY_IN, PGASYNC_COPY_OUT, PGQUERY_SIMPLE, PGRES_COMMAND_OK, PQclear, pqFlush(), PQgetResult, pqInternalNotice(), PQisBusy(), pqIsnonblocking, PqMsg_CopyDone, PqMsg_Sync, pqPutMsgEnd(), pqPutMsgStart(), PGcmdQueueEntry::queryclass, and result.

Referenced by PQendcopy().

◆ pqFlush()

int pqFlush ( PGconn conn)
extern

◆ pqFunctionCall3()

PGresult * pqFunctionCall3 ( PGconn conn,
Oid  fnid,
int result_buf,
int actual_result_len,
int  result_is_int,
const PQArgBlock args,
int  nargs 
)
extern

Definition at line 2206 of file fe-protocol3.c.

2210{
2211 bool needInput = false;
2213 char id;
2214 int msgLength;
2215 int avail;
2216 int i;
2217
2218 /* already validated by PQfn */
2220
2221 /* PQfn already validated connection state */
2222
2224 pqPutInt(fnid, 4, conn) < 0 || /* function id */
2225 pqPutInt(1, 2, conn) < 0 || /* # of format codes */
2226 pqPutInt(1, 2, conn) < 0 || /* format code: BINARY */
2227 pqPutInt(nargs, 2, conn) < 0) /* # of args */
2228 {
2229 /* error message should be set up already */
2230 return NULL;
2231 }
2232
2233 for (i = 0; i < nargs; ++i)
2234 { /* len.int4 + contents */
2235 if (pqPutInt(args[i].len, 4, conn))
2236 return NULL;
2237 if (args[i].len == -1)
2238 continue; /* it's NULL */
2239
2240 if (args[i].isint)
2241 {
2242 if (pqPutInt(args[i].u.integer, args[i].len, conn))
2243 return NULL;
2244 }
2245 else
2246 {
2247 if (pqPutnchar(args[i].u.ptr, args[i].len, conn))
2248 return NULL;
2249 }
2250 }
2251
2252 if (pqPutInt(1, 2, conn) < 0) /* result format code: BINARY */
2253 return NULL;
2254
2255 if (pqPutMsgEnd(conn) < 0 ||
2256 pqFlush(conn))
2257 return NULL;
2258
2259 for (;;)
2260 {
2261 if (needInput)
2262 {
2263 /* Wait for some data to arrive (or for the channel to close) */
2264 if (pqWait(true, false, conn) ||
2265 pqReadData(conn) < 0)
2266 break;
2267 }
2268
2269 /*
2270 * Scan the message. If we run out of data, loop around to try again.
2271 */
2272 needInput = true;
2273
2275 if (pqGetc(&id, conn))
2276 continue;
2277 if (pqGetInt(&msgLength, 4, conn))
2278 continue;
2279
2280 /*
2281 * Try to validate message type/length here. A length less than 4 is
2282 * definitely broken. Large lengths should only be believed for a few
2283 * message types.
2284 */
2285 if (msgLength < 4)
2286 {
2288 break;
2289 }
2290 if (msgLength > 30000 && !VALID_LONG_MESSAGE_TYPE(id))
2291 {
2293 break;
2294 }
2295
2296 /*
2297 * Can't process if message body isn't all here yet.
2298 */
2299 msgLength -= 4;
2300 avail = conn->inEnd - conn->inCursor;
2301 if (avail < msgLength)
2302 {
2303 /*
2304 * Before looping, enlarge the input buffer if needed to hold the
2305 * whole message. See notes in parseInput.
2306 */
2308 conn))
2309 {
2310 /*
2311 * Abandon the connection. There's not much else we can
2312 * safely do; we can't just ignore the message or we could
2313 * miss important changes to the connection state.
2314 * pqCheckInBufferSpace() already reported the error.
2315 */
2317 break;
2318 }
2319 continue;
2320 }
2321
2322 /*
2323 * We should see V or E response to the command, but might get N
2324 * and/or A notices first. We also need to swallow the final Z before
2325 * returning.
2326 */
2327 switch (id)
2328 {
2331 continue;
2332 if (*actual_result_len != -1)
2333 {
2334 if (result_is_int)
2335 {
2337 continue;
2338 }
2339 else
2340 {
2343 conn))
2344 continue;
2345 }
2346 }
2347 /* correctly finished function result message */
2348 status = PGRES_COMMAND_OK;
2349 break;
2351 if (pqGetErrorNotice3(conn, true))
2352 continue;
2353 status = PGRES_FATAL_ERROR;
2354 break;
2356 /* handle notify and go back to processing return values */
2357 if (getNotify(conn))
2358 continue;
2359 break;
2361 /* handle notice and go back to processing return values */
2362 if (pqGetErrorNotice3(conn, false))
2363 continue;
2364 break;
2367 continue;
2368
2369 /* consume the message */
2371
2372 /*
2373 * If we already have a result object (probably an error), use
2374 * that. Otherwise, if we saw a function result message,
2375 * report COMMAND_OK. Otherwise, the backend violated the
2376 * protocol, so complain.
2377 */
2379 {
2380 if (status == PGRES_COMMAND_OK)
2381 {
2382 conn->result = PQmakeEmptyPGresult(conn, status);
2383 if (!conn->result)
2384 {
2385 libpq_append_conn_error(conn, "out of memory");
2387 }
2388 }
2389 else
2390 {
2391 libpq_append_conn_error(conn, "protocol error: no function result");
2393 }
2394 }
2395 /* and we're out */
2396 return pqPrepareAsyncResult(conn);
2399 continue;
2400 break;
2401 default:
2402 /* The backend violates the protocol. */
2403 libpq_append_conn_error(conn, "protocol error: id=0x%x", id);
2405
2406 /*
2407 * We can't call parsing done due to the protocol violation
2408 * (so message tracing wouldn't work), but trust the specified
2409 * message length as what to skip.
2410 */
2411 conn->inStart += 5 + msgLength;
2412 return pqPrepareAsyncResult(conn);
2413 }
2414
2415 /* Completed parsing this message, keep going */
2417 needInput = false;
2418 }
2419
2420 /*
2421 * We fall out of the loop only upon failing to read data.
2422 * conn->errorMessage has been set by pqWait or pqReadData. We want to
2423 * append it to any already-received error message.
2424 */
2426 return pqPrepareAsyncResult(conn);
2427}
PGresult * pqPrepareAsyncResult(PGconn *conn)
Definition fe-exec.c:857
void pqSaveErrorResult(PGconn *conn)
Definition fe-exec.c:809
PGresult * PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
Definition fe-exec.c:160
int pqReadData(PGconn *conn)
Definition fe-misc.c:606
int pqPutInt(int value, size_t bytes, PGconn *conn)
Definition fe-misc.c:253
void pqParseDone(PGconn *conn, int newInStart)
Definition fe-misc.c:443
int pqGetc(char *result, PGconn *conn)
Definition fe-misc.c:77
int pqGetInt(int *result, size_t bytes, PGconn *conn)
Definition fe-misc.c:216
int pqWait(int forRead, int forWrite, PGconn *conn)
Definition fe-misc.c:1019
int pqPutnchar(const void *s, size_t len, PGconn *conn)
Definition fe-misc.c:202
int pqCheckInBufferSpace(size_t bytes_needed, PGconn *conn)
Definition fe-misc.c:351
int pqGetnchar(void *s, size_t len, PGconn *conn)
Definition fe-misc.c:165
static int getNotify(PGconn *conn)
static int getParameterStatus(PGconn *conn)
static void handleFatalError(PGconn *conn)
#define VALID_LONG_MESSAGE_TYPE(id)
static void handleSyncLoss(PGconn *conn, char id, int msgLength)
static int getReadyForQuery(PGconn *conn)
int pqGetErrorNotice3(PGconn *conn, bool isError)
ExecStatusType
Definition libpq-fe.h:129
#define pgHavePendingResult(conn)
Definition libpq-int.h:933
#define PqMsg_NotificationResponse
Definition protocol.h:41
#define PqMsg_FunctionCall
Definition protocol.h:23
#define PqMsg_FunctionCallResponse
Definition protocol.h:53
#define PqMsg_ReadyForQuery
Definition protocol.h:55
#define PqMsg_ParameterStatus
Definition protocol.h:51
#define PqMsg_ErrorResponse
Definition protocol.h:44
#define PqMsg_NoticeResponse
Definition protocol.h:49

References Assert, conn, fb(), getNotify(), getParameterStatus(), getReadyForQuery(), handleFatalError(), handleSyncLoss(), i, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, len, libpq_append_conn_error(), pgHavePendingResult, PGRES_COMMAND_OK, PGRES_FATAL_ERROR, pg_conn::pipelineStatus, PQ_PIPELINE_OFF, pqCheckInBufferSpace(), pqFlush(), pqGetc(), pqGetErrorNotice3(), pqGetInt(), pqGetnchar(), PQmakeEmptyPGresult(), PqMsg_ErrorResponse, PqMsg_FunctionCall, PqMsg_FunctionCallResponse, PqMsg_NoticeResponse, PqMsg_NotificationResponse, PqMsg_ParameterStatus, PqMsg_ReadyForQuery, pqParseDone(), pqPrepareAsyncResult(), pqPutInt(), pqPutMsgEnd(), pqPutMsgStart(), pqPutnchar(), pqReadData(), pqSaveErrorResult(), pqWait(), pg_conn::result, and VALID_LONG_MESSAGE_TYPE.

Referenced by PQfn().

◆ pqGetc()

int pqGetc ( char result,
PGconn conn 
)
extern

◆ pqGetCopyData3()

int pqGetCopyData3 ( PGconn conn,
char **  buffer,
int  async 
)
extern

Definition at line 1948 of file fe-protocol3.c.

1949{
1950 int msgLength;
1951
1952 for (;;)
1953 {
1954 /*
1955 * Collect the next input message. To make life simpler for async
1956 * callers, we keep returning 0 until the next message is fully
1957 * available, even if it is not Copy Data.
1958 */
1960 if (msgLength < 0)
1961 return msgLength; /* end-of-copy or error */
1962 if (msgLength == 0)
1963 {
1964 /* Don't block if async read requested */
1965 if (async)
1966 return 0;
1967 /* Need to load more data */
1968 if (pqWait(true, false, conn) ||
1969 pqReadData(conn) < 0)
1970 return -2;
1971 continue;
1972 }
1973
1974 /*
1975 * Drop zero-length messages (shouldn't happen anyway). Otherwise
1976 * pass the data back to the caller.
1977 */
1978 msgLength -= 4;
1979 if (msgLength > 0)
1980 {
1981 *buffer = (char *) malloc(msgLength + 1);
1982 if (*buffer == NULL)
1983 {
1984 libpq_append_conn_error(conn, "out of memory");
1985 return -2;
1986 }
1987 memcpy(*buffer, &conn->inBuffer[conn->inCursor], msgLength);
1988 (*buffer)[msgLength] = '\0'; /* Add terminating null */
1989
1990 /* Mark message consumed */
1992
1993 return msgLength;
1994 }
1995
1996 /* Empty, so drop it and loop around for another */
1998 }
1999}
static int getCopyDataMessage(PGconn *conn)

References conn, fb(), getCopyDataMessage(), pg_conn::inBuffer, pg_conn::inCursor, libpq_append_conn_error(), malloc, memcpy(), pqParseDone(), pqReadData(), and pqWait().

Referenced by PQgetCopyData().

◆ pqGetErrorNotice3()

int pqGetErrorNotice3 ( PGconn conn,
bool  isError 
)
extern

Definition at line 898 of file fe-protocol3.c.

899{
900 PGresult *res = NULL;
901 bool have_position = false;
903 char id;
904
905 /* If in pipeline mode, set error indicator for it */
908
909 /*
910 * If this is an error message, pre-emptively clear any incomplete query
911 * result we may have. We'd just throw it away below anyway, and
912 * releasing it before collecting the error might avoid out-of-memory.
913 */
914 if (isError)
916
917 /*
918 * Since the fields might be pretty long, we create a temporary
919 * PQExpBuffer rather than using conn->workBuffer. workBuffer is intended
920 * for stuff that is expected to be short. We shouldn't use
921 * conn->errorMessage either, since this might be only a notice.
922 */
924
925 /*
926 * Make a PGresult to hold the accumulated fields. We temporarily lie
927 * about the result status, so that PQmakeEmptyPGresult doesn't uselessly
928 * copy conn->errorMessage.
929 *
930 * NB: This allocation can fail, if you run out of memory. The rest of the
931 * function handles that gracefully, and we still try to set the error
932 * message as the connection's error message.
933 */
935 if (res)
937
938 /*
939 * Read the fields and save into res.
940 *
941 * While at it, save the SQLSTATE in conn->last_sqlstate, and note whether
942 * we saw a PG_DIAG_STATEMENT_POSITION field.
943 */
944 for (;;)
945 {
946 if (pqGetc(&id, conn))
947 goto fail;
948 if (id == '\0')
949 break; /* terminator found */
950 if (pqGets(&workBuf, conn))
951 goto fail;
952 pqSaveMessageField(res, id, workBuf.data);
953 if (id == PG_DIAG_SQLSTATE)
955 sizeof(conn->last_sqlstate));
956 else if (id == PG_DIAG_STATEMENT_POSITION)
957 have_position = true;
958 }
959
960 /*
961 * Save the active query text, if any, into res as well; but only if we
962 * might need it for an error cursor display, which is only true if there
963 * is a PG_DIAG_STATEMENT_POSITION field.
964 */
967
968 /*
969 * Now build the "overall" error message for PQresultErrorMessage.
970 */
973
974 /*
975 * Either save error as current async result, or just emit the notice.
976 */
977 if (isError)
978 {
979 pqClearAsyncResult(conn); /* redundant, but be safe */
980 if (res)
981 {
982 pqSetResultError(res, &workBuf, 0);
983 conn->result = res;
984 }
985 else
986 {
987 /* Fall back to using the internal-error processing paths */
988 conn->error_result = true;
989 }
990
992 libpq_append_conn_error(conn, "out of memory");
993 else
995 }
996 else
997 {
998 /* if we couldn't allocate the result set, just discard the NOTICE */
999 if (res)
1000 {
1001 /*
1002 * We can cheat a little here and not copy the message. But if we
1003 * were unlucky enough to run out of memory while filling workBuf,
1004 * insert "out of memory", as in pqSetResultError.
1005 */
1007 res->errMsg = libpq_gettext("out of memory\n");
1008 else
1009 res->errMsg = workBuf.data;
1010 if (res->noticeHooks.noticeRec != NULL)
1012 PQclear(res);
1013 }
1014 }
1015
1017 return 0;
1018
1019fail:
1020 PQclear(res);
1022 return EOF;
1023}
void pqSaveMessageField(PGresult *res, char code, const char *value)
Definition fe-exec.c:1066
void pqSetResultError(PGresult *res, PQExpBuffer errorMessage, int offset)
Definition fe-exec.c:698
char * pqResultStrdup(PGresult *res, const char *str)
Definition fe-exec.c:681
int pqGets(PQExpBuffer buf, PGconn *conn)
Definition fe-misc.c:136
void pqBuildErrorMessage3(PQExpBuffer msg, const PGresult *res, PGVerbosity verbosity, PGContextVisibility show_context)
@ PGRES_EMPTY_QUERY
Definition libpq-fe.h:130
@ PGRES_NONFATAL_ERROR
Definition libpq-fe.h:141
@ PQ_PIPELINE_ABORTED
Definition libpq-fe.h:195
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition strlcpy.c:45
void initPQExpBuffer(PQExpBuffer str)
Definition pqexpbuffer.c:90
void termPQExpBuffer(PQExpBuffer str)
#define PQExpBufferDataBroken(buf)
Definition pqexpbuffer.h:67
PQnoticeReceiver noticeRec
Definition libpq-int.h:149
void * noticeRecArg
Definition libpq-int.h:150
PGVerbosity verbosity
Definition libpq-int.h:561
char last_sqlstate[6]
Definition libpq-int.h:466
PGContextVisibility show_context
Definition libpq-int.h:562
PGNoticeHooks noticeHooks
Definition libpq-int.h:183

References appendPQExpBufferStr(), pg_conn::cmd_queue_head, conn, PQExpBufferData::data, pg_result::errMsg, pg_conn::error_result, pg_conn::errorMessage, pg_result::errQuery, fb(), initPQExpBuffer(), pg_conn::last_sqlstate, libpq_append_conn_error(), libpq_gettext, pg_result::noticeHooks, PGNoticeHooks::noticeRec, PGNoticeHooks::noticeRecArg, PG_DIAG_SQLSTATE, PG_DIAG_STATEMENT_POSITION, PGRES_EMPTY_QUERY, PGRES_FATAL_ERROR, PGRES_NONFATAL_ERROR, pg_conn::pipelineStatus, PQ_PIPELINE_ABORTED, PQ_PIPELINE_OFF, pqBuildErrorMessage3(), PQclear, pqClearAsyncResult(), PQExpBufferDataBroken, pqGetc(), pqGets(), PQmakeEmptyPGresult(), pqResultStrdup(), pqSaveMessageField(), pqSetResultError(), PGcmdQueueEntry::query, resetPQExpBuffer(), pg_conn::result, pg_result::resultStatus, pg_conn::show_context, strlcpy(), termPQExpBuffer(), and pg_conn::verbosity.

Referenced by getCopyDataMessage(), PQconnectPoll(), pqFunctionCall3(), and pqParseInput3().

◆ pqGetHomeDirectory()

bool pqGetHomeDirectory ( char buf,
int  bufsize 
)
extern

Definition at line 8270 of file fe-connect.c.

8271{
8272#ifndef WIN32
8273 const char *home;
8274
8275 home = getenv("HOME");
8276 if (home && home[0])
8277 {
8279 return true;
8280 }
8281 else
8282 {
8283 struct passwd pwbuf;
8284 struct passwd *pw;
8285 char tmpbuf[1024];
8286 int rc;
8287
8288 rc = getpwuid_r(geteuid(), &pwbuf, tmpbuf, sizeof tmpbuf, &pw);
8289 if (rc != 0 || !pw)
8290 return false;
8291 strlcpy(buf, pw->pw_dir, bufsize);
8292 return true;
8293 }
8294#else
8295 char tmppath[MAX_PATH];
8296
8297 ZeroMemory(tmppath, sizeof(tmppath));
8299 return false;
8300 snprintf(buf, bufsize, "%s/postgresql", tmppath);
8301 return true;
8302#endif
8303}
#define bufsize
static char buf[DEFAULT_XLOG_SEG_SIZE]
static StringInfoData tmpbuf
Definition walsender.c:195

References buf, bufsize, fb(), snprintf, strlcpy(), and tmpbuf.

Referenced by initialize_SSL(), parseServiceInfo(), and pqConnectOptions2().

◆ pqGetInt()

int pqGetInt ( int result,
size_t  bytes,
PGconn conn 
)
extern

Definition at line 216 of file fe-misc.c.

217{
218 uint16 tmp2;
219 uint32 tmp4;
220
221 switch (bytes)
222 {
223 case 2:
224 if (conn->inCursor + 2 > conn->inEnd)
225 return EOF;
227 conn->inCursor += 2;
228 *result = (int) pg_ntoh16(tmp2);
229 break;
230 case 4:
231 if (conn->inCursor + 4 > conn->inEnd)
232 return EOF;
234 conn->inCursor += 4;
235 *result = (int) pg_ntoh32(tmp4);
236 break;
237 default:
239 "integer of size %zu not supported by pqGetInt",
240 bytes);
241 return EOF;
242 }
243
244 return 0;
245}
uint16_t uint16
Definition c.h:623
#define pg_ntoh32(x)
Definition pg_bswap.h:125
#define pg_ntoh16(x)
Definition pg_bswap.h:124

References conn, fb(), pg_conn::inBuffer, pg_conn::inCursor, pg_conn::inEnd, memcpy(), pg_conn::noticeHooks, pg_ntoh16, pg_ntoh32, pqInternalNotice(), and result.

Referenced by getAnotherTuple(), getBackendKeyData(), getCopyDataMessage(), getCopyStart(), getNotify(), getParamDescriptions(), getRowDescriptions(), PQconnectPoll(), pqFunctionCall3(), pqGetNegotiateProtocolVersion3(), and pqParseInput3().

◆ pqGetline3()

int pqGetline3 ( PGconn conn,
char s,
int  maxlen 
)
extern

Definition at line 2007 of file fe-protocol3.c.

2008{
2009 int status;
2010
2011 if (conn->sock == PGINVALID_SOCKET ||
2015 {
2016 libpq_append_conn_error(conn, "PQgetline: not doing text COPY OUT");
2017 *s = '\0';
2018 return EOF;
2019 }
2020
2021 while ((status = PQgetlineAsync(conn, s, maxlen - 1)) == 0)
2022 {
2023 /* need to load more data */
2024 if (pqWait(true, false, conn) ||
2025 pqReadData(conn) < 0)
2026 {
2027 *s = '\0';
2028 return EOF;
2029 }
2030 }
2031
2032 if (status < 0)
2033 {
2034 /* End of copy detected; gin up old-style terminator */
2035 strcpy(s, "\\.");
2036 return 0;
2037 }
2038
2039 /* Add null terminator, and strip trailing \n if present */
2040 if (s[status - 1] == '\n')
2041 {
2042 s[status - 1] = '\0';
2043 return 0;
2044 }
2045 else
2046 {
2047 s[status] = '\0';
2048 return 1;
2049 }
2050}
int PQgetlineAsync(PGconn *conn, char *buffer, int bufsize)
Definition fe-exec.c:2918
char copy_is_binary
Definition libpq-int.h:475

References pg_conn::asyncStatus, conn, pg_conn::copy_is_binary, fb(), libpq_append_conn_error(), PGASYNC_COPY_BOTH, PGASYNC_COPY_OUT, PGINVALID_SOCKET, PQgetlineAsync(), pqReadData(), pqWait(), and pg_conn::sock.

Referenced by PQgetline().

◆ pqGetlineAsync3()

int pqGetlineAsync3 ( PGconn conn,
char buffer,
int  bufsize 
)
extern

Definition at line 2058 of file fe-protocol3.c.

2059{
2060 int msgLength;
2061 int avail;
2062
2065 return -1; /* we are not doing a copy... */
2066
2067 /*
2068 * Recognize the next input message. To make life simpler for async
2069 * callers, we keep returning 0 until the next message is fully available
2070 * even if it is not Copy Data. This should keep PQendcopy from blocking.
2071 * (Note: unlike pqGetCopyData3, we do not change asyncStatus here.)
2072 */
2074 if (msgLength < 0)
2075 return -1; /* end-of-copy or error */
2076 if (msgLength == 0)
2077 return 0; /* no data yet */
2078
2079 /*
2080 * Move data from libpq's buffer to the caller's. In the case where a
2081 * prior call found the caller's buffer too small, we use
2082 * conn->copy_already_done to remember how much of the row was already
2083 * returned to the caller.
2084 */
2086 avail = msgLength - 4 - conn->copy_already_done;
2087 if (avail <= bufsize)
2088 {
2089 /* Able to consume the whole message */
2090 memcpy(buffer, &conn->inBuffer[conn->inCursor], avail);
2091 /* Mark message consumed */
2092 conn->inStart = conn->inCursor + avail;
2093 /* Reset state for next time */
2095 return avail;
2096 }
2097 else
2098 {
2099 /* We must return a partial message */
2100 memcpy(buffer, &conn->inBuffer[conn->inCursor], bufsize);
2101 /* The message is NOT consumed from libpq's buffer */
2103 return bufsize;
2104 }
2105}
int copy_already_done
Definition libpq-int.h:476

References pg_conn::asyncStatus, bufsize, conn, pg_conn::copy_already_done, fb(), getCopyDataMessage(), pg_conn::inBuffer, pg_conn::inCursor, pg_conn::inStart, memcpy(), PGASYNC_COPY_BOTH, and PGASYNC_COPY_OUT.

Referenced by PQgetlineAsync().

◆ pqGetnchar()

int pqGetnchar ( void s,
size_t  len,
PGconn conn 
)
extern

Definition at line 165 of file fe-misc.c.

166{
167 if (len > (size_t) (conn->inEnd - conn->inCursor))
168 return EOF;
169
171 /* no terminating null */
172
173 conn->inCursor += len;
174
175 return 0;
176}

References conn, fb(), pg_conn::inBuffer, pg_conn::inCursor, pg_conn::inEnd, len, and memcpy().

Referenced by getBackendKeyData(), pg_password_sendauth(), pg_SASL_continue(), and pqFunctionCall3().

◆ pqGetNegotiateProtocolVersion3()

int pqGetNegotiateProtocolVersion3 ( PGconn conn)
extern

Definition at line 1443 of file fe-protocol3.c.

1444{
1445 int their_version;
1446 int num;
1449
1450 /*
1451 * During 19beta only, if protocol grease is in use, assume that it's the
1452 * cause of any invalid messages encountered below. We'll print extra
1453 * information for the end user in that case.
1454 */
1456
1457 if (pqGetInt(&their_version, 4, conn) != 0)
1458 goto eof;
1459
1460 if (pqGetInt(&num, 4, conn) != 0)
1461 goto eof;
1462
1463 /*
1464 * Check the protocol version.
1465 *
1466 * PG_PROTOCOL_GREASE is intentionally unsupported and reserved. It's
1467 * higher than any real version, so check for that first, to get the most
1468 * specific error message. Then check the upper and lower bounds.
1469 */
1471 {
1472 libpq_append_conn_error(conn, "received invalid protocol negotiation message: server requested \"grease\" protocol version 3.9999");
1473 goto failure;
1474 }
1475
1477 {
1478 libpq_append_conn_error(conn, "received invalid protocol negotiation message: server requested downgrade to a higher-numbered version");
1479 goto failure;
1480 }
1481
1482 if (their_version < PG_PROTOCOL(3, 0))
1483 {
1484 libpq_append_conn_error(conn, "received invalid protocol negotiation message: server requested downgrade to pre-3.0 protocol version");
1485 goto failure;
1486 }
1487
1488 /* 3.1 never existed, we went straight from 3.0 to 3.2 */
1490 {
1491 libpq_append_conn_error(conn, "received invalid protocol negotiation message: server requested downgrade to non-existent 3.1 protocol version");
1492 goto failure;
1493 }
1494
1495 if (num < 0)
1496 {
1497 libpq_append_conn_error(conn, "received invalid protocol negotiation message: server reported negative number of unsupported parameters");
1498 goto failure;
1499 }
1500
1501 if (their_version == conn->pversion && num == 0)
1502 {
1503 libpq_append_conn_error(conn, "received invalid protocol negotiation message: server negotiated but asks for no changes");
1504 goto failure;
1505 }
1506
1507 if (their_version < conn->min_pversion)
1508 {
1509 libpq_append_conn_error(conn, "server only supports protocol version %d.%d, but \"%s\" was set to %d.%d",
1512 "min_protocol_version",
1515
1516 need_grease_info = false; /* this is valid server behavior */
1517 goto failure;
1518 }
1519
1520 /* the version is acceptable */
1522
1523 /*
1524 * Check that all expected unsupported parameters are reported by the
1525 * server.
1526 */
1529
1530 for (int i = 0; i < num; i++)
1531 {
1532 if (pqGets(&conn->workBuffer, conn))
1533 {
1534 goto eof;
1535 }
1536 if (strncmp(conn->workBuffer.data, "_pq_.", 5) != 0)
1537 {
1538 libpq_append_conn_error(conn, "received invalid protocol negotiation message: server reported unsupported parameter name without a \"%s\" prefix (\"%s\")", "_pq_.", conn->workBuffer.data);
1539 goto failure;
1540 }
1541
1542 /* Check if this is the expected test parameter */
1544 strcmp(conn->workBuffer.data, "_pq_.test_protocol_negotiation") == 0)
1545 {
1547 }
1548 else
1549 {
1550 libpq_append_conn_error(conn, "received invalid protocol negotiation message: server reported an unsupported parameter that was not requested (\"%s\")",
1552 goto failure;
1553 }
1554 }
1555
1556 /*
1557 * If we requested protocol grease, the server must report
1558 * _pq_.test_protocol_negotiation as unsupported. This ensures
1559 * comprehensive NegotiateProtocolVersion implementation.
1560 */
1562 {
1563 libpq_append_conn_error(conn, "server did not report the unsupported `_pq_.test_protocol_negotiation` parameter in its protocol negotiation message");
1564 goto failure;
1565 }
1566
1567 return 0;
1568
1569eof:
1570 libpq_append_conn_error(conn, "received invalid protocol negotiation message: message too short");
1571failure:
1572 if (need_grease_info)
1576 return 1;
1577}
void libpq_append_grease_info(PGconn *conn)
Definition fe-misc.c:1432
#define PG_PROTOCOL_MAJOR(v)
Definition pqcomm.h:86
#define PG_PROTOCOL_RESERVED_31
Definition pqcomm.h:105
#define PG_PROTOCOL(m, n)
Definition pqcomm.h:89
#define PG_PROTOCOL_MINOR(v)
Definition pqcomm.h:87
ProtocolVersion pversion
Definition libpq-int.h:504
PQExpBufferData workBuffer
Definition libpq-int.h:688

References pg_conn::asyncStatus, conn, PQExpBufferData::data, fb(), i, libpq_append_conn_error(), libpq_append_grease_info(), pg_conn::max_pversion, pg_conn::min_pversion, PG_PROTOCOL, PG_PROTOCOL_GREASE, PG_PROTOCOL_MAJOR, PG_PROTOCOL_MINOR, PG_PROTOCOL_RESERVED_31, PGASYNC_READY, pqGetInt(), pqGets(), pqSaveErrorResult(), pg_conn::pversion, and pg_conn::workBuffer.

Referenced by PQconnectPoll().

◆ pqGets()

int pqGets ( PQExpBuffer  buf,
PGconn conn 
)
extern

Definition at line 136 of file fe-misc.c.

137{
138 return pqGets_internal(buf, conn, true);
139}
static int pqGets_internal(PQExpBuffer buf, PGconn *conn, bool resetbuffer)
Definition fe-misc.c:109

References buf, conn, and pqGets_internal().

Referenced by getNotify(), getParameterStatus(), getRowDescriptions(), pg_SASL_init(), pqGetErrorNotice3(), pqGetNegotiateProtocolVersion3(), and pqParseInput3().

◆ pqGets_append()

int pqGets_append ( PQExpBuffer  buf,
PGconn conn 
)
extern

Definition at line 142 of file fe-misc.c.

143{
144 return pqGets_internal(buf, conn, false);
145}

References buf, conn, and pqGets_internal().

Referenced by PQconnectPoll().

◆ pqInternalNotice()

void pqInternalNotice ( const PGNoticeHooks hooks,
const char fmt,
  ... 
)
extern

◆ pqMakeEmptyPGconn()

PGconn * pqMakeEmptyPGconn ( void  )
extern

Definition at line 4991 of file fe-connect.c.

4992{
4993 PGconn *conn;
4994
4995#ifdef WIN32
4996
4997 /*
4998 * Make sure socket support is up and running in this process.
4999 *
5000 * Note: the Windows documentation says that we should eventually do a
5001 * matching WSACleanup() call, but experience suggests that that is at
5002 * least as likely to cause problems as fix them. So we don't.
5003 */
5004 static bool wsastartup_done = false;
5005
5006 if (!wsastartup_done)
5007 {
5009
5010 if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
5011 return NULL;
5012 wsastartup_done = true;
5013 }
5014
5015 /* Forget any earlier error */
5016 WSASetLastError(0);
5017#endif /* WIN32 */
5018
5019 conn = (PGconn *) malloc(sizeof(PGconn));
5020 if (conn == NULL)
5021 return conn;
5022
5023 /* Zero all pointers and booleans */
5024 MemSet(conn, 0, sizeof(PGconn));
5025
5026 /* install default notice hooks */
5029
5034 conn->options_valid = false;
5035 conn->nonblocking = false;
5037 conn->std_strings = false; /* unless server says differently */
5045 conn->Pfdebug = NULL;
5046
5047 /*
5048 * We try to send at least 8K at a time, which is the usual size of pipe
5049 * buffers on Unix systems. That way, when we are sending a large amount
5050 * of data, we avoid incurring extra kernel context swaps for partial
5051 * bufferloads. The output buffer is initially made 16K in size, and we
5052 * try to dump it after accumulating 8K.
5053 *
5054 * With the same goal of minimizing context swaps, the input buffer will
5055 * be enlarged anytime it has less than 8K free, so we initially allocate
5056 * twice that.
5057 */
5058 conn->inBufSize = 16 * 1024;
5059 conn->inBuffer = (char *) malloc(conn->inBufSize);
5060 conn->outBufSize = 16 * 1024;
5061 conn->outBuffer = (char *) malloc(conn->outBufSize);
5062 conn->rowBufLen = 32;
5066
5067 if (conn->inBuffer == NULL ||
5068 conn->outBuffer == NULL ||
5069 conn->rowBuf == NULL ||
5072 {
5073 /* out of memory already :-( */
5075 conn = NULL;
5076 }
5077
5078 return conn;
5079}
#define MemSet(start, val, len)
Definition c.h:1107
static void defaultNoticeReceiver(void *arg, const PGresult *res)
static void defaultNoticeProcessor(void *arg, const char *message)
static void freePGconn(PGconn *conn)
@ PQERRORS_DEFAULT
Definition libpq-fe.h:163
@ PG_BOOL_UNKNOWN
Definition oauth-utils.h:33
@ PG_SQL_ASCII
Definition pg_wchar.h:76
#define PQExpBufferBroken(str)
Definition pqexpbuffer.h:59
#define SCRAM_SHA_256_DEFAULT_ITERATIONS
PQnoticeProcessor noticeProc
Definition libpq-int.h:151
PGdataValue * rowBuf
Definition libpq-int.h:594
bool std_strings
Definition libpq-int.h:558
PGTernaryBool in_hot_standby
Definition libpq-int.h:560
int client_encoding
Definition libpq-int.h:557
PGTernaryBool default_transaction_read_only
Definition libpq-int.h:559
int rowBufLen
Definition libpq-int.h:595
int scram_sha_256_iterations
Definition libpq-int.h:614

References pg_conn::altsock, pg_conn::asyncStatus, pg_conn::client_encoding, conn, CONNECTION_BAD, pg_conn::default_transaction_read_only, defaultNoticeProcessor(), defaultNoticeReceiver(), pg_conn::errorMessage, fb(), freePGconn(), pg_conn::in_hot_standby, pg_conn::inBuffer, pg_conn::inBufSize, initPQExpBuffer(), malloc, MemSet, pg_conn::nonblocking, pg_conn::noticeHooks, PGNoticeHooks::noticeProc, PGNoticeHooks::noticeRec, pg_conn::options_valid, pg_conn::outBuffer, pg_conn::outBufSize, pg_conn::Pfdebug, PG_BOOL_UNKNOWN, PG_SQL_ASCII, PGASYNC_IDLE, PGINVALID_SOCKET, pg_conn::pipelineStatus, PQ_PIPELINE_OFF, PQERRORS_DEFAULT, PQExpBufferBroken, PQSHOW_CONTEXT_ERRORS, PQTRANS_IDLE, pg_conn::rowBuf, pg_conn::rowBufLen, SCRAM_SHA_256_DEFAULT_ITERATIONS, pg_conn::scram_sha_256_iterations, pg_conn::show_context, pg_conn::sock, pg_conn::status, pg_conn::std_strings, pg_conn::verbosity, pg_conn::workBuffer, and pg_conn::xactStatus.

Referenced by PQcancelCreate(), PQconnectStart(), PQconnectStartParams(), and PQsetdbLogin().

◆ pqPacketSend()

int pqPacketSend ( PGconn conn,
char  pack_type,
const void buf,
size_t  buf_len 
)
extern

Definition at line 5462 of file fe-connect.c.

5464{
5465 /* Start the message. */
5467 return STATUS_ERROR;
5468
5469 /* Send the message body. */
5470 if (pqPutnchar(buf, buf_len, conn))
5471 return STATUS_ERROR;
5472
5473 /* Finish the message. */
5474 if (pqPutMsgEnd(conn))
5475 return STATUS_ERROR;
5476
5477 /* Flush to ensure backend gets it. */
5478 if (pqFlush(conn))
5479 return STATUS_ERROR;
5480
5481 return STATUS_OK;
5482}
#define STATUS_OK
Definition c.h:1258
#define STATUS_ERROR
Definition c.h:1259

References buf, conn, fb(), pqFlush(), pqPutMsgEnd(), pqPutMsgStart(), pqPutnchar(), STATUS_ERROR, and STATUS_OK.

Referenced by pg_password_sendauth(), pg_SASL_continue(), and PQconnectPoll().

◆ pqParseDone()

void pqParseDone ( PGconn conn,
int  newInStart 
)
extern

Definition at line 443 of file fe-misc.c.

444{
445 /* trace server-to-client message */
446 if (conn->Pfdebug)
448
449 /* Mark message as done */
451}
void pqTraceOutputMessage(PGconn *conn, const char *message, bool toServer)
Definition fe-trace.c:624

References conn, fb(), pg_conn::inBuffer, pg_conn::inStart, pg_conn::Pfdebug, and pqTraceOutputMessage().

Referenced by getCopyDataMessage(), PQconnectPoll(), pqFunctionCall3(), pqGetCopyData3(), and pqParseInput3().

◆ pqParseInput3()

void pqParseInput3 ( PGconn conn)
extern

Definition at line 70 of file fe-protocol3.c.

71{
72 char id;
73 int msgLength;
74 int avail;
75
76 /*
77 * Loop to parse successive complete messages available in the buffer.
78 */
79 for (;;)
80 {
81 /*
82 * Try to read a message. First get the type code and length. Return
83 * if not enough data.
84 */
86 if (pqGetc(&id, conn))
87 return;
88 if (pqGetInt(&msgLength, 4, conn))
89 return;
90
91 /*
92 * Try to validate message type/length here. A length less than 4 is
93 * definitely broken. Large lengths should only be believed for a few
94 * message types.
95 */
96 if (msgLength < 4)
97 {
99 return;
100 }
101 if (msgLength > 30000 && !VALID_LONG_MESSAGE_TYPE(id))
102 {
104 return;
105 }
106
107 /*
108 * Can't process if message body isn't all here yet.
109 */
110 msgLength -= 4;
111 avail = conn->inEnd - conn->inCursor;
112 if (avail < msgLength)
113 {
114 /*
115 * Before returning, enlarge the input buffer if needed to hold
116 * the whole message. This is better than leaving it to
117 * pqReadData because we can avoid multiple cycles of realloc()
118 * when the message is large; also, we can implement a reasonable
119 * recovery strategy if we are unable to make the buffer big
120 * enough.
121 */
123 conn))
124 {
125 /*
126 * Abandon the connection. There's not much else we can
127 * safely do; we can't just ignore the message or we could
128 * miss important changes to the connection state.
129 * pqCheckInBufferSpace() already reported the error.
130 */
132 }
133 return;
134 }
135
136 /*
137 * NOTIFY and NOTICE messages can happen in any state; always process
138 * them right away.
139 *
140 * Most other messages should only be processed while in BUSY state.
141 * (In particular, in READY state we hold off further parsing until
142 * the application collects the current PGresult.)
143 *
144 * However, if the state is IDLE then we got trouble; we need to deal
145 * with the unexpected message somehow.
146 *
147 * ParameterStatus ('S') messages are a special case: in IDLE state we
148 * must process 'em (this case could happen if a new value was adopted
149 * from config file due to SIGHUP), but otherwise we hold off until
150 * BUSY state.
151 */
153 {
154 if (getNotify(conn))
155 return;
156 }
157 else if (id == PqMsg_NoticeResponse)
158 {
159 if (pqGetErrorNotice3(conn, false))
160 return;
161 }
162 else if (conn->asyncStatus != PGASYNC_BUSY)
163 {
164 /* If not IDLE state, just wait ... */
166 return;
167
168 /*
169 * Unexpected message in IDLE state; need to recover somehow.
170 * ERROR messages are handled using the notice processor;
171 * ParameterStatus is handled normally; anything else is just
172 * dropped on the floor after displaying a suitable warning
173 * notice. (An ERROR is very possibly the backend telling us why
174 * it is about to close the connection, so we don't want to just
175 * discard it...)
176 */
177 if (id == PqMsg_ErrorResponse)
178 {
179 if (pqGetErrorNotice3(conn, false /* treat as notice */ ))
180 return;
181 }
182 else if (id == PqMsg_ParameterStatus)
183 {
185 return;
186 }
187 else
188 {
189 /* Any other case is unexpected and we summarily skip it */
191 "message type 0x%02x arrived from server while idle",
192 id);
193 /* Discard the unexpected message */
195 }
196 }
197 else
198 {
199 /*
200 * In BUSY state, we can process everything.
201 */
202 switch (id)
203 {
205 if (pqGets(&conn->workBuffer, conn))
206 return;
208 {
211 if (!conn->result)
212 {
213 libpq_append_conn_error(conn, "out of memory");
215 }
216 }
217 if (conn->result)
221 break;
223 if (pqGetErrorNotice3(conn, true))
224 return;
226 break;
229 return;
231 {
234 if (!conn->result)
235 {
236 libpq_append_conn_error(conn, "out of memory");
238 }
239 else
240 {
243 }
244 }
245 else
246 {
247 /* Advance the command queue and set us idle */
248 pqCommandQueueAdvance(conn, true, false);
250 }
251 break;
254 {
257 if (!conn->result)
258 {
259 libpq_append_conn_error(conn, "out of memory");
261 }
262 }
264 break;
266 /* If we're doing PQprepare, we're done; else ignore */
267 if (conn->cmd_queue_head &&
269 {
271 {
274 if (!conn->result)
275 {
276 libpq_append_conn_error(conn, "out of memory");
278 }
279 }
281 }
282 break;
284 /* Nothing to do for this message type */
285 break;
287 /* If we're doing PQsendClose, we're done; else ignore */
288 if (conn->cmd_queue_head &&
290 {
292 {
295 if (!conn->result)
296 {
297 libpq_append_conn_error(conn, "out of memory");
299 }
300 }
302 }
303 break;
306 return;
307 break;
309
310 /*
311 * This is expected only during backend startup, but it's
312 * just as easy to handle it as part of the main loop.
313 * Save the data and continue processing.
314 */
316 return;
317 break;
319 if (conn->error_result ||
320 (conn->result != NULL &&
322 {
323 /*
324 * We've already choked for some reason. Just discard
325 * the data till we get to the end of the query.
326 */
328 }
329 else if (conn->result == NULL ||
332 {
333 /* First 'T' in a query sequence */
335 return;
336 }
337 else
338 {
339 /*
340 * A new 'T' message is treated as the start of
341 * another PGresult. (It is not clear that this is
342 * really possible with the current backend.) We stop
343 * parsing until the application accepts the current
344 * result.
345 */
347 return;
348 }
349 break;
350 case PqMsg_NoData:
351
352 /*
353 * NoData indicates that we will not be seeing a
354 * RowDescription message because the statement or portal
355 * inquired about doesn't return rows.
356 *
357 * If we're doing a Describe, we have to pass something
358 * back to the client, so set up a COMMAND_OK result,
359 * instead of PGRES_TUPLES_OK. Otherwise we can just
360 * ignore this message.
361 */
362 if (conn->cmd_queue_head &&
364 {
366 {
369 if (!conn->result)
370 {
371 libpq_append_conn_error(conn, "out of memory");
373 }
374 }
376 }
377 break;
380 return;
381 break;
382 case PqMsg_DataRow:
383 if (conn->result != NULL &&
386 {
387 /* Read another tuple of a normal query response */
389 return;
390 }
391 else if (conn->error_result ||
392 (conn->result != NULL &&
394 {
395 /*
396 * We've already choked for some reason. Just discard
397 * tuples till we get to the end of the query.
398 */
400 }
401 else
402 {
403 /* Set up to report error at end of query */
404 libpq_append_conn_error(conn, "server sent data (\"D\" message) without prior row description (\"T\" message)");
406 /* Discard the unexpected message */
408 }
409 break;
412 return;
414 break;
417 return;
420 break;
423 return;
426 break;
427 case PqMsg_CopyData:
428
429 /*
430 * If we see Copy Data, just silently drop it. This would
431 * only occur if application exits COPY OUT mode too
432 * early.
433 */
435 break;
436 case PqMsg_CopyDone:
437
438 /*
439 * If we see Copy Done, just silently drop it. This is
440 * the normal case during PQendcopy. We will keep
441 * swallowing data, expecting to see command-complete for
442 * the COPY command.
443 */
444 break;
445 default:
446 libpq_append_conn_error(conn, "unexpected response from server; first received character was \"%c\"", id);
447 /* build an error result holding the error message */
449 /* not sure if we will see more, so go to ready state */
451 /* Discard the unexpected message */
453 break;
454 } /* switch on protocol character */
455 }
456 /* Successfully consumed this message */
457 if (conn->inCursor == conn->inStart + 5 + msgLength)
458 {
459 /* Normal case: parsing agrees with specified length */
461 }
462 else if (conn->error_result && conn->status == CONNECTION_BAD)
463 {
464 /* The connection was abandoned and we already reported it */
465 return;
466 }
467 else
468 {
469 /* Trouble --- report it */
470 libpq_append_conn_error(conn, "message contents do not agree with length in message type \"%c\"", id);
471 /* build an error result holding the error message */
474 /* trust the specified message length as what to skip */
475 conn->inStart += 5 + msgLength;
476 }
477 }
478}
void pqCommandQueueAdvance(PGconn *conn, bool isReadyForQuery, bool gotSync)
Definition fe-exec.c:3159
static int getAnotherTuple(PGconn *conn, int msgLength)
static int getRowDescriptions(PGconn *conn, int msgLength)
static int getCopyStart(PGconn *conn, ExecStatusType copytype)
static int getBackendKeyData(PGconn *conn, int msgLength)
static int getParamDescriptions(PGconn *conn, int msgLength)
@ PGRES_COPY_IN
Definition libpq-fe.h:138
@ PGRES_COPY_BOTH
Definition libpq-fe.h:143
@ PGRES_TUPLES_CHUNK
Definition libpq-fe.h:148
@ PGRES_COPY_OUT
Definition libpq-fe.h:137
@ PGRES_PIPELINE_SYNC
Definition libpq-fe.h:145
@ PGRES_TUPLES_OK
Definition libpq-fe.h:134
@ PQ_PIPELINE_ON
Definition libpq-fe.h:194
#define CMDSTATUS_LEN
Definition libpq-int.h:83
#define PqMsg_CloseComplete
Definition protocol.h:40
#define PqMsg_BindComplete
Definition protocol.h:39
#define PqMsg_CopyData
Definition protocol.h:65
#define PqMsg_ParameterDescription
Definition protocol.h:58
#define PqMsg_CopyInResponse
Definition protocol.h:45
#define PqMsg_EmptyQueryResponse
Definition protocol.h:47
#define PqMsg_RowDescription
Definition protocol.h:52
#define PqMsg_CopyBothResponse
Definition protocol.h:54
#define PqMsg_NoData
Definition protocol.h:56
#define PqMsg_BackendKeyData
Definition protocol.h:48
#define PqMsg_CommandComplete
Definition protocol.h:42
#define PqMsg_DataRow
Definition protocol.h:43
#define PqMsg_CopyOutResponse
Definition protocol.h:46
#define PqMsg_ParseComplete
Definition protocol.h:38
char cmdStatus[CMDSTATUS_LEN]
Definition libpq-int.h:175

References pg_conn::asyncStatus, pg_conn::cmd_queue_head, pg_result::cmdStatus, CMDSTATUS_LEN, conn, CONNECTION_BAD, pg_conn::copy_already_done, PQExpBufferData::data, pg_conn::error_result, fb(), getAnotherTuple(), getBackendKeyData(), getCopyStart(), getNotify(), getParamDescriptions(), getParameterStatus(), getReadyForQuery(), getRowDescriptions(), handleFatalError(), handleSyncLoss(), pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, libpq_append_conn_error(), pg_conn::noticeHooks, PGASYNC_BUSY, PGASYNC_COPY_BOTH, PGASYNC_COPY_IN, PGASYNC_COPY_OUT, PGASYNC_IDLE, PGASYNC_READY, pgHavePendingResult, PGQUERY_CLOSE, PGQUERY_DESCRIBE, PGQUERY_PREPARE, PGRES_COMMAND_OK, PGRES_COPY_BOTH, PGRES_COPY_IN, PGRES_COPY_OUT, PGRES_EMPTY_QUERY, PGRES_FATAL_ERROR, PGRES_PIPELINE_SYNC, PGRES_TUPLES_CHUNK, PGRES_TUPLES_OK, pg_conn::pipelineStatus, PQ_PIPELINE_OFF, PQ_PIPELINE_ON, pqCheckInBufferSpace(), pqCommandQueueAdvance(), pqGetc(), pqGetErrorNotice3(), pqGetInt(), pqGets(), pqInternalNotice(), PQmakeEmptyPGresult(), PqMsg_BackendKeyData, PqMsg_BindComplete, PqMsg_CloseComplete, PqMsg_CommandComplete, PqMsg_CopyBothResponse, PqMsg_CopyData, PqMsg_CopyDone, PqMsg_CopyInResponse, PqMsg_CopyOutResponse, PqMsg_DataRow, PqMsg_EmptyQueryResponse, PqMsg_ErrorResponse, PqMsg_NoData, PqMsg_NoticeResponse, PqMsg_NotificationResponse, PqMsg_ParameterDescription, PqMsg_ParameterStatus, PqMsg_ParseComplete, PqMsg_ReadyForQuery, PqMsg_RowDescription, pqParseDone(), pqSaveErrorResult(), PGcmdQueueEntry::queryclass, pg_conn::result, pg_result::resultStatus, pg_conn::status, strlcpy(), VALID_LONG_MESSAGE_TYPE, and pg_conn::workBuffer.

Referenced by parseInput().

◆ pqParseIntParam()

bool pqParseIntParam ( const char value,
int result,
PGconn conn,
const char context 
)
extern

Definition at line 8311 of file fe-connect.c.

8313{
8314 char *end;
8315 long numval;
8316
8317 Assert(value != NULL);
8318
8319 *result = 0;
8320
8321 /* strtol(3) skips leading whitespaces */
8322 errno = 0;
8323 numval = strtol(value, &end, 10);
8324
8325 /*
8326 * If no progress was done during the parsing or an error happened, fail.
8327 * This tests properly for overflows of the result.
8328 */
8329 if (value == end || errno != 0 || numval != (int) numval)
8330 goto error;
8331
8332 /*
8333 * Skip any trailing whitespace; if anything but whitespace remains before
8334 * the terminating character, fail
8335 */
8336 while (*end != '\0' && isspace((unsigned char) *end))
8337 end++;
8338
8339 if (*end != '\0')
8340 goto error;
8341
8342 *result = numval;
8343 return true;
8344
8345error:
8346 libpq_append_conn_error(conn, "invalid integer value \"%s\" for connection option \"%s\"",
8347 value, context);
8348 return false;
8349}
static struct @177 value
static void error(void)

References Assert, conn, error(), fb(), libpq_append_conn_error(), result, and value.

Referenced by pqConnectDBComplete(), PQconnectPoll(), PQgetCancel(), setKeepalivesCount(), setKeepalivesIdle(), setKeepalivesInterval(), setTCPUserTimeout(), and useKeepalives().

◆ pqPrepareAsyncResult()

PGresult * pqPrepareAsyncResult ( PGconn conn)
extern

Definition at line 857 of file fe-exec.c.

858{
859 PGresult *res;
860
861 res = conn->result;
862 if (res)
863 {
864 /*
865 * If the pre-existing result is an ERROR (presumably something
866 * received from the server), assume that it represents whatever is in
867 * conn->errorMessage, and advance errorReported.
868 */
871 }
872 else
873 {
874 /*
875 * We get here after internal-to-libpq errors. We should probably
876 * always have error_result = true, but if we don't, gin up some error
877 * text.
878 */
879 if (!conn->error_result)
880 libpq_append_conn_error(conn, "no error text available");
881
882 /* Paranoia: be sure errorReported offset is sane */
883 if (conn->errorReported < 0 ||
885 conn->errorReported = 0;
886
887 /*
888 * Make a PGresult struct for the error. We temporarily lie about the
889 * result status, so that PQmakeEmptyPGresult doesn't uselessly copy
890 * all of conn->errorMessage.
891 */
893 if (res)
894 {
895 /*
896 * Report whatever new error text we have, and advance
897 * errorReported.
898 */
902 }
903 else
904 {
905 /*
906 * Ouch, not enough memory for a PGresult. Fortunately, we have a
907 * card up our sleeve: we can use the static OOM_result. Casting
908 * away const here is a bit ugly, but it seems best to declare
909 * OOM_result as const, in hopes it will be allocated in read-only
910 * storage.
911 */
912 res = unconstify(PGresult *, &OOM_result);
913
914 /*
915 * Don't advance errorReported. Perhaps we'll be able to report
916 * the text later.
917 */
918 }
919 }
920
921 /*
922 * Replace conn->result with saved_result, if any. In the normal case
923 * there isn't a saved result and we're just dropping ownership of the
924 * current result. In partial-result mode this restores the situation to
925 * what it was before we created the current partial result.
926 */
928 conn->error_result = false; /* saved_result is never an error */
930
931 return res;
932}
#define unconstify(underlying_type, expr)
Definition c.h:1325
static const PGresult OOM_result
Definition fe-exec.c:50
int errorReported
Definition libpq-int.h:685

References conn, pg_conn::error_result, pg_conn::errorMessage, pg_conn::errorReported, fb(), PQExpBufferData::len, libpq_append_conn_error(), OOM_result, PGRES_EMPTY_QUERY, PGRES_FATAL_ERROR, PQmakeEmptyPGresult(), pqSetResultError(), pg_conn::result, pg_result::resultStatus, pg_conn::saved_result, and unconstify.

Referenced by getCopyResult(), pqFunctionCall3(), and PQgetResult().

◆ pqPutc()

int pqPutc ( char  c,
PGconn conn 
)
extern

Definition at line 92 of file fe-misc.c.

93{
94 if (pqPutMsgBytes(&c, 1, conn))
95 return EOF;
96
97 return 0;
98}
static int pqPutMsgBytes(const void *buf, size_t len, PGconn *conn)
Definition fe-misc.c:509
char * c

References conn, fb(), and pqPutMsgBytes().

Referenced by PQsendQueryGuts(), and PQsendTypedCommand().

◆ pqPutInt()

int pqPutInt ( int  value,
size_t  bytes,
PGconn conn 
)
extern

Definition at line 253 of file fe-misc.c.

254{
255 uint16 tmp2;
256 uint32 tmp4;
257
258 switch (bytes)
259 {
260 case 2:
262 if (pqPutMsgBytes((const char *) &tmp2, 2, conn))
263 return EOF;
264 break;
265 case 4:
267 if (pqPutMsgBytes((const char *) &tmp4, 4, conn))
268 return EOF;
269 break;
270 default:
272 "integer of size %zu not supported by pqPutInt",
273 bytes);
274 return EOF;
275 }
276
277 return 0;
278}
#define pg_hton32(x)
Definition pg_bswap.h:121
#define pg_hton16(x)
Definition pg_bswap.h:120

References conn, fb(), pg_conn::noticeHooks, pg_hton16, pg_hton32, pqInternalNotice(), pqPutMsgBytes(), and value.

Referenced by pg_SASL_init(), pqFunctionCall3(), PQsendPrepare(), and PQsendQueryGuts().

◆ pqPutMsgEnd()

int pqPutMsgEnd ( PGconn conn)
extern

Definition at line 532 of file fe-misc.c.

533{
534 /* Fill in length word if needed */
535 if (conn->outMsgStart >= 0)
536 {
538
541 }
542
543 /* trace client-to-server message */
544 if (conn->Pfdebug)
545 {
548 else
551 }
552
553 /* Make message eligible to send */
555
556 /* If appropriate, try to push out some data */
557 if (conn->outCount >= 8192)
558 {
559 int toSend = conn->outCount;
560
561 /*
562 * On Unix-pipe connections, it seems profitable to prefer sending
563 * pipe-buffer-sized packets not randomly-sized ones, so retain the
564 * last partial-8K chunk in our buffer for now. On TCP connections,
565 * the advantage of that is far less clear. Moreover, it flat out
566 * isn't safe when using SSL or GSSAPI, because those code paths have
567 * API stipulations that if they fail to send all the data that was
568 * offered in the previous write attempt, we mustn't offer less data
569 * in this write attempt. The previous write attempt might've been
570 * pqFlush attempting to send everything in the buffer, so we mustn't
571 * offer less now. (Presently, we won't try to use SSL or GSSAPI on
572 * Unix connections, so those checks are just Asserts. They'll have
573 * to become part of the regular if-test if we ever change that.)
574 */
575 if (conn->raddr.addr.ss_family == AF_UNIX)
576 {
577#ifdef USE_SSL
579#endif
580#ifdef ENABLE_GSS
581 Assert(!conn->gssenc);
582#endif
583 toSend -= toSend % 8192;
584 }
585
586 if (pqSendSome(conn, toSend) < 0)
587 return EOF;
588 /* in nonblock mode, don't complain if unable to send it all */
589 }
590
591 return 0;
592}
void pqTraceOutputNoTypeByteMessage(PGconn *conn, const char *message)
Definition fe-trace.c:841
struct sockaddr_storage addr
Definition pqcomm.h:32
int outMsgStart
Definition libpq-int.h:589
SockAddr raddr
Definition libpq-int.h:503
int outMsgEnd
Definition libpq-int.h:591

References SockAddr::addr, Assert, conn, fb(), memcpy(), pg_conn::outBuffer, pg_conn::outCount, pg_conn::outMsgEnd, pg_conn::outMsgStart, pg_conn::Pfdebug, pg_hton32, pqSendSome(), pqTraceOutputMessage(), pqTraceOutputNoTypeByteMessage(), pg_conn::raddr, and pg_conn::ssl_in_use.

Referenced by pg_SASL_init(), pqEndcopy3(), pqFunctionCall3(), pqPacketSend(), pqPipelineSyncInternal(), PQputCopyData(), PQputCopyEnd(), PQsendCancelRequest(), PQsendFlushRequest(), PQsendPrepare(), PQsendQueryGuts(), PQsendQueryInternal(), PQsendTypedCommand(), and sendTerminateConn().

◆ pqPutMsgStart()

int pqPutMsgStart ( char  msg_type,
PGconn conn 
)
extern

Definition at line 473 of file fe-misc.c.

474{
475 int lenPos;
476 int endPos;
477
478 /* allow room for message type byte */
479 if (msg_type)
480 endPos = conn->outCount + 1;
481 else
483
484 /* do we want a length word? */
485 lenPos = endPos;
486 /* allow room for message length */
487 endPos += 4;
488
489 /* make sure there is room for message header */
491 return EOF;
492 /* okay, save the message type byte if any */
493 if (msg_type)
495 /* set up the message pointers */
498 /* length word, if needed, will be filled in by pqPutMsgEnd */
499
500 return 0;
501}
int pqCheckOutBufferSpace(size_t bytes_needed, PGconn *conn)
Definition fe-misc.c:287

References conn, fb(), pg_conn::outBuffer, pg_conn::outCount, pg_conn::outMsgEnd, pg_conn::outMsgStart, and pqCheckOutBufferSpace().

Referenced by pg_SASL_init(), pqEndcopy3(), pqFunctionCall3(), pqPacketSend(), pqPipelineSyncInternal(), PQputCopyData(), PQputCopyEnd(), PQsendCancelRequest(), PQsendFlushRequest(), PQsendPrepare(), PQsendQueryGuts(), PQsendQueryInternal(), PQsendTypedCommand(), and sendTerminateConn().

◆ pqPutnchar()

int pqPutnchar ( const void s,
size_t  len,
PGconn conn 
)
extern

Definition at line 202 of file fe-misc.c.

203{
204 if (pqPutMsgBytes(s, len, conn))
205 return EOF;
206
207 return 0;
208}

References conn, fb(), len, and pqPutMsgBytes().

Referenced by pg_SASL_init(), pqFunctionCall3(), pqPacketSend(), PQputCopyData(), PQsendCancelRequest(), and PQsendQueryGuts().

◆ pqPuts()

int pqPuts ( const char s,
PGconn conn 
)
extern

Definition at line 152 of file fe-misc.c.

153{
154 if (pqPutMsgBytes(s, strlen(s) + 1, conn))
155 return EOF;
156
157 return 0;
158}

References conn, fb(), and pqPutMsgBytes().

Referenced by pg_SASL_init(), PQputCopyEnd(), PQsendPrepare(), PQsendQueryGuts(), PQsendQueryInternal(), and PQsendTypedCommand().

◆ pqReadData()

int pqReadData ( PGconn conn)
extern

Definition at line 606 of file fe-misc.c.

607{
608 int someread = 0;
609 int nread;
610
611 if (conn->sock == PGINVALID_SOCKET)
612 {
613 libpq_append_conn_error(conn, "connection not open");
614 return -1;
615 }
616
617 /* Left-justify any data in the buffer to make room */
618 if (conn->inStart < conn->inEnd)
619 {
620 if (conn->inStart > 0)
621 {
623 conn->inEnd - conn->inStart);
624 conn->inEnd -= conn->inStart;
626 conn->inStart = 0;
627 }
628 }
629 else
630 {
631 /* buffer is logically empty, reset it */
632 conn->inStart = conn->inCursor = conn->inEnd = 0;
633 }
634
635 /*
636 * If the buffer is fairly full, enlarge it. We need to be able to enlarge
637 * the buffer in case a single message exceeds the initial buffer size. We
638 * enlarge before filling the buffer entirely so as to avoid asking the
639 * kernel for a partial packet. The magic constant here should be large
640 * enough for a TCP packet or Unix pipe bufferload. 8K is the usual pipe
641 * buffer size, so...
642 */
643 if (conn->inBufSize - conn->inEnd < 8192)
644 {
645 if (pqCheckInBufferSpace(conn->inEnd + (size_t) 8192, conn))
646 {
647 /*
648 * We don't insist that the enlarge worked, but we need some room
649 */
650 if (conn->inBufSize - conn->inEnd < 100)
651 return -1; /* errorMessage already set */
652 }
653 }
654
655 /* OK, try to read some data */
656retry3:
659 if (nread < 0)
660 {
661 switch (SOCK_ERRNO)
662 {
663 case EINTR:
664 goto retry3;
665
666 /* Some systems return EAGAIN/EWOULDBLOCK for no data */
667#ifdef EAGAIN
668 case EAGAIN:
669 return someread;
670#endif
671#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
672 case EWOULDBLOCK:
673 return someread;
674#endif
675
676 /* We might get ECONNRESET etc here if connection failed */
678 goto definitelyFailed;
679
680 default:
681 /* pqsecure_read set the error message for us */
682 return -1;
683 }
684 }
685 if (nread > 0)
686 {
687 conn->inEnd += nread;
688
689 /*
690 * Hack to deal with the fact that some kernels will only give us back
691 * 1 packet per recv() call, even if we asked for more and there is
692 * more available. If it looks like we are reading a long message,
693 * loop back to recv() again immediately, until we run out of data or
694 * buffer space. Without this, the block-and-restart behavior of
695 * libpq's higher levels leads to O(N^2) performance on long messages.
696 *
697 * Since we left-justified the data above, conn->inEnd gives the
698 * amount of data already read in the current message. We consider
699 * the message "long" once we have acquired 32k ...
700 */
701 if (conn->inEnd > 32768 &&
702 (conn->inBufSize - conn->inEnd) >= 8192)
703 {
704 someread = 1;
705 goto retry3;
706 }
707 return 1;
708 }
709
710 if (someread)
711 return 1; /* got a zero read after successful tries */
712
713 /*
714 * A return value of 0 could mean just that no data is now available, or
715 * it could mean EOF --- that is, the server has closed the connection.
716 * Since we have the socket in nonblock mode, the only way to tell the
717 * difference is to see if select() is saying that the file is ready.
718 * Grumble. Fortunately, we don't expect this path to be taken much,
719 * since in normal practice we should not be trying to read data unless
720 * the file selected for reading already.
721 *
722 * In SSL mode it's even worse: SSL_read() could say WANT_READ and then
723 * data could arrive before we make the pqReadReady() test, but the second
724 * SSL_read() could still say WANT_READ because the data received was not
725 * a complete SSL record. So we must play dumb and assume there is more
726 * data, relying on the SSL layer to detect true EOF.
727 */
728
729#ifdef USE_SSL
730 if (conn->ssl_in_use)
731 return 0;
732#endif
733
734 switch (pqReadReady(conn))
735 {
736 case 0:
737 /* definitely no data available */
738 return 0;
739 case 1:
740 /* ready for read */
741 break;
742 default:
743 /* we override pqReadReady's message with something more useful */
744 goto definitelyEOF;
745 }
746
747 /*
748 * Still not sure that it's EOF, because some data could have just
749 * arrived.
750 */
751retry4:
754 if (nread < 0)
755 {
756 switch (SOCK_ERRNO)
757 {
758 case EINTR:
759 goto retry4;
760
761 /* Some systems return EAGAIN/EWOULDBLOCK for no data */
762#ifdef EAGAIN
763 case EAGAIN:
764 return 0;
765#endif
766#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
767 case EWOULDBLOCK:
768 return 0;
769#endif
770
771 /* We might get ECONNRESET etc here if connection failed */
773 goto definitelyFailed;
774
775 default:
776 /* pqsecure_read set the error message for us */
777 return -1;
778 }
779 }
780 if (nread > 0)
781 {
782 conn->inEnd += nread;
783 return 1;
784 }
785
786 /*
787 * OK, we are getting a zero read even though select() says ready. This
788 * means the connection has been closed. Cope.
789 */
791 libpq_append_conn_error(conn, "server closed the connection unexpectedly\n"
792 "\tThis probably means the server terminated abnormally\n"
793 "\tbefore or while processing the request.");
794
795 /* Come here if lower-level code already set a suitable errorMessage */
797 /* Do *not* drop any already-read data; caller still wants it */
798 pqDropConnection(conn, false);
799 conn->status = CONNECTION_BAD; /* No more connection to backend */
800 return -1;
801}
int pqReadReady(PGconn *conn)
Definition fe-misc.c:1058
ssize_t pqsecure_read(PGconn *conn, void *ptr, size_t len)
Definition fe-secure.c:167
#define ALL_CONNECTION_FAILURE_ERRNOS
Definition port.h:122
#define EINTR
Definition win32_port.h:361
#define EWOULDBLOCK
Definition win32_port.h:367
#define EAGAIN
Definition win32_port.h:359

References ALL_CONNECTION_FAILURE_ERRNOS, conn, CONNECTION_BAD, EAGAIN, EINTR, EWOULDBLOCK, fb(), pg_conn::inBuffer, pg_conn::inBufSize, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, libpq_append_conn_error(), PGINVALID_SOCKET, pqCheckInBufferSpace(), pqDropConnection(), pqReadReady(), pqsecure_read(), pg_conn::sock, SOCK_ERRNO, pg_conn::ssl_in_use, and pg_conn::status.

Referenced by PQcancelPoll(), PQconnectPoll(), PQconsumeInput(), pqFunctionCall3(), pqGetCopyData3(), pqGetline3(), PQgetResult(), and pqSendSome().

◆ pqReadReady()

int pqReadReady ( PGconn conn)
extern

Definition at line 1058 of file fe-misc.c.

1059{
1060 return pqSocketCheck(conn, 1, 0, 0);
1061}
static int pqSocketCheck(PGconn *conn, int forRead, int forWrite, pg_usec_time_t end_time)
Definition fe-misc.c:1083

References conn, and pqSocketCheck().

Referenced by gss_read(), and pqReadData().

◆ pqReleaseConnHosts()

void pqReleaseConnHosts ( PGconn conn)
extern

Definition at line 5190 of file fe-connect.c.

5191{
5192 if (conn->connhost)
5193 {
5194 for (int i = 0; i < conn->nconnhost; ++i)
5195 {
5196 free(conn->connhost[i].host);
5198 free(conn->connhost[i].port);
5199 if (conn->connhost[i].password != NULL)
5200 {
5204 }
5205 }
5206 free(conn->connhost);
5207 conn->connhost = NULL;
5208 }
5209}
void explicit_bzero(void *buf, size_t len)

References conn, pg_conn::connhost, explicit_bzero(), fb(), free, pg_conn_host::host, pg_conn_host::hostaddr, i, pg_conn::nconnhost, pg_conn_host::password, and pg_conn_host::port.

Referenced by freePGconn(), and PQcancelCreate().

◆ pqResultAlloc()

void * pqResultAlloc ( PGresult res,
size_t  nBytes,
bool  isBinary 
)
extern

Definition at line 564 of file fe-exec.c.

565{
566 char *space;
567 PGresult_data *block;
568
569 if (!res)
570 return NULL;
571
572 if (nBytes <= 0)
573 return res->null_field;
574
575 /*
576 * If alignment is needed, round up the current position to an alignment
577 * boundary.
578 */
579 if (isBinary)
580 {
581 int offset = res->curOffset % PGRESULT_ALIGN_BOUNDARY;
582
583 if (offset)
584 {
585 res->curOffset += PGRESULT_ALIGN_BOUNDARY - offset;
586 res->spaceLeft -= PGRESULT_ALIGN_BOUNDARY - offset;
587 }
588 }
589
590 /* If there's enough space in the current block, no problem. */
591 if (nBytes <= (size_t) res->spaceLeft)
592 {
593 space = res->curBlock->space + res->curOffset;
594 res->curOffset += nBytes;
595 res->spaceLeft -= nBytes;
596 return space;
597 }
598
599 /*
600 * If the requested object is very large, give it its own block; this
601 * avoids wasting what might be most of the current block to start a new
602 * block. (We'd have to special-case requests bigger than the block size
603 * anyway.) The object is always given binary alignment in this case.
604 */
606 {
607 size_t alloc_size;
608
609 /* Don't wrap around with overly large requests. */
611 return NULL;
612
614 block = (PGresult_data *) malloc(alloc_size);
615 if (!block)
616 return NULL;
617 res->memorySize += alloc_size;
618 space = block->space + PGRESULT_BLOCK_OVERHEAD;
619 if (res->curBlock)
620 {
621 /*
622 * Tuck special block below the active block, so that we don't
623 * have to waste the free space in the active block.
624 */
625 block->next = res->curBlock->next;
626 res->curBlock->next = block;
627 }
628 else
629 {
630 /* Must set up the new block as the first active block. */
631 block->next = NULL;
632 res->curBlock = block;
633 res->spaceLeft = 0; /* be sure it's marked full */
634 }
635 return space;
636 }
637
638 /* Otherwise, start a new block. */
640 if (!block)
641 return NULL;
643 block->next = res->curBlock;
644 res->curBlock = block;
645 if (isBinary)
646 {
647 /* object needs full alignment */
650 }
651 else
652 {
653 /* we can cram it right after the overhead pointer */
654 res->curOffset = sizeof(PGresult_data);
656 }
657
658 space = block->space + res->curOffset;
659 res->curOffset += nBytes;
660 res->spaceLeft -= nBytes;
661 return space;
662}
#define PGRESULT_DATA_BLOCKSIZE
Definition fe-exec.c:143
#define PGRESULT_BLOCK_OVERHEAD
Definition fe-exec.c:145
#define PGRESULT_SEP_ALLOC_THRESHOLD
Definition fe-exec.c:146
#define PGRESULT_ALIGN_BOUNDARY
Definition fe-exec.c:144
union pgresult_data PGresult_data
Definition libpq-int.h:98
size_t memorySize
Definition libpq-int.h:209
int curOffset
Definition libpq-int.h:206
char null_field[1]
Definition libpq-int.h:198
int spaceLeft
Definition libpq-int.h:207
PGresult_data * curBlock
Definition libpq-int.h:205
PGresult_data * next
Definition libpq-int.h:102
char space[1]
Definition libpq-int.h:103

References pg_result::curBlock, pg_result::curOffset, fb(), malloc, pg_result::memorySize, pgresult_data::next, pg_result::null_field, PGRESULT_ALIGN_BOUNDARY, PGRESULT_BLOCK_OVERHEAD, PGRESULT_DATA_BLOCKSIZE, PGRESULT_SEP_ALLOC_THRESHOLD, pgresult_data::space, and pg_result::spaceLeft.

Referenced by getCopyStart(), getParamDescriptions(), getRowDescriptions(), pqInternalNotice(), PQresultAlloc(), pqResultStrdup(), pqRowProcessor(), pqSaveMessageField(), and PQsetvalue().

◆ pqResultStrdup()

char * pqResultStrdup ( PGresult res,
const char str 
)
extern

Definition at line 681 of file fe-exec.c.

682{
683 char *space = (char *) pqResultAlloc(res, strlen(str) + 1, false);
684
685 if (space)
686 strcpy(space, str);
687 return space;
688}
void * pqResultAlloc(PGresult *res, size_t nBytes, bool isBinary)
Definition fe-exec.c:564
const char * str

References fb(), pqResultAlloc(), and str.

Referenced by getRowDescriptions(), pqGetErrorNotice3(), PQsetResultAttrs(), and pqSetResultError().

◆ pqRowProcessor()

int pqRowProcessor ( PGconn conn,
const char **  errmsgp 
)
extern

Definition at line 1223 of file fe-exec.c.

1224{
1225 PGresult *res = conn->result;
1226 int nfields = res->numAttributes;
1227 const PGdataValue *columns = conn->rowBuf;
1229 int i;
1230
1231 /*
1232 * In partial-result mode, if we don't already have a partial PGresult
1233 * then make one by cloning conn->result (which should hold the correct
1234 * result metadata by now). Then the original conn->result is moved over
1235 * to saved_result so that we can re-use it as a reference for future
1236 * partial results. The saved result will become active again after
1237 * pqPrepareAsyncResult() returns the partial result to the application.
1238 */
1240 {
1241 /* Copy everything that should be in the result at this point */
1242 res = PQcopyResult(res,
1245 if (!res)
1246 return 0;
1247 /* Change result status to appropriate special value */
1249 /* And stash it as the active result */
1251 conn->result = res;
1252 }
1253
1254 /*
1255 * Basically we just allocate space in the PGresult for each field and
1256 * copy the data over.
1257 *
1258 * Note: on malloc failure, we return 0 leaving *errmsgp still NULL, which
1259 * caller will take to mean "out of memory". This is preferable to trying
1260 * to set up such a message here, because evidently there's not enough
1261 * memory for gettext() to do anything.
1262 */
1263 tup = (PGresAttValue *)
1264 pqResultAlloc(res, nfields * sizeof(PGresAttValue), true);
1265 if (tup == NULL)
1266 return 0;
1267
1268 for (i = 0; i < nfields; i++)
1269 {
1270 int clen = columns[i].len;
1271
1272 if (clen < 0)
1273 {
1274 /* null field */
1275 tup[i].len = NULL_LEN;
1276 tup[i].value = res->null_field;
1277 }
1278 else
1279 {
1280 bool isbinary = (res->attDescs[i].format != 0);
1281 char *val;
1282
1283 val = (char *) pqResultAlloc(res, (size_t) clen + 1, isbinary);
1284 if (val == NULL)
1285 return 0;
1286
1287 /* copy and zero-terminate the data (even if it's binary) */
1288 memcpy(val, columns[i].value, clen);
1289 val[clen] = '\0';
1290
1291 tup[i].len = clen;
1292 tup[i].value = val;
1293 }
1294 }
1295
1296 /* And add the tuple to the PGresult's tuple array */
1297 if (!pqAddTuple(res, tup, errmsgp))
1298 return 0;
1299
1300 /*
1301 * Success. In partial-result mode, if we have enough rows then make the
1302 * result available to the client immediately.
1303 */
1304 if (conn->partialResMode && res->ntups >= conn->maxChunkSize)
1306
1307 return 1;
1308}
PGresult * PQcopyResult(const PGresult *src, int flags)
Definition fe-exec.c:319
static bool pqAddTuple(PGresult *res, PGresAttValue *tup, const char **errmsgp)
Definition fe-exec.c:999
@ PGRES_SINGLE_TUPLE
Definition libpq-fe.h:144
#define PG_COPYRES_ATTRS
Definition libpq-fe.h:75
#define PG_COPYRES_EVENTS
Definition libpq-fe.h:77
#define PG_COPYRES_NOTICEHOOKS
Definition libpq-fe.h:78
#define NULL_LEN
Definition libpq-int.h:130
int maxChunkSize
Definition libpq-int.h:473
bool singleRowMode
Definition libpq-int.h:472
bool partialResMode
Definition libpq-int.h:471
PGresAttDesc * attDescs
Definition libpq-int.h:168
int numAttributes
Definition libpq-int.h:167

References pg_conn::asyncStatus, pg_result::attDescs, conn, fb(), pgresAttDesc::format, i, pgDataValue::len, pg_conn::maxChunkSize, memcpy(), pg_result::ntups, pg_result::null_field, NULL_LEN, pg_result::numAttributes, pg_conn::partialResMode, PG_COPYRES_ATTRS, PG_COPYRES_EVENTS, PG_COPYRES_NOTICEHOOKS, PGASYNC_READY_MORE, PGRES_SINGLE_TUPLE, PGRES_TUPLES_CHUNK, pqAddTuple(), PQcopyResult(), pqResultAlloc(), pg_conn::result, pg_result::resultStatus, pg_conn::rowBuf, pg_conn::saved_result, pg_conn::singleRowMode, val, and value.

Referenced by getAnotherTuple().

◆ pqSaveErrorResult()

void pqSaveErrorResult ( PGconn conn)
extern

Definition at line 809 of file fe-exec.c.

810{
811 /* Drop any pending result ... */
813 /* ... and set flag to remember to make an error result later */
814 conn->error_result = true;
815}

References conn, pg_conn::error_result, and pqClearAsyncResult().

Referenced by getAnotherTuple(), getCopyResult(), getParamDescriptions(), getRowDescriptions(), handleFatalError(), pqFunctionCall3(), pqGetNegotiateProtocolVersion3(), PQgetResult(), pqParseInput3(), pqPipelineProcessQueue(), and pqSaveWriteError().

◆ pqSaveMessageField()

void void pqSaveMessageField ( PGresult res,
char  code,
const char value 
)
extern

Definition at line 1066 of file fe-exec.c.

1067{
1069
1071 pqResultAlloc(res,
1072 offsetof(PGMessageField, contents) +
1073 strlen(value) + 1,
1074 true);
1075 if (!pfield)
1076 return; /* out of memory? */
1077 pfield->code = code;
1078 strcpy(pfield->contents, value);
1079 pfield->next = res->errFields;
1080 res->errFields = pfield;
1081}

References pgMessageField::code, pg_result::errFields, fb(), pqResultAlloc(), and value.

Referenced by pqGetErrorNotice3(), and pqInternalNotice().

◆ pqSaveParameterStatus()

int pqSaveParameterStatus ( PGconn conn,
const char name,
const char value 
)
extern

Definition at line 1091 of file fe-exec.c.

1092{
1093 pgParameterStatus *pstatus;
1094 pgParameterStatus *prev;
1095
1096 /*
1097 * Forget any old information about the parameter
1098 */
1099 for (pstatus = conn->pstatus, prev = NULL;
1100 pstatus != NULL;
1101 prev = pstatus, pstatus = pstatus->next)
1102 {
1103 if (strcmp(pstatus->name, name) == 0)
1104 {
1105 if (prev)
1106 prev->next = pstatus->next;
1107 else
1108 conn->pstatus = pstatus->next;
1109 free(pstatus); /* frees name and value strings too */
1110 break;
1111 }
1112 }
1113
1114 /*
1115 * Store new info as a single malloc block
1116 */
1117 pstatus = (pgParameterStatus *) malloc(sizeof(pgParameterStatus) +
1118 strlen(name) + strlen(value) + 2);
1119 if (pstatus)
1120 {
1121 char *ptr;
1122
1123 ptr = ((char *) pstatus) + sizeof(pgParameterStatus);
1124 pstatus->name = ptr;
1125 strcpy(ptr, name);
1126 ptr += strlen(name) + 1;
1127 pstatus->value = ptr;
1128 strcpy(ptr, value);
1129 pstatus->next = conn->pstatus;
1130 conn->pstatus = pstatus;
1131 }
1132 else
1133 {
1134 /* out of memory */
1135 return 0;
1136 }
1137
1138 /*
1139 * Save values of settings that are of interest to libpq in fields of the
1140 * PGconn object. We keep client_encoding and standard_conforming_strings
1141 * in static variables as well, so that PQescapeString and PQescapeBytea
1142 * can behave somewhat sanely (at least in single-connection-using
1143 * programs).
1144 */
1145 if (strcmp(name, "client_encoding") == 0)
1146 {
1148 /* if we don't recognize the encoding name, fall back to SQL_ASCII */
1149 if (conn->client_encoding < 0)
1152 }
1153 else if (strcmp(name, "standard_conforming_strings") == 0)
1154 {
1155 conn->std_strings = (strcmp(value, "on") == 0);
1157 }
1158 else if (strcmp(name, "server_version") == 0)
1159 {
1160 /* We convert the server version to numeric form. */
1161 int cnt;
1162 int vmaj,
1163 vmin,
1164 vrev;
1165
1166 cnt = sscanf(value, "%d.%d.%d", &vmaj, &vmin, &vrev);
1167
1168 if (cnt == 3)
1169 {
1170 /* old style, e.g. 9.6.1 */
1171 conn->sversion = (100 * vmaj + vmin) * 100 + vrev;
1172 }
1173 else if (cnt == 2)
1174 {
1175 if (vmaj >= 10)
1176 {
1177 /* new style, e.g. 10.1 */
1178 conn->sversion = 100 * 100 * vmaj + vmin;
1179 }
1180 else
1181 {
1182 /* old style without minor version, e.g. 9.6devel */
1183 conn->sversion = (100 * vmaj + vmin) * 100;
1184 }
1185 }
1186 else if (cnt == 1)
1187 {
1188 /* new style without minor version, e.g. 10devel */
1189 conn->sversion = 100 * 100 * vmaj;
1190 }
1191 else
1192 conn->sversion = 0; /* unknown */
1193 }
1194 else if (strcmp(name, "default_transaction_read_only") == 0)
1195 {
1197 (strcmp(value, "on") == 0) ? PG_BOOL_YES : PG_BOOL_NO;
1198 }
1199 else if (strcmp(name, "in_hot_standby") == 0)
1200 {
1202 (strcmp(value, "on") == 0) ? PG_BOOL_YES : PG_BOOL_NO;
1203 }
1204 else if (strcmp(name, "scram_iterations") == 0)
1205 {
1207 }
1208
1209 return 1;
1210}
static bool static_std_strings
Definition fe-exec.c:61
static int static_client_encoding
Definition fe-exec.c:60
@ PG_BOOL_YES
Definition oauth-utils.h:34
@ PG_BOOL_NO
Definition oauth-utils.h:35
#define pg_char_to_encoding
Definition pg_wchar.h:482
struct pgParameterStatus * next
Definition libpq-int.h:271
int sversion
Definition libpq-int.h:505
pgParameterStatus * pstatus
Definition libpq-int.h:556

References pg_conn::client_encoding, conn, pg_conn::default_transaction_read_only, fb(), free, pg_conn::in_hot_standby, malloc, name, pgParameterStatus::name, pgParameterStatus::next, PG_BOOL_NO, PG_BOOL_YES, pg_char_to_encoding, PG_SQL_ASCII, pg_conn::pstatus, pg_conn::scram_sha_256_iterations, static_client_encoding, static_std_strings, pg_conn::std_strings, pg_conn::sversion, value, and pgParameterStatus::value.

Referenced by getParameterStatus().

◆ pqsecure_close()

void pqsecure_close ( PGconn conn)
extern

Definition at line 152 of file fe-secure.c.

153{
154#ifdef USE_SSL
156#endif
157}

References conn, and pgtls_close().

Referenced by pqDropConnection().

◆ pqsecure_open_client()

PostgresPollingStatusType pqsecure_open_client ( PGconn conn)
extern

Definition at line 138 of file fe-secure.c.

139{
140#ifdef USE_SSL
141 return pgtls_open_client(conn);
142#else
143 /* shouldn't get here */
145#endif
146}
PostgresPollingStatusType pgtls_open_client(PGconn *conn)

References conn, PGRES_POLLING_FAILED, and pgtls_open_client().

Referenced by PQconnectPoll().

◆ pqsecure_raw_read()

ssize_t pqsecure_raw_read ( PGconn conn,
void ptr,
size_t  len 
)
extern

Definition at line 193 of file fe-secure.c.

194{
195 ssize_t n;
196 int result_errno = 0;
198
200
201 n = recv(conn->sock, ptr, len, 0);
202
203 if (n < 0)
204 {
206
207 /* Set error message if appropriate */
208 switch (result_errno)
209 {
210#ifdef EAGAIN
211 case EAGAIN:
212#endif
213#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
214 case EWOULDBLOCK:
215#endif
216 case EINTR:
217 /* no error message, caller is expected to retry */
218 break;
219
220 case EPIPE:
221 case ECONNRESET:
222 libpq_append_conn_error(conn, "server closed the connection unexpectedly\n"
223 "\tThis probably means the server terminated abnormally\n"
224 "\tbefore or while processing the request.");
225 break;
226
227 case 0:
228 /* If errno didn't get set, treat it as regular EOF */
229 n = 0;
230 break;
231
232 default:
233 libpq_append_conn_error(conn, "could not receive data from server: %s",
235 sebuf, sizeof(sebuf)));
236 break;
237 }
238 }
239
240 /* ensure we return the intended errno to caller */
242
243 return n;
244}
#define recv(s, buf, len, flags)
Definition win32_port.h:501

References conn, EAGAIN, ECONNRESET, EINTR, EWOULDBLOCK, fb(), len, libpq_append_conn_error(), PG_STRERROR_R_BUFLEN, recv, pg_conn::sock, SOCK_ERRNO, SOCK_ERRNO_SET, and SOCK_STRERROR.

Referenced by gss_read(), pg_GSS_read(), pgconn_bio_read(), and pqsecure_read().

◆ pqsecure_raw_write()

ssize_t pqsecure_raw_write ( PGconn conn,
const void ptr,
size_t  len 
)
extern

Definition at line 316 of file fe-secure.c.

317{
318 ssize_t n;
319 int flags = 0;
320 int result_errno = 0;
321 char msgbuf[1024];
323
325
326 /*
327 * If we already had a write failure, we will never again try to send data
328 * on that connection. Even if the kernel would let us, we've probably
329 * lost message boundary sync with the server. conn->write_failed
330 * therefore persists until the connection is reset, and we just discard
331 * all data presented to be written.
332 */
333 if (conn->write_failed)
334 return len;
335
336#ifdef MSG_NOSIGNAL
337 if (conn->sigpipe_flag)
338 flags |= MSG_NOSIGNAL;
339
341#endif /* MSG_NOSIGNAL */
342
343 DISABLE_SIGPIPE(conn, spinfo, return -1);
344
345 n = send(conn->sock, ptr, len, flags);
346
347 if (n < 0)
348 {
350
351 /*
352 * If we see an EINVAL, it may be because MSG_NOSIGNAL isn't available
353 * on this machine. So, clear sigpipe_flag so we don't try the flag
354 * again, and retry the send().
355 */
356#ifdef MSG_NOSIGNAL
357 if (flags != 0 && result_errno == EINVAL)
358 {
359 conn->sigpipe_flag = false;
360 flags = 0;
361 goto retry_masked;
362 }
363#endif /* MSG_NOSIGNAL */
364
365 /* Set error message if appropriate */
366 switch (result_errno)
367 {
368#ifdef EAGAIN
369 case EAGAIN:
370#endif
371#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
372 case EWOULDBLOCK:
373#endif
374 case EINTR:
375 /* no error message, caller is expected to retry */
376 break;
377
378 case EPIPE:
379 /* Set flag for EPIPE */
380 REMEMBER_EPIPE(spinfo, true);
381
383
384 case ECONNRESET:
385 conn->write_failed = true;
386 /* Store error message in conn->write_err_msg, if possible */
387 /* (strdup failure is OK, we'll cope later) */
388 snprintf(msgbuf, sizeof(msgbuf),
389 libpq_gettext("server closed the connection unexpectedly\n"
390 "\tThis probably means the server terminated abnormally\n"
391 "\tbefore or while processing the request."));
392 /* keep newline out of translated string */
393 strlcat(msgbuf, "\n", sizeof(msgbuf));
395 /* Now claim the write succeeded */
396 n = len;
397 break;
398
399 default:
400 conn->write_failed = true;
401 /* Store error message in conn->write_err_msg, if possible */
402 /* (strdup failure is OK, we'll cope later) */
403 snprintf(msgbuf, sizeof(msgbuf),
404 libpq_gettext("could not send data to server: %s"),
406 sebuf, sizeof(sebuf)));
407 /* keep newline out of translated string */
408 strlcat(msgbuf, "\n", sizeof(msgbuf));
410 /* Now claim the write succeeded */
411 n = len;
412 break;
413 }
414 }
415
417
418 /* ensure we return the intended errno to caller */
420
421 return n;
422}
#define pg_fallthrough
Definition c.h:161
#define REMEMBER_EPIPE(spinfo, cond)
Definition fe-secure.c:77
#define DISABLE_SIGPIPE(conn, spinfo, failaction)
Definition fe-secure.c:66
#define DECLARE_SIGPIPE_INFO(spinfo)
Definition fe-secure.c:64
#define RESTORE_SIGPIPE(conn, spinfo)
Definition fe-secure.c:83
size_t strlcat(char *dst, const char *src, size_t siz)
Definition strlcat.c:33
char * write_err_msg
Definition libpq-int.h:514
bool sigpipe_flag
Definition libpq-int.h:512
bool write_failed
Definition libpq-int.h:513
#define send(s, buf, len, flags)
Definition win32_port.h:502

References conn, DECLARE_SIGPIPE_INFO, DISABLE_SIGPIPE, EAGAIN, ECONNRESET, EINTR, EWOULDBLOCK, fb(), len, libpq_gettext, pg_fallthrough, PG_STRERROR_R_BUFLEN, REMEMBER_EPIPE, RESTORE_SIGPIPE, send, pg_conn::sigpipe_flag, snprintf, pg_conn::sock, SOCK_ERRNO, SOCK_ERRNO_SET, SOCK_STRERROR, strlcat(), pg_conn::write_err_msg, and pg_conn::write_failed.

Referenced by pg_GSS_write(), pgconn_bio_write(), pqsecure_open_gss(), and pqsecure_write().

◆ pqsecure_read()

ssize_t pqsecure_read ( PGconn conn,
void ptr,
size_t  len 
)
extern

Definition at line 167 of file fe-secure.c.

168{
169 ssize_t n;
170
171#ifdef USE_SSL
172 if (conn->ssl_in_use)
173 {
174 n = pgtls_read(conn, ptr, len);
175 }
176 else
177#endif
178#ifdef ENABLE_GSS
179 if (conn->gssenc)
180 {
181 n = pg_GSS_read(conn, ptr, len);
182 }
183 else
184#endif
185 {
186 n = pqsecure_raw_read(conn, ptr, len);
187 }
188
189 return n;
190}
ssize_t pg_GSS_read(PGconn *conn, void *ptr, size_t len)
ssize_t pgtls_read(PGconn *conn, void *ptr, size_t len)
ssize_t pqsecure_raw_read(PGconn *conn, void *ptr, size_t len)
Definition fe-secure.c:193

References conn, fb(), len, pg_GSS_read(), pgtls_read(), pqsecure_raw_read(), and pg_conn::ssl_in_use.

Referenced by pqReadData().

◆ pqsecure_write()

ssize_t pqsecure_write ( PGconn conn,
const void ptr,
size_t  len 
)
extern

Definition at line 267 of file fe-secure.c.

268{
269 ssize_t n;
270
271#ifdef USE_SSL
272 if (conn->ssl_in_use)
273 {
274 n = pgtls_write(conn, ptr, len);
275 }
276 else
277#endif
278#ifdef ENABLE_GSS
279 if (conn->gssenc)
280 {
281 n = pg_GSS_write(conn, ptr, len);
282 }
283 else
284#endif
285 {
286 n = pqsecure_raw_write(conn, ptr, len);
287 }
288
289 return n;
290}
ssize_t pg_GSS_write(PGconn *conn, const void *ptr, size_t len)
ssize_t pgtls_write(PGconn *conn, const void *ptr, size_t len)
ssize_t pqsecure_raw_write(PGconn *conn, const void *ptr, size_t len)
Definition fe-secure.c:316

References conn, fb(), len, pg_GSS_write(), pgtls_write(), pqsecure_raw_write(), and pg_conn::ssl_in_use.

Referenced by pqSendSome().

◆ PQsendCancelRequest()

int PQsendCancelRequest ( PGconn cancelConn)
extern

Definition at line 472 of file fe-cancel.c.

473{
475
476 /* Start the message. */
478 return STATUS_ERROR;
479
480 /* Send the message body. */
481 memset(&req, 0, offsetof(CancelRequestPacket, cancelAuthCode));
482 req.cancelRequestCode = pg_hton32(CANCEL_REQUEST_CODE);
483 req.backendPID = pg_hton32(cancelConn->be_pid);
484 if (pqPutnchar(&req, offsetof(CancelRequestPacket, cancelAuthCode), cancelConn))
485 return STATUS_ERROR;
486 if (pqPutnchar(cancelConn->be_cancel_key, cancelConn->be_cancel_key_len, cancelConn))
487 return STATUS_ERROR;
488
489 /* Finish the message. */
491 return STATUS_ERROR;
492
493 /* Flush to ensure backend gets it. */
494 if (pqFlush(cancelConn))
495 return STATUS_ERROR;
496
497 return STATUS_OK;
498}
static PGcancel *volatile cancelConn
Definition cancel.c:43
#define CANCEL_REQUEST_CODE
Definition pqcomm.h:122
int be_pid
Definition fe-cancel.c:43

References pg_cancel::be_pid, CANCEL_REQUEST_CODE, cancelConn, fb(), pg_hton32, pqFlush(), pqPutMsgEnd(), pqPutMsgStart(), pqPutnchar(), STATUS_ERROR, and STATUS_OK.

Referenced by PQconnectPoll().

◆ PQsendQueryContinue()

int PQsendQueryContinue ( PGconn conn,
const char query 
)
extern

Definition at line 1439 of file fe-exec.c.

1440{
1441 return PQsendQueryInternal(conn, query, false);
1442}
static int PQsendQueryInternal(PGconn *conn, const char *query, bool newQuery)
Definition fe-exec.c:1445

References conn, and PQsendQueryInternal().

Referenced by PQconnectPoll().

◆ pqSetResultError()

void pqSetResultError ( PGresult res,
PQExpBuffer  errorMessage,
int  offset 
)
extern

Definition at line 698 of file fe-exec.c.

699{
700 char *msg;
701
702 if (!res)
703 return;
704
705 /*
706 * We handle two OOM scenarios here. The errorMessage buffer might be
707 * marked "broken" due to having previously failed to allocate enough
708 * memory for the message, or it might be fine but pqResultStrdup fails
709 * and returns NULL. In either case, just make res->errMsg point directly
710 * at a constant "out of memory" string.
711 */
712 if (!PQExpBufferBroken(errorMessage))
713 msg = pqResultStrdup(res, errorMessage->data + offset);
714 else
715 msg = NULL;
716 if (msg)
717 res->errMsg = msg;
718 else
719 res->errMsg = libpq_gettext("out of memory\n");
720}

References PQExpBufferData::data, pg_result::errMsg, fb(), libpq_gettext, PQExpBufferBroken, and pqResultStrdup().

Referenced by pqGetErrorNotice3(), PQmakeEmptyPGresult(), and pqPrepareAsyncResult().

◆ pqSkipnchar()

int pqSkipnchar ( size_t  len,
PGconn conn 
)
extern

Definition at line 187 of file fe-misc.c.

188{
189 if (len > (size_t) (conn->inEnd - conn->inCursor))
190 return EOF;
191
192 conn->inCursor += len;
193
194 return 0;
195}

References conn, fb(), pg_conn::inCursor, pg_conn::inEnd, and len.

Referenced by getAnotherTuple().

◆ pqTraceOutputCharResponse()

void pqTraceOutputCharResponse ( PGconn conn,
const char responseType,
char  response 
)
extern

Definition at line 915 of file fe-trace.c.

917{
919 {
920 char timestr[128];
921
923 fprintf(conn->Pfdebug, "%s\t", timestr);
924 }
925
926 fprintf(conn->Pfdebug, "B\t1\t%s\t %c\n", responseType, response);
927}
#define fprintf(file, fmt, msg)
Definition cubescan.l:21
static void pqTraceFormatTimestamp(char *timestr, size_t ts_len)
Definition fe-trace.c:80
#define PQTRACE_SUPPRESS_TIMESTAMPS
Definition libpq-fe.h:488
int traceFlags
Definition libpq-int.h:452

References conn, fb(), fprintf, pg_conn::Pfdebug, PQTRACE_SUPPRESS_TIMESTAMPS, pqTraceFormatTimestamp(), and pg_conn::traceFlags.

Referenced by PQconnectPoll().

◆ pqTraceOutputMessage()

void pqTraceOutputMessage ( PGconn conn,
const char message,
bool  toServer 
)
extern

Definition at line 624 of file fe-trace.c.

625{
626 char id;
627 int length;
628 char *prefix = toServer ? "F" : "B";
629 int logCursor = 0;
630 bool regress;
631
633 {
634 char timestr[128];
635
637 fprintf(conn->Pfdebug, "%s\t", timestr);
638 }
640
641 id = message[logCursor++];
642
643 memcpy(&length, message + logCursor, 4);
644 length = (int) pg_ntoh32(length);
645 logCursor += 4;
646
647 /*
648 * In regress mode, suppress the length of ErrorResponse and
649 * NoticeResponse. The F (file name), L (line number) and R (routine
650 * name) fields can change as server code is modified, and if their
651 * lengths differ from the originals, that would break tests.
652 */
653 if (regress && !toServer && (id == PqMsg_ErrorResponse || id == PqMsg_NoticeResponse))
654 fprintf(conn->Pfdebug, "%s\tNN\t", prefix);
655 else
656 fprintf(conn->Pfdebug, "%s\t%d\t", prefix, length);
657
658 switch (id)
659 {
661 fprintf(conn->Pfdebug, "ParseComplete");
662 /* No message content */
663 break;
665 fprintf(conn->Pfdebug, "BindComplete");
666 /* No message content */
667 break;
669 fprintf(conn->Pfdebug, "CloseComplete");
670 /* No message content */
671 break;
674 break;
675 case PqMsg_Bind:
677 break;
678 case PqMsg_CopyDone:
679 fprintf(conn->Pfdebug, "CopyDone");
680 /* No message content */
681 break;
683 /* Close(F) and CommandComplete(B) use the same identifier. */
685 if (toServer)
687 else
689 break;
690 case PqMsg_CopyData:
692 length, regress);
693 break;
694 case PqMsg_Describe:
695 /* Describe(F) and DataRow(B) use the same identifier. */
697 if (toServer)
699 else
701 break;
702 case PqMsg_Execute:
703 /* Execute(F) and ErrorResponse(B) use the same identifier. */
705 if (toServer)
707 else
709 break;
710 case PqMsg_CopyFail:
712 break;
717
718 /*
719 * These messages share a common type byte, so we discriminate by
720 * having the code store the auth type separately.
721 */
723 {
726 &logCursor, length, regress);
727 break;
730 &logCursor);
731 break;
735 break;
738 &logCursor, length, regress);
739 break;
740 default:
741 fprintf(conn->Pfdebug, "UnknownAuthenticationResponse");
742 break;
743 }
745 break;
748 break;
751 break;
752 case PqMsg_Flush:
753 /* Flush(F) and CopyOutResponse(B) use the same identifier */
755 if (toServer)
756 fprintf(conn->Pfdebug, "Flush"); /* no message content */
757 else
759 break;
761 fprintf(conn->Pfdebug, "EmptyQueryResponse");
762 /* No message content */
763 break;
766 break;
767 case PqMsg_NoData:
768 fprintf(conn->Pfdebug, "NoData");
769 /* No message content */
770 break;
773 break;
774 case PqMsg_Parse:
776 break;
777 case PqMsg_Query:
779 break;
782 length, regress);
783 break;
785 fprintf(conn->Pfdebug, "PortalSuspended");
786 /* No message content */
787 break;
788 case PqMsg_Sync:
789 /* ParameterStatus(B) and Sync(F) use the same identifier */
791 if (toServer)
792 fprintf(conn->Pfdebug, "Sync"); /* no message content */
793 else
795 break;
798 break;
801 break;
804 break;
807 break;
810 break;
811 case PqMsg_Terminate:
812 fprintf(conn->Pfdebug, "Terminate");
813 /* No message content */
814 break;
817 break;
818 default:
819 fprintf(conn->Pfdebug, "Unknown message: %02x", id);
820 break;
821 }
822
823 fputc('\n', conn->Pfdebug);
824
825 /*
826 * Verify the printing routine did it right. Note that the one-byte
827 * message identifier is not included in the length, but our cursor does
828 * include it.
829 */
830 if (logCursor - 1 != length)
832 "mismatched message length: consumed %d, expected %d\n",
833 logCursor - 1, length);
834}
static void pqTraceOutput_RowDescription(FILE *f, const char *message, int *cursor, bool regress)
Definition fe-trace.c:559
static void pqTraceOutput_GSSResponse(FILE *f, const char *message, int *cursor, int length, bool regress)
Definition fe-trace.c:367
static void pqTraceOutput_FunctionCall(FILE *f, const char *message, int *cursor, bool regress)
Definition fe-trace.c:403
static void pqTraceOutput_CopyInResponse(FILE *f, const char *message, int *cursor)
Definition fe-trace.c:429
static void pqTraceOutput_BackendKeyData(FILE *f, const char *message, int *cursor, bool regress)
Definition fe-trace.c:455
static void pqTraceOutput_Authentication(FILE *f, const char *message, int *cursor, int length, bool suppress)
Definition fe-trace.c:484
static void pqTraceOutput_Parse(FILE *f, const char *message, int *cursor, bool regress)
Definition fe-trace.c:463
static void pqTraceOutput_NoticeResponse(FILE *f, const char *message, int *cursor, bool regress)
Definition fe-trace.c:346
static void pqTraceOutput_ParameterDescription(FILE *f, const char *message, int *cursor, bool regress)
Definition fe-trace.c:547
static void pqTraceOutput_DataRow(FILE *f, const char *message, int *cursor)
Definition fe-trace.c:293
static void pqTraceOutput_SASLResponse(FILE *f, const char *message, int *cursor, int length, bool regress)
Definition fe-trace.c:395
static void pqTraceOutput_Query(FILE *f, const char *message, int *cursor)
Definition fe-trace.c:477
static void pqTraceOutput_CopyData(FILE *f, const char *message, int *cursor, int length, bool suppress)
Definition fe-trace.c:285
static void pqTraceOutput_SASLInitialResponse(FILE *f, const char *message, int *cursor, bool regress)
Definition fe-trace.c:382
static void pqTraceOutput_NegotiateProtocolVersion(FILE *f, const char *message, int *cursor)
Definition fe-trace.c:579
static void pqTraceOutput_CopyBothResponse(FILE *f, const char *message, int *cursor, int length)
Definition fe-trace.c:604
static void pqTraceOutput_Bind(FILE *f, const char *message, int *cursor)
Definition fe-trace.c:240
static void pqTraceOutput_ErrorResponse(FILE *f, const char *message, int *cursor, bool regress)
Definition fe-trace.c:340
static void pqTraceOutput_Close(FILE *f, const char *message, int *cursor)
Definition fe-trace.c:270
static void pqTraceOutput_Describe(FILE *f, const char *message, int *cursor)
Definition fe-trace.c:311
static void pqTraceOutput_NotificationResponse(FILE *f, const char *message, int *cursor, bool regress)
Definition fe-trace.c:231
static void pqTraceOutput_CommandComplete(FILE *f, const char *message, int *cursor)
Definition fe-trace.c:278
static void pqTraceOutput_ParameterStatus(FILE *f, const char *message, int *cursor)
Definition fe-trace.c:539
static void pqTraceOutput_Execute(FILE *f, const char *message, int *cursor, bool regress)
Definition fe-trace.c:352
static void pqTraceOutput_CopyOutResponse(FILE *f, const char *message, int *cursor)
Definition fe-trace.c:442
static void pqTraceOutput_ReadyForQuery(FILE *f, const char *message, int *cursor)
Definition fe-trace.c:614
static void pqTraceOutput_CopyFail(FILE *f, const char *message, int *cursor)
Definition fe-trace.c:360
static void pqTraceOutput_PasswordMessage(FILE *f, const char *message, int *cursor)
Definition fe-trace.c:375
static void pqTraceOutput_FunctionCallResponse(FILE *f, const char *message, int *cursor)
Definition fe-trace.c:593
#define PQTRACE_REGRESS_MODE
Definition libpq-fe.h:490
#define AUTH_RESPONSE_PASSWORD
Definition libpq-int.h:336
#define AUTH_RESPONSE_SASL
Definition libpq-int.h:338
#define AUTH_RESPONSE_SASL_INITIAL
Definition libpq-int.h:337
#define AUTH_RESPONSE_GSS
Definition libpq-int.h:335
#define PqMsg_GSSResponse
Definition protocol.h:30
#define PqMsg_SASLResponse
Definition protocol.h:33
#define PqMsg_Describe
Definition protocol.h:21
#define PqMsg_SASLInitialResponse
Definition protocol.h:32
#define PqMsg_AuthenticationRequest
Definition protocol.h:50
#define PqMsg_NegotiateProtocolVersion
Definition protocol.h:59
#define PqMsg_PortalSuspended
Definition protocol.h:57
#define PqMsg_Parse
Definition protocol.h:25
#define PqMsg_Bind
Definition protocol.h:19
#define PqMsg_PasswordMessage
Definition protocol.h:31
#define PqMsg_CopyFail
Definition protocol.h:29
#define PqMsg_Flush
Definition protocol.h:24
#define PqMsg_Query
Definition protocol.h:26
#define PqMsg_Terminate
Definition protocol.h:28
#define PqMsg_Execute
Definition protocol.h:22
#define PqMsg_Close
Definition protocol.h:20
char current_auth_response
Definition libpq-int.h:524

References Assert, AUTH_RESPONSE_GSS, AUTH_RESPONSE_PASSWORD, AUTH_RESPONSE_SASL, AUTH_RESPONSE_SASL_INITIAL, conn, pg_conn::current_auth_response, fb(), fprintf, memcpy(), pg_conn::Pfdebug, pg_ntoh32, PqMsg_AuthenticationRequest, PqMsg_BackendKeyData, PqMsg_Bind, PqMsg_BindComplete, PqMsg_Close, PqMsg_CloseComplete, PqMsg_CommandComplete, PqMsg_CopyBothResponse, PqMsg_CopyData, PqMsg_CopyDone, PqMsg_CopyFail, PqMsg_CopyInResponse, PqMsg_CopyOutResponse, PqMsg_DataRow, PqMsg_Describe, PqMsg_EmptyQueryResponse, PqMsg_ErrorResponse, PqMsg_Execute, PqMsg_Flush, PqMsg_FunctionCall, PqMsg_FunctionCallResponse, PqMsg_GSSResponse, PqMsg_NegotiateProtocolVersion, PqMsg_NoData, PqMsg_NoticeResponse, PqMsg_NotificationResponse, PqMsg_ParameterDescription, PqMsg_ParameterStatus, PqMsg_Parse, PqMsg_ParseComplete, PqMsg_PasswordMessage, PqMsg_PortalSuspended, PqMsg_Query, PqMsg_ReadyForQuery, PqMsg_RowDescription, PqMsg_SASLInitialResponse, PqMsg_SASLResponse, PqMsg_Sync, PqMsg_Terminate, PQTRACE_REGRESS_MODE, PQTRACE_SUPPRESS_TIMESTAMPS, pqTraceFormatTimestamp(), pqTraceOutput_Authentication(), pqTraceOutput_BackendKeyData(), pqTraceOutput_Bind(), pqTraceOutput_Close(), pqTraceOutput_CommandComplete(), pqTraceOutput_CopyBothResponse(), pqTraceOutput_CopyData(), pqTraceOutput_CopyFail(), pqTraceOutput_CopyInResponse(), pqTraceOutput_CopyOutResponse(), pqTraceOutput_DataRow(), pqTraceOutput_Describe(), pqTraceOutput_ErrorResponse(), pqTraceOutput_Execute(), pqTraceOutput_FunctionCall(), pqTraceOutput_FunctionCallResponse(), pqTraceOutput_GSSResponse(), pqTraceOutput_NegotiateProtocolVersion(), pqTraceOutput_NoticeResponse(), pqTraceOutput_NotificationResponse(), pqTraceOutput_ParameterDescription(), pqTraceOutput_ParameterStatus(), pqTraceOutput_Parse(), pqTraceOutput_PasswordMessage(), pqTraceOutput_Query(), pqTraceOutput_ReadyForQuery(), pqTraceOutput_RowDescription(), pqTraceOutput_SASLInitialResponse(), pqTraceOutput_SASLResponse(), and pg_conn::traceFlags.

Referenced by pg_password_sendauth(), pg_SASL_continue(), pg_SASL_init(), pqParseDone(), and pqPutMsgEnd().

◆ pqTraceOutputNoTypeByteMessage()

void pqTraceOutputNoTypeByteMessage ( PGconn conn,
const char message 
)
extern

Definition at line 841 of file fe-trace.c.

842{
843 int length;
844 int version;
845 bool regress;
846 int logCursor = 0;
847
849
851 {
852 char timestr[128];
853
855 fprintf(conn->Pfdebug, "%s\t", timestr);
856 }
857
858 memcpy(&length, message + logCursor, 4);
859 length = (int) pg_ntoh32(length);
860 logCursor += 4;
861
862 fprintf(conn->Pfdebug, "F\t%d\t", length);
863
864 if (length < 8)
865 {
866 fprintf(conn->Pfdebug, "Unknown message\n");
867 return;
868 }
869
870 memcpy(&version, message + logCursor, 4);
871 version = (int) pg_ntoh32(version);
872
873 if (version == CANCEL_REQUEST_CODE && length >= 16)
874 {
875 fprintf(conn->Pfdebug, "CancelRequest\t");
880 }
881 else if (version == NEGOTIATE_SSL_CODE)
882 {
883 fprintf(conn->Pfdebug, "SSLRequest\t");
886 }
887 else if (version == NEGOTIATE_GSS_CODE)
888 {
889 fprintf(conn->Pfdebug, "GSSENCRequest\t");
892 }
893 else
894 {
895 fprintf(conn->Pfdebug, "StartupMessage\t");
898 while (message[logCursor] != '\0')
899 {
900 /* XXX should we suppress anything in regress mode? */
901 pqTraceOutputString(conn->Pfdebug, message, &logCursor, false);
902 pqTraceOutputString(conn->Pfdebug, message, &logCursor, false);
903 }
904 }
905
906 fputc('\n', conn->Pfdebug);
907}
static void pqTraceOutputString(FILE *pfdebug, const char *data, int *cursor, bool suppress)
Definition fe-trace.c:166
static int pqTraceOutputInt16(FILE *pfdebug, const char *data, int *cursor)
Definition fe-trace.c:126
static int pqTraceOutputInt32(FILE *pfdebug, const char *data, int *cursor, bool suppress)
Definition fe-trace.c:145
#define NEGOTIATE_GSS_CODE
Definition pqcomm.h:129
#define NEGOTIATE_SSL_CODE
Definition pqcomm.h:128

References CANCEL_REQUEST_CODE, conn, fb(), fprintf, memcpy(), NEGOTIATE_GSS_CODE, NEGOTIATE_SSL_CODE, pg_conn::Pfdebug, pg_ntoh32, PQTRACE_REGRESS_MODE, PQTRACE_SUPPRESS_TIMESTAMPS, pqTraceFormatTimestamp(), pqTraceOutputInt16(), pqTraceOutputInt32(), pqTraceOutputString(), and pg_conn::traceFlags.

Referenced by pqPutMsgEnd().

◆ pqWait()

int pqWait ( int  forRead,
int  forWrite,
PGconn conn 
)
extern

Definition at line 1019 of file fe-misc.c.

1020{
1021 return pqWaitTimed(forRead, forWrite, conn, -1);
1022}

References conn, fb(), and pqWaitTimed().

Referenced by pqFunctionCall3(), pqGetCopyData3(), pqGetline3(), PQgetResult(), and pqSendSome().

◆ pqWaitTimed()

int pqWaitTimed ( int  forRead,
int  forWrite,
PGconn conn,
pg_usec_time_t  end_time 
)
extern

Definition at line 1035 of file fe-misc.c.

1036{
1037 int result;
1038
1040
1041 if (result < 0)
1042 return -1; /* errorMessage is already set */
1043
1044 if (result == 0)
1045 {
1046 libpq_append_conn_error(conn, "timeout expired");
1047 return 1;
1048 }
1049
1050 return 0;
1051}

References conn, end_time, fb(), libpq_append_conn_error(), pqSocketCheck(), and result.

Referenced by pqConnectDBComplete(), and pqWait().

◆ pqWriteReady()

int pqWriteReady ( PGconn conn)
extern

Definition at line 1068 of file fe-misc.c.

1069{
1070 return pqSocketCheck(conn, 0, 1, 0);
1071}

References conn, and pqSocketCheck().

Variable Documentation

◆ pg_g_threadlock

pgthreadlock_t pg_g_threadlock
extern

Definition at line 35 of file oauth-utils.c.

Referenced by libpq_oauth_init(), PQgetThreadLock(), and PQregisterThreadLock().

◆ pgresStatus

char* const pgresStatus[]
extern

Definition at line 33 of file fe-exec.c.

33 {
34 "PGRES_EMPTY_QUERY",
35 "PGRES_COMMAND_OK",
36 "PGRES_TUPLES_OK",
37 "PGRES_COPY_OUT",
38 "PGRES_COPY_IN",
39 "PGRES_BAD_RESPONSE",
40 "PGRES_NONFATAL_ERROR",
41 "PGRES_FATAL_ERROR",
42 "PGRES_COPY_BOTH",
43 "PGRES_SINGLE_TUPLE",
44 "PGRES_PIPELINE_SYNC",
45 "PGRES_PIPELINE_ABORTED",
46 "PGRES_TUPLES_CHUNK"
47};

Referenced by PQresStatus().