PostgreSQL Source Code  git master
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 "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
 
struct  pg_cancel
 

Macros

#define CMDSTATUS_LEN   64 /* should match COMPLETION_TAG_BUFSIZE */
 
#define NULL_LEN   (-1) /* pg_result len for NULL value */
 
#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)
 
int pqPacketSend (PGconn *conn, char pack_type, const void *buf, size_t buf_len)
 
bool pqGetHomeDirectory (char *buf, int bufsize)
 
void pqSetResultError (PGresult *res, PQExpBuffer errorMessage, int offset)
 
void * pqResultAlloc (PGresult *res, size_t nBytes, bool isBinary)
 
char * pqResultStrdup (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)
 
void pqSaveParameterStatus (PGconn *conn, const char *name, const char *value)
 
int pqRowProcessor (PGconn *conn, const char **errmsgp)
 
void pqCommandQueueAdvance (PGconn *conn)
 
int PQsendQueryContinue (PGconn *conn, const char *query)
 
char * pqBuildStartupPacket3 (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 pqCheckOutBufferSpace (size_t bytes_needed, PGconn *conn)
 
int pqCheckInBufferSpace (size_t bytes_needed, PGconn *conn)
 
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 (char *s, size_t len, PGconn *conn)
 
int pqSkipnchar (size_t len, PGconn *conn)
 
int pqPutnchar (const char *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, time_t finish_time)
 
int pqReadReady (PGconn *conn)
 
int pqWriteReady (PGconn *conn)
 
int pqsecure_initialize (PGconn *, bool, bool)
 
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)
 
void pgtls_init_library (bool do_ssl, int do_crypto)
 
int pgtls_init (PGconn *conn, bool do_ssl, bool do_crypto)
 
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)
 
char * pgtls_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 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
 

Variables

char *const pgresStatus []
 
pgthreadlock_t pg_g_threadlock
 

Macro Definition Documentation

◆ CMDSTATUS_LEN

#define CMDSTATUS_LEN   64 /* should match COMPLETION_TAG_BUFSIZE */

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

◆ libpq_gettext

#define libpq_gettext (   x)    (x)

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

◆ libpq_ngettext

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

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

◆ NULL_LEN

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

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

◆ OUTBUFFER_THRESHOLD

#define OUTBUFFER_THRESHOLD   65536

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

◆ pgHavePendingResult

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

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

◆ pglock_thread

#define pglock_thread ( )    pg_g_threadlock(true)

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

◆ pgunlock_thread

#define pgunlock_thread ( )    pg_g_threadlock(false)

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

◆ pqClearConnErrorState

#define pqClearConnErrorState (   conn)
Value:
(resetPQExpBuffer(&(conn)->errorMessage), \
(conn)->errorReported = 0)
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:146
PGconn * conn
Definition: streamutil.c:54

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

◆ pqIsnonblocking

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

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

◆ SOCK_ERRNO

#define SOCK_ERRNO   errno

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

◆ SOCK_ERRNO_SET

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

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

◆ SOCK_STRERROR

#define SOCK_STRERROR   strerror_r

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

Typedef Documentation

◆ pg_conn_host

typedef struct pg_conn_host pg_conn_host

◆ pg_conn_host_type

◆ PGcmdQueueEntry

◆ PGdataValue

typedef struct pgDataValue PGdataValue

◆ PGEvent

typedef struct PGEvent PGEvent

◆ PGlobjfuncs

typedef struct pgLobjfuncs PGlobjfuncs

◆ PGMessageField

◆ pgParameterStatus

◆ PGresAttValue

typedef struct pgresAttValue PGresAttValue

◆ PGresParamDesc

◆ PGresult_data

Definition at line 1 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 219 of file libpq-int.h.

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

◆ 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 */
326 } PGQueryClass;
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) */
259 } PGTernaryBool;
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,
  ... 
)

◆ libpq_append_error()

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

◆ pgtls_close()

void pgtls_close ( PGconn conn)

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

1611 {
1612  bool destroy_needed = false;
1613 
1614  if (conn->ssl_in_use)
1615  {
1616  if (conn->ssl)
1617  {
1618  /*
1619  * We can't destroy everything SSL-related here due to the
1620  * possible later calls to OpenSSL routines which may need our
1621  * thread callbacks, so set a flag here and check at the end.
1622  */
1623 
1624  SSL_shutdown(conn->ssl);
1625  SSL_free(conn->ssl);
1626  conn->ssl = NULL;
1627  conn->ssl_in_use = false;
1628 
1629  destroy_needed = true;
1630  }
1631 
1632  if (conn->peer)
1633  {
1634  X509_free(conn->peer);
1635  conn->peer = NULL;
1636  }
1637 
1638 #ifdef USE_SSL_ENGINE
1639  if (conn->engine)
1640  {
1641  ENGINE_finish(conn->engine);
1642  ENGINE_free(conn->engine);
1643  conn->engine = NULL;
1644  }
1645 #endif
1646  }
1647  else
1648  {
1649  /*
1650  * In the non-SSL case, just remove the crypto callbacks if the
1651  * connection has then loaded. This code path has no dependency on
1652  * any pending SSL calls.
1653  */
1654  if (conn->crypto_loaded)
1655  destroy_needed = true;
1656  }
1657 
1658  /*
1659  * This will remove our crypto locking hooks if this is the last
1660  * connection using libcrypto which means we must wait to call it until
1661  * after all the potential SSL calls have been made, otherwise we can end
1662  * up with a race condition and possible deadlocks.
1663  *
1664  * See comments above destroy_ssl_system().
1665  */
1666  if (destroy_needed)
1667  {
1669  conn->crypto_loaded = false;
1670  }
1671 }
static void destroy_ssl_system(void)
bool ssl_in_use
Definition: libpq-int.h:547

References conn, destroy_ssl_system(), 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 
)

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

362 {
363  X509 *peer_cert;
364  const EVP_MD *algo_type;
365  unsigned char hash[EVP_MAX_MD_SIZE]; /* size for SHA-512 */
366  unsigned int hash_size;
367  int algo_nid;
368  char *cert_hash;
369 
370  *len = 0;
371 
372  if (!conn->peer)
373  return NULL;
374 
375  peer_cert = conn->peer;
376 
377  /*
378  * Get the signature algorithm of the certificate to determine the hash
379  * algorithm to use for the result. Prefer X509_get_signature_info(),
380  * introduced in OpenSSL 1.1.1, which can handle RSA-PSS signatures.
381  */
382 #if HAVE_X509_GET_SIGNATURE_INFO
383  if (!X509_get_signature_info(peer_cert, &algo_nid, NULL, NULL, NULL))
384 #else
385  if (!OBJ_find_sigid_algs(X509_get_signature_nid(peer_cert),
386  &algo_nid, NULL))
387 #endif
388  {
389  libpq_append_conn_error(conn, "could not determine server certificate signature algorithm");
390  return NULL;
391  }
392 
393  /*
394  * The TLS server's certificate bytes need to be hashed with SHA-256 if
395  * its signature algorithm is MD5 or SHA-1 as per RFC 5929
396  * (https://tools.ietf.org/html/rfc5929#section-4.1). If something else
397  * is used, the same hash as the signature algorithm is used.
398  */
399  switch (algo_nid)
400  {
401  case NID_md5:
402  case NID_sha1:
403  algo_type = EVP_sha256();
404  break;
405  default:
406  algo_type = EVP_get_digestbynid(algo_nid);
407  if (algo_type == NULL)
408  {
409  libpq_append_conn_error(conn, "could not find digest for NID %s",
410  OBJ_nid2sn(algo_nid));
411  return NULL;
412  }
413  break;
414  }
415 
416  if (!X509_digest(peer_cert, algo_type, hash, &hash_size))
417  {
418  libpq_append_conn_error(conn, "could not generate peer certificate hash");
419  return NULL;
420  }
421 
422  /* save result */
423  cert_hash = malloc(hash_size);
424  if (cert_hash == NULL)
425  {
426  libpq_append_conn_error(conn, "out of memory");
427  return NULL;
428  }
429  memcpy(cert_hash, hash, hash_size);
430  *len = hash_size;
431 
432  return cert_hash;
433 }
void libpq_append_conn_error(PGconn *conn, const char *fmt,...)
Definition: fe-misc.c:1312
#define malloc(a)
Definition: header.h:50
const void size_t len
static unsigned hash(unsigned *uv, int n)
Definition: rege_dfa.c:715

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

Referenced by build_client_final_message().

◆ pgtls_init()

int pgtls_init ( PGconn conn,
bool  do_ssl,
bool  do_crypto 
)

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

769 {
770 #ifdef WIN32
771  /* Also see similar code in fe-connect.c, default_threadlock() */
772  if (ssl_config_mutex == NULL)
773  {
774  while (InterlockedExchange(&win32_ssl_create_mutex, 1) == 1)
775  /* loop, another thread own the lock */ ;
776  if (ssl_config_mutex == NULL)
777  {
779  return -1;
780  }
781  InterlockedExchange(&win32_ssl_create_mutex, 0);
782  }
783 #endif
785  return -1;
786 
787 #ifdef HAVE_CRYPTO_LOCK
788  if (pq_init_crypto_lib)
789  {
790  /*
791  * If necessary, set up an array to hold locks for libcrypto.
792  * libcrypto will tell us how big to make this array.
793  */
794  if (pq_lockarray == NULL)
795  {
796  int i;
797 
798  pq_lockarray = malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks());
799  if (!pq_lockarray)
800  {
802  return -1;
803  }
804  for (i = 0; i < CRYPTO_num_locks(); i++)
805  {
806  if (pthread_mutex_init(&pq_lockarray[i], NULL))
807  {
808  free(pq_lockarray);
809  pq_lockarray = NULL;
811  return -1;
812  }
813  }
814  }
815 
816  if (do_crypto && !conn->crypto_loaded)
817  {
818  if (crypto_open_connections++ == 0)
819  {
820  /*
821  * These are only required for threaded libcrypto
822  * applications, but make sure we don't stomp on them if
823  * they're already set.
824  */
825  if (CRYPTO_get_id_callback() == NULL)
826  CRYPTO_set_id_callback(pq_threadidcallback);
827  if (CRYPTO_get_locking_callback() == NULL)
828  CRYPTO_set_locking_callback(pq_lockingcallback);
829  }
830 
831  conn->crypto_loaded = true;
832  }
833  }
834 #endif /* HAVE_CRYPTO_LOCK */
835 
836  if (!ssl_lib_initialized && do_ssl)
837  {
838  if (pq_init_ssl_lib)
839  {
840 #ifdef HAVE_OPENSSL_INIT_SSL
841  OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
842 #else
843  OPENSSL_config(NULL);
844  SSL_library_init();
845  SSL_load_error_strings();
846 #endif
847  }
848  ssl_lib_initialized = true;
849  }
850 
852  return 0;
853 }
static bool pq_init_crypto_lib
static long crypto_open_connections
static bool ssl_lib_initialized
static bool pq_init_ssl_lib
static pthread_mutex_t ssl_config_mutex
#define free(a)
Definition: header.h:65
int i
Definition: isn.c:73
int pthread_mutex_unlock(pthread_mutex_t *mp)
Definition: pthread-win32.c:54
int pthread_mutex_lock(pthread_mutex_t *mp)
Definition: pthread-win32.c:45
int pthread_mutex_init(pthread_mutex_t *mp, void *attr)
Definition: pthread-win32.c:35
CRITICAL_SECTION * pthread_mutex_t
Definition: pthread-win32.h:8

References conn, crypto_open_connections, free, i, malloc, pq_init_crypto_lib, pq_init_ssl_lib, pthread_mutex_init(), pthread_mutex_lock(), pthread_mutex_unlock(), ssl_config_mutex, and ssl_lib_initialized.

Referenced by pqsecure_initialize().

◆ pgtls_init_library()

void pgtls_init_library ( bool  do_ssl,
int  do_crypto 
)

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

110 {
111  /*
112  * Disallow changing the flags while we have open connections, else we'd
113  * get completely confused.
114  */
115  if (crypto_open_connections != 0)
116  return;
117 
118  pq_init_ssl_lib = do_ssl;
119  pq_init_crypto_lib = do_crypto;
120 }

References crypto_open_connections, pq_init_crypto_lib, and pq_init_ssl_lib.

Referenced by PQinitOpenSSL(), and PQinitSSL().

◆ pgtls_open_client()

PostgresPollingStatusType pgtls_open_client ( PGconn conn)

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

124 {
125  /* First time through? */
126  if (conn->ssl == NULL)
127  {
128  /*
129  * Create a connection-specific SSL object, and load client
130  * certificate, private key, and trusted CA certs.
131  */
132  if (initialize_SSL(conn) != 0)
133  {
134  /* initialize_SSL already put a message in conn->errorMessage */
135  pgtls_close(conn);
136  return PGRES_POLLING_FAILED;
137  }
138  }
139 
140  /* Begin or continue the actual handshake */
141  return open_client_SSL(conn);
142 }
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:86

References conn, 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 
)

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

146 {
147  ssize_t n;
148  int result_errno = 0;
149  char sebuf[PG_STRERROR_R_BUFLEN];
150  int err;
151  unsigned long ecode;
152 
153 rloop:
154 
155  /*
156  * Prepare to call SSL_get_error() by clearing thread's OpenSSL error
157  * queue. In general, the current thread's error queue must be empty
158  * before the TLS/SSL I/O operation is attempted, or SSL_get_error() will
159  * not work reliably. Since the possibility exists that other OpenSSL
160  * clients running in the same thread but not under our control will fail
161  * to call ERR_get_error() themselves (after their own I/O operations),
162  * pro-actively clear the per-thread error queue now.
163  */
164  SOCK_ERRNO_SET(0);
165  ERR_clear_error();
166  n = SSL_read(conn->ssl, ptr, len);
167  err = SSL_get_error(conn->ssl, n);
168 
169  /*
170  * Other clients of OpenSSL may fail to call ERR_get_error(), but we
171  * always do, so as to not cause problems for OpenSSL clients that don't
172  * call ERR_clear_error() defensively. Be sure that this happens by
173  * calling now. SSL_get_error() relies on the OpenSSL per-thread error
174  * queue being intact, so this is the earliest possible point
175  * ERR_get_error() may be called.
176  */
177  ecode = (err != SSL_ERROR_NONE || n < 0) ? ERR_get_error() : 0;
178  switch (err)
179  {
180  case SSL_ERROR_NONE:
181  if (n < 0)
182  {
183  /* Not supposed to happen, so we don't translate the msg */
185  "SSL_read failed but did not provide error information\n");
186  /* assume the connection is broken */
187  result_errno = ECONNRESET;
188  }
189  break;
190  case SSL_ERROR_WANT_READ:
191  n = 0;
192  break;
193  case SSL_ERROR_WANT_WRITE:
194 
195  /*
196  * Returning 0 here would cause caller to wait for read-ready,
197  * which is not correct since what SSL wants is wait for
198  * write-ready. The former could get us stuck in an infinite
199  * wait, so don't risk it; busy-loop instead.
200  */
201  goto rloop;
202  case SSL_ERROR_SYSCALL:
203  if (n < 0)
204  {
205  result_errno = SOCK_ERRNO;
206  if (result_errno == EPIPE ||
207  result_errno == ECONNRESET)
208  libpq_append_conn_error(conn, "server closed the connection unexpectedly\n"
209  "\tThis probably means the server terminated abnormally\n"
210  "\tbefore or while processing the request.");
211  else
212  libpq_append_conn_error(conn, "SSL SYSCALL error: %s",
213  SOCK_STRERROR(result_errno,
214  sebuf, sizeof(sebuf)));
215  }
216  else
217  {
218  libpq_append_conn_error(conn, "SSL SYSCALL error: EOF detected");
219  /* assume the connection is broken */
220  result_errno = ECONNRESET;
221  n = -1;
222  }
223  break;
224  case SSL_ERROR_SSL:
225  {
226  char *errm = SSLerrmessage(ecode);
227 
228  libpq_append_conn_error(conn, "SSL error: %s", errm);
229  SSLerrfree(errm);
230  /* assume the connection is broken */
231  result_errno = ECONNRESET;
232  n = -1;
233  break;
234  }
235  case SSL_ERROR_ZERO_RETURN:
236 
237  /*
238  * Per OpenSSL documentation, this error code is only returned for
239  * a clean connection closure, so we should not report it as a
240  * server crash.
241  */
242  libpq_append_conn_error(conn, "SSL connection has been closed unexpectedly");
243  result_errno = ECONNRESET;
244  n = -1;
245  break;
246  default:
247  libpq_append_conn_error(conn, "unrecognized SSL error code: %d", err);
248  /* assume the connection is broken */
249  result_errno = ECONNRESET;
250  n = -1;
251  break;
252  }
253 
254  /* ensure we return the intended errno to caller */
255  SOCK_ERRNO_SET(result_errno);
256 
257  return n;
258 }
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:922
#define SOCK_ERRNO
Definition: libpq-int.h:921
#define SOCK_ERRNO_SET(e)
Definition: libpq-int.h:923
#define PG_STRERROR_R_BUFLEN
Definition: port.h:256
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:367
PQExpBufferData errorMessage
Definition: libpq-int.h:617
#define ECONNRESET
Definition: win32_port.h:384

References appendPQExpBufferStr(), conn, ECONNRESET, err(), pg_conn::errorMessage, 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)

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

262 {
263  return SSL_pending(conn->ssl) > 0;
264 }

References conn.

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 
)

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

576 {
577  STACK_OF(GENERAL_NAME) * peer_san;
578  int i;
579  int rc = 0;
580  char *host = conn->connhost[conn->whichhost].host;
581  int host_type;
582  bool check_cn = true;
583 
584  Assert(host && host[0]); /* should be guaranteed by caller */
585 
586  /*
587  * We try to match the NSS behavior here, which is a slight departure from
588  * the spec but seems to make more intuitive sense:
589  *
590  * If connhost contains a DNS name, and the certificate's SANs contain any
591  * dNSName entries, then we'll ignore the Subject Common Name entirely;
592  * otherwise, we fall back to checking the CN. (This behavior matches the
593  * RFC.)
594  *
595  * If connhost contains an IP address, and the SANs contain iPAddress
596  * entries, we again ignore the CN. Otherwise, we allow the CN to match,
597  * EVEN IF there is a dNSName in the SANs. (RFC 6125 prohibits this: "A
598  * client MUST NOT seek a match for a reference identifier of CN-ID if the
599  * presented identifiers include a DNS-ID, SRV-ID, URI-ID, or any
600  * application-specific identifier types supported by the client.")
601  *
602  * NOTE: Prior versions of libpq did not consider iPAddress entries at
603  * all, so this new behavior might break a certificate that has different
604  * IP addresses in the Subject CN and the SANs.
605  */
606  if (is_ip_address(host))
607  host_type = GEN_IPADD;
608  else
609  host_type = GEN_DNS;
610 
611  /*
612  * First, get the Subject Alternative Names (SANs) from the certificate,
613  * and compare them against the originally given hostname.
614  */
615  peer_san = (STACK_OF(GENERAL_NAME) *)
616  X509_get_ext_d2i(conn->peer, NID_subject_alt_name, NULL, NULL);
617 
618  if (peer_san)
619  {
620  int san_len = sk_GENERAL_NAME_num(peer_san);
621 
622  for (i = 0; i < san_len; i++)
623  {
624  const GENERAL_NAME *name = sk_GENERAL_NAME_value(peer_san, i);
625  char *alt_name = NULL;
626 
627  if (name->type == host_type)
628  {
629  /*
630  * This SAN is of the same type (IP or DNS) as our host name,
631  * so don't allow a fallback check of the CN.
632  */
633  check_cn = false;
634  }
635 
636  if (name->type == GEN_DNS)
637  {
638  (*names_examined)++;
640  name->d.dNSName,
641  &alt_name);
642  }
643  else if (name->type == GEN_IPADD)
644  {
645  (*names_examined)++;
647  name->d.iPAddress,
648  &alt_name);
649  }
650 
651  if (alt_name)
652  {
653  if (!*first_name)
654  *first_name = alt_name;
655  else
656  free(alt_name);
657  }
658 
659  if (rc != 0)
660  {
661  /*
662  * Either we hit an error or a match, and either way we should
663  * not fall back to the CN.
664  */
665  check_cn = false;
666  break;
667  }
668  }
669  sk_GENERAL_NAME_pop_free(peer_san, GENERAL_NAME_free);
670  }
671 
672  /*
673  * If there is no subjectAltName extension of the matching type, check the
674  * Common Name.
675  *
676  * (Per RFC 2818 and RFC 6125, if the subjectAltName extension of type
677  * dNSName is present, the CN must be ignored. We break this rule if host
678  * is an IP address; see the comment above.)
679  */
680  if (check_cn)
681  {
682  X509_NAME *subject_name;
683 
684  subject_name = X509_get_subject_name(conn->peer);
685  if (subject_name != NULL)
686  {
687  int cn_index;
688 
689  cn_index = X509_NAME_get_index_by_NID(subject_name,
690  NID_commonName, -1);
691  if (cn_index >= 0)
692  {
693  char *common_name = NULL;
694 
695  (*names_examined)++;
697  X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subject_name, cn_index)),
698  &common_name);
699 
700  if (common_name)
701  {
702  if (!*first_name)
703  *first_name = common_name;
704  else
705  free(common_name);
706  }
707  }
708  }
709  }
710 
711  return rc;
712 }
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)
Assert(fmt[strlen(fmt) - 1] !='\n')
char * host
Definition: libpq-int.h:346
int whichhost
Definition: libpq-int.h:441
pg_conn_host * connhost
Definition: libpq-int.h:442
const char * name

References Assert(), conn, pg_conn::connhost, 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 
)

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

268 {
269  ssize_t n;
270  int result_errno = 0;
271  char sebuf[PG_STRERROR_R_BUFLEN];
272  int err;
273  unsigned long ecode;
274 
275  SOCK_ERRNO_SET(0);
276  ERR_clear_error();
277  n = SSL_write(conn->ssl, ptr, len);
278  err = SSL_get_error(conn->ssl, n);
279  ecode = (err != SSL_ERROR_NONE || n < 0) ? ERR_get_error() : 0;
280  switch (err)
281  {
282  case SSL_ERROR_NONE:
283  if (n < 0)
284  {
285  /* Not supposed to happen, so we don't translate the msg */
287  "SSL_write failed but did not provide error information\n");
288  /* assume the connection is broken */
289  result_errno = ECONNRESET;
290  }
291  break;
292  case SSL_ERROR_WANT_READ:
293 
294  /*
295  * Returning 0 here causes caller to wait for write-ready, which
296  * is not really the right thing, but it's the best we can do.
297  */
298  n = 0;
299  break;
300  case SSL_ERROR_WANT_WRITE:
301  n = 0;
302  break;
303  case SSL_ERROR_SYSCALL:
304  if (n < 0)
305  {
306  result_errno = SOCK_ERRNO;
307  if (result_errno == EPIPE || result_errno == ECONNRESET)
308  libpq_append_conn_error(conn, "server closed the connection unexpectedly\n"
309  "\tThis probably means the server terminated abnormally\n"
310  "\tbefore or while processing the request.");
311  else
312  libpq_append_conn_error(conn, "SSL SYSCALL error: %s",
313  SOCK_STRERROR(result_errno,
314  sebuf, sizeof(sebuf)));
315  }
316  else
317  {
318  libpq_append_conn_error(conn, "SSL SYSCALL error: EOF detected");
319  /* assume the connection is broken */
320  result_errno = ECONNRESET;
321  n = -1;
322  }
323  break;
324  case SSL_ERROR_SSL:
325  {
326  char *errm = SSLerrmessage(ecode);
327 
328  libpq_append_conn_error(conn, "SSL error: %s", errm);
329  SSLerrfree(errm);
330  /* assume the connection is broken */
331  result_errno = ECONNRESET;
332  n = -1;
333  break;
334  }
335  case SSL_ERROR_ZERO_RETURN:
336 
337  /*
338  * Per OpenSSL documentation, this error code is only returned for
339  * a clean connection closure, so we should not report it as a
340  * server crash.
341  */
342  libpq_append_conn_error(conn, "SSL connection has been closed unexpectedly");
343  result_errno = ECONNRESET;
344  n = -1;
345  break;
346  default:
347  libpq_append_conn_error(conn, "unrecognized SSL error code: %d", err);
348  /* assume the connection is broken */
349  result_errno = ECONNRESET;
350  n = -1;
351  break;
352  }
353 
354  /* ensure we return the intended errno to caller */
355  SOCK_ERRNO_SET(result_errno);
356 
357  return n;
358 }

References appendPQExpBufferStr(), conn, ECONNRESET, err(), pg_conn::errorMessage, 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 
)

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

513 {
514  sigset_t sigpipe_sigset;
515  sigset_t sigset;
516 
517  sigemptyset(&sigpipe_sigset);
518  sigaddset(&sigpipe_sigset, SIGPIPE);
519 
520  /* Block SIGPIPE and save previous mask for later reset */
521  SOCK_ERRNO_SET(pthread_sigmask(SIG_BLOCK, &sigpipe_sigset, osigset));
522  if (SOCK_ERRNO)
523  return -1;
524 
525  /* We can have a pending SIGPIPE only if it was blocked before */
526  if (sigismember(osigset, SIGPIPE))
527  {
528  /* Is there a pending SIGPIPE? */
529  if (sigpending(&sigset) != 0)
530  return -1;
531 
532  if (sigismember(&sigset, SIGPIPE))
533  *sigpipe_pending = true;
534  else
535  *sigpipe_pending = false;
536  }
537  else
538  *sigpipe_pending = false;
539 
540  return 0;
541 }
#define SIGPIPE
Definition: win32_port.h:173

References SIGPIPE, SOCK_ERRNO, and SOCK_ERRNO_SET.

Referenced by PQprint().

◆ pq_reset_sigpipe()

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

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

563 {
564  int save_errno = SOCK_ERRNO;
565  int signo;
566  sigset_t sigset;
567 
568  /* Clear SIGPIPE only if none was pending */
569  if (got_epipe && !sigpipe_pending)
570  {
571  if (sigpending(&sigset) == 0 &&
572  sigismember(&sigset, SIGPIPE))
573  {
574  sigset_t sigpipe_sigset;
575 
576  sigemptyset(&sigpipe_sigset);
577  sigaddset(&sigpipe_sigset, SIGPIPE);
578 
579  sigwait(&sigpipe_sigset, &signo);
580  }
581  }
582 
583  /* Restore saved block mask */
584  pthread_sigmask(SIG_SETMASK, osigset, NULL);
585 
586  SOCK_ERRNO_SET(save_errno);
587 }

References SIGPIPE, SOCK_ERRNO, and SOCK_ERRNO_SET.

Referenced by PQprint().

◆ pqBuildErrorMessage3()

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

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

1020 {
1021  const char *val;
1022  const char *querytext = NULL;
1023  int querypos = 0;
1024 
1025  /* If we couldn't allocate a PGresult, just say "out of memory" */
1026  if (res == NULL)
1027  {
1028  appendPQExpBufferStr(msg, libpq_gettext("out of memory\n"));
1029  return;
1030  }
1031 
1032  /*
1033  * If we don't have any broken-down fields, just return the base message.
1034  * This mainly applies if we're given a libpq-generated error result.
1035  */
1036  if (res->errFields == NULL)
1037  {
1038  if (res->errMsg && res->errMsg[0])
1040  else
1041  appendPQExpBufferStr(msg, libpq_gettext("no error message available\n"));
1042  return;
1043  }
1044 
1045  /* Else build error message from relevant fields */
1047  if (val)
1048  appendPQExpBuffer(msg, "%s: ", val);
1049 
1050  if (verbosity == PQERRORS_SQLSTATE)
1051  {
1052  /*
1053  * If we have a SQLSTATE, print that and nothing else. If not (which
1054  * shouldn't happen for server-generated errors, but might possibly
1055  * happen for libpq-generated ones), fall back to TERSE format, as
1056  * that seems better than printing nothing at all.
1057  */
1059  if (val)
1060  {
1061  appendPQExpBuffer(msg, "%s\n", val);
1062  return;
1063  }
1064  verbosity = PQERRORS_TERSE;
1065  }
1066 
1067  if (verbosity == PQERRORS_VERBOSE)
1068  {
1070  if (val)
1071  appendPQExpBuffer(msg, "%s: ", val);
1072  }
1074  if (val)
1075  appendPQExpBufferStr(msg, val);
1077  if (val)
1078  {
1079  if (verbosity != PQERRORS_TERSE && res->errQuery != NULL)
1080  {
1081  /* emit position as a syntax cursor display */
1082  querytext = res->errQuery;
1083  querypos = atoi(val);
1084  }
1085  else
1086  {
1087  /* emit position as text addition to primary message */
1088  /* translator: %s represents a digit string */
1089  appendPQExpBuffer(msg, libpq_gettext(" at character %s"),
1090  val);
1091  }
1092  }
1093  else
1094  {
1096  if (val)
1097  {
1099  if (verbosity != PQERRORS_TERSE && querytext != NULL)
1100  {
1101  /* emit position as a syntax cursor display */
1102  querypos = atoi(val);
1103  }
1104  else
1105  {
1106  /* emit position as text addition to primary message */
1107  /* translator: %s represents a digit string */
1108  appendPQExpBuffer(msg, libpq_gettext(" at character %s"),
1109  val);
1110  }
1111  }
1112  }
1113  appendPQExpBufferChar(msg, '\n');
1114  if (verbosity != PQERRORS_TERSE)
1115  {
1116  if (querytext && querypos > 0)
1117  reportErrorPosition(msg, querytext, querypos,
1118  res->client_encoding);
1120  if (val)
1121  appendPQExpBuffer(msg, libpq_gettext("DETAIL: %s\n"), val);
1123  if (val)
1124  appendPQExpBuffer(msg, libpq_gettext("HINT: %s\n"), val);
1126  if (val)
1127  appendPQExpBuffer(msg, libpq_gettext("QUERY: %s\n"), val);
1128  if (show_context == PQSHOW_CONTEXT_ALWAYS ||
1129  (show_context == PQSHOW_CONTEXT_ERRORS &&
1131  {
1133  if (val)
1134  appendPQExpBuffer(msg, libpq_gettext("CONTEXT: %s\n"),
1135  val);
1136  }
1137  }
1138  if (verbosity == PQERRORS_VERBOSE)
1139  {
1141  if (val)
1142  appendPQExpBuffer(msg,
1143  libpq_gettext("SCHEMA NAME: %s\n"), val);
1145  if (val)
1146  appendPQExpBuffer(msg,
1147  libpq_gettext("TABLE NAME: %s\n"), val);
1149  if (val)
1150  appendPQExpBuffer(msg,
1151  libpq_gettext("COLUMN NAME: %s\n"), val);
1153  if (val)
1154  appendPQExpBuffer(msg,
1155  libpq_gettext("DATATYPE NAME: %s\n"), val);
1157  if (val)
1158  appendPQExpBuffer(msg,
1159  libpq_gettext("CONSTRAINT NAME: %s\n"), val);
1160  }
1161  if (verbosity == PQERRORS_VERBOSE)
1162  {
1163  const char *valf;
1164  const char *vall;
1165 
1169  if (val || valf || vall)
1170  {
1171  appendPQExpBufferStr(msg, libpq_gettext("LOCATION: "));
1172  if (val)
1173  appendPQExpBuffer(msg, libpq_gettext("%s, "), val);
1174  if (valf && vall) /* unlikely we'd have just one */
1175  appendPQExpBuffer(msg, libpq_gettext("%s:%s"),
1176  valf, vall);
1177  appendPQExpBufferChar(msg, '\n');
1178  }
1179  }
1180 }
char * PQresultErrorField(const PGresult *res, int fieldcode)
Definition: fe-exec.c:3388
static void reportErrorPosition(PQExpBuffer msg, const char *query, int loc, int encoding)
long val
Definition: informix.c:664
@ PGRES_FATAL_ERROR
Definition: libpq-fe.h:108
@ PQSHOW_CONTEXT_ALWAYS
Definition: libpq-fe.h:137
@ PQSHOW_CONTEXT_ERRORS
Definition: libpq-fe.h:136
@ PQERRORS_VERBOSE
Definition: libpq-fe.h:129
@ PQERRORS_TERSE
Definition: libpq-fe.h:127
@ PQERRORS_SQLSTATE
Definition: libpq-fe.h:130
#define libpq_gettext(x)
Definition: libpq-int.h:900
#define PG_DIAG_INTERNAL_QUERY
Definition: postgres_ext.h:62
#define PG_DIAG_SCHEMA_NAME
Definition: postgres_ext.h:64
#define PG_DIAG_CONSTRAINT_NAME
Definition: postgres_ext.h:68
#define PG_DIAG_DATATYPE_NAME
Definition: postgres_ext.h:67
#define PG_DIAG_SOURCE_LINE
Definition: postgres_ext.h:70
#define PG_DIAG_STATEMENT_POSITION
Definition: postgres_ext.h:60
#define PG_DIAG_SOURCE_FILE
Definition: postgres_ext.h:69
#define PG_DIAG_MESSAGE_HINT
Definition: postgres_ext.h:59
#define PG_DIAG_SQLSTATE
Definition: postgres_ext.h:56
#define PG_DIAG_TABLE_NAME
Definition: postgres_ext.h:65
#define PG_DIAG_MESSAGE_PRIMARY
Definition: postgres_ext.h:57
#define PG_DIAG_COLUMN_NAME
Definition: postgres_ext.h:66
#define PG_DIAG_MESSAGE_DETAIL
Definition: postgres_ext.h:58
#define PG_DIAG_CONTEXT
Definition: postgres_ext.h:63
#define PG_DIAG_SEVERITY
Definition: postgres_ext.h:54
#define PG_DIAG_SOURCE_FUNCTION
Definition: postgres_ext.h:71
#define PG_DIAG_INTERNAL_POSITION
Definition: postgres_ext.h:61
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:265
void appendPQExpBufferChar(PQExpBuffer str, char ch)
Definition: pqexpbuffer.c:378
char * errMsg
Definition: libpq-int.h:199
PGMessageField * errFields
Definition: libpq-int.h:200
ExecStatusType resultStatus
Definition: libpq-int.h:180
char * errQuery
Definition: libpq-int.h:201
int client_encoding
Definition: libpq-int.h:192

References appendPQExpBuffer(), appendPQExpBufferChar(), appendPQExpBufferStr(), pg_result::client_encoding, pg_result::errFields, pg_result::errMsg, pg_result::errQuery, 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(), res, pg_result::resultStatus, and val.

Referenced by pqGetErrorNotice3(), and PQresultVerboseErrorMessage().

◆ pqBuildStartupPacket3()

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

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

2243 {
2244  char *startpacket;
2245 
2246  *packetlen = build_startup_packet(conn, NULL, options);
2247  startpacket = (char *) malloc(*packetlen);
2248  if (!startpacket)
2249  return NULL;
2250  *packetlen = build_startup_packet(conn, startpacket, options);
2251  return startpacket;
2252 }
static int build_startup_packet(const PGconn *conn, char *packet, const PQEnvironmentOption *options)

References build_startup_packet(), conn, and malloc.

Referenced by PQconnectPoll().

◆ pqCheckInBufferSpace()

int pqCheckInBufferSpace ( size_t  bytes_needed,
PGconn conn 
)

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

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

References appendPQExpBufferStr(), conn, pg_conn::errorMessage, 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 
)

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

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

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

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

◆ pqClearAsyncResult()

void pqClearAsyncResult ( PGconn conn)

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

777 {
778  PQclear(conn->result);
779  conn->result = NULL;
780  conn->error_result = false;
782  conn->next_result = NULL;
783 }
void PQclear(PGresult *res)
Definition: fe-exec.c:718
PGresult * next_result
Definition: libpq-int.h:539
PGresult * result
Definition: libpq-int.h:537
bool error_result
Definition: libpq-int.h:538

References conn, pg_conn::error_result, pg_conn::next_result, PQclear(), and pg_conn::result.

Referenced by closePGconn(), getAnotherTuple(), getParamDescriptions(), getRowDescriptions(), PQconnectPoll(), pqGetErrorNotice3(), pqPipelineProcessQueue(), pqSaveErrorResult(), and PQsendQueryStart().

◆ pqCommandQueueAdvance()

void pqCommandQueueAdvance ( PGconn conn)

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

3096 {
3097  PGcmdQueueEntry *prevquery;
3098 
3099  if (conn->cmd_queue_head == NULL)
3100  return;
3101 
3102  /* delink from queue */
3103  prevquery = conn->cmd_queue_head;
3105 
3106  /* If the queue is now empty, reset the tail too */
3107  if (conn->cmd_queue_head == NULL)
3108  conn->cmd_queue_tail = NULL;
3109 
3110  /* and make it recyclable */
3111  prevquery->next = NULL;
3112  pqRecycleCmdQueueEntry(conn, prevquery);
3113 }
static void pqRecycleCmdQueueEntry(PGconn *conn, PGcmdQueueEntry *entry)
Definition: fe-exec.c:1392
struct PGcmdQueueEntry * next
Definition: libpq-int.h:335
PGcmdQueueEntry * cmd_queue_tail
Definition: libpq-int.h:450
PGcmdQueueEntry * cmd_queue_head
Definition: libpq-int.h:449

References pg_conn::cmd_queue_head, pg_conn::cmd_queue_tail, conn, PGcmdQueueEntry::next, and pqRecycleCmdQueueEntry().

Referenced by PQgetResult(), and pqParseInput3().

◆ pqDropConnection()

void pqDropConnection ( PGconn conn,
bool  flushInput 
)

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

468 {
469  /* Drop any SSL state */
471 
472  /* Close the socket itself */
473  if (conn->sock != PGINVALID_SOCKET)
476 
477  /* Optionally discard any unread data */
478  if (flushInput)
479  conn->inStart = conn->inCursor = conn->inEnd = 0;
480 
481  /* Always discard any unsent data */
482  conn->outCount = 0;
483 
484  /* Likewise, discard any pending pipelined commands */
488  conn->cmd_queue_recycle = NULL;
489 
490  /* Free authentication/encryption state */
491 #ifdef ENABLE_GSS
492  {
493  OM_uint32 min_s;
494 
495  if (conn->gcred != GSS_C_NO_CREDENTIAL)
496  {
497  gss_release_cred(&min_s, &conn->gcred);
498  conn->gcred = GSS_C_NO_CREDENTIAL;
499  }
500  if (conn->gctx)
501  gss_delete_sec_context(&min_s, &conn->gctx, GSS_C_NO_BUFFER);
502  if (conn->gtarg_nam)
503  gss_release_name(&min_s, &conn->gtarg_nam);
504  if (conn->gss_SendBuffer)
505  {
506  free(conn->gss_SendBuffer);
507  conn->gss_SendBuffer = NULL;
508  }
509  if (conn->gss_RecvBuffer)
510  {
511  free(conn->gss_RecvBuffer);
512  conn->gss_RecvBuffer = NULL;
513  }
514  if (conn->gss_ResultBuffer)
515  {
516  free(conn->gss_ResultBuffer);
517  conn->gss_ResultBuffer = NULL;
518  }
519  conn->gssenc = false;
520  }
521 #endif
522 #ifdef ENABLE_SSPI
523  if (conn->sspitarget)
524  {
525  free(conn->sspitarget);
526  conn->sspitarget = NULL;
527  }
528  if (conn->sspicred)
529  {
530  FreeCredentialsHandle(conn->sspicred);
531  free(conn->sspicred);
532  conn->sspicred = NULL;
533  }
534  if (conn->sspictx)
535  {
536  DeleteSecurityContext(conn->sspictx);
537  free(conn->sspictx);
538  conn->sspictx = NULL;
539  }
540  conn->usesspi = 0;
541 #endif
542  if (conn->sasl_state)
543  {
545  conn->sasl_state = NULL;
546  }
547 }
static void pqFreeCommandQueue(PGcmdQueueEntry *queue)
Definition: fe-connect.c:554
void pqsecure_close(PGconn *conn)
Definition: fe-secure.c:167
#define PGINVALID_SOCKET
Definition: port.h:31
#define closesocket
Definition: port.h:349
pgsocket sock
Definition: libpq-int.h:459
const pg_fe_sasl_mech * sasl
Definition: libpq-int.h:542
PGcmdQueueEntry * cmd_queue_recycle
Definition: libpq-int.h:456
void * sasl_state
Definition: libpq-int.h:543
int outCount
Definition: libpq-int.h:517
void(* free)(void *state)
Definition: fe-auth-sasl.h:127

References closesocket, pg_conn::cmd_queue_head, pg_conn::cmd_queue_recycle, pg_conn::cmd_queue_tail, conn, 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 closePGconn(), connectDBStart(), handleSyncLoss(), PQconnectPoll(), and pqReadData().

◆ pqEndcopy3()

int pqEndcopy3 ( PGconn conn)

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

1921 {
1922  PGresult *result;
1923 
1924  if (conn->asyncStatus != PGASYNC_COPY_IN &&
1927  {
1928  libpq_append_conn_error(conn, "no COPY in progress");
1929  return 1;
1930  }
1931 
1932  /* Send the CopyDone message if needed */
1933  if (conn->asyncStatus == PGASYNC_COPY_IN ||
1935  {
1936  if (pqPutMsgStart(PqMsg_CopyDone, conn) < 0 ||
1937  pqPutMsgEnd(conn) < 0)
1938  return 1;
1939 
1940  /*
1941  * If we sent the COPY command in extended-query mode, we must issue a
1942  * Sync as well.
1943  */
1944  if (conn->cmd_queue_head &&
1946  {
1947  if (pqPutMsgStart(PqMsg_Sync, conn) < 0 ||
1948  pqPutMsgEnd(conn) < 0)
1949  return 1;
1950  }
1951  }
1952 
1953  /*
1954  * make sure no data is waiting to be sent, abort if we are non-blocking
1955  * and the flush fails
1956  */
1957  if (pqFlush(conn) && pqIsnonblocking(conn))
1958  return 1;
1959 
1960  /* Return to active duty */
1962 
1963  /*
1964  * Non blocking connections may have to abort at this point. If everyone
1965  * played the game there should be no problem, but in error scenarios the
1966  * expected messages may not have arrived yet. (We are assuming that the
1967  * backend's packetizing will ensure that CommandComplete arrives along
1968  * with the CopyDone; are there corner cases where that doesn't happen?)
1969  */
1970  if (pqIsnonblocking(conn) && PQisBusy(conn))
1971  return 1;
1972 
1973  /* Wait for the completion response */
1974  result = PQgetResult(conn);
1975 
1976  /* Expecting a successful result */
1977  if (result && result->resultStatus == PGRES_COMMAND_OK)
1978  {
1979  PQclear(result);
1980  return 0;
1981  }
1982 
1983  /*
1984  * Trouble. For backwards-compatibility reasons, we issue the error
1985  * message as if it were a notice (would be nice to get rid of this
1986  * silliness, but too many apps probably don't handle errors from
1987  * PQendcopy reasonably). Note that the app can still obtain the error
1988  * status from the PGconn object.
1989  */
1990  if (conn->errorMessage.len > 0)
1991  {
1992  /* We have to strip the trailing newline ... pain in neck... */
1993  char svLast = conn->errorMessage.data[conn->errorMessage.len - 1];
1994 
1995  if (svLast == '\n')
1996  conn->errorMessage.data[conn->errorMessage.len - 1] = '\0';
1998  conn->errorMessage.data[conn->errorMessage.len - 1] = svLast;
1999  }
2000 
2001  PQclear(result);
2002 
2003  return 1;
2004 }
void pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt,...)
Definition: fe-exec.c:933
int PQisBusy(PGconn *conn)
Definition: fe-exec.c:2004
PGresult * PQgetResult(PGconn *conn)
Definition: fe-exec.c:2035
int pqFlush(PGconn *conn)
Definition: fe-misc.c:954
int pqPutMsgStart(char msg_type, PGconn *conn)
Definition: fe-misc.c:459
int pqPutMsgEnd(PGconn *conn)
Definition: fe-misc.c:518
@ PGRES_COMMAND_OK
Definition: libpq-fe.h:97
#define pqIsnonblocking(conn)
Definition: libpq-int.h:889
#define PqMsg_CopyDone
Definition: protocol.h:64
#define PqMsg_Sync
Definition: protocol.h:27
PGQueryClass queryclass
Definition: libpq-int.h:333
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:426
PGNoticeHooks noticeHooks
Definition: libpq-int.h:417

References pg_conn::asyncStatus, pg_conn::cmd_queue_head, conn, PQExpBufferData::data, pg_conn::errorMessage, 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 pg_result::resultStatus.

Referenced by PQendcopy().

◆ pqFlush()

int pqFlush ( PGconn conn)

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

955 {
956  if (conn->outCount > 0)
957  {
958  if (conn->Pfdebug)
959  fflush(conn->Pfdebug);
960 
961  return pqSendSome(conn, conn->outCount);
962  }
963 
964  return 0;
965 }
static int pqSendSome(PGconn *conn, int len)
Definition: fe-misc.c:785
static void const char fflush(stdout)
FILE * Pfdebug
Definition: libpq-int.h:413

References conn, fflush(), pg_conn::outCount, pg_conn::Pfdebug, and pqSendSome().

Referenced by pg_SASL_init(), PQconnectPoll(), PQconsumeInput(), pqEndcopy3(), PQexitPipelineMode(), PQflush(), pqFunctionCall3(), PQgetResult(), pqPacketSend(), pqPipelineFlush(), PQputCopyData(), PQputCopyEnd(), PQsendQueryInternal(), PQsetnonblocking(), and sendTerminateConn().

◆ pqFunctionCall3()

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

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

2017 {
2018  bool needInput = false;
2020  char id;
2021  int msgLength;
2022  int avail;
2023  int i;
2024 
2025  /* already validated by PQfn */
2027 
2028  /* PQfn already validated connection state */
2029 
2031  pqPutInt(fnid, 4, conn) < 0 || /* function id */
2032  pqPutInt(1, 2, conn) < 0 || /* # of format codes */
2033  pqPutInt(1, 2, conn) < 0 || /* format code: BINARY */
2034  pqPutInt(nargs, 2, conn) < 0) /* # of args */
2035  {
2036  /* error message should be set up already */
2037  return NULL;
2038  }
2039 
2040  for (i = 0; i < nargs; ++i)
2041  { /* len.int4 + contents */
2042  if (pqPutInt(args[i].len, 4, conn))
2043  return NULL;
2044  if (args[i].len == -1)
2045  continue; /* it's NULL */
2046 
2047  if (args[i].isint)
2048  {
2049  if (pqPutInt(args[i].u.integer, args[i].len, conn))
2050  return NULL;
2051  }
2052  else
2053  {
2054  if (pqPutnchar((char *) args[i].u.ptr, args[i].len, conn))
2055  return NULL;
2056  }
2057  }
2058 
2059  if (pqPutInt(1, 2, conn) < 0) /* result format code: BINARY */
2060  return NULL;
2061 
2062  if (pqPutMsgEnd(conn) < 0 ||
2063  pqFlush(conn))
2064  return NULL;
2065 
2066  for (;;)
2067  {
2068  if (needInput)
2069  {
2070  /* Wait for some data to arrive (or for the channel to close) */
2071  if (pqWait(true, false, conn) ||
2072  pqReadData(conn) < 0)
2073  break;
2074  }
2075 
2076  /*
2077  * Scan the message. If we run out of data, loop around to try again.
2078  */
2079  needInput = true;
2080 
2081  conn->inCursor = conn->inStart;
2082  if (pqGetc(&id, conn))
2083  continue;
2084  if (pqGetInt(&msgLength, 4, conn))
2085  continue;
2086 
2087  /*
2088  * Try to validate message type/length here. A length less than 4 is
2089  * definitely broken. Large lengths should only be believed for a few
2090  * message types.
2091  */
2092  if (msgLength < 4)
2093  {
2094  handleSyncLoss(conn, id, msgLength);
2095  break;
2096  }
2097  if (msgLength > 30000 && !VALID_LONG_MESSAGE_TYPE(id))
2098  {
2099  handleSyncLoss(conn, id, msgLength);
2100  break;
2101  }
2102 
2103  /*
2104  * Can't process if message body isn't all here yet.
2105  */
2106  msgLength -= 4;
2107  avail = conn->inEnd - conn->inCursor;
2108  if (avail < msgLength)
2109  {
2110  /*
2111  * Before looping, enlarge the input buffer if needed to hold the
2112  * whole message. See notes in parseInput.
2113  */
2114  if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength,
2115  conn))
2116  {
2117  /*
2118  * XXX add some better recovery code... plan is to skip over
2119  * the message using its length, then report an error. For the
2120  * moment, just treat this like loss of sync (which indeed it
2121  * might be!)
2122  */
2123  handleSyncLoss(conn, id, msgLength);
2124  break;
2125  }
2126  continue;
2127  }
2128 
2129  /*
2130  * We should see V or E response to the command, but might get N
2131  * and/or A notices first. We also need to swallow the final Z before
2132  * returning.
2133  */
2134  switch (id)
2135  {
2136  case 'V': /* function result */
2137  if (pqGetInt(actual_result_len, 4, conn))
2138  continue;
2139  if (*actual_result_len != -1)
2140  {
2141  if (result_is_int)
2142  {
2143  if (pqGetInt(result_buf, *actual_result_len, conn))
2144  continue;
2145  }
2146  else
2147  {
2148  if (pqGetnchar((char *) result_buf,
2149  *actual_result_len,
2150  conn))
2151  continue;
2152  }
2153  }
2154  /* correctly finished function result message */
2155  status = PGRES_COMMAND_OK;
2156  break;
2157  case 'E': /* error return */
2158  if (pqGetErrorNotice3(conn, true))
2159  continue;
2160  status = PGRES_FATAL_ERROR;
2161  break;
2162  case 'A': /* notify message */
2163  /* handle notify and go back to processing return values */
2164  if (getNotify(conn))
2165  continue;
2166  break;
2167  case 'N': /* notice */
2168  /* handle notice and go back to processing return values */
2169  if (pqGetErrorNotice3(conn, false))
2170  continue;
2171  break;
2172  case 'Z': /* backend is ready for new query */
2173  if (getReadyForQuery(conn))
2174  continue;
2175  /* consume the message and exit */
2176  conn->inStart += 5 + msgLength;
2177 
2178  /*
2179  * If we already have a result object (probably an error), use
2180  * that. Otherwise, if we saw a function result message,
2181  * report COMMAND_OK. Otherwise, the backend violated the
2182  * protocol, so complain.
2183  */
2184  if (!pgHavePendingResult(conn))
2185  {
2186  if (status == PGRES_COMMAND_OK)
2187  {
2188  conn->result = PQmakeEmptyPGresult(conn, status);
2189  if (!conn->result)
2190  {
2191  libpq_append_conn_error(conn, "out of memory");
2193  }
2194  }
2195  else
2196  {
2197  libpq_append_conn_error(conn, "protocol error: no function result");
2199  }
2200  }
2201  return pqPrepareAsyncResult(conn);
2202  case 'S': /* parameter status */
2203  if (getParameterStatus(conn))
2204  continue;
2205  break;
2206  default:
2207  /* The backend violates the protocol. */
2208  libpq_append_conn_error(conn, "protocol error: id=0x%x", id);
2210  /* trust the specified message length as what to skip */
2211  conn->inStart += 5 + msgLength;
2212  return pqPrepareAsyncResult(conn);
2213  }
2214 
2215  /* trace server-to-client message */
2216  if (conn->Pfdebug)
2218 
2219  /* Completed this message, keep going */
2220  /* trust the specified message length as what to skip */
2221  conn->inStart += 5 + msgLength;
2222  needInput = false;
2223  }
2224 
2225  /*
2226  * We fall out of the loop only upon failing to read data.
2227  * conn->errorMessage has been set by pqWait or pqReadData. We want to
2228  * append it to any already-received error message.
2229  */
2231  return pqPrepareAsyncResult(conn);
2232 }
void pqSaveErrorResult(PGconn *conn)
Definition: fe-exec.c:800
PGresult * PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
Definition: fe-exec.c:157
PGresult * pqPrepareAsyncResult(PGconn *conn)
Definition: fe-exec.c:846
int pqReadData(PGconn *conn)
Definition: fe-misc.c:566
int pqPutInt(int value, size_t bytes, PGconn *conn)
Definition: fe-misc.c:254
int pqGetc(char *result, PGconn *conn)
Definition: fe-misc.c:78
int pqGetInt(int *result, size_t bytes, PGconn *conn)
Definition: fe-misc.c:217
int pqGetnchar(char *s, size_t len, PGconn *conn)
Definition: fe-misc.c:166
int pqWait(int forRead, int forWrite, PGconn *conn)
Definition: fe-misc.c:979
int pqCheckInBufferSpace(size_t bytes_needed, PGconn *conn)
Definition: fe-misc.c:352
int pqPutnchar(const char *s, size_t len, PGconn *conn)
Definition: fe-misc.c:203
static int getNotify(PGconn *conn)
static int getParameterStatus(PGconn *conn)
#define VALID_LONG_MESSAGE_TYPE(id)
Definition: fe-protocol3.c:36
static void handleSyncLoss(PGconn *conn, char id, int msgLength)
Definition: fe-protocol3.c:487
static int getReadyForQuery(PGconn *conn)
int pqGetErrorNotice3(PGconn *conn, bool isError)
Definition: fe-protocol3.c:886
void pqTraceOutputMessage(PGconn *conn, const char *message, bool toServer)
Definition: fe-trace.c:529
ExecStatusType
Definition: libpq-fe.h:95
@ PQ_PIPELINE_OFF
Definition: libpq-fe.h:158
#define pgHavePendingResult(conn)
Definition: libpq-int.h:882
#define PqMsg_FunctionCall
Definition: protocol.h:23
PGpipelineStatus pipelineStatus
Definition: libpq-int.h:432

References generate_unaccent_rules::args, Assert(), conn, getNotify(), getParameterStatus(), getReadyForQuery(), handleSyncLoss(), i, pg_conn::inBuffer, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, len, libpq_append_conn_error(), pg_conn::Pfdebug, pgHavePendingResult, PGRES_COMMAND_OK, PGRES_FATAL_ERROR, pg_conn::pipelineStatus, PQ_PIPELINE_OFF, pqCheckInBufferSpace(), pqFlush(), pqGetc(), pqGetErrorNotice3(), pqGetInt(), pqGetnchar(), PQmakeEmptyPGresult(), PqMsg_FunctionCall, pqPrepareAsyncResult(), pqPutInt(), pqPutMsgEnd(), pqPutMsgStart(), pqPutnchar(), pqReadData(), pqSaveErrorResult(), pqTraceOutputMessage(), pqWait(), pg_conn::result, and VALID_LONG_MESSAGE_TYPE.

Referenced by PQfn().

◆ pqGetc()

int pqGetc ( char *  result,
PGconn conn 
)

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

79 {
80  if (conn->inCursor >= conn->inEnd)
81  return EOF;
82 
83  *result = conn->inBuffer[conn->inCursor++];
84 
85  return 0;
86 }

References conn, pg_conn::inBuffer, pg_conn::inCursor, and pg_conn::inEnd.

Referenced by getCopyDataMessage(), getCopyStart(), getReadyForQuery(), PQconnectPoll(), pqFunctionCall3(), pqGetErrorNotice3(), and pqParseInput3().

◆ pqGetCopyData3()

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

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

1756 {
1757  int msgLength;
1758 
1759  for (;;)
1760  {
1761  /*
1762  * Collect the next input message. To make life simpler for async
1763  * callers, we keep returning 0 until the next message is fully
1764  * available, even if it is not Copy Data.
1765  */
1766  msgLength = getCopyDataMessage(conn);
1767  if (msgLength < 0)
1768  return msgLength; /* end-of-copy or error */
1769  if (msgLength == 0)
1770  {
1771  /* Don't block if async read requested */
1772  if (async)
1773  return 0;
1774  /* Need to load more data */
1775  if (pqWait(true, false, conn) ||
1776  pqReadData(conn) < 0)
1777  return -2;
1778  continue;
1779  }
1780 
1781  /*
1782  * Drop zero-length messages (shouldn't happen anyway). Otherwise
1783  * pass the data back to the caller.
1784  */
1785  msgLength -= 4;
1786  if (msgLength > 0)
1787  {
1788  *buffer = (char *) malloc(msgLength + 1);
1789  if (*buffer == NULL)
1790  {
1791  libpq_append_conn_error(conn, "out of memory");
1792  return -2;
1793  }
1794  memcpy(*buffer, &conn->inBuffer[conn->inCursor], msgLength);
1795  (*buffer)[msgLength] = '\0'; /* Add terminating null */
1796 
1797  /* Mark message consumed */
1798  conn->inStart = conn->inCursor + msgLength;
1799 
1800  return msgLength;
1801  }
1802 
1803  /* Empty, so drop it and loop around for another */
1804  conn->inStart = conn->inCursor;
1805  }
1806 }
static int getCopyDataMessage(PGconn *conn)

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

Referenced by PQgetCopyData().

◆ pqGetErrorNotice3()

int pqGetErrorNotice3 ( PGconn conn,
bool  isError 
)

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

887 {
888  PGresult *res = NULL;
889  bool have_position = false;
890  PQExpBufferData workBuf;
891  char id;
892 
893  /* If in pipeline mode, set error indicator for it */
894  if (isError && conn->pipelineStatus != PQ_PIPELINE_OFF)
896 
897  /*
898  * If this is an error message, pre-emptively clear any incomplete query
899  * result we may have. We'd just throw it away below anyway, and
900  * releasing it before collecting the error might avoid out-of-memory.
901  */
902  if (isError)
904 
905  /*
906  * Since the fields might be pretty long, we create a temporary
907  * PQExpBuffer rather than using conn->workBuffer. workBuffer is intended
908  * for stuff that is expected to be short. We shouldn't use
909  * conn->errorMessage either, since this might be only a notice.
910  */
911  initPQExpBuffer(&workBuf);
912 
913  /*
914  * Make a PGresult to hold the accumulated fields. We temporarily lie
915  * about the result status, so that PQmakeEmptyPGresult doesn't uselessly
916  * copy conn->errorMessage.
917  *
918  * NB: This allocation can fail, if you run out of memory. The rest of the
919  * function handles that gracefully, and we still try to set the error
920  * message as the connection's error message.
921  */
923  if (res)
925 
926  /*
927  * Read the fields and save into res.
928  *
929  * While at it, save the SQLSTATE in conn->last_sqlstate, and note whether
930  * we saw a PG_DIAG_STATEMENT_POSITION field.
931  */
932  for (;;)
933  {
934  if (pqGetc(&id, conn))
935  goto fail;
936  if (id == '\0')
937  break; /* terminator found */
938  if (pqGets(&workBuf, conn))
939  goto fail;
940  pqSaveMessageField(res, id, workBuf.data);
941  if (id == PG_DIAG_SQLSTATE)
942  strlcpy(conn->last_sqlstate, workBuf.data,
943  sizeof(conn->last_sqlstate));
944  else if (id == PG_DIAG_STATEMENT_POSITION)
945  have_position = true;
946  }
947 
948  /*
949  * Save the active query text, if any, into res as well; but only if we
950  * might need it for an error cursor display, which is only true if there
951  * is a PG_DIAG_STATEMENT_POSITION field.
952  */
953  if (have_position && res && conn->cmd_queue_head && conn->cmd_queue_head->query)
955 
956  /*
957  * Now build the "overall" error message for PQresultErrorMessage.
958  */
959  resetPQExpBuffer(&workBuf);
961 
962  /*
963  * Either save error as current async result, or just emit the notice.
964  */
965  if (isError)
966  {
967  pqClearAsyncResult(conn); /* redundant, but be safe */
968  if (res)
969  {
970  pqSetResultError(res, &workBuf, 0);
971  conn->result = res;
972  }
973  else
974  {
975  /* Fall back to using the internal-error processing paths */
976  conn->error_result = true;
977  }
978 
979  if (PQExpBufferDataBroken(workBuf))
980  libpq_append_conn_error(conn, "out of memory");
981  else
983  }
984  else
985  {
986  /* if we couldn't allocate the result set, just discard the NOTICE */
987  if (res)
988  {
989  /*
990  * We can cheat a little here and not copy the message. But if we
991  * were unlucky enough to run out of memory while filling workBuf,
992  * insert "out of memory", as in pqSetResultError.
993  */
994  if (PQExpBufferDataBroken(workBuf))
995  res->errMsg = libpq_gettext("out of memory\n");
996  else
997  res->errMsg = workBuf.data;
998  if (res->noticeHooks.noticeRec != NULL)
1000  PQclear(res);
1001  }
1002  }
1003 
1004  termPQExpBuffer(&workBuf);
1005  return 0;
1006 
1007 fail:
1008  PQclear(res);
1009  termPQExpBuffer(&workBuf);
1010  return EOF;
1011 }
void pqSaveMessageField(PGresult *res, char code, const char *value)
Definition: fe-exec.c:1055
void pqSetResultError(PGresult *res, PQExpBuffer errorMessage, int offset)
Definition: fe-exec.c:689
char * pqResultStrdup(PGresult *res, const char *str)
Definition: fe-exec.c:672
void pqClearAsyncResult(PGconn *conn)
Definition: fe-exec.c:776
int pqGets(PQExpBuffer buf, PGconn *conn)
Definition: fe-misc.c:137
void pqBuildErrorMessage3(PQExpBuffer msg, const PGresult *res, PGVerbosity verbosity, PGContextVisibility show_context)
@ PGRES_EMPTY_QUERY
Definition: libpq-fe.h:96
@ PGRES_NONFATAL_ERROR
Definition: libpq-fe.h:107
@ PQ_PIPELINE_ABORTED
Definition: libpq-fe.h:160
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)
Definition: pqexpbuffer.c:129
#define PQExpBufferDataBroken(buf)
Definition: pqexpbuffer.h:67
PQnoticeReceiver noticeRec
Definition: libpq-int.h:155
void * noticeRecArg
Definition: libpq-int.h:156
PGVerbosity verbosity
Definition: libpq-int.h:501
char last_sqlstate[6]
Definition: libpq-int.h:428
PGContextVisibility show_context
Definition: libpq-int.h:502
PGNoticeHooks noticeHooks
Definition: libpq-int.h:189

References appendPQExpBufferStr(), pg_conn::cmd_queue_head, conn, PQExpBufferData::data, pg_result::errMsg, pg_conn::error_result, pg_conn::errorMessage, pg_result::errQuery, 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, res, 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 
)

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

7757 {
7758 #ifndef WIN32
7759  const char *home;
7760 
7761  home = getenv("HOME");
7762  if (home == NULL || home[0] == '\0')
7763  return pg_get_user_home_dir(geteuid(), buf, bufsize);
7764  strlcpy(buf, home, bufsize);
7765  return true;
7766 #else
7767  char tmppath[MAX_PATH];
7768 
7769  ZeroMemory(tmppath, sizeof(tmppath));
7770  if (SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, tmppath) != S_OK)
7771  return false;
7772  snprintf(buf, bufsize, "%s/postgresql", tmppath);
7773  return true;
7774 #endif
7775 }
#define bufsize
Definition: indent_globs.h:36
static char * buf
Definition: pg_test_fsync.c:73
bool pg_get_user_home_dir(uid_t user_id, char *buffer, size_t buflen)
Definition: user.c:64
#define snprintf
Definition: port.h:238

References buf, bufsize, pg_get_user_home_dir(), snprintf, and strlcpy().

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

◆ pqGetInt()

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

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

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

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

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

◆ pqGetline3()

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

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

1815 {
1816  int status;
1817 
1818  if (conn->sock == PGINVALID_SOCKET ||
1822  {
1823  libpq_append_conn_error(conn, "PQgetline: not doing text COPY OUT");
1824  *s = '\0';
1825  return EOF;
1826  }
1827 
1828  while ((status = PQgetlineAsync(conn, s, maxlen - 1)) == 0)
1829  {
1830  /* need to load more data */
1831  if (pqWait(true, false, conn) ||
1832  pqReadData(conn) < 0)
1833  {
1834  *s = '\0';
1835  return EOF;
1836  }
1837  }
1838 
1839  if (status < 0)
1840  {
1841  /* End of copy detected; gin up old-style terminator */
1842  strcpy(s, "\\.");
1843  return 0;
1844  }
1845 
1846  /* Add null terminator, and strip trailing \n if present */
1847  if (s[status - 1] == '\n')
1848  {
1849  s[status - 1] = '\0';
1850  return 0;
1851  }
1852  else
1853  {
1854  s[status] = '\0';
1855  return 1;
1856  }
1857 }
int PQgetlineAsync(PGconn *conn, char *buffer, int bufsize)
Definition: fe-exec.c:2867
char copy_is_binary
Definition: libpq-int.h:434

References pg_conn::asyncStatus, conn, pg_conn::copy_is_binary, 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 
)

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

1866 {
1867  int msgLength;
1868  int avail;
1869 
1872  return -1; /* we are not doing a copy... */
1873 
1874  /*
1875  * Recognize the next input message. To make life simpler for async
1876  * callers, we keep returning 0 until the next message is fully available
1877  * even if it is not Copy Data. This should keep PQendcopy from blocking.
1878  * (Note: unlike pqGetCopyData3, we do not change asyncStatus here.)
1879  */
1880  msgLength = getCopyDataMessage(conn);
1881  if (msgLength < 0)
1882  return -1; /* end-of-copy or error */
1883  if (msgLength == 0)
1884  return 0; /* no data yet */
1885 
1886  /*
1887  * Move data from libpq's buffer to the caller's. In the case where a
1888  * prior call found the caller's buffer too small, we use
1889  * conn->copy_already_done to remember how much of the row was already
1890  * returned to the caller.
1891  */
1893  avail = msgLength - 4 - conn->copy_already_done;
1894  if (avail <= bufsize)
1895  {
1896  /* Able to consume the whole message */
1897  memcpy(buffer, &conn->inBuffer[conn->inCursor], avail);
1898  /* Mark message consumed */
1899  conn->inStart = conn->inCursor + avail;
1900  /* Reset state for next time */
1901  conn->copy_already_done = 0;
1902  return avail;
1903  }
1904  else
1905  {
1906  /* We must return a partial message */
1907  memcpy(buffer, &conn->inBuffer[conn->inCursor], bufsize);
1908  /* The message is NOT consumed from libpq's buffer */
1910  return bufsize;
1911  }
1912 }
int copy_already_done
Definition: libpq-int.h:435

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

Referenced by PQgetlineAsync().

◆ pqGetnchar()

int pqGetnchar ( char *  s,
size_t  len,
PGconn conn 
)

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

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

References conn, pg_conn::inBuffer, pg_conn::inCursor, pg_conn::inEnd, and len.

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

◆ pqGetNegotiateProtocolVersion3()

int pqGetNegotiateProtocolVersion3 ( PGconn conn)

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

1417 {
1418  int tmp;
1419  ProtocolVersion their_version;
1420  int num;
1422 
1423  if (pqGetInt(&tmp, 4, conn) != 0)
1424  return EOF;
1425  their_version = tmp;
1426 
1427  if (pqGetInt(&num, 4, conn) != 0)
1428  return EOF;
1429 
1430  initPQExpBuffer(&buf);
1431  for (int i = 0; i < num; i++)
1432  {
1433  if (pqGets(&conn->workBuffer, conn))
1434  {
1435  termPQExpBuffer(&buf);
1436  return EOF;
1437  }
1438  if (buf.len > 0)
1439  appendPQExpBufferChar(&buf, ' ');
1441  }
1442 
1443  if (their_version < conn->pversion)
1444  libpq_append_conn_error(conn, "protocol version not supported by server: client uses %u.%u, server supports up to %u.%u",
1446  PG_PROTOCOL_MAJOR(their_version), PG_PROTOCOL_MINOR(their_version));
1447  if (num > 0)
1448  {
1450  libpq_ngettext("protocol extension not supported by server: %s",
1451  "protocol extensions not supported by server: %s", num),
1452  buf.data);
1454  }
1455 
1456  /* neither -- server shouldn't have sent it */
1457  if (!(their_version < conn->pversion) && !(num > 0))
1458  libpq_append_conn_error(conn, "invalid %s message", "NegotiateProtocolVersion");
1459 
1460  termPQExpBuffer(&buf);
1461  return 0;
1462 }
#define libpq_ngettext(s, p, n)
Definition: libpq-int.h:901
#define PG_PROTOCOL_MAJOR(v)
Definition: pqcomm.h:87
uint32 ProtocolVersion
Definition: pqcomm.h:99
#define PG_PROTOCOL_MINOR(v)
Definition: pqcomm.h:88
ProtocolVersion pversion
Definition: libpq-int.h:463
PQExpBufferData workBuffer
Definition: libpq-int.h:621

References appendPQExpBuffer(), appendPQExpBufferChar(), appendPQExpBufferStr(), buf, conn, PQExpBufferData::data, pg_conn::errorMessage, i, initPQExpBuffer(), libpq_append_conn_error(), libpq_ngettext, PG_PROTOCOL_MAJOR, PG_PROTOCOL_MINOR, pqGetInt(), pqGets(), pg_conn::pversion, termPQExpBuffer(), and pg_conn::workBuffer.

Referenced by PQconnectPoll().

◆ pqGets()

int pqGets ( PQExpBuffer  buf,
PGconn conn 
)

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

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

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 
)

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

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

References buf, conn, and pqGets_internal().

Referenced by PQconnectPoll().

◆ pqInternalNotice()

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

◆ pqPacketSend()

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

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

5079 {
5080  /* Start the message. */
5081  if (pqPutMsgStart(pack_type, conn))
5082  return STATUS_ERROR;
5083 
5084  /* Send the message body. */
5085  if (pqPutnchar(buf, buf_len, conn))
5086  return STATUS_ERROR;
5087 
5088  /* Finish the message. */
5089  if (pqPutMsgEnd(conn))
5090  return STATUS_ERROR;
5091 
5092  /* Flush to ensure backend gets it. */
5093  if (pqFlush(conn))
5094  return STATUS_ERROR;
5095 
5096  return STATUS_OK;
5097 }
#define STATUS_OK
Definition: c.h:1182
#define STATUS_ERROR
Definition: c.h:1183

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

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

◆ pqParseInput3()

void pqParseInput3 ( PGconn conn)

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

67 {
68  char id;
69  int msgLength;
70  int avail;
71 
72  /*
73  * Loop to parse successive complete messages available in the buffer.
74  */
75  for (;;)
76  {
77  /*
78  * Try to read a message. First get the type code and length. Return
79  * if not enough data.
80  */
82  if (pqGetc(&id, conn))
83  return;
84  if (pqGetInt(&msgLength, 4, conn))
85  return;
86 
87  /*
88  * Try to validate message type/length here. A length less than 4 is
89  * definitely broken. Large lengths should only be believed for a few
90  * message types.
91  */
92  if (msgLength < 4)
93  {
94  handleSyncLoss(conn, id, msgLength);
95  return;
96  }
97  if (msgLength > 30000 && !VALID_LONG_MESSAGE_TYPE(id))
98  {
99  handleSyncLoss(conn, id, msgLength);
100  return;
101  }
102 
103  /*
104  * Can't process if message body isn't all here yet.
105  */
106  msgLength -= 4;
107  avail = conn->inEnd - conn->inCursor;
108  if (avail < msgLength)
109  {
110  /*
111  * Before returning, enlarge the input buffer if needed to hold
112  * the whole message. This is better than leaving it to
113  * pqReadData because we can avoid multiple cycles of realloc()
114  * when the message is large; also, we can implement a reasonable
115  * recovery strategy if we are unable to make the buffer big
116  * enough.
117  */
118  if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength,
119  conn))
120  {
121  /*
122  * XXX add some better recovery code... plan is to skip over
123  * the message using its length, then report an error. For the
124  * moment, just treat this like loss of sync (which indeed it
125  * might be!)
126  */
127  handleSyncLoss(conn, id, msgLength);
128  }
129  return;
130  }
131 
132  /*
133  * NOTIFY and NOTICE messages can happen in any state; always process
134  * them right away.
135  *
136  * Most other messages should only be processed while in BUSY state.
137  * (In particular, in READY state we hold off further parsing until
138  * the application collects the current PGresult.)
139  *
140  * However, if the state is IDLE then we got trouble; we need to deal
141  * with the unexpected message somehow.
142  *
143  * ParameterStatus ('S') messages are a special case: in IDLE state we
144  * must process 'em (this case could happen if a new value was adopted
145  * from config file due to SIGHUP), but otherwise we hold off until
146  * BUSY state.
147  */
148  if (id == PqMsg_NotificationResponse)
149  {
150  if (getNotify(conn))
151  return;
152  }
153  else if (id == PqMsg_NoticeResponse)
154  {
155  if (pqGetErrorNotice3(conn, false))
156  return;
157  }
158  else if (conn->asyncStatus != PGASYNC_BUSY)
159  {
160  /* If not IDLE state, just wait ... */
161  if (conn->asyncStatus != PGASYNC_IDLE)
162  return;
163 
164  /*
165  * Unexpected message in IDLE state; need to recover somehow.
166  * ERROR messages are handled using the notice processor;
167  * ParameterStatus is handled normally; anything else is just
168  * dropped on the floor after displaying a suitable warning
169  * notice. (An ERROR is very possibly the backend telling us why
170  * it is about to close the connection, so we don't want to just
171  * discard it...)
172  */
173  if (id == PqMsg_ErrorResponse)
174  {
175  if (pqGetErrorNotice3(conn, false /* treat as notice */ ))
176  return;
177  }
178  else if (id == PqMsg_ParameterStatus)
179  {
181  return;
182  }
183  else
184  {
185  /* Any other case is unexpected and we summarily skip it */
187  "message type 0x%02x arrived from server while idle",
188  id);
189  /* Discard the unexpected message */
190  conn->inCursor += msgLength;
191  }
192  }
193  else
194  {
195  /*
196  * In BUSY state, we can process everything.
197  */
198  switch (id)
199  {
201  if (pqGets(&conn->workBuffer, conn))
202  return;
204  {
207  if (!conn->result)
208  {
209  libpq_append_conn_error(conn, "out of memory");
211  }
212  }
213  if (conn->result)
215  CMDSTATUS_LEN);
217  break;
218  case PqMsg_ErrorResponse:
219  if (pqGetErrorNotice3(conn, true))
220  return;
222  break;
223  case PqMsg_ReadyForQuery:
224  if (getReadyForQuery(conn))
225  return;
227  {
230  if (!conn->result)
231  {
232  libpq_append_conn_error(conn, "out of memory");
234  }
235  else
236  {
239  }
240  }
241  else
242  {
243  /*
244  * In simple query protocol, advance the command queue
245  * (see PQgetResult).
246  */
247  if (conn->cmd_queue_head &&
251  }
252  break;
255  {
258  if (!conn->result)
259  {
260  libpq_append_conn_error(conn, "out of memory");
262  }
263  }
265  break;
266  case PqMsg_ParseComplete:
267  /* If we're doing PQprepare, we're done; else ignore */
268  if (conn->cmd_queue_head &&
270  {
272  {
275  if (!conn->result)
276  {
277  libpq_append_conn_error(conn, "out of memory");
279  }
280  }
282  }
283  break;
284  case PqMsg_BindComplete:
285  /* Nothing to do for this message type */
286  break;
287  case PqMsg_CloseComplete:
288  /* If we're doing PQsendClose, we're done; else ignore */
289  if (conn->cmd_queue_head &&
291  {
293  {
296  if (!conn->result)
297  {
298  libpq_append_conn_error(conn, "out of memory");
300  }
301  }
303  }
304  break;
307  return;
308  break;
310 
311  /*
312  * This is expected only during backend startup, but it's
313  * just as easy to handle it as part of the main loop.
314  * Save the data and continue processing.
315  */
316  if (pqGetInt(&(conn->be_pid), 4, conn))
317  return;
318  if (pqGetInt(&(conn->be_key), 4, conn))
319  return;
320  break;
322  if (conn->error_result ||
323  (conn->result != NULL &&
325  {
326  /*
327  * We've already choked for some reason. Just discard
328  * the data till we get to the end of the query.
329  */
330  conn->inCursor += msgLength;
331  }
332  else if (conn->result == NULL ||
333  (conn->cmd_queue_head &&
335  {
336  /* First 'T' in a query sequence */
337  if (getRowDescriptions(conn, msgLength))
338  return;
339  }
340  else
341  {
342  /*
343  * A new 'T' message is treated as the start of
344  * another PGresult. (It is not clear that this is
345  * really possible with the current backend.) We stop
346  * parsing until the application accepts the current
347  * result.
348  */
350  return;
351  }
352  break;
353  case PqMsg_NoData:
354 
355  /*
356  * NoData indicates that we will not be seeing a
357  * RowDescription message because the statement or portal
358  * inquired about doesn't return rows.
359  *
360  * If we're doing a Describe, we have to pass something
361  * back to the client, so set up a COMMAND_OK result,
362  * instead of PGRES_TUPLES_OK. Otherwise we can just
363  * ignore this message.
364  */
365  if (conn->cmd_queue_head &&
367  {
369  {
372  if (!conn->result)
373  {
374  libpq_append_conn_error(conn, "out of memory");
376  }
377  }
379  }
380  break;
382  if (getParamDescriptions(conn, msgLength))
383  return;
384  break;
385  case PqMsg_DataRow:
386  if (conn->result != NULL &&
388  {
389  /* Read another tuple of a normal query response */
390  if (getAnotherTuple(conn, msgLength))
391  return;
392  }
393  else if (conn->error_result ||
394  (conn->result != NULL &&
396  {
397  /*
398  * We've already choked for some reason. Just discard
399  * tuples till we get to the end of the query.
400  */
401  conn->inCursor += msgLength;
402  }
403  else
404  {
405  /* Set up to report error at end of query */
406  libpq_append_conn_error(conn, "server sent data (\"D\" message) without prior row description (\"T\" message)");
408  /* Discard the unexpected message */
409  conn->inCursor += msgLength;
410  }
411  break;
414  return;
416  break;
419  return;
421  conn->copy_already_done = 0;
422  break;
425  return;
427  conn->copy_already_done = 0;
428  break;
429  case PqMsg_CopyData:
430 
431  /*
432  * If we see Copy Data, just silently drop it. This would
433  * only occur if application exits COPY OUT mode too
434  * early.
435  */
436  conn->inCursor += msgLength;
437  break;
438  case PqMsg_CopyDone:
439 
440  /*
441  * If we see Copy Done, just silently drop it. This is
442  * the normal case during PQendcopy. We will keep
443  * swallowing data, expecting to see command-complete for
444  * the COPY command.
445  */
446  break;
447  default:
448  libpq_append_conn_error(conn, "unexpected response from server; first received character was \"%c\"", id);
449  /* build an error result holding the error message */
451  /* not sure if we will see more, so go to ready state */
453  /* Discard the unexpected message */
454  conn->inCursor += msgLength;
455  break;
456  } /* switch on protocol character */
457  }
458  /* Successfully consumed this message */
459  if (conn->inCursor == conn->inStart + 5 + msgLength)
460  {
461  /* trace server-to-client message */
462  if (conn->Pfdebug)
464 
465  /* Normal case: parsing agrees with specified length */
467  }
468  else
469  {
470  /* Trouble --- report it */
471  libpq_append_conn_error(conn, "message contents do not agree with length in message type \"%c\"", id);
472  /* build an error result holding the error message */
475  /* trust the specified message length as what to skip */
476  conn->inStart += 5 + msgLength;
477  }
478  }
479 }
void pqCommandQueueAdvance(PGconn *conn)
Definition: fe-exec.c:3095
static int getAnotherTuple(PGconn *conn, int msgLength)
Definition: fe-protocol3.c:766
static int getRowDescriptions(PGconn *conn, int msgLength)
Definition: fe-protocol3.c:507
static int getCopyStart(PGconn *conn, ExecStatusType copytype)
static int getParamDescriptions(PGconn *conn, int msgLength)
Definition: fe-protocol3.c:678
@ PGRES_COPY_IN
Definition: libpq-fe.h:104
@ PGRES_COPY_BOTH
Definition: libpq-fe.h:109
@ PGRES_COPY_OUT
Definition: libpq-fe.h:103
@ PGRES_PIPELINE_SYNC
Definition: libpq-fe.h:111
@ PGRES_TUPLES_OK
Definition: libpq-fe.h:100
@ PQ_PIPELINE_ON
Definition: libpq-fe.h:159
#define CMDSTATUS_LEN
Definition: libpq-int.h:89
#define PqMsg_CloseComplete
Definition: protocol.h:40
#define PqMsg_NotificationResponse
Definition: protocol.h:41
#define PqMsg_BindComplete
Definition: protocol.h:39
#define PqMsg_CopyData
Definition: protocol.h:65
#define PqMsg_ParameterDescription
Definition: protocol.h:58
#define PqMsg_ReadyForQuery
Definition: protocol.h:55
#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_ParameterStatus
Definition: protocol.h:51
#define PqMsg_NoData
Definition: protocol.h:56
#define PqMsg_BackendKeyData
Definition: protocol.h:48
#define PqMsg_CommandComplete
Definition: protocol.h:42
#define PqMsg_ErrorResponse
Definition: protocol.h:44
#define PqMsg_DataRow
Definition: protocol.h:43
#define PqMsg_NoticeResponse
Definition: protocol.h:49
#define PqMsg_CopyOutResponse
Definition: protocol.h:46
#define PqMsg_ParseComplete
Definition: protocol.h:38
int be_pid
Definition: libpq-int.h:494
int be_key
Definition: libpq-int.h:495
char cmdStatus[CMDSTATUS_LEN]
Definition: libpq-int.h:181

References pg_conn::asyncStatus, pg_conn::be_key, pg_conn::be_pid, pg_conn::cmd_queue_head, pg_result::cmdStatus, CMDSTATUS_LEN, conn, pg_conn::copy_already_done, PQExpBufferData::data, pg_conn::error_result, getAnotherTuple(), getCopyStart(), getNotify(), getParamDescriptions(), getParameterStatus(), getReadyForQuery(), getRowDescriptions(), handleSyncLoss(), pg_conn::inBuffer, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, libpq_append_conn_error(), pg_conn::noticeHooks, pg_conn::Pfdebug, PGASYNC_BUSY, PGASYNC_COPY_BOTH, PGASYNC_COPY_IN, PGASYNC_COPY_OUT, PGASYNC_IDLE, PGASYNC_READY, pgHavePendingResult, PGQUERY_CLOSE, PGQUERY_DESCRIBE, PGQUERY_PREPARE, PGQUERY_SIMPLE, PGRES_COMMAND_OK, PGRES_COPY_BOTH, PGRES_COPY_IN, PGRES_COPY_OUT, PGRES_EMPTY_QUERY, PGRES_FATAL_ERROR, PGRES_PIPELINE_SYNC, 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, pqSaveErrorResult(), pqTraceOutputMessage(), PGcmdQueueEntry::queryclass, pg_conn::result, pg_result::resultStatus, strlcpy(), VALID_LONG_MESSAGE_TYPE, and pg_conn::workBuffer.

Referenced by parseInput().

◆ pqPrepareAsyncResult()

PGresult* pqPrepareAsyncResult ( PGconn conn)

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

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

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

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

◆ pqPutc()

int pqPutc ( char  c,
PGconn conn 
)

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

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

References conn, and pqPutMsgBytes().

Referenced by PQsendQueryGuts(), and PQsendTypedCommand().

◆ pqPutInt()

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

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

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

References conn, 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)

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

519 {
520  /* Fill in length word if needed */
521  if (conn->outMsgStart >= 0)
522  {
523  uint32 msgLen = conn->outMsgEnd - conn->outMsgStart;
524 
525  msgLen = pg_hton32(msgLen);
526  memcpy(conn->outBuffer + conn->outMsgStart, &msgLen, 4);
527  }
528 
529  /* trace client-to-server message */
530  if (conn->Pfdebug)
531  {
532  if (conn->outCount < conn->outMsgStart)
534  else
537  }
538 
539  /* Make message eligible to send */
541 
542  if (conn->outCount >= 8192)
543  {
544  int toSend = conn->outCount - (conn->outCount % 8192);
545 
546  if (pqSendSome(conn, toSend) < 0)
547  return EOF;
548  /* in nonblock mode, don't complain if unable to send it all */
549  }
550 
551  return 0;
552 }
void pqTraceOutputNoTypeByteMessage(PGconn *conn, const char *message)
Definition: fe-trace.c:704
int outMsgStart
Definition: libpq-int.h:520
int outMsgEnd
Definition: libpq-int.h:522

References conn, pg_conn::outBuffer, pg_conn::outCount, pg_conn::outMsgEnd, pg_conn::outMsgStart, pg_conn::Pfdebug, pg_hton32, pqSendSome(), pqTraceOutputMessage(), and pqTraceOutputNoTypeByteMessage().

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

◆ pqPutMsgStart()

int pqPutMsgStart ( char  msg_type,
PGconn conn 
)

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

460 {
461  int lenPos;
462  int endPos;
463 
464  /* allow room for message type byte */
465  if (msg_type)
466  endPos = conn->outCount + 1;
467  else
468  endPos = conn->outCount;
469 
470  /* do we want a length word? */
471  lenPos = endPos;
472  /* allow room for message length */
473  endPos += 4;
474 
475  /* make sure there is room for message header */
476  if (pqCheckOutBufferSpace(endPos, conn))
477  return EOF;
478  /* okay, save the message type byte if any */
479  if (msg_type)
480  conn->outBuffer[conn->outCount] = msg_type;
481  /* set up the message pointers */
482  conn->outMsgStart = lenPos;
483  conn->outMsgEnd = endPos;
484  /* length word, if needed, will be filled in by pqPutMsgEnd */
485 
486  return 0;
487 }
int pqCheckOutBufferSpace(size_t bytes_needed, PGconn *conn)
Definition: fe-misc.c:288

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

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

◆ pqPutnchar()

int pqPutnchar ( const char *  s,
size_t  len,
PGconn conn 
)

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

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

References conn, len, and pqPutMsgBytes().

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

◆ pqPuts()

int pqPuts ( const char *  s,
PGconn conn 
)

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

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

References conn, and pqPutMsgBytes().

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

◆ pqReadData()

int pqReadData ( PGconn conn)

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

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

References ALL_CONNECTION_FAILURE_ERRNOS, conn, CONNECTION_BAD, EAGAIN, EINTR, EWOULDBLOCK, 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 PQconnectPoll(), PQconsumeInput(), pqFunctionCall3(), pqGetCopyData3(), pqGetline3(), PQgetResult(), and pqSendSome().

◆ pqReadReady()

int pqReadReady ( PGconn conn)

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

1016 {
1017  return pqSocketCheck(conn, 1, 0, (time_t) 0);
1018 }
static int pqSocketCheck(PGconn *conn, int forRead, int forWrite, time_t end_time)
Definition: fe-misc.c:1039

References conn, and pqSocketCheck().

Referenced by gss_read(), and pqReadData().

◆ pqResultAlloc()

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

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

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

References pg_result::curBlock, pg_result::curOffset, malloc, pg_result::memorySize, pgresult_data::next, pg_result::null_field, PGRESULT_ALIGN_BOUNDARY, PGRESULT_BLOCK_OVERHEAD, PGRESULT_DATA_BLOCKSIZE, PGRESULT_SEP_ALLOC_THRESHOLD, res, 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 
)

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

673 {
674  char *space = (char *) pqResultAlloc(res, strlen(str) + 1, false);
675 
676  if (space)
677  strcpy(space, str);
678  return space;
679 }
void * pqResultAlloc(PGresult *res, size_t nBytes, bool isBinary)
Definition: fe-exec.c:560

References pqResultAlloc(), res, and generate_unaccent_rules::str.

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

◆ pqRowProcessor()

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

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

1207 {
1208  PGresult *res = conn->result;
1209  int nfields = res->numAttributes;
1210  const PGdataValue *columns = conn->rowBuf;
1211  PGresAttValue *tup;
1212  int i;
1213 
1214  /*
1215  * In single-row mode, make a new PGresult that will hold just this one
1216  * row; the original conn->result is left unchanged so that it can be used
1217  * again as the template for future rows.
1218  */
1219  if (conn->singleRowMode)
1220  {
1221  /* Copy everything that should be in the result at this point */
1222  res = PQcopyResult(res,
1225  if (!res)
1226  return 0;
1227  }
1228 
1229  /*
1230  * Basically we just allocate space in the PGresult for each field and
1231  * copy the data over.
1232  *
1233  * Note: on malloc failure, we return 0 leaving *errmsgp still NULL, which
1234  * caller will take to mean "out of memory". This is preferable to trying
1235  * to set up such a message here, because evidently there's not enough
1236  * memory for gettext() to do anything.
1237  */
1238  tup = (PGresAttValue *)
1239  pqResultAlloc(res, nfields * sizeof(PGresAttValue), true);
1240  if (tup == NULL)
1241  goto fail;
1242 
1243  for (i = 0; i < nfields; i++)
1244  {
1245  int clen = columns[i].len;
1246 
1247  if (clen < 0)
1248  {
1249  /* null field */
1250  tup[i].len = NULL_LEN;
1251  tup[i].value = res->null_field;
1252  }
1253  else
1254  {
1255  bool isbinary = (res->attDescs[i].format != 0);
1256  char *val;
1257 
1258  val = (char *) pqResultAlloc(res, clen + 1, isbinary);
1259  if (val == NULL)
1260  goto fail;
1261 
1262  /* copy and zero-terminate the data (even if it's binary) */
1263  memcpy(val, columns[i].value, clen);
1264  val[clen] = '\0';
1265 
1266  tup[i].len = clen;
1267  tup[i].value = val;
1268  }
1269  }
1270 
1271  /* And add the tuple to the PGresult's tuple array */
1272  if (!pqAddTuple(res, tup, errmsgp))
1273  goto fail;
1274 
1275  /*
1276  * Success. In single-row mode, make the result available to the client
1277  * immediately.
1278  */
1279  if (conn->singleRowMode)
1280  {
1281  /* Change result status to special single-row value */
1283  /* Stash old result for re-use later */
1285  conn->result = res;
1286  /* And mark the result ready to return */
1288  }
1289 
1290  return 1;
1291 
1292 fail:
1293  /* release locally allocated PGresult, if we made one */
1294  if (res != conn->result)
1295  PQclear(res);
1296  return 0;
1297 }
PGresult * PQcopyResult(const PGresult *src, int flags)
Definition: fe-exec.c:315
static bool pqAddTuple(PGresult *res, PGresAttValue *tup, const char **errmsgp)
Definition: fe-exec.c:988
@ PGRES_SINGLE_TUPLE
Definition: libpq-fe.h:110
#define PG_COPYRES_ATTRS
Definition: libpq-fe.h:45
#define PG_COPYRES_EVENTS
Definition: libpq-fe.h:47
#define PG_COPYRES_NOTICEHOOKS
Definition: libpq-fe.h:48
#define NULL_LEN
Definition: libpq-int.h:136
PGdataValue * rowBuf
Definition: libpq-int.h:525
bool singleRowMode
Definition: libpq-int.h:433
PGresAttDesc * attDescs
Definition: libpq-int.h:174
int numAttributes
Definition: libpq-int.h:173
char * value
Definition: libpq-int.h:141

References pg_conn::asyncStatus, pg_result::attDescs, conn, pgresAttDesc::format, i, pgresAttValue::len, pgDataValue::len, pg_conn::next_result, pg_result::null_field, NULL_LEN, pg_result::numAttributes, PG_COPYRES_ATTRS, PG_COPYRES_EVENTS, PG_COPYRES_NOTICEHOOKS, PGASYNC_READY_MORE, PGRES_SINGLE_TUPLE, pqAddTuple(), PQclear(), PQcopyResult(), pqResultAlloc(), res, pg_conn::result, pg_result::resultStatus, pg_conn::rowBuf, pg_conn::singleRowMode, val, value, and pgresAttValue::value.

Referenced by getAnotherTuple().

◆ pqSaveErrorResult()

void pqSaveErrorResult ( PGconn conn)

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

801 {
802  /* Drop any pending result ... */
804  /* ... and set flag to remember to make an error result later */
805  conn->error_result = true;
806 }

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

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

◆ pqSaveMessageField()

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

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

1056 {
1057  PGMessageField *pfield;
1058 
1059  pfield = (PGMessageField *)
1061  offsetof(PGMessageField, contents) +
1062  strlen(value) + 1,
1063  true);
1064  if (!pfield)
1065  return; /* out of memory? */
1066  pfield->code = code;
1067  strcpy(pfield->contents, value);
1068  pfield->next = res->errFields;
1069  res->errFields = pfield;
1070 }
struct pgMessageField * next
Definition: libpq-int.h:147
char contents[FLEXIBLE_ARRAY_MEMBER]
Definition: libpq-int.h:149

References pgMessageField::code, pgMessageField::contents, pg_result::errFields, pgMessageField::next, pqResultAlloc(), res, and value.

Referenced by pqGetErrorNotice3(), and pqInternalNotice().

◆ pqSaveParameterStatus()

void pqSaveParameterStatus ( PGconn conn,
const char *  name,
const char *  value 
)

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

1077 {
1078  pgParameterStatus *pstatus;
1079  pgParameterStatus *prev;
1080 
1081  /*
1082  * Forget any old information about the parameter
1083  */
1084  for (pstatus = conn->pstatus, prev = NULL;
1085  pstatus != NULL;
1086  prev = pstatus, pstatus = pstatus->next)
1087  {
1088  if (strcmp(pstatus->name, name) == 0)
1089  {
1090  if (prev)
1091  prev->next = pstatus->next;
1092  else
1093  conn->pstatus = pstatus->next;
1094  free(pstatus); /* frees name and value strings too */
1095  break;
1096  }
1097  }
1098 
1099  /*
1100  * Store new info as a single malloc block
1101  */
1102  pstatus = (pgParameterStatus *) malloc(sizeof(pgParameterStatus) +
1103  strlen(name) + strlen(value) + 2);
1104  if (pstatus)
1105  {
1106  char *ptr;
1107 
1108  ptr = ((char *) pstatus) + sizeof(pgParameterStatus);
1109  pstatus->name = ptr;
1110  strcpy(ptr, name);
1111  ptr += strlen(name) + 1;
1112  pstatus->value = ptr;
1113  strcpy(ptr, value);
1114  pstatus->next = conn->pstatus;
1115  conn->pstatus = pstatus;
1116  }
1117 
1118  /*
1119  * Save values of settings that are of interest to libpq in fields of the
1120  * PGconn object. We keep client_encoding and standard_conforming_strings
1121  * in static variables as well, so that PQescapeString and PQescapeBytea
1122  * can behave somewhat sanely (at least in single-connection-using
1123  * programs).
1124  */
1125  if (strcmp(name, "client_encoding") == 0)
1126  {
1128  /* if we don't recognize the encoding name, fall back to SQL_ASCII */
1129  if (conn->client_encoding < 0)
1132  }
1133  else if (strcmp(name, "standard_conforming_strings") == 0)
1134  {
1135  conn->std_strings = (strcmp(value, "on") == 0);
1137  }
1138  else if (strcmp(name, "server_version") == 0)
1139  {
1140  /* We convert the server version to numeric form. */
1141  int cnt;
1142  int vmaj,
1143  vmin,
1144  vrev;
1145 
1146  cnt = sscanf(value, "%d.%d.%d", &vmaj, &vmin, &vrev);
1147 
1148  if (cnt == 3)
1149  {
1150  /* old style, e.g. 9.6.1 */
1151  conn->sversion = (100 * vmaj + vmin) * 100 + vrev;
1152  }
1153  else if (cnt == 2)
1154  {
1155  if (vmaj >= 10)
1156  {
1157  /* new style, e.g. 10.1 */
1158  conn->sversion = 100 * 100 * vmaj + vmin;
1159  }
1160  else
1161  {
1162  /* old style without minor version, e.g. 9.6devel */
1163  conn->sversion = (100 * vmaj + vmin) * 100;
1164  }
1165  }
1166  else if (cnt == 1)
1167  {
1168  /* new style without minor version, e.g. 10devel */
1169  conn->sversion = 100 * 100 * vmaj;
1170  }
1171  else
1172  conn->sversion = 0; /* unknown */
1173  }
1174  else if (strcmp(name, "default_transaction_read_only") == 0)
1175  {
1177  (strcmp(value, "on") == 0) ? PG_BOOL_YES : PG_BOOL_NO;
1178  }
1179  else if (strcmp(name, "in_hot_standby") == 0)
1180  {
1181  conn->in_hot_standby =
1182  (strcmp(value, "on") == 0) ? PG_BOOL_YES : PG_BOOL_NO;
1183  }
1184  else if (strcmp(name, "scram_iterations") == 0)
1185  {
1187  }
1188 }
static bool static_std_strings
Definition: fe-exec.c:59
static int static_client_encoding
Definition: fe-exec.c:58
struct pgParameterStatus pgParameterStatus
@ PG_SQL_ASCII
Definition: pg_wchar.h:229
#define pg_char_to_encoding
Definition: pg_wchar.h:562
struct pgParameterStatus * next
Definition: libpq-int.h:271
bool std_strings
Definition: libpq-int.h:498
PGTernaryBool in_hot_standby
Definition: libpq-int.h:500
int client_encoding
Definition: libpq-int.h:497
int sversion
Definition: libpq-int.h:464
PGTernaryBool default_transaction_read_only
Definition: libpq-int.h:499
pgParameterStatus * pstatus
Definition: libpq-int.h:496
int scram_sha_256_iterations
Definition: libpq-int.h:544

References pg_conn::client_encoding, conn, pg_conn::default_transaction_read_only, 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)

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

168 {
169 #ifdef USE_SSL
170  pgtls_close(conn);
171 #endif
172 }

References conn, and pgtls_close().

Referenced by pqDropConnection().

◆ pqsecure_initialize()

int pqsecure_initialize ( PGconn conn,
bool  do_ssl,
bool  do_crypto 
)

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

139 {
140  int r = 0;
141 
142 #ifdef USE_SSL
143  r = pgtls_init(conn, do_ssl, do_crypto);
144 #endif
145 
146  return r;
147 }
int pgtls_init(PGconn *conn, bool do_ssl, bool do_crypto)

References conn, and pgtls_init().

Referenced by PQconnectPoll().

◆ pqsecure_open_client()

PostgresPollingStatusType pqsecure_open_client ( PGconn conn)

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

154 {
155 #ifdef USE_SSL
156  return pgtls_open_client(conn);
157 #else
158  /* shouldn't get here */
159  return PGRES_POLLING_FAILED;
160 #endif
161 }
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 
)

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

209 {
210  ssize_t n;
211  int result_errno = 0;
212  char sebuf[PG_STRERROR_R_BUFLEN];
213 
214  n = recv(conn->sock, ptr, len, 0);
215 
216  if (n < 0)
217  {
218  result_errno = SOCK_ERRNO;
219 
220  /* Set error message if appropriate */
221  switch (result_errno)
222  {
223 #ifdef EAGAIN
224  case EAGAIN:
225 #endif
226 #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
227  case EWOULDBLOCK:
228 #endif
229  case EINTR:
230  /* no error message, caller is expected to retry */
231  break;
232 
233  case EPIPE:
234  case ECONNRESET:
235  libpq_append_conn_error(conn, "server closed the connection unexpectedly\n"
236  "\tThis probably means the server terminated abnormally\n"
237  "\tbefore or while processing the request.");
238  break;
239 
240  default:
241  libpq_append_conn_error(conn, "could not receive data from server: %s",
242  SOCK_STRERROR(result_errno,
243  sebuf, sizeof(sebuf)));
244  break;
245  }
246  }
247 
248  /* ensure we return the intended errno to caller */
249  SOCK_ERRNO_SET(result_errno);
250 
251  return n;
252 }
#define recv(s, buf, len, flags)
Definition: win32_port.h:496

References conn, EAGAIN, ECONNRESET, EINTR, EWOULDBLOCK, 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(), my_sock_read(), pg_GSS_read(), and pqsecure_read().

◆ pqsecure_raw_write()

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

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

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

References conn, DECLARE_SIGPIPE_INFO, DISABLE_SIGPIPE, EAGAIN, ECONNRESET, EINTR, EWOULDBLOCK, len, libpq_gettext, 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 my_sock_write(), pg_GSS_write(), pqsecure_open_gss(), and pqsecure_write().

◆ pqsecure_read()

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

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

183 {
184  ssize_t n;
185 
186 #ifdef USE_SSL
187  if (conn->ssl_in_use)
188  {
189  n = pgtls_read(conn, ptr, len);
190  }
191  else
192 #endif
193 #ifdef ENABLE_GSS
194  if (conn->gssenc)
195  {
196  n = pg_GSS_read(conn, ptr, len);
197  }
198  else
199 #endif
200  {
201  n = pqsecure_raw_read(conn, ptr, len);
202  }
203 
204  return n;
205 }
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:208

References conn, 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 
)

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

276 {
277  ssize_t n;
278 
279 #ifdef USE_SSL
280  if (conn->ssl_in_use)
281  {
282  n = pgtls_write(conn, ptr, len);
283  }
284  else
285 #endif
286 #ifdef ENABLE_GSS
287  if (conn->gssenc)
288  {
289  n = pg_GSS_write(conn, ptr, len);
290  }
291  else
292 #endif
293  {
294  n = pqsecure_raw_write(conn, ptr, len);
295  }
296 
297  return n;
298 }
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:324

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

Referenced by pqSendSome().

◆ PQsendQueryContinue()

int PQsendQueryContinue ( PGconn conn,
const char *  query 
)

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

1429 {
1430  return PQsendQueryInternal(conn, query, false);
1431 }
static int PQsendQueryInternal(PGconn *conn, const char *query, bool newQuery)
Definition: fe-exec.c:1434

References conn, and PQsendQueryInternal().

Referenced by PQconnectPoll().

◆ pqSetResultError()

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

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

690 {
691  char *msg;
692 
693  if (!res)
694  return;
695 
696  /*
697  * We handle two OOM scenarios here. The errorMessage buffer might be
698  * marked "broken" due to having previously failed to allocate enough
699  * memory for the message, or it might be fine but pqResultStrdup fails
700  * and returns NULL. In either case, just make res->errMsg point directly
701  * at a constant "out of memory" string.
702  */
703  if (!PQExpBufferBroken(errorMessage))
704  msg = pqResultStrdup(res, errorMessage->data + offset);
705  else
706  msg = NULL;
707  if (msg)
708  res->errMsg = msg;
709  else
710  res->errMsg = libpq_gettext("out of memory\n");
711 }
#define PQExpBufferBroken(str)
Definition: pqexpbuffer.h:59

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

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

◆ pqSkipnchar()

int pqSkipnchar ( size_t  len,
PGconn conn 
)

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

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

References conn, pg_conn::inCursor, pg_conn::inEnd, and len.

Referenced by getAnotherTuple().

◆ pqTraceOutputMessage()

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

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

530 {
531  char id;
532  int length;
533  char *prefix = toServer ? "F" : "B";
534  int logCursor = 0;
535  bool regress;
536 
538  {
539  char timestr[128];
540 
541  pqTraceFormatTimestamp(timestr, sizeof(timestr));
542  fprintf(conn->Pfdebug, "%s\t", timestr);
543  }
544  regress = (conn->traceFlags & PQTRACE_REGRESS_MODE) != 0;
545 
546  id = message[logCursor++];
547 
548  memcpy(&length, message + logCursor, 4);
549  length = (int) pg_ntoh32(length);
550  logCursor += 4;
551 
552  /*
553  * In regress mode, suppress the length of ErrorResponse and
554  * NoticeResponse. The F (file name), L (line number) and R (routine
555  * name) fields can change as server code is modified, and if their
556  * lengths differ from the originals, that would break tests.
557  */
558  if (regress && !toServer && (id == 'E' || id == 'N'))
559  fprintf(conn->Pfdebug, "%s\tNN\t", prefix);
560  else
561  fprintf(conn->Pfdebug, "%s\t%d\t", prefix, length);
562 
563  switch (id)
564  {
565  case PqMsg_ParseComplete:
566  fprintf(conn->Pfdebug, "ParseComplete");
567  /* No message content */
568  break;
569  case PqMsg_BindComplete:
570  fprintf(conn->Pfdebug, "BindComplete");
571  /* No message content */
572  break;
573  case PqMsg_CloseComplete:
574  fprintf(conn->Pfdebug, "CloseComplete");
575  /* No message content */
576  break;
578  pqTraceOutputA(conn->Pfdebug, message, &logCursor, regress);
579  break;
580  case PqMsg_Bind:
581  pqTraceOutputB(conn->Pfdebug, message, &logCursor);
582  break;
583  case PqMsg_CopyDone:
584  fprintf(conn->Pfdebug, "CopyDone");
585  /* No message content */
586  break;
588  /* Close(F) and CommandComplete(B) use the same identifier. */
590  pqTraceOutputC(conn->Pfdebug, toServer, message, &logCursor);
591  break;
592  case PqMsg_CopyData:
593  /* Drop COPY data to reduce the overhead of logging. */
594  break;
595  case PqMsg_Describe:
596  /* Describe(F) and DataRow(B) use the same identifier. */
598  pqTraceOutputD(conn->Pfdebug, toServer, message, &logCursor);
599  break;
600  case PqMsg_Execute:
601  /* Execute(F) and ErrorResponse(B) use the same identifier. */
603  pqTraceOutputE(conn->Pfdebug, toServer, message, &logCursor,
604  regress);
605  break;
606  case PqMsg_CopyFail:
607  pqTraceOutputf(conn->Pfdebug, message, &logCursor);
608  break;
609  case PqMsg_FunctionCall:
610  pqTraceOutputF(conn->Pfdebug, message, &logCursor, regress);
611  break;
613  pqTraceOutputG(conn->Pfdebug, message, &logCursor);
614  break;
615  case PqMsg_Flush:
616  /* Flush(F) and CopyOutResponse(B) use the same identifier */
618  if (!toServer)
619  pqTraceOutputH(conn->Pfdebug, message, &logCursor);
620  else
621  fprintf(conn->Pfdebug, "Flush"); /* no message content */
622  break;
624  fprintf(conn->Pfdebug, "EmptyQueryResponse");
625  /* No message content */
626  break;
628  pqTraceOutputK(conn->Pfdebug, message, &logCursor, regress);
629  break;
630  case PqMsg_NoData:
631  fprintf(conn->Pfdebug, "NoData");
632  /* No message content */
633  break;
635  pqTraceOutputNR(conn->Pfdebug, "NoticeResponse", message,
636  &logCursor, regress);
637  break;
638  case PqMsg_Parse:
639  pqTraceOutputP(conn->Pfdebug, message, &logCursor, regress);
640  break;
641  case PqMsg_Query:
642  pqTraceOutputQ(conn->Pfdebug, message, &logCursor);
643  break;
645  pqTraceOutputR(conn->Pfdebug, message, &logCursor);
646  break;
648  fprintf(conn->Pfdebug, "PortalSuspended");
649  /* No message content */
650  break;
651  case PqMsg_Sync:
652  /* Parameter Status(B) and Sync(F) use the same identifier */
654  if (!toServer)
655  pqTraceOutputS(conn->Pfdebug, message, &logCursor);
656  else
657  fprintf(conn->Pfdebug, "Sync"); /* no message content */
658  break;
660  pqTraceOutputt(conn->Pfdebug, message, &logCursor, regress);
661  break;
663  pqTraceOutputT(conn->Pfdebug, message, &logCursor, regress);
664  break;
666  pqTraceOutputv(conn->Pfdebug, message, &logCursor);
667  break;
669  pqTraceOutputV(conn->Pfdebug, message, &logCursor);
670  break;
672  pqTraceOutputW(conn->Pfdebug, message, &logCursor, length);
673  break;
674  case PqMsg_Terminate:
675  fprintf(conn->Pfdebug, "Terminate");
676  /* No message content */
677  break;
678  case PqMsg_ReadyForQuery:
679  pqTraceOutputZ(conn->Pfdebug, message, &logCursor);
680  break;
681  default:
682  fprintf(conn->Pfdebug, "Unknown message: %02x", id);
683  break;
684  }
685 
686  fputc('\n', conn->Pfdebug);
687 
688  /*
689  * Verify the printing routine did it right. Note that the one-byte
690  * message identifier is not included in the length, but our cursor does
691  * include it.
692  */
693  if (logCursor - 1 != length)
695  "mismatched message length: consumed %d, expected %d\n",
696  logCursor - 1, length);
697 }
static void pqTraceOutputQ(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:428
static void pqTraceOutputS(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:444
static void pqTraceOutputH(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:390
static void pqTraceOutputZ(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:519
static void pqTraceOutputW(FILE *f, const char *message, int *cursor, int length)
Definition: fe-trace.c:508
static void pqTraceOutputE(FILE *f, bool toServer, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:327
static void pqTraceOutputV(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:496
static void pqTraceOutputK(FILE *f, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:404
static void pqTraceOutputF(FILE *f, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:349
static void pqTraceOutputP(FILE *f, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:413
static void pqTraceOutputT(FILE *f, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:466
static void pqTraceOutputA(FILE *f, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:220
static void pqTraceOutputD(FILE *f, bool toServer, const char *message, int *cursor)
Definition: fe-trace.c:278
static void pqTraceOutputG(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:376
static void pqTraceOutputf(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:341
static void pqTraceOutputNR(FILE *f, const char *type, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:306
static void pqTraceOutputR(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:436
static void pqTraceOutputt(FILE *f, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:453
static void pqTraceOutputB(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:230
static void pqTraceOutputv(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:487
static void pqTraceOutputC(FILE *f, bool toServer, const char *message, int *cursor)
Definition: fe-trace.c:261
static void pqTraceFormatTimestamp(char *timestr, size_t ts_len)
Definition: fe-trace.c:80
#define PQTRACE_SUPPRESS_TIMESTAMPS
Definition: libpq-fe.h:415
#define PQTRACE_REGRESS_MODE
Definition: libpq-fe.h:417
#define fprintf
Definition: port.h:242
#define PqMsg_Describe
Definition: protocol.h:21
#define PqMsg_FunctionCallResponse
Definition: protocol.h:53
#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_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
int traceFlags
Definition: libpq-int.h:414

References Assert(), conn, fprintf, 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_NegotiateProtocolVersion, PqMsg_NoData, PqMsg_NoticeResponse, PqMsg_NotificationResponse, PqMsg_ParameterDescription, PqMsg_ParameterStatus, PqMsg_Parse, PqMsg_ParseComplete, PqMsg_PortalSuspended, PqMsg_Query, PqMsg_ReadyForQuery, PqMsg_RowDescription, PqMsg_Sync, PqMsg_Terminate, PQTRACE_REGRESS_MODE, PQTRACE_SUPPRESS_TIMESTAMPS, pqTraceFormatTimestamp(), pqTraceOutputA(), pqTraceOutputB(), pqTraceOutputC(), pqTraceOutputD(), pqTraceOutputE(), pqTraceOutputf(), pqTraceOutputF(), pqTraceOutputG(), pqTraceOutputH(), pqTraceOutputK(), pqTraceOutputNR(), pqTraceOutputP(), pqTraceOutputQ(), pqTraceOutputR(), pqTraceOutputS(), pqTraceOutputt(), pqTraceOutputT(), pqTraceOutputv(), pqTraceOutputV(), pqTraceOutputW(), pqTraceOutputZ(), and pg_conn::traceFlags.

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

◆ pqTraceOutputNoTypeByteMessage()

void pqTraceOutputNoTypeByteMessage ( PGconn conn,
const char *  message 
)

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

705 {
706  int length;
707  int logCursor = 0;
708 
710  {
711  char timestr[128];
712 
713  pqTraceFormatTimestamp(timestr, sizeof(timestr));
714  fprintf(conn->Pfdebug, "%s\t", timestr);
715  }
716 
717  memcpy(&length, message + logCursor, 4);
718  length = (int) pg_ntoh32(length);
719  logCursor += 4;
720 
721  fprintf(conn->Pfdebug, "F\t%d\t", length);
722 
723  switch (length)
724  {
725  case 16: /* CancelRequest */
726  fprintf(conn->Pfdebug, "CancelRequest\t");
727  pqTraceOutputInt32(conn->Pfdebug, message, &logCursor, false);
728  pqTraceOutputInt32(conn->Pfdebug, message, &logCursor, false);
729  pqTraceOutputInt32(conn->Pfdebug, message, &logCursor, false);
730  break;
731  case 8: /* GSSENCRequest or SSLRequest */
732  /* These messages do not reach here. */
733  default:
734  fprintf(conn->Pfdebug, "Unknown message: length is %d", length);
735  break;
736  }
737 
738  fputc('\n', conn->Pfdebug);
739 }
static int pqTraceOutputInt32(FILE *pfdebug, const char *data, int *cursor, bool suppress)
Definition: fe-trace.c:144

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

Referenced by pqPutMsgEnd().

◆ pqWait()

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

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

980 {
981  return pqWaitTimed(forRead, forWrite, conn, (time_t) -1);
982 }
int pqWaitTimed(int forRead, int forWrite, PGconn *conn, time_t finish_time)
Definition: fe-misc.c:992

References conn, and pqWaitTimed().

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

◆ pqWaitTimed()

int pqWaitTimed ( int  forRead,
int  forWrite,
PGconn conn,
time_t  finish_time 
)

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

993 {
994  int result;
995 
996  result = pqSocketCheck(conn, forRead, forWrite, finish_time);
997 
998  if (result < 0)
999  return -1; /* errorMessage is already set */
1000 
1001  if (result == 0)
1002  {
1003  libpq_append_conn_error(conn, "timeout expired");
1004  return 1;
1005  }
1006 
1007  return 0;
1008 }

References conn, libpq_append_conn_error(), and pqSocketCheck().

Referenced by connectDBComplete(), and pqWait().

◆ pqWriteReady()

int pqWriteReady ( PGconn conn)

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

1026 {
1027  return pqSocketCheck(conn, 0, 1, (time_t) 0);
1028 }

References conn, and pqSocketCheck().

Variable Documentation

◆ pg_g_threadlock