PostgreSQL Source Code  git master
libpq-int.h File Reference
#include "libpq-events.h"
#include <time.h>
#include "getaddrinfo.h"
#include "libpq/pqcomm.h"
#include "fe-auth-sasl.h"
#include "pqexpbuffer.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()   ((void) 0)
 
#define pgunlock_thread()   ((void) 0)
 
#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  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 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)
 
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)
 
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)
 

Variables

char *const pgresStatus []
 

Macro Definition Documentation

◆ CMDSTATUS_LEN

#define CMDSTATUS_LEN   64 /* should match COMPLETION_TAG_BUFSIZE */

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

◆ libpq_gettext

#define libpq_gettext (   x)    (x)

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

◆ libpq_ngettext

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

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

◆ NULL_LEN

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

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

◆ OUTBUFFER_THRESHOLD

#define OUTBUFFER_THRESHOLD   65536

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

◆ pgHavePendingResult

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

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

◆ pglock_thread

#define pglock_thread ( )    ((void) 0)

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

◆ pgunlock_thread

#define pgunlock_thread ( )    ((void) 0)

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

◆ pqClearConnErrorState

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

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

◆ pqIsnonblocking

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

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

◆ SOCK_ERRNO

#define SOCK_ERRNO   errno

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

◆ SOCK_ERRNO_SET

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

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

◆ SOCK_STRERROR

#define SOCK_STRERROR   strerror_r

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

299 {
pg_conn_host_type
Definition: libpq-int.h:299
@ CHT_UNIX_SOCKET
Definition: libpq-int.h:302
@ CHT_HOST_ADDRESS
Definition: libpq-int.h:301
@ CHT_HOST_NAME
Definition: libpq-int.h:300

◆ 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 217 of file libpq-int.h.

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

◆ PGQueryClass

Enumerator
PGQUERY_SIMPLE 
PGQUERY_EXTENDED 
PGQUERY_PREPARE 
PGQUERY_DESCRIBE 
PGQUERY_SYNC 
PGQUERY_CLOSE 

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

310 {
311  PGQUERY_SIMPLE, /* simple Query protocol (PQexec) */
312  PGQUERY_EXTENDED, /* full Extended protocol (PQexecParams) */
313  PGQUERY_PREPARE, /* Parse only (PQprepare) */
314  PGQUERY_DESCRIBE, /* Describe Statement or Portal */
315  PGQUERY_SYNC, /* Sync (at end of a pipeline) */
317 } PGQueryClass;
PGQueryClass
Definition: libpq-int.h:310
@ PGQUERY_SIMPLE
Definition: libpq-int.h:311
@ PGQUERY_SYNC
Definition: libpq-int.h:315
@ PGQUERY_EXTENDED
Definition: libpq-int.h:312
@ PGQUERY_DESCRIBE
Definition: libpq-int.h:314
@ PGQUERY_CLOSE
Definition: libpq-int.h:316
@ PGQUERY_PREPARE
Definition: libpq-int.h:313

◆ 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 233 of file libpq-int.h.

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

◆ PGTernaryBool

Enumerator
PG_BOOL_UNKNOWN 
PG_BOOL_YES 
PG_BOOL_NO 

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

246 {
247  PG_BOOL_UNKNOWN = 0, /* Currently unknown */
248  PG_BOOL_YES, /* Yes (true) */
249  PG_BOOL_NO /* No (false) */
250 } PGTernaryBool;
PGTernaryBool
Definition: libpq-int.h:246
@ PG_BOOL_YES
Definition: libpq-int.h:248
@ PG_BOOL_NO
Definition: libpq-int.h:249
@ PG_BOOL_UNKNOWN
Definition: libpq-int.h:247

Function Documentation

◆ pgtls_close()

void pgtls_close ( PGconn conn)

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

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

References conn, destroy_ssl_system(), and pg_conn::ssl_in_use.

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

◆ pgtls_init()

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

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

767 {
768 #ifdef ENABLE_THREAD_SAFETY
769 #ifdef WIN32
770  /* Also see similar code in fe-connect.c, default_threadlock() */
771  if (ssl_config_mutex == NULL)
772  {
773  while (InterlockedExchange(&win32_ssl_create_mutex, 1) == 1)
774  /* loop, another thread own the lock */ ;
775  if (ssl_config_mutex == NULL)
776  {
777  if (pthread_mutex_init(&ssl_config_mutex, NULL))
778  return -1;
779  }
780  InterlockedExchange(&win32_ssl_create_mutex, 0);
781  }
782 #endif
783  if (pthread_mutex_lock(&ssl_config_mutex))
784  return -1;
785 
786 #ifdef HAVE_CRYPTO_LOCK
787  if (pq_init_crypto_lib)
788  {
789  /*
790  * If necessary, set up an array to hold locks for libcrypto.
791  * libcrypto will tell us how big to make this array.
792  */
793  if (pq_lockarray == NULL)
794  {
795  int i;
796 
797  pq_lockarray = malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks());
798  if (!pq_lockarray)
799  {
800  pthread_mutex_unlock(&ssl_config_mutex);
801  return -1;
802  }
803  for (i = 0; i < CRYPTO_num_locks(); i++)
804  {
805  if (pthread_mutex_init(&pq_lockarray[i], NULL))
806  {
807  free(pq_lockarray);
808  pq_lockarray = NULL;
809  pthread_mutex_unlock(&ssl_config_mutex);
810  return -1;
811  }
812  }
813  }
814 
815  if (do_crypto && !conn->crypto_loaded)
816  {
817  if (crypto_open_connections++ == 0)
818  {
819  /*
820  * These are only required for threaded libcrypto
821  * applications, but make sure we don't stomp on them if
822  * they're already set.
823  */
824  if (CRYPTO_get_id_callback() == NULL)
825  CRYPTO_set_id_callback(pq_threadidcallback);
826  if (CRYPTO_get_locking_callback() == NULL)
827  CRYPTO_set_locking_callback(pq_lockingcallback);
828  }
829 
830  conn->crypto_loaded = true;
831  }
832  }
833 #endif /* HAVE_CRYPTO_LOCK */
834 #endif /* ENABLE_THREAD_SAFETY */
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 
851 #ifdef ENABLE_THREAD_SAFETY
852  pthread_mutex_unlock(&ssl_config_mutex);
853 #endif
854  return 0;
855 }
static bool pq_init_crypto_lib
static bool ssl_lib_initialized
static bool pq_init_ssl_lib
#define free(a)
Definition: header.h:65
#define malloc(a)
Definition: header.h:50
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, free, i, malloc, pq_init_crypto_lib, pq_init_ssl_lib, pthread_mutex_init(), pthread_mutex_lock(), pthread_mutex_unlock(), and ssl_lib_initialized.

Referenced by pqsecure_initialize().

◆ pgtls_init_library()

void pgtls_init_library ( bool  do_ssl,
int  do_crypto 
)

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

116 {
117 #ifdef ENABLE_THREAD_SAFETY
118 
119  /*
120  * Disallow changing the flags while we have open connections, else we'd
121  * get completely confused.
122  */
123  if (crypto_open_connections != 0)
124  return;
125 #endif
126 
127  pq_init_ssl_lib = do_ssl;
128  pq_init_crypto_lib = do_crypto;
129 }

References 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 132 of file fe-secure-openssl.c.

133 {
134  /* First time through? */
135  if (conn->ssl == NULL)
136  {
137  /*
138  * Create a connection-specific SSL object, and load client
139  * certificate, private key, and trusted CA certs.
140  */
141  if (initialize_SSL(conn) != 0)
142  {
143  /* initialize_SSL already put a message in conn->errorMessage */
144  pgtls_close(conn);
145  return PGRES_POLLING_FAILED;
146  }
147  }
148 
149  /* Begin or continue the actual handshake */
150  return open_client_SSL(conn);
151 }
static PostgresPollingStatusType open_client_SSL(PGconn *)
static int initialize_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 154 of file fe-secure-openssl.c.

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

References appendPQExpBuffer(), appendPQExpBufferStr(), conn, ECONNRESET, pg_conn::errorMessage, len, libpq_gettext, 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 277 of file fe-secure-openssl.c.

278 {
279  return SSL_pending(conn->ssl) > 0;
280 }

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 571 of file fe-secure-openssl.c.

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

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 283 of file fe-secure-openssl.c.

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

References appendPQExpBuffer(), appendPQExpBufferStr(), conn, ECONNRESET, pg_conn::errorMessage, len, libpq_gettext, PG_STRERROR_R_BUFLEN, SOCK_ERRNO, SOCK_ERRNO_SET, SOCK_STRERROR, SSLerrfree(), and SSLerrmessage().

Referenced by pqsecure_write().

◆ pqBuildErrorMessage3()

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

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

1029 {
1030  const char *val;
1031  const char *querytext = NULL;
1032  int querypos = 0;
1033 
1034  /* If we couldn't allocate a PGresult, just say "out of memory" */
1035  if (res == NULL)
1036  {
1037  appendPQExpBufferStr(msg, libpq_gettext("out of memory\n"));
1038  return;
1039  }
1040 
1041  /*
1042  * If we don't have any broken-down fields, just return the base message.
1043  * This mainly applies if we're given a libpq-generated error result.
1044  */
1045  if (res->errFields == NULL)
1046  {
1047  if (res->errMsg && res->errMsg[0])
1049  else
1050  appendPQExpBufferStr(msg, libpq_gettext("no error message available\n"));
1051  return;
1052  }
1053 
1054  /* Else build error message from relevant fields */
1056  if (val)
1057  appendPQExpBuffer(msg, "%s: ", val);
1058 
1059  if (verbosity == PQERRORS_SQLSTATE)
1060  {
1061  /*
1062  * If we have a SQLSTATE, print that and nothing else. If not (which
1063  * shouldn't happen for server-generated errors, but might possibly
1064  * happen for libpq-generated ones), fall back to TERSE format, as
1065  * that seems better than printing nothing at all.
1066  */
1068  if (val)
1069  {
1070  appendPQExpBuffer(msg, "%s\n", val);
1071  return;
1072  }
1073  verbosity = PQERRORS_TERSE;
1074  }
1075 
1076  if (verbosity == PQERRORS_VERBOSE)
1077  {
1079  if (val)
1080  appendPQExpBuffer(msg, "%s: ", val);
1081  }
1083  if (val)
1084  appendPQExpBufferStr(msg, val);
1086  if (val)
1087  {
1088  if (verbosity != PQERRORS_TERSE && res->errQuery != NULL)
1089  {
1090  /* emit position as a syntax cursor display */
1091  querytext = res->errQuery;
1092  querypos = atoi(val);
1093  }
1094  else
1095  {
1096  /* emit position as text addition to primary message */
1097  /* translator: %s represents a digit string */
1098  appendPQExpBuffer(msg, libpq_gettext(" at character %s"),
1099  val);
1100  }
1101  }
1102  else
1103  {
1105  if (val)
1106  {
1108  if (verbosity != PQERRORS_TERSE && querytext != NULL)
1109  {
1110  /* emit position as a syntax cursor display */
1111  querypos = atoi(val);
1112  }
1113  else
1114  {
1115  /* emit position as text addition to primary message */
1116  /* translator: %s represents a digit string */
1117  appendPQExpBuffer(msg, libpq_gettext(" at character %s"),
1118  val);
1119  }
1120  }
1121  }
1122  appendPQExpBufferChar(msg, '\n');
1123  if (verbosity != PQERRORS_TERSE)
1124  {
1125  if (querytext && querypos > 0)
1126  reportErrorPosition(msg, querytext, querypos,
1127  res->client_encoding);
1129  if (val)
1130  appendPQExpBuffer(msg, libpq_gettext("DETAIL: %s\n"), val);
1132  if (val)
1133  appendPQExpBuffer(msg, libpq_gettext("HINT: %s\n"), val);
1135  if (val)
1136  appendPQExpBuffer(msg, libpq_gettext("QUERY: %s\n"), val);
1137  if (show_context == PQSHOW_CONTEXT_ALWAYS ||
1138  (show_context == PQSHOW_CONTEXT_ERRORS &&
1140  {
1142  if (val)
1143  appendPQExpBuffer(msg, libpq_gettext("CONTEXT: %s\n"),
1144  val);
1145  }
1146  }
1147  if (verbosity == PQERRORS_VERBOSE)
1148  {
1150  if (val)
1151  appendPQExpBuffer(msg,
1152  libpq_gettext("SCHEMA NAME: %s\n"), val);
1154  if (val)
1155  appendPQExpBuffer(msg,
1156  libpq_gettext("TABLE NAME: %s\n"), val);
1158  if (val)
1159  appendPQExpBuffer(msg,
1160  libpq_gettext("COLUMN NAME: %s\n"), val);
1162  if (val)
1163  appendPQExpBuffer(msg,
1164  libpq_gettext("DATATYPE NAME: %s\n"), val);
1166  if (val)
1167  appendPQExpBuffer(msg,
1168  libpq_gettext("CONSTRAINT NAME: %s\n"), val);
1169  }
1170  if (verbosity == PQERRORS_VERBOSE)
1171  {
1172  const char *valf;
1173  const char *vall;
1174 
1178  if (val || valf || vall)
1179  {
1180  appendPQExpBufferStr(msg, libpq_gettext("LOCATION: "));
1181  if (val)
1182  appendPQExpBuffer(msg, libpq_gettext("%s, "), val);
1183  if (valf && vall) /* unlikely we'd have just one */
1184  appendPQExpBuffer(msg, libpq_gettext("%s:%s"),
1185  valf, vall);
1186  appendPQExpBufferChar(msg, '\n');
1187  }
1188  }
1189 }
char * PQresultErrorField(const PGresult *res, int fieldcode)
Definition: fe-exec.c:3400
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 PG_DIAG_INTERNAL_QUERY
Definition: postgres_ext.h:63
#define PG_DIAG_SCHEMA_NAME
Definition: postgres_ext.h:65
#define PG_DIAG_CONSTRAINT_NAME
Definition: postgres_ext.h:69
#define PG_DIAG_DATATYPE_NAME
Definition: postgres_ext.h:68
#define PG_DIAG_SOURCE_LINE
Definition: postgres_ext.h:71
#define PG_DIAG_STATEMENT_POSITION
Definition: postgres_ext.h:61
#define PG_DIAG_SOURCE_FILE
Definition: postgres_ext.h:70
#define PG_DIAG_MESSAGE_HINT
Definition: postgres_ext.h:60
#define PG_DIAG_SQLSTATE
Definition: postgres_ext.h:57
#define PG_DIAG_TABLE_NAME
Definition: postgres_ext.h:66
#define PG_DIAG_MESSAGE_PRIMARY
Definition: postgres_ext.h:58
#define PG_DIAG_COLUMN_NAME
Definition: postgres_ext.h:67
#define PG_DIAG_MESSAGE_DETAIL
Definition: postgres_ext.h:59
#define PG_DIAG_CONTEXT
Definition: postgres_ext.h:64
#define PG_DIAG_SEVERITY
Definition: postgres_ext.h:55
#define PG_DIAG_SOURCE_FUNCTION
Definition: postgres_ext.h:72
#define PG_DIAG_INTERNAL_POSITION
Definition: postgres_ext.h:62
void appendPQExpBufferChar(PQExpBuffer str, char ch)
Definition: pqexpbuffer.c:380
char * errMsg
Definition: libpq-int.h:197
PGMessageField * errFields
Definition: libpq-int.h:198
ExecStatusType resultStatus
Definition: libpq-int.h:178
char * errQuery
Definition: libpq-int.h:199
int client_encoding
Definition: libpq-int.h:190

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 2201 of file fe-protocol3.c.

2203 {
2204  char *startpacket;
2205 
2206  *packetlen = build_startup_packet(conn, NULL, options);
2207  startpacket = (char *) malloc(*packetlen);
2208  if (!startpacket)
2209  return NULL;
2210  *packetlen = build_startup_packet(conn, startpacket, options);
2211  return startpacket;
2212 }
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 354 of file fe-misc.c.

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

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 290 of file fe-misc.c.

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

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:512
PGresult * result
Definition: libpq-int.h:510
bool error_result
Definition: libpq-int.h:511

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 3112 of file fe-exec.c.

3113 {
3114  PGcmdQueueEntry *prevquery;
3115 
3116  if (conn->cmd_queue_head == NULL)
3117  return;
3118 
3119  /* delink from queue */
3120  prevquery = conn->cmd_queue_head;
3122 
3123  /* If the queue is now empty, reset the tail too */
3124  if (conn->cmd_queue_head == NULL)
3125  conn->cmd_queue_tail = NULL;
3126 
3127  /* and make it recyclable */
3128  prevquery->next = NULL;
3129  pqRecycleCmdQueueEntry(conn, prevquery);
3130 }
static void pqRecycleCmdQueueEntry(PGconn *conn, PGcmdQueueEntry *entry)
Definition: fe-exec.c:1391
struct PGcmdQueueEntry * next
Definition: libpq-int.h:326
PGcmdQueueEntry * cmd_queue_tail
Definition: libpq-int.h:437
PGcmdQueueEntry * cmd_queue_head
Definition: libpq-int.h:436

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 449 of file fe-connect.c.

450 {
451  /* Drop any SSL state */
453 
454  /* Close the socket itself */
455  if (conn->sock != PGINVALID_SOCKET)
458 
459  /* Optionally discard any unread data */
460  if (flushInput)
461  conn->inStart = conn->inCursor = conn->inEnd = 0;
462 
463  /* Always discard any unsent data */
464  conn->outCount = 0;
465 
466  /* Likewise, discard any pending pipelined commands */
470  conn->cmd_queue_recycle = NULL;
471 
472  /* Free authentication/encryption state */
473 #ifdef ENABLE_GSS
474  {
475  OM_uint32 min_s;
476 
477  if (conn->gcred != GSS_C_NO_CREDENTIAL)
478  {
479  gss_release_cred(&min_s, &conn->gcred);
480  conn->gcred = GSS_C_NO_CREDENTIAL;
481  }
482  if (conn->gctx)
483  gss_delete_sec_context(&min_s, &conn->gctx, GSS_C_NO_BUFFER);
484  if (conn->gtarg_nam)
485  gss_release_name(&min_s, &conn->gtarg_nam);
486  if (conn->gss_SendBuffer)
487  {
488  free(conn->gss_SendBuffer);
489  conn->gss_SendBuffer = NULL;
490  }
491  if (conn->gss_RecvBuffer)
492  {
493  free(conn->gss_RecvBuffer);
494  conn->gss_RecvBuffer = NULL;
495  }
496  if (conn->gss_ResultBuffer)
497  {
498  free(conn->gss_ResultBuffer);
499  conn->gss_ResultBuffer = NULL;
500  }
501  conn->gssenc = false;
502  }
503 #endif
504 #ifdef ENABLE_SSPI
505  if (conn->sspitarget)
506  {
507  free(conn->sspitarget);
508  conn->sspitarget = NULL;
509  }
510  if (conn->sspicred)
511  {
512  FreeCredentialsHandle(conn->sspicred);
513  free(conn->sspicred);
514  conn->sspicred = NULL;
515  }
516  if (conn->sspictx)
517  {
518  DeleteSecurityContext(conn->sspictx);
519  free(conn->sspictx);
520  conn->sspictx = NULL;
521  }
522  conn->usesspi = 0;
523 #endif
524  if (conn->sasl_state)
525  {
527  conn->sasl_state = NULL;
528  }
529 }
static void pqFreeCommandQueue(PGcmdQueueEntry *queue)
Definition: fe-connect.c:536
void pqsecure_close(PGconn *conn)
Definition: fe-secure.c:191
#define PGINVALID_SOCKET
Definition: port.h:31
#define closesocket
Definition: port.h:342
pgsocket sock
Definition: libpq-int.h:446
const pg_fe_sasl_mech * sasl
Definition: libpq-int.h:515
PGcmdQueueEntry * cmd_queue_recycle
Definition: libpq-int.h:443
void * sasl_state
Definition: libpq-int.h:516
int outCount
Definition: libpq-int.h:490
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 1875 of file fe-protocol3.c.

1876 {
1877  PGresult *result;
1878 
1879  if (conn->asyncStatus != PGASYNC_COPY_IN &&
1882  {
1884  libpq_gettext("no COPY in progress\n"));
1885  return 1;
1886  }
1887 
1888  /* Send the CopyDone message if needed */
1889  if (conn->asyncStatus == PGASYNC_COPY_IN ||
1891  {
1892  if (pqPutMsgStart('c', conn) < 0 ||
1893  pqPutMsgEnd(conn) < 0)
1894  return 1;
1895 
1896  /*
1897  * If we sent the COPY command in extended-query mode, we must issue a
1898  * Sync as well.
1899  */
1900  if (conn->cmd_queue_head &&
1902  {
1903  if (pqPutMsgStart('S', conn) < 0 ||
1904  pqPutMsgEnd(conn) < 0)
1905  return 1;
1906  }
1907  }
1908 
1909  /*
1910  * make sure no data is waiting to be sent, abort if we are non-blocking
1911  * and the flush fails
1912  */
1913  if (pqFlush(conn) && pqIsnonblocking(conn))
1914  return 1;
1915 
1916  /* Return to active duty */
1918 
1919  /*
1920  * Non blocking connections may have to abort at this point. If everyone
1921  * played the game there should be no problem, but in error scenarios the
1922  * expected messages may not have arrived yet. (We are assuming that the
1923  * backend's packetizing will ensure that CommandComplete arrives along
1924  * with the CopyDone; are there corner cases where that doesn't happen?)
1925  */
1926  if (pqIsnonblocking(conn) && PQisBusy(conn))
1927  return 1;
1928 
1929  /* Wait for the completion response */
1930  result = PQgetResult(conn);
1931 
1932  /* Expecting a successful result */
1933  if (result && result->resultStatus == PGRES_COMMAND_OK)
1934  {
1935  PQclear(result);
1936  return 0;
1937  }
1938 
1939  /*
1940  * Trouble. For backwards-compatibility reasons, we issue the error
1941  * message as if it were a notice (would be nice to get rid of this
1942  * silliness, but too many apps probably don't handle errors from
1943  * PQendcopy reasonably). Note that the app can still obtain the error
1944  * status from the PGconn object.
1945  */
1946  if (conn->errorMessage.len > 0)
1947  {
1948  /* We have to strip the trailing newline ... pain in neck... */
1949  char svLast = conn->errorMessage.data[conn->errorMessage.len - 1];
1950 
1951  if (svLast == '\n')
1952  conn->errorMessage.data[conn->errorMessage.len - 1] = '\0';
1954  conn->errorMessage.data[conn->errorMessage.len - 1] = svLast;
1955  }
1956 
1957  PQclear(result);
1958 
1959  return 1;
1960 }
void pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt,...)
Definition: fe-exec.c:935
int PQisBusy(PGconn *conn)
Definition: fe-exec.c:2071
PGresult * PQgetResult(PGconn *conn)
Definition: fe-exec.c:2102
int pqFlush(PGconn *conn)
Definition: fe-misc.c:958
int pqPutMsgStart(char msg_type, PGconn *conn)
Definition: fe-misc.c:461
int pqPutMsgEnd(PGconn *conn)
Definition: fe-misc.c:520
@ PGRES_COMMAND_OK
Definition: libpq-fe.h:97
#define pqIsnonblocking(conn)
Definition: libpq-int.h:869
PGQueryClass queryclass
Definition: libpq-int.h:324
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:413
PGNoticeHooks noticeHooks
Definition: libpq-int.h:404

References appendPQExpBufferStr(), pg_conn::asyncStatus, pg_conn::cmd_queue_head, conn, PQExpBufferData::data, pg_conn::errorMessage, PQExpBufferData::len, libpq_gettext, 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, pqPutMsgEnd(), pqPutMsgStart(), PGcmdQueueEntry::queryclass, and pg_result::resultStatus.

Referenced by PQendcopy().

◆ pqFlush()

int pqFlush ( PGconn conn)

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

959 {
960  if (conn->outCount > 0)
961  {
962  if (conn->Pfdebug)
963  fflush(conn->Pfdebug);
964 
965  return pqSendSome(conn, conn->outCount);
966  }
967 
968  return 0;
969 }
static int pqSendSome(PGconn *conn, int len)
Definition: fe-misc.c:789
static void const char fflush(stdout)
FILE * Pfdebug
Definition: libpq-int.h:400

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(), 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 1969 of file fe-protocol3.c.

1973 {
1974  bool needInput = false;
1976  char id;
1977  int msgLength;
1978  int avail;
1979  int i;
1980 
1981  /* already validated by PQfn */
1983 
1984  /* PQfn already validated connection state */
1985 
1986  if (pqPutMsgStart('F', conn) < 0 || /* function call msg */
1987  pqPutInt(fnid, 4, conn) < 0 || /* function id */
1988  pqPutInt(1, 2, conn) < 0 || /* # of format codes */
1989  pqPutInt(1, 2, conn) < 0 || /* format code: BINARY */
1990  pqPutInt(nargs, 2, conn) < 0) /* # of args */
1991  {
1992  /* error message should be set up already */
1993  return NULL;
1994  }
1995 
1996  for (i = 0; i < nargs; ++i)
1997  { /* len.int4 + contents */
1998  if (pqPutInt(args[i].len, 4, conn))
1999  return NULL;
2000  if (args[i].len == -1)
2001  continue; /* it's NULL */
2002 
2003  if (args[i].isint)
2004  {
2005  if (pqPutInt(args[i].u.integer, args[i].len, conn))
2006  return NULL;
2007  }
2008  else
2009  {
2010  if (pqPutnchar((char *) args[i].u.ptr, args[i].len, conn))
2011  return NULL;
2012  }
2013  }
2014 
2015  if (pqPutInt(1, 2, conn) < 0) /* result format code: BINARY */
2016  return NULL;
2017 
2018  if (pqPutMsgEnd(conn) < 0 ||
2019  pqFlush(conn))
2020  return NULL;
2021 
2022  for (;;)
2023  {
2024  if (needInput)
2025  {
2026  /* Wait for some data to arrive (or for the channel to close) */
2027  if (pqWait(true, false, conn) ||
2028  pqReadData(conn) < 0)
2029  break;
2030  }
2031 
2032  /*
2033  * Scan the message. If we run out of data, loop around to try again.
2034  */
2035  needInput = true;
2036 
2037  conn->inCursor = conn->inStart;
2038  if (pqGetc(&id, conn))
2039  continue;
2040  if (pqGetInt(&msgLength, 4, conn))
2041  continue;
2042 
2043  /*
2044  * Try to validate message type/length here. A length less than 4 is
2045  * definitely broken. Large lengths should only be believed for a few
2046  * message types.
2047  */
2048  if (msgLength < 4)
2049  {
2050  handleSyncLoss(conn, id, msgLength);
2051  break;
2052  }
2053  if (msgLength > 30000 && !VALID_LONG_MESSAGE_TYPE(id))
2054  {
2055  handleSyncLoss(conn, id, msgLength);
2056  break;
2057  }
2058 
2059  /*
2060  * Can't process if message body isn't all here yet.
2061  */
2062  msgLength -= 4;
2063  avail = conn->inEnd - conn->inCursor;
2064  if (avail < msgLength)
2065  {
2066  /*
2067  * Before looping, enlarge the input buffer if needed to hold the
2068  * whole message. See notes in parseInput.
2069  */
2070  if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength,
2071  conn))
2072  {
2073  /*
2074  * XXX add some better recovery code... plan is to skip over
2075  * the message using its length, then report an error. For the
2076  * moment, just treat this like loss of sync (which indeed it
2077  * might be!)
2078  */
2079  handleSyncLoss(conn, id, msgLength);
2080  break;
2081  }
2082  continue;
2083  }
2084 
2085  /*
2086  * We should see V or E response to the command, but might get N
2087  * and/or A notices first. We also need to swallow the final Z before
2088  * returning.
2089  */
2090  switch (id)
2091  {
2092  case 'V': /* function result */
2093  if (pqGetInt(actual_result_len, 4, conn))
2094  continue;
2095  if (*actual_result_len != -1)
2096  {
2097  if (result_is_int)
2098  {
2099  if (pqGetInt(result_buf, *actual_result_len, conn))
2100  continue;
2101  }
2102  else
2103  {
2104  if (pqGetnchar((char *) result_buf,
2105  *actual_result_len,
2106  conn))
2107  continue;
2108  }
2109  }
2110  /* correctly finished function result message */
2112  break;
2113  case 'E': /* error return */
2114  if (pqGetErrorNotice3(conn, true))
2115  continue;
2117  break;
2118  case 'A': /* notify message */
2119  /* handle notify and go back to processing return values */
2120  if (getNotify(conn))
2121  continue;
2122  break;
2123  case 'N': /* notice */
2124  /* handle notice and go back to processing return values */
2125  if (pqGetErrorNotice3(conn, false))
2126  continue;
2127  break;
2128  case 'Z': /* backend is ready for new query */
2129  if (getReadyForQuery(conn))
2130  continue;
2131  /* consume the message and exit */
2132  conn->inStart += 5 + msgLength;
2133 
2134  /*
2135  * If we already have a result object (probably an error), use
2136  * that. Otherwise, if we saw a function result message,
2137  * report COMMAND_OK. Otherwise, the backend violated the
2138  * protocol, so complain.
2139  */
2140  if (!pgHavePendingResult(conn))
2141  {
2142  if (status == PGRES_COMMAND_OK)
2143  {
2145  if (!conn->result)
2146  {
2148  libpq_gettext("out of memory\n"));
2150  }
2151  }
2152  else
2153  {
2155  libpq_gettext("protocol error: no function result\n"));
2157  }
2158  }
2159  return pqPrepareAsyncResult(conn);
2160  case 'S': /* parameter status */
2161  if (getParameterStatus(conn))
2162  continue;
2163  break;
2164  default:
2165  /* The backend violates the protocol. */
2167  libpq_gettext("protocol error: id=0x%x\n"),
2168  id);
2170  /* trust the specified message length as what to skip */
2171  conn->inStart += 5 + msgLength;
2172  return pqPrepareAsyncResult(conn);
2173  }
2174 
2175  /* trace server-to-client message */
2176  if (conn->Pfdebug)
2178 
2179  /* Completed this message, keep going */
2180  /* trust the specified message length as what to skip */
2181  conn->inStart += 5 + msgLength;
2182  needInput = false;
2183  }
2184 
2185  /*
2186  * We fall out of the loop only upon failing to read data.
2187  * conn->errorMessage has been set by pqWait or pqReadData. We want to
2188  * append it to any already-received error message.
2189  */
2191  return pqPrepareAsyncResult(conn);
2192 }
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:847
int pqReadData(PGconn *conn)
Definition: fe-misc.c:568
int pqPutInt(int value, size_t bytes, PGconn *conn)
Definition: fe-misc.c:256
int pqGetc(char *result, PGconn *conn)
Definition: fe-misc.c:80
int pqGetInt(int *result, size_t bytes, PGconn *conn)
Definition: fe-misc.c:219
int pqGetnchar(char *s, size_t len, PGconn *conn)
Definition: fe-misc.c:168
int pqWait(int forRead, int forWrite, PGconn *conn)
Definition: fe-misc.c:983
int pqCheckInBufferSpace(size_t bytes_needed, PGconn *conn)
Definition: fe-misc.c:354
int pqPutnchar(const char *s, size_t len, PGconn *conn)
Definition: fe-misc.c:205
static int getNotify(PGconn *conn)
static int getParameterStatus(PGconn *conn)
#define VALID_LONG_MESSAGE_TYPE(id)
Definition: fe-protocol3.c:38
static void handleSyncLoss(PGconn *conn, char id, int msgLength)
Definition: fe-protocol3.c:494
static int getReadyForQuery(PGconn *conn)
int pqGetErrorNotice3(PGconn *conn, bool isError)
Definition: fe-protocol3.c:894
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:862
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:229
PGpipelineStatus pipelineStatus
Definition: libpq-int.h:419

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

Referenced by PQfn().

◆ pqGetc()

int pqGetc ( char *  result,
PGconn conn 
)

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

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

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 1708 of file fe-protocol3.c.

1709 {
1710  int msgLength;
1711 
1712  for (;;)
1713  {
1714  /*
1715  * Collect the next input message. To make life simpler for async
1716  * callers, we keep returning 0 until the next message is fully
1717  * available, even if it is not Copy Data.
1718  */
1719  msgLength = getCopyDataMessage(conn);
1720  if (msgLength < 0)
1721  return msgLength; /* end-of-copy or error */
1722  if (msgLength == 0)
1723  {
1724  /* Don't block if async read requested */
1725  if (async)
1726  return 0;
1727  /* Need to load more data */
1728  if (pqWait(true, false, conn) ||
1729  pqReadData(conn) < 0)
1730  return -2;
1731  continue;
1732  }
1733 
1734  /*
1735  * Drop zero-length messages (shouldn't happen anyway). Otherwise
1736  * pass the data back to the caller.
1737  */
1738  msgLength -= 4;
1739  if (msgLength > 0)
1740  {
1741  *buffer = (char *) malloc(msgLength + 1);
1742  if (*buffer == NULL)
1743  {
1745  libpq_gettext("out of memory\n"));
1746  return -2;
1747  }
1748  memcpy(*buffer, &conn->inBuffer[conn->inCursor], msgLength);
1749  (*buffer)[msgLength] = '\0'; /* Add terminating null */
1750 
1751  /* Mark message consumed */
1752  conn->inStart = conn->inCursor + msgLength;
1753 
1754  return msgLength;
1755  }
1756 
1757  /* Empty, so drop it and loop around for another */
1758  conn->inStart = conn->inCursor;
1759  }
1760 }
static int getCopyDataMessage(PGconn *conn)

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

Referenced by PQgetCopyData().

◆ pqGetErrorNotice3()

int pqGetErrorNotice3 ( PGconn conn,
bool  isError 
)

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

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

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_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 7333 of file fe-connect.c.

7334 {
7335 #ifndef WIN32
7336  const char *home;
7337 
7338  home = getenv("HOME");
7339  if (home == NULL || home[0] == '\0')
7340  return pg_get_user_home_dir(geteuid(), buf, bufsize);
7341  strlcpy(buf, home, bufsize);
7342  return true;
7343 #else
7344  char tmppath[MAX_PATH];
7345 
7346  ZeroMemory(tmppath, sizeof(tmppath));
7347  if (SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, tmppath) != S_OK)
7348  return false;
7349  snprintf(buf, bufsize, "%s/postgresql", tmppath);
7350  return true;
7351 #endif
7352 }
static char * buf
Definition: pg_test_fsync.c:67
bool pg_get_user_home_dir(uid_t user_id, char *buffer, size_t buflen)
Definition: thread.c:121
#define snprintf
Definition: port.h:225

References buf, 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 219 of file fe-misc.c.

220 {
221  uint16 tmp2;
222  uint32 tmp4;
223 
224  switch (bytes)
225  {
226  case 2:
227  if (conn->inCursor + 2 > conn->inEnd)
228  return EOF;
229  memcpy(&tmp2, conn->inBuffer + conn->inCursor, 2);
230  conn->inCursor += 2;
231  *result = (int) pg_ntoh16(tmp2);
232  break;
233  case 4:
234  if (conn->inCursor + 4 > conn->inEnd)
235  return EOF;
236  memcpy(&tmp4, conn->inBuffer + conn->inCursor, 4);
237  conn->inCursor += 4;
238  *result = (int) pg_ntoh32(tmp4);
239  break;
240  default:
242  "integer of size %lu not supported by pqGetInt",
243  (unsigned long) bytes);
244  return EOF;
245  }
246 
247  return 0;
248 }
unsigned short uint16
Definition: c.h:451
unsigned int uint32
Definition: c.h:452
#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(), and pqParseInput3().

◆ pqGetline3()

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

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

1769 {
1770  int status;
1771 
1772  if (conn->sock == PGINVALID_SOCKET ||
1776  {
1778  libpq_gettext("PQgetline: not doing text COPY OUT\n"));
1779  *s = '\0';
1780  return EOF;
1781  }
1782 
1783  while ((status = PQgetlineAsync(conn, s, maxlen - 1)) == 0)
1784  {
1785  /* need to load more data */
1786  if (pqWait(true, false, conn) ||
1787  pqReadData(conn) < 0)
1788  {
1789  *s = '\0';
1790  return EOF;
1791  }
1792  }
1793 
1794  if (status < 0)
1795  {
1796  /* End of copy detected; gin up old-style terminator */
1797  strcpy(s, "\\.");
1798  return 0;
1799  }
1800 
1801  /* Add null terminator, and strip trailing \n if present */
1802  if (s[status - 1] == '\n')
1803  {
1804  s[status - 1] = '\0';
1805  return 0;
1806  }
1807  else
1808  {
1809  s[status] = '\0';
1810  return 1;
1811  }
1812 }
int PQgetlineAsync(PGconn *conn, char *buffer, int bufsize)
Definition: fe-exec.c:2877
char copy_is_binary
Definition: libpq-int.h:421

References appendPQExpBufferStr(), pg_conn::asyncStatus, conn, pg_conn::copy_is_binary, pg_conn::errorMessage, libpq_gettext, PGASYNC_COPY_BOTH, PGASYNC_COPY_OUT, PGINVALID_SOCKET, PQgetlineAsync(), pqReadData(), pqWait(), pg_conn::sock, and status().

Referenced by PQgetline().

◆ pqGetlineAsync3()

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

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

1821 {
1822  int msgLength;
1823  int avail;
1824 
1827  return -1; /* we are not doing a copy... */
1828 
1829  /*
1830  * Recognize the next input message. To make life simpler for async
1831  * callers, we keep returning 0 until the next message is fully available
1832  * even if it is not Copy Data. This should keep PQendcopy from blocking.
1833  * (Note: unlike pqGetCopyData3, we do not change asyncStatus here.)
1834  */
1835  msgLength = getCopyDataMessage(conn);
1836  if (msgLength < 0)
1837  return -1; /* end-of-copy or error */
1838  if (msgLength == 0)
1839  return 0; /* no data yet */
1840 
1841  /*
1842  * Move data from libpq's buffer to the caller's. In the case where a
1843  * prior call found the caller's buffer too small, we use
1844  * conn->copy_already_done to remember how much of the row was already
1845  * returned to the caller.
1846  */
1848  avail = msgLength - 4 - conn->copy_already_done;
1849  if (avail <= bufsize)
1850  {
1851  /* Able to consume the whole message */
1852  memcpy(buffer, &conn->inBuffer[conn->inCursor], avail);
1853  /* Mark message consumed */
1854  conn->inStart = conn->inCursor + avail;
1855  /* Reset state for next time */
1856  conn->copy_already_done = 0;
1857  return avail;
1858  }
1859  else
1860  {
1861  /* We must return a partial message */
1862  memcpy(buffer, &conn->inBuffer[conn->inCursor], bufsize);
1863  /* The message is NOT consumed from libpq's buffer */
1864  conn->copy_already_done += bufsize;
1865  return bufsize;
1866  }
1867 }
int copy_already_done
Definition: libpq-int.h:422

References pg_conn::asyncStatus, 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 168 of file fe-misc.c.

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

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

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

◆ pqGets()

int pqGets ( PQExpBuffer  buf,
PGconn conn 
)

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

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

References buf, conn, and pqGets_internal().

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

◆ pqGets_append()

int pqGets_append ( PQExpBuffer  buf,
PGconn conn 
)

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

146 {
147  return pqGets_internal(buf, conn, false);
148 }

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 4673 of file fe-connect.c.

4675 {
4676  /* Start the message. */
4677  if (pqPutMsgStart(pack_type, conn))
4678  return STATUS_ERROR;
4679 
4680  /* Send the message body. */
4681  if (pqPutnchar(buf, buf_len, conn))
4682  return STATUS_ERROR;
4683 
4684  /* Finish the message. */
4685  if (pqPutMsgEnd(conn))
4686  return STATUS_ERROR;
4687 
4688  /* Flush to ensure backend gets it. */
4689  if (pqFlush(conn))
4690  return STATUS_ERROR;
4691 
4692  return STATUS_OK;
4693 }
#define STATUS_OK
Definition: c.h:1178
#define STATUS_ERROR
Definition: c.h:1179

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 63 of file fe-protocol3.c.

64 {
65  char id;
66  int msgLength;
67  int avail;
68 
69  /*
70  * Loop to parse successive complete messages available in the buffer.
71  */
72  for (;;)
73  {
74  /*
75  * Try to read a message. First get the type code and length. Return
76  * if not enough data.
77  */
79  if (pqGetc(&id, conn))
80  return;
81  if (pqGetInt(&msgLength, 4, conn))
82  return;
83 
84  /*
85  * Try to validate message type/length here. A length less than 4 is
86  * definitely broken. Large lengths should only be believed for a few
87  * message types.
88  */
89  if (msgLength < 4)
90  {
91  handleSyncLoss(conn, id, msgLength);
92  return;
93  }
94  if (msgLength > 30000 && !VALID_LONG_MESSAGE_TYPE(id))
95  {
96  handleSyncLoss(conn, id, msgLength);
97  return;
98  }
99 
100  /*
101  * Can't process if message body isn't all here yet.
102  */
103  msgLength -= 4;
104  avail = conn->inEnd - conn->inCursor;
105  if (avail < msgLength)
106  {
107  /*
108  * Before returning, enlarge the input buffer if needed to hold
109  * the whole message. This is better than leaving it to
110  * pqReadData because we can avoid multiple cycles of realloc()
111  * when the message is large; also, we can implement a reasonable
112  * recovery strategy if we are unable to make the buffer big
113  * enough.
114  */
115  if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength,
116  conn))
117  {
118  /*
119  * XXX add some better recovery code... plan is to skip over
120  * the message using its length, then report an error. For the
121  * moment, just treat this like loss of sync (which indeed it
122  * might be!)
123  */
124  handleSyncLoss(conn, id, msgLength);
125  }
126  return;
127  }
128 
129  /*
130  * NOTIFY and NOTICE messages can happen in any state; always process
131  * them right away.
132  *
133  * Most other messages should only be processed while in BUSY state.
134  * (In particular, in READY state we hold off further parsing until
135  * the application collects the current PGresult.)
136  *
137  * However, if the state is IDLE then we got trouble; we need to deal
138  * with the unexpected message somehow.
139  *
140  * ParameterStatus ('S') messages are a special case: in IDLE state we
141  * must process 'em (this case could happen if a new value was adopted
142  * from config file due to SIGHUP), but otherwise we hold off until
143  * BUSY state.
144  */
145  if (id == 'A')
146  {
147  if (getNotify(conn))
148  return;
149  }
150  else if (id == 'N')
151  {
152  if (pqGetErrorNotice3(conn, false))
153  return;
154  }
155  else if (conn->asyncStatus != PGASYNC_BUSY)
156  {
157  /* If not IDLE state, just wait ... */
158  if (conn->asyncStatus != PGASYNC_IDLE)
159  return;
160 
161  /*
162  * Unexpected message in IDLE state; need to recover somehow.
163  * ERROR messages are handled using the notice processor;
164  * ParameterStatus is handled normally; anything else is just
165  * dropped on the floor after displaying a suitable warning
166  * notice. (An ERROR is very possibly the backend telling us why
167  * it is about to close the connection, so we don't want to just
168  * discard it...)
169  */
170  if (id == 'E')
171  {
172  if (pqGetErrorNotice3(conn, false /* treat as notice */ ))
173  return;
174  }
175  else if (id == 'S')
176  {
178  return;
179  }
180  else
181  {
182  /* Any other case is unexpected and we summarily skip it */
184  "message type 0x%02x arrived from server while idle",
185  id);
186  /* Discard the unexpected message */
187  conn->inCursor += msgLength;
188  }
189  }
190  else
191  {
192  /*
193  * In BUSY state, we can process everything.
194  */
195  switch (id)
196  {
197  case 'C': /* command complete */
198  if (pqGets(&conn->workBuffer, conn))
199  return;
201  {
204  if (!conn->result)
205  {
207  libpq_gettext("out of memory"));
209  }
210  }
211  if (conn->result)
213  CMDSTATUS_LEN);
215  break;
216  case 'E': /* error return */
217  if (pqGetErrorNotice3(conn, true))
218  return;
220  break;
221  case 'Z': /* sync response, backend is ready for new
222  * query */
223  if (getReadyForQuery(conn))
224  return;
226  {
229  if (!conn->result)
230  {
232  libpq_gettext("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;
253  case 'I': /* empty query */
255  {
258  if (!conn->result)
259  {
261  libpq_gettext("out of memory"));
263  }
264  }
266  break;
267  case '1': /* Parse Complete */
268  /* If we're doing PQprepare, we're done; else ignore */
269  if (conn->cmd_queue_head &&
271  {
273  {
276  if (!conn->result)
277  {
279  libpq_gettext("out of memory"));
281  }
282  }
284  }
285  break;
286  case '2': /* Bind Complete */
287  /* Nothing to do for this message type */
288  break;
289  case '3': /* Close Complete */
290  /*
291  * If we get CloseComplete when waiting for it, consume
292  * the queue element and keep going. A result is not
293  * expected from this message; it is just there so that
294  * we know to wait for it when PQsendQuery is used in
295  * pipeline mode, before going in IDLE state. Failing to
296  * do this makes us receive CloseComplete when IDLE, which
297  * creates problems.
298  */
299  if (conn->cmd_queue_head &&
301  {
303  }
304 
305  break;
306  case 'S': /* parameter status */
308  return;
309  break;
310  case 'K': /* secret key data from the backend */
311 
312  /*
313  * This is expected only during backend startup, but it's
314  * just as easy to handle it as part of the main loop.
315  * Save the data and continue processing.
316  */
317  if (pqGetInt(&(conn->be_pid), 4, conn))
318  return;
319  if (pqGetInt(&(conn->be_key), 4, conn))
320  return;
321  break;
322  case 'T': /* Row Description */
323  if (conn->error_result ||
324  (conn->result != NULL &&
326  {
327  /*
328  * We've already choked for some reason. Just discard
329  * the data till we get to the end of the query.
330  */
331  conn->inCursor += msgLength;
332  }
333  else if (conn->result == NULL ||
334  (conn->cmd_queue_head &&
336  {
337  /* First 'T' in a query sequence */
338  if (getRowDescriptions(conn, msgLength))
339  return;
340  }
341  else
342  {
343  /*
344  * A new 'T' message is treated as the start of
345  * another PGresult. (It is not clear that this is
346  * really possible with the current backend.) We stop
347  * parsing until the application accepts the current
348  * result.
349  */
351  return;
352  }
353  break;
354  case 'n': /* No Data */
355 
356  /*
357  * NoData indicates that we will not be seeing a
358  * RowDescription message because the statement or portal
359  * inquired about doesn't return rows.
360  *
361  * If we're doing a Describe, we have to pass something
362  * back to the client, so set up a COMMAND_OK result,
363  * instead of PGRES_TUPLES_OK. Otherwise we can just
364  * ignore this message.
365  */
366  if (conn->cmd_queue_head &&
368  {
370  {
373  if (!conn->result)
374  {
376  libpq_gettext("out of memory"));
378  }
379  }
381  }
382  break;
383  case 't': /* Parameter Description */
384  if (getParamDescriptions(conn, msgLength))
385  return;
386  break;
387  case 'D': /* Data Row */
388  if (conn->result != NULL &&
390  {
391  /* Read another tuple of a normal query response */
392  if (getAnotherTuple(conn, msgLength))
393  return;
394  }
395  else if (conn->error_result ||
396  (conn->result != NULL &&
398  {
399  /*
400  * We've already choked for some reason. Just discard
401  * tuples till we get to the end of the query.
402  */
403  conn->inCursor += msgLength;
404  }
405  else
406  {
407  /* Set up to report error at end of query */
409  libpq_gettext("server sent data (\"D\" message) without prior row description (\"T\" message)\n"));
411  /* Discard the unexpected message */
412  conn->inCursor += msgLength;
413  }
414  break;
415  case 'G': /* Start Copy In */
417  return;
419  break;
420  case 'H': /* Start Copy Out */
422  return;
424  conn->copy_already_done = 0;
425  break;
426  case 'W': /* Start Copy Both */
428  return;
430  conn->copy_already_done = 0;
431  break;
432  case 'd': /* Copy Data */
433 
434  /*
435  * If we see Copy Data, just silently drop it. This would
436  * only occur if application exits COPY OUT mode too
437  * early.
438  */
439  conn->inCursor += msgLength;
440  break;
441  case 'c': /* Copy Done */
442 
443  /*
444  * If we see Copy Done, just silently drop it. This is
445  * the normal case during PQendcopy. We will keep
446  * swallowing data, expecting to see command-complete for
447  * the COPY command.
448  */
449  break;
450  default:
452  libpq_gettext("unexpected response from server; first received character was \"%c\"\n"),
453  id);
454  /* build an error result holding the error message */
456  /* not sure if we will see more, so go to ready state */
458  /* Discard the unexpected message */
459  conn->inCursor += msgLength;
460  break;
461  } /* switch on protocol character */
462  }
463  /* Successfully consumed this message */
464  if (conn->inCursor == conn->inStart + 5 + msgLength)
465  {
466  /* trace server-to-client message */
467  if (conn->Pfdebug)
469 
470  /* Normal case: parsing agrees with specified length */
472  }
473  else
474  {
475  /* Trouble --- report it */
477  libpq_gettext("message contents do not agree with length in message type \"%c\"\n"),
478  id);
479  /* build an error result holding the error message */
482  /* trust the specified message length as what to skip */
483  conn->inStart += 5 + msgLength;
484  }
485  }
486 }
void pqCommandQueueAdvance(PGconn *conn)
Definition: fe-exec.c:3112
static int getAnotherTuple(PGconn *conn, int msgLength)
Definition: fe-protocol3.c:774
static int getRowDescriptions(PGconn *conn, int msgLength)
Definition: fe-protocol3.c:515
static int getCopyStart(PGconn *conn, ExecStatusType copytype)
static int getParamDescriptions(PGconn *conn, int msgLength)
Definition: fe-protocol3.c:686
@ 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:87
int be_pid
Definition: libpq-int.h:469
int be_key
Definition: libpq-int.h:470
PQExpBufferData workBuffer
Definition: libpq-int.h:591
char cmdStatus[CMDSTATUS_LEN]
Definition: libpq-int.h:179

References appendPQExpBuffer(), appendPQExpBufferStr(), 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, pg_conn::errorMessage, getAnotherTuple(), getCopyStart(), getNotify(), getParamDescriptions(), getParameterStatus(), getReadyForQuery(), getRowDescriptions(), handleSyncLoss(), pg_conn::inBuffer, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, libpq_gettext, 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(), 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 847 of file fe-exec.c.

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

References appendPQExpBufferStr(), conn, pg_conn::error_result, pg_conn::errorMessage, pg_conn::errorReported, PQExpBufferData::len, libpq_gettext, 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 95 of file fe-misc.c.

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

References conn, and pqPutMsgBytes().

Referenced by PQsendDescribe(), PQsendQueryGuts(), and PQsendQueryInternal().

◆ pqPutInt()

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

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

257 {
258  uint16 tmp2;
259  uint32 tmp4;
260 
261  switch (bytes)
262  {
263  case 2:
264  tmp2 = pg_hton16((uint16) value);
265  if (pqPutMsgBytes((const char *) &tmp2, 2, conn))
266  return EOF;
267  break;
268  case 4:
269  tmp4 = pg_hton32((uint32) value);
270  if (pqPutMsgBytes((const char *) &tmp4, 4, conn))
271  return EOF;
272  break;
273  default:
275  "integer of size %lu not supported by pqPutInt",
276  (unsigned long) bytes);
277  return EOF;
278  }
279 
280  return 0;
281 }
static struct @151 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(), PQsendQueryGuts(), and PQsendQueryInternal().

◆ pqPutMsgEnd()

int pqPutMsgEnd ( PGconn conn)

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

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

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(), PQsendDescribe(), PQsendFlushRequest(), PQsendPrepare(), PQsendQueryGuts(), PQsendQueryInternal(), and sendTerminateConn().

◆ pqPutMsgStart()

int pqPutMsgStart ( char  msg_type,
PGconn conn 
)

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

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

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(), PQsendDescribe(), PQsendFlushRequest(), PQsendPrepare(), PQsendQueryGuts(), PQsendQueryInternal(), and sendTerminateConn().

◆ pqPutnchar()

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

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

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

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 155 of file fe-misc.c.

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

References conn, and pqPutMsgBytes().

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

◆ pqReadData()

int pqReadData ( PGconn conn)

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

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

References ALL_CONNECTION_FAILURE_ERRNOS, appendPQExpBufferStr(), conn, CONNECTION_BAD, EAGAIN, EINTR, pg_conn::errorMessage, EWOULDBLOCK, pg_conn::inBuffer, pg_conn::inBufSize, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, libpq_gettext, 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 1020 of file fe-misc.c.

1021 {
1022  return pqSocketCheck(conn, 1, 0, (time_t) 0);
1023 }
static int pqSocketCheck(PGconn *conn, int forRead, int forWrite, time_t end_time)
Definition: fe-misc.c:1044

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:102
size_t memorySize
Definition: libpq-int.h:213
int curOffset
Definition: libpq-int.h:210
char null_field[1]
Definition: libpq-int.h:202
int spaceLeft
Definition: libpq-int.h:211
PGresult_data * curBlock
Definition: libpq-int.h:209
PGresult_data * next
Definition: libpq-int.h:106
char space[1]
Definition: libpq-int.h:107

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 1204 of file fe-exec.c.

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

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 1057 of file fe-exec.c.

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

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

Referenced by pqGetErrorNotice3(), and pqInternalNotice().

◆ pqSaveParameterStatus()

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

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

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

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, 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 191 of file fe-secure.c.

192 {
193 #ifdef USE_SSL
194  pgtls_close(conn);
195 #endif
196 }

References conn, and pgtls_close().

Referenced by pqDropConnection().

◆ pqsecure_initialize()

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

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

163 {
164  int r = 0;
165 
166 #ifdef USE_SSL
167  r = pgtls_init(conn, do_ssl, do_crypto);
168 #endif
169 
170  return r;
171 }
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 177 of file fe-secure.c.

178 {
179 #ifdef USE_SSL
180  return pgtls_open_client(conn);
181 #else
182  /* shouldn't get here */
183  return PGRES_POLLING_FAILED;
184 #endif
185 }
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 232 of file fe-secure.c.

233 {
234  ssize_t n;
235  int result_errno = 0;
236  char sebuf[PG_STRERROR_R_BUFLEN];
237 
238  n = recv(conn->sock, ptr, len, 0);
239 
240  if (n < 0)
241  {
242  result_errno = SOCK_ERRNO;
243 
244  /* Set error message if appropriate */
245  switch (result_errno)
246  {
247 #ifdef EAGAIN
248  case EAGAIN:
249 #endif
250 #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
251  case EWOULDBLOCK:
252 #endif
253  case EINTR:
254  /* no error message, caller is expected to retry */
255  break;
256 
257  case EPIPE:
258  case ECONNRESET:
260  libpq_gettext("server closed the connection unexpectedly\n"
261  "\tThis probably means the server terminated abnormally\n"
262  "\tbefore or while processing the request.\n"));
263  break;
264 
265  default:
267  libpq_gettext("could not receive data from server: %s\n"),
268  SOCK_STRERROR(result_errno,
269  sebuf, sizeof(sebuf)));
270  break;
271  }
272  }
273 
274  /* ensure we return the intended errno to caller */
275  SOCK_ERRNO_SET(result_errno);
276 
277  return n;
278 }
#define recv(s, buf, len, flags)
Definition: win32_port.h:475

References appendPQExpBuffer(), appendPQExpBufferStr(), conn, EAGAIN, ECONNRESET, EINTR, pg_conn::errorMessage, EWOULDBLOCK, len, libpq_gettext, 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 350 of file fe-secure.c.

351 {
352  ssize_t n;
353  int flags = 0;
354  int result_errno = 0;
355  char msgbuf[1024];
356  char sebuf[PG_STRERROR_R_BUFLEN];
357 
358  DECLARE_SIGPIPE_INFO(spinfo);
359 
360  /*
361  * If we already had a write failure, we will never again try to send data
362  * on that connection. Even if the kernel would let us, we've probably
363  * lost message boundary sync with the server. conn->write_failed
364  * therefore persists until the connection is reset, and we just discard
365  * all data presented to be written.
366  */
367  if (conn->write_failed)
368  return len;
369 
370 #ifdef MSG_NOSIGNAL
371  if (conn->sigpipe_flag)
372  flags |= MSG_NOSIGNAL;
373 
374 retry_masked:
375 #endif /* MSG_NOSIGNAL */
376 
377  DISABLE_SIGPIPE(conn, spinfo, return -1);
378 
379  n = send(conn->sock, ptr, len, flags);
380 
381  if (n < 0)
382  {
383  result_errno = SOCK_ERRNO;
384 
385  /*
386  * If we see an EINVAL, it may be because MSG_NOSIGNAL isn't available
387  * on this machine. So, clear sigpipe_flag so we don't try the flag
388  * again, and retry the send().
389  */
390 #ifdef MSG_NOSIGNAL
391  if (flags != 0 && result_errno == EINVAL)
392  {
393  conn->sigpipe_flag = false;
394  flags = 0;
395  goto retry_masked;
396  }
397 #endif /* MSG_NOSIGNAL */
398 
399  /* Set error message if appropriate */
400  switch (result_errno)
401  {
402 #ifdef EAGAIN
403  case EAGAIN:
404 #endif
405 #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
406  case EWOULDBLOCK:
407 #endif
408  case EINTR:
409  /* no error message, caller is expected to retry */
410  break;
411 
412  case EPIPE:
413  /* Set flag for EPIPE */
414  REMEMBER_EPIPE(spinfo, true);
415 
416  /* FALL THRU */
417 
418  case ECONNRESET:
419  conn->write_failed = true;
420  /* Store error message in conn->write_err_msg, if possible */
421  /* (strdup failure is OK, we'll cope later) */
422  snprintf(msgbuf, sizeof(msgbuf),
423  libpq_gettext("server closed the connection unexpectedly\n"
424  "\tThis probably means the server terminated abnormally\n"
425  "\tbefore or while processing the request.\n"));
426  conn->write_err_msg = strdup(msgbuf);
427  /* Now claim the write succeeded */
428  n = len;
429  break;
430 
431  default:
432  conn->write_failed = true;
433  /* Store error message in conn->write_err_msg, if possible */
434  /* (strdup failure is OK, we'll cope later) */
435  snprintf(msgbuf, sizeof(msgbuf),
436  libpq_gettext("could not send data to server: %s\n"),
437  SOCK_STRERROR(result_errno,
438  sebuf, sizeof(sebuf)));
439  conn->write_err_msg = strdup(msgbuf);
440  /* Now claim the write succeeded */
441  n = len;
442  break;
443  }
444  }
445 
446  RESTORE_SIGPIPE(conn, spinfo);
447 
448  /* ensure we return the intended errno to caller */
449  SOCK_ERRNO_SET(result_errno);
450 
451  return n;
452 }
#define REMEMBER_EPIPE(spinfo, cond)
Definition: fe-secure.c:105
#define DISABLE_SIGPIPE(conn, spinfo, failaction)
Definition: fe-secure.c:99
#define DECLARE_SIGPIPE_INFO(spinfo)
Definition: fe-secure.c:97
#define RESTORE_SIGPIPE(conn, spinfo)
Definition: fe-secure.c:107
char * write_err_msg
Definition: libpq-int.h:457
bool sigpipe_flag
Definition: libpq-int.h:455
bool write_failed
Definition: libpq-int.h:456
#define send(s, buf, len, flags)
Definition: win32_port.h:476

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, 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 206 of file fe-secure.c.

207 {
208  ssize_t n;
209 
210 #ifdef USE_SSL
211  if (conn->ssl_in_use)
212  {
213  n = pgtls_read(conn, ptr, len);
214  }
215  else
216 #endif
217 #ifdef ENABLE_GSS
218  if (conn->gssenc)
219  {
220  n = pg_GSS_read(conn, ptr, len);
221  }
222  else
223 #endif
224  {
225  n = pqsecure_raw_read(conn, ptr, len);
226  }
227 
228  return n;
229 }
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:232

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 301 of file fe-secure.c.

302 {
303  ssize_t n;
304 
305 #ifdef USE_SSL
306  if (conn->ssl_in_use)
307  {
308  n = pgtls_write(conn, ptr, len);
309  }
310  else
311 #endif
312 #ifdef ENABLE_GSS
313  if (conn->gssenc)
314  {
315  n = pg_GSS_write(conn, ptr, len);
316  }
317  else
318 #endif
319  {
320  n = pqsecure_raw_write(conn, ptr, len);
321  }
322 
323  return n;
324 }
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:350

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 1427 of file fe-exec.c.

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

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 190 of file fe-misc.c.

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

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 '1':
566  fprintf(conn->Pfdebug, "ParseComplete");
567  /* No message content */
568  break;
569  case '2':
570  fprintf(conn->Pfdebug, "BindComplete");
571  /* No message content */
572  break;
573  case '3':
574  fprintf(conn->Pfdebug, "CloseComplete");
575  /* No message content */
576  break;
577  case 'A': /* Notification Response */
578  pqTraceOutputA(conn->Pfdebug, message, &logCursor, regress);
579  break;
580  case 'B': /* Bind */
581  pqTraceOutputB(conn->Pfdebug, message, &logCursor);
582  break;
583  case 'c':
584  fprintf(conn->Pfdebug, "CopyDone");
585  /* No message content */
586  break;
587  case 'C': /* Close(F) or Command Complete(B) */
588  pqTraceOutputC(conn->Pfdebug, toServer, message, &logCursor);
589  break;
590  case 'd': /* Copy Data */
591  /* Drop COPY data to reduce the overhead of logging. */
592  break;
593  case 'D': /* Describe(F) or Data Row(B) */
594  pqTraceOutputD(conn->Pfdebug, toServer, message, &logCursor);
595  break;
596  case 'E': /* Execute(F) or Error Response(B) */
597  pqTraceOutputE(conn->Pfdebug, toServer, message, &logCursor,
598  regress);
599  break;
600  case 'f': /* Copy Fail */
601  pqTraceOutputf(conn->Pfdebug, message, &logCursor);
602  break;
603  case 'F': /* Function Call */
604  pqTraceOutputF(conn->Pfdebug, message, &logCursor, regress);
605  break;
606  case 'G': /* Start Copy In */
607  pqTraceOutputG(conn->Pfdebug, message, &logCursor);
608  break;
609  case 'H': /* Flush(F) or Start Copy Out(B) */
610  if (!toServer)
611  pqTraceOutputH(conn->Pfdebug, message, &logCursor);
612  else
613  fprintf(conn->Pfdebug, "Flush"); /* no message content */
614  break;
615  case 'I':
616  fprintf(conn->Pfdebug, "EmptyQueryResponse");
617  /* No message content */
618  break;
619  case 'K': /* secret key data from the backend */
620  pqTraceOutputK(conn->Pfdebug, message, &logCursor, regress);
621  break;
622  case 'n':
623  fprintf(conn->Pfdebug, "NoData");
624  /* No message content */
625  break;
626  case 'N':
627  pqTraceOutputNR(conn->Pfdebug, "NoticeResponse", message,
628  &logCursor, regress);
629  break;
630  case 'P': /* Parse */
631  pqTraceOutputP(conn->Pfdebug, message, &logCursor, regress);
632  break;
633  case 'Q': /* Query */
634  pqTraceOutputQ(conn->Pfdebug, message, &logCursor);
635  break;
636  case 'R': /* Authentication */
637  pqTraceOutputR(conn->Pfdebug, message, &logCursor);
638  break;
639  case 's':
640  fprintf(conn->Pfdebug, "PortalSuspended");
641  /* No message content */
642  break;
643  case 'S': /* Parameter Status(B) or Sync(F) */
644  if (!toServer)
645  pqTraceOutputS(conn->Pfdebug, message, &logCursor);
646  else
647  fprintf(conn->Pfdebug, "Sync"); /* no message content */
648  break;
649  case 't': /* Parameter Description */
650  pqTraceOutputt(conn->Pfdebug, message, &logCursor, regress);
651  break;
652  case 'T': /* Row Description */
653  pqTraceOutputT(conn->Pfdebug, message, &logCursor, regress);
654  break;
655  case 'v': /* Negotiate Protocol Version */
656  pqTraceOutputv(conn->Pfdebug, message, &logCursor);
657  break;
658  case 'V': /* Function Call response */
659  pqTraceOutputV(conn->Pfdebug, message, &logCursor);
660  break;
661  case 'W': /* Start Copy Both */
662  pqTraceOutputW(conn->Pfdebug, message, &logCursor, length);
663  break;
664  case 'X':
665  fprintf(conn->Pfdebug, "Terminate");
666  /* No message content */
667  break;
668  case 'Z': /* Ready For Query */
669  pqTraceOutputZ(conn->Pfdebug, message, &logCursor);
670  break;
671  default:
672  fprintf(conn->Pfdebug, "Unknown message: %02x", id);
673  break;
674  }
675 
676  fputc('\n', conn->Pfdebug);
677 
678  /*
679  * Verify the printing routine did it right. Note that the one-byte
680  * message identifier is not included in the length, but our cursor does
681  * include it.
682  */
683  if (logCursor - 1 != length)
685  "mismatched message length: consumed %d, expected %d\n",
686  logCursor - 1, length);
687 }
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:414
#define PQTRACE_REGRESS_MODE
Definition: libpq-fe.h:416
#define fprintf
Definition: port.h:229
int traceFlags
Definition: libpq-int.h:401

References conn, fprintf, pg_conn::Pfdebug, pg_ntoh32, 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 694 of file fe-trace.c.

695 {
696  int length;
697  int logCursor = 0;
698 
700  {
701  char timestr[128];
702 
703  pqTraceFormatTimestamp(timestr, sizeof(timestr));
704  fprintf(conn->Pfdebug, "%s\t", timestr);
705  }
706 
707  memcpy(&length, message + logCursor, 4);
708  length = (int) pg_ntoh32(length);
709  logCursor += 4;
710 
711  fprintf(conn->Pfdebug, "F\t%d\t", length);
712 
713  switch (length)
714  {
715  case 16: /* CancelRequest */
716  fprintf(conn->Pfdebug, "CancelRequest\t");
717  pqTraceOutputInt32(conn->Pfdebug, message, &logCursor, false);
718  pqTraceOutputInt32(conn->Pfdebug, message, &logCursor, false);
719  pqTraceOutputInt32(conn->Pfdebug, message, &logCursor, false);
720  break;
721  case 8: /* GSSENCRequest or SSLRequest */
722  /* These messages do not reach here. */
723  default:
724  fprintf(conn->Pfdebug, "Unknown message: length is %d", length);
725  break;
726  }
727 
728  fputc('\n', conn->Pfdebug);
729 }
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 983 of file fe-misc.c.

984 {
985  return pqWaitTimed(forRead, forWrite, conn, (time_t) -1);
986 }
int pqWaitTimed(int forRead, int forWrite, PGconn *conn, time_t finish_time)
Definition: fe-misc.c:996

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 996 of file fe-misc.c.

997 {
998  int result;
999 
1000  result = pqSocketCheck(conn, forRead, forWrite, finish_time);
1001 
1002  if (result < 0)
1003  return -1; /* errorMessage is already set */
1004 
1005  if (result == 0)
1006  {
1008  libpq_gettext("timeout expired\n"));
1009  return 1;
1010  }
1011 
1012  return 0;
1013 }

References appendPQExpBufferStr(), conn, pg_conn::errorMessage, libpq_gettext, and pqSocketCheck().

Referenced by connectDBComplete(), and pqWait().

◆ pqWriteReady()

int pqWriteReady ( PGconn conn)

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

1031 {
1032  return pqSocketCheck(conn, 0, 1, (time_t) 0);
1033 }

References conn, and pqSocketCheck().

Variable Documentation

◆ pgresStatus

char* const pgresStatus[]
extern

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

Referenced by PQresStatus().