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 "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  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 pqIsnonblocking(conn)   ((conn)->nonblocking)
 
#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 pg_conn_host pg_conn_host
 

Enumerations

enum  PGAsyncStatusType {
  PGASYNC_IDLE, PGASYNC_BUSY, PGASYNC_READY, PGASYNC_COPY_IN,
  PGASYNC_COPY_OUT, PGASYNC_COPY_BOTH
}
 
enum  PGQueryClass { PGQUERY_SIMPLE, PGQUERY_EXTENDED, PGQUERY_PREPARE, PGQUERY_DESCRIBE }
 
enum  PGSetenvStatusType {
  SETENV_STATE_CLIENT_ENCODING_SEND, SETENV_STATE_CLIENT_ENCODING_WAIT, SETENV_STATE_OPTION_SEND, SETENV_STATE_OPTION_WAIT,
  SETENV_STATE_QUERY1_SEND, SETENV_STATE_QUERY1_WAIT, SETENV_STATE_QUERY2_SEND, SETENV_STATE_QUERY2_WAIT,
  SETENV_STATE_IDLE
}
 
enum  pg_conn_host_type { CHT_HOST_NAME, CHT_HOST_ADDRESS, CHT_UNIX_SOCKET }
 

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, const char *msg)
 
void pqCatenateResultError (PGresult *res, const char *msg)
 
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)
 
PostgresPollingStatusType pqSetenvPoll (PGconn *conn)
 
char * pqBuildStartupPacket2 (PGconn *conn, int *packetlen, const PQEnvironmentOption *options)
 
void pqParseInput2 (PGconn *conn)
 
int pqGetCopyData2 (PGconn *conn, char **buffer, int async)
 
int pqGetline2 (PGconn *conn, char *s, int maxlen)
 
int pqGetlineAsync2 (PGconn *conn, char *buffer, int bufsize)
 
int pqEndcopy2 (PGconn *conn)
 
PGresultpqFunctionCall2 (PGconn *conn, Oid fnid, int *result_buf, int *actual_result_len, int result_is_int, const PQArgBlock *args, int nargs)
 
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, bool force_len, 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 *)
 
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)
 
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)
 

Variables

char *const pgresStatus []
 

Macro Definition Documentation

◆ CMDSTATUS_LEN

#define CMDSTATUS_LEN   64 /* should match COMPLETION_TAG_BUFSIZE */

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

Referenced by pqParseInput2(), and pqParseInput3().

◆ libpq_gettext

#define libpq_gettext (   x)    (x)

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

Referenced by build_client_final_message(), build_client_first_message(), check_expected_areq(), connectFailureMessage(), connectNoDelay(), connectOptions2(), conninfo_add_defaults(), conninfo_array_parse(), conninfo_init(), conninfo_parse(), conninfo_storeval(), conninfo_uri_decode(), conninfo_uri_parse_options(), conninfo_uri_parse_params(), do_field(), do_header(), fillPGconn(), getAnotherTuple(), getParamDescriptions(), getRowDescriptions(), handleSyncLoss(), initialize_SSL(), lo_create(), lo_export(), lo_import_internal(), lo_initialize(), lo_lseek64(), lo_read(), lo_tell64(), lo_truncate(), lo_truncate64(), lo_write(), open_client_SSL(), openssl_verify_peer_name_matches_certificate_name(), parse_int_param(), parseServiceFile(), parseServiceInfo(), passwordFromFile(), pg_fe_getauthname(), pg_fe_scram_exchange(), pg_fe_sendauth(), pg_GSS_load_servicename(), pg_GSS_read(), pg_GSS_write(), pg_local_sendauth(), pg_password_sendauth(), pg_SASL_continue(), pg_SASL_init(), pgpassfileWarning(), pgtls_read(), pgtls_write(), pq_verify_peer_name_matches_certificate(), pq_verify_peer_name_matches_certificate_name(), pqAddTuple(), pqBuildErrorMessage3(), PQconnectPoll(), PQdefaultSSLKeyPassHook_OpenSSL(), PQdisplayTuples(), PQencryptPasswordConn(), pqEndcopy2(), pqEndcopy3(), PQenv2encoding(), PQerrorMessage(), PQescapeByteaInternal(), PQescapeInternal(), PQescapeStringInternal(), PQexecStart(), PQfn(), pqFunctionCall2(), pqFunctionCall3(), PQgetCopyData(), pqGetCopyData2(), pqGetCopyData3(), pqGetErrorNotice2(), pqGetErrorNotice3(), pqGetline3(), PQgetResult(), pqInternalNotice(), pqPacketSend(), pqParseInput2(), pqParseInput3(), PQprint(), PQprintTuples(), PQputCopyData(), PQputCopyEnd(), pqReadData(), PQreset(), PQresetPoll(), PQresStatus(), PQresultVerboseErrorMessage(), pqSaveWriteError(), pqsecure_open_gss(), pqsecure_raw_read(), pqsecure_raw_write(), PQsendDescribe(), PQsendPrepare(), PQsendQuery(), PQsendQueryGuts(), PQsendQueryParams(), PQsendQueryPrepared(), PQsendQueryStart(), pqSendSome(), PQsetdbLogin(), pqSetenvPoll(), PQsetvalue(), pqSocketCheck(), pqWaitTimed(), read_attr_value(), read_server_final_message(), read_server_first_message(), reportErrorPosition(), restoreErrorMessage(), saveErrorMessage(), setKeepalivesCount(), setKeepalivesIdle(), setKeepalivesInterval(), setTCPUserTimeout(), and SSLerrmessage().

◆ libpq_ngettext

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

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

Referenced by pq_verify_peer_name_matches_certificate(), and PQenv2encoding().

◆ NULL_LEN

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

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

Referenced by getAnotherTuple(), PQgetisnull(), PQgetlength(), pqRowProcessor(), and PQsetvalue().

◆ pglock_thread

#define pglock_thread ( )    ((void) 0)

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

Referenced by pg_fe_getauthname(), and pg_fe_sendauth().

◆ pgunlock_thread

#define pgunlock_thread ( )    ((void) 0)

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

Referenced by pg_fe_getauthname(), and pg_fe_sendauth().

◆ pqIsnonblocking

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

◆ SOCK_ERRNO

◆ SOCK_ERRNO_SET

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

◆ SOCK_STRERROR

Typedef Documentation

◆ pg_conn_host

typedef struct pg_conn_host pg_conn_host

◆ pg_conn_host_type

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

◆ PGAsyncStatusType

Enumerator
PGASYNC_IDLE 
PGASYNC_BUSY 
PGASYNC_READY 
PGASYNC_COPY_IN 
PGASYNC_COPY_OUT 
PGASYNC_COPY_BOTH 

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

217 {
218  PGASYNC_IDLE, /* nothing's happening, dude */
219  PGASYNC_BUSY, /* query in progress */
220  PGASYNC_READY, /* result ready for PQgetResult */
221  PGASYNC_COPY_IN, /* Copy In data transfer in progress */
222  PGASYNC_COPY_OUT, /* Copy Out data transfer in progress */
223  PGASYNC_COPY_BOTH /* Copy In/Out data transfer in progress */
PGAsyncStatusType
Definition: libpq-int.h:216

◆ PGQueryClass

Enumerator
PGQUERY_SIMPLE 
PGQUERY_EXTENDED 
PGQUERY_PREPARE 
PGQUERY_DESCRIBE 

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

228 {
229  PGQUERY_SIMPLE, /* simple Query protocol (PQexec) */
230  PGQUERY_EXTENDED, /* full Extended protocol (PQexecParams) */
231  PGQUERY_PREPARE, /* Parse only (PQprepare) */
232  PGQUERY_DESCRIBE /* Describe Statement or Portal */
233 } PGQueryClass;
PGQueryClass
Definition: libpq-int.h:227

◆ PGSetenvStatusType

Enumerator
SETENV_STATE_CLIENT_ENCODING_SEND 
SETENV_STATE_CLIENT_ENCODING_WAIT 
SETENV_STATE_OPTION_SEND 
SETENV_STATE_OPTION_WAIT 
SETENV_STATE_QUERY1_SEND 
SETENV_STATE_QUERY1_WAIT 
SETENV_STATE_QUERY2_SEND 
SETENV_STATE_QUERY2_WAIT 
SETENV_STATE_IDLE 

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

239 {
240  SETENV_STATE_CLIENT_ENCODING_SEND, /* About to send an Environment Option */
241  SETENV_STATE_CLIENT_ENCODING_WAIT, /* Waiting for above send to complete */
242  SETENV_STATE_OPTION_SEND, /* About to send an Environment Option */
243  SETENV_STATE_OPTION_WAIT, /* Waiting for above send to complete */
244  SETENV_STATE_QUERY1_SEND, /* About to send a status query */
245  SETENV_STATE_QUERY1_WAIT, /* Waiting for query to complete */
246  SETENV_STATE_QUERY2_SEND, /* About to send a status query */
247  SETENV_STATE_QUERY2_WAIT, /* Waiting for query to complete */
PGSetenvStatusType
Definition: libpq-int.h:238

Function Documentation

◆ pgtls_close()

void pgtls_close ( PGconn conn)

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

References destroy_ssl_system(), and pg_conn::ssl_in_use.

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

1392 {
1393  bool destroy_needed = false;
1394 
1395  if (conn->ssl)
1396  {
1397  /*
1398  * We can't destroy everything SSL-related here due to the possible
1399  * later calls to OpenSSL routines which may need our thread
1400  * callbacks, so set a flag here and check at the end.
1401  */
1402  destroy_needed = true;
1403 
1404  SSL_shutdown(conn->ssl);
1405  SSL_free(conn->ssl);
1406  conn->ssl = NULL;
1407  conn->ssl_in_use = false;
1408  }
1409 
1410  if (conn->peer)
1411  {
1412  X509_free(conn->peer);
1413  conn->peer = NULL;
1414  }
1415 
1416 #ifdef USE_SSL_ENGINE
1417  if (conn->engine)
1418  {
1419  ENGINE_finish(conn->engine);
1420  ENGINE_free(conn->engine);
1421  conn->engine = NULL;
1422  }
1423 #endif
1424 
1425  /*
1426  * This will remove our SSL locking hooks, if this is the last SSL
1427  * connection, which means we must wait to call it until after all SSL
1428  * calls have been made, otherwise we can end up with a race condition and
1429  * possible deadlocks.
1430  *
1431  * See comments above destroy_ssl_system().
1432  */
1433  if (destroy_needed)
1435 }
bool ssl_in_use
Definition: libpq-int.h:472
static void destroy_ssl_system(void)

◆ pgtls_init()

int pgtls_init ( PGconn conn)

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

References 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().

639 {
640 #ifdef ENABLE_THREAD_SAFETY
641 #ifdef WIN32
642  /* Also see similar code in fe-connect.c, default_threadlock() */
643  if (ssl_config_mutex == NULL)
644  {
645  while (InterlockedExchange(&win32_ssl_create_mutex, 1) == 1)
646  /* loop, another thread own the lock */ ;
647  if (ssl_config_mutex == NULL)
648  {
649  if (pthread_mutex_init(&ssl_config_mutex, NULL))
650  return -1;
651  }
652  InterlockedExchange(&win32_ssl_create_mutex, 0);
653  }
654 #endif
655  if (pthread_mutex_lock(&ssl_config_mutex))
656  return -1;
657 
658 #ifdef HAVE_CRYPTO_LOCK
659  if (pq_init_crypto_lib)
660  {
661  /*
662  * If necessary, set up an array to hold locks for libcrypto.
663  * libcrypto will tell us how big to make this array.
664  */
665  if (pq_lockarray == NULL)
666  {
667  int i;
668 
669  pq_lockarray = malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks());
670  if (!pq_lockarray)
671  {
672  pthread_mutex_unlock(&ssl_config_mutex);
673  return -1;
674  }
675  for (i = 0; i < CRYPTO_num_locks(); i++)
676  {
677  if (pthread_mutex_init(&pq_lockarray[i], NULL))
678  {
679  free(pq_lockarray);
680  pq_lockarray = NULL;
681  pthread_mutex_unlock(&ssl_config_mutex);
682  return -1;
683  }
684  }
685  }
686 
687  if (ssl_open_connections++ == 0)
688  {
689  /*
690  * These are only required for threaded libcrypto applications,
691  * but make sure we don't stomp on them if they're already set.
692  */
693  if (CRYPTO_get_id_callback() == NULL)
694  CRYPTO_set_id_callback(pq_threadidcallback);
695  if (CRYPTO_get_locking_callback() == NULL)
696  CRYPTO_set_locking_callback(pq_lockingcallback);
697  }
698  }
699 #endif /* HAVE_CRYPTO_LOCK */
700 #endif /* ENABLE_THREAD_SAFETY */
701 
702  if (!ssl_lib_initialized)
703  {
704  if (pq_init_ssl_lib)
705  {
706 #ifdef HAVE_OPENSSL_INIT_SSL
707  OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
708 #else
709  OPENSSL_config(NULL);
710  SSL_library_init();
711  SSL_load_error_strings();
712 #endif
713  }
714  ssl_lib_initialized = true;
715  }
716 
717 #ifdef ENABLE_THREAD_SAFETY
718  pthread_mutex_unlock(&ssl_config_mutex);
719 #endif
720  return 0;
721 }
static bool pq_init_ssl_lib
CRITICAL_SECTION * pthread_mutex_t
Definition: pthread-win32.h:8
int pthread_mutex_init(pthread_mutex_t *mp, void *attr)
Definition: pthread-win32.c:35
#define malloc(a)
Definition: header.h:50
int pthread_mutex_lock(pthread_mutex_t *mp)
Definition: pthread-win32.c:45
int pthread_mutex_unlock(pthread_mutex_t *mp)
Definition: pthread-win32.c:54
static bool pq_init_crypto_lib
#define free(a)
Definition: header.h:65
int i
static bool ssl_lib_initialized

◆ pgtls_init_library()

void pgtls_init_library ( bool  do_ssl,
int  do_crypto 
)

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

References pq_init_crypto_lib, and pq_init_ssl_lib.

Referenced by PQinitOpenSSL(), and PQinitSSL().

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

◆ pgtls_open_client()

PostgresPollingStatusType pgtls_open_client ( PGconn conn)

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

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

Referenced by pqsecure_open_client().

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

◆ pgtls_read()

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

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

References ECONNRESET, pg_conn::errorMessage, libpq_gettext, PG_STRERROR_R_BUFLEN, printfPQExpBuffer(), SOCK_ERRNO, SOCK_ERRNO_SET, SOCK_STRERROR, SSLerrfree(), and SSLerrmessage().

Referenced by pqsecure_read().

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

◆ pgtls_read_pending()

bool pgtls_read_pending ( PGconn conn)

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

Referenced by pqSocketCheck().

269 {
270  return SSL_pending(conn->ssl) > 0;
271 }

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

References free, i, mode, name, openssl_verify_peer_name_matches_certificate_name(), pthread_mutex_lock(), pthread_mutex_unlock(), and pthread_self().

Referenced by pq_verify_peer_name_matches_certificate().

515 {
516  STACK_OF(GENERAL_NAME) * peer_san;
517  int i;
518  int rc = 0;
519 
520  /*
521  * First, get the Subject Alternative Names (SANs) from the certificate,
522  * and compare them against the originally given hostname.
523  */
524  peer_san = (STACK_OF(GENERAL_NAME) *)
525  X509_get_ext_d2i(conn->peer, NID_subject_alt_name, NULL, NULL);
526 
527  if (peer_san)
528  {
529  int san_len = sk_GENERAL_NAME_num(peer_san);
530 
531  for (i = 0; i < san_len; i++)
532  {
533  const GENERAL_NAME *name = sk_GENERAL_NAME_value(peer_san, i);
534 
535  if (name->type == GEN_DNS)
536  {
537  char *alt_name;
538 
539  (*names_examined)++;
541  name->d.dNSName,
542  &alt_name);
543 
544  if (alt_name)
545  {
546  if (!*first_name)
547  *first_name = alt_name;
548  else
549  free(alt_name);
550  }
551  }
552  if (rc != 0)
553  break;
554  }
555  sk_GENERAL_NAME_pop_free(peer_san, GENERAL_NAME_free);
556  }
557 
558  /*
559  * If there is no subjectAltName extension of type dNSName, check the
560  * Common Name.
561  *
562  * (Per RFC 2818 and RFC 6125, if the subjectAltName extension of type
563  * dNSName is present, the CN must be ignored.)
564  */
565  if (*names_examined == 0)
566  {
567  X509_NAME *subject_name;
568 
569  subject_name = X509_get_subject_name(conn->peer);
570  if (subject_name != NULL)
571  {
572  int cn_index;
573 
574  cn_index = X509_NAME_get_index_by_NID(subject_name,
575  NID_commonName, -1);
576  if (cn_index >= 0)
577  {
578  (*names_examined)++;
580  X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subject_name, cn_index)),
581  first_name);
582  }
583  }
584  }
585 
586  return rc;
587 }
static int openssl_verify_peer_name_matches_certificate_name(PGconn *conn, ASN1_STRING *name, char **store_name)
#define free(a)
Definition: header.h:65
const char * name
Definition: encode.c:561
int i

◆ pgtls_write()

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

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

References conn, ECONNRESET, pg_conn::errorMessage, hash(), libpq_gettext, malloc, PG_STRERROR_R_BUFLEN, printfPQExpBuffer(), SOCK_ERRNO, SOCK_ERRNO_SET, SOCK_STRERROR, SSLerrfree(), and SSLerrmessage().

Referenced by pqsecure_write().

275 {
276  ssize_t n;
277  int result_errno = 0;
278  char sebuf[PG_STRERROR_R_BUFLEN];
279  int err;
280  unsigned long ecode;
281 
282  SOCK_ERRNO_SET(0);
283  ERR_clear_error();
284  n = SSL_write(conn->ssl, ptr, len);
285  err = SSL_get_error(conn->ssl, n);
286  ecode = (err != SSL_ERROR_NONE || n < 0) ? ERR_get_error() : 0;
287  switch (err)
288  {
289  case SSL_ERROR_NONE:
290  if (n < 0)
291  {
292  /* Not supposed to happen, so we don't translate the msg */
294  "SSL_write failed but did not provide error information\n");
295  /* assume the connection is broken */
296  result_errno = ECONNRESET;
297  }
298  break;
299  case SSL_ERROR_WANT_READ:
300 
301  /*
302  * Returning 0 here causes caller to wait for write-ready, which
303  * is not really the right thing, but it's the best we can do.
304  */
305  n = 0;
306  break;
307  case SSL_ERROR_WANT_WRITE:
308  n = 0;
309  break;
310  case SSL_ERROR_SYSCALL:
311  if (n < 0)
312  {
313  result_errno = SOCK_ERRNO;
314  if (result_errno == EPIPE || result_errno == ECONNRESET)
316  libpq_gettext("server closed the connection unexpectedly\n"
317  "\tThis probably means the server terminated abnormally\n"
318  "\tbefore or while processing the request.\n"));
319  else
321  libpq_gettext("SSL SYSCALL error: %s\n"),
322  SOCK_STRERROR(result_errno,
323  sebuf, sizeof(sebuf)));
324  }
325  else
326  {
328  libpq_gettext("SSL SYSCALL error: EOF detected\n"));
329  /* assume the connection is broken */
330  result_errno = ECONNRESET;
331  n = -1;
332  }
333  break;
334  case SSL_ERROR_SSL:
335  {
336  char *errm = SSLerrmessage(ecode);
337 
339  libpq_gettext("SSL error: %s\n"), errm);
340  SSLerrfree(errm);
341  /* assume the connection is broken */
342  result_errno = ECONNRESET;
343  n = -1;
344  break;
345  }
346  case SSL_ERROR_ZERO_RETURN:
347 
348  /*
349  * Per OpenSSL documentation, this error code is only returned for
350  * a clean connection closure, so we should not report it as a
351  * server crash.
352  */
354  libpq_gettext("SSL connection has been closed unexpectedly\n"));
355  result_errno = ECONNRESET;
356  n = -1;
357  break;
358  default:
360  libpq_gettext("unrecognized SSL error code: %d\n"),
361  err);
362  /* assume the connection is broken */
363  result_errno = ECONNRESET;
364  n = -1;
365  break;
366  }
367 
368  /* ensure we return the intended errno to caller */
369  SOCK_ERRNO_SET(result_errno);
370 
371  return n;
372 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
#define PG_STRERROR_R_BUFLEN
Definition: port.h:233
#define SOCK_STRERROR
Definition: libpq-int.h:819
#define SOCK_ERRNO
Definition: libpq-int.h:818
#define SOCK_ERRNO_SET(e)
Definition: libpq-int.h:820
static void SSLerrfree(char *buf)
PQExpBufferData errorMessage
Definition: libpq-int.h:526
#define ECONNRESET
Definition: win32_port.h:353
static char * SSLerrmessage(unsigned long ecode)
#define libpq_gettext(x)
Definition: libpq-int.h:805

◆ pqBuildErrorMessage3()

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

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

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(), pg_result::resultStatus, and val.

Referenced by pqGetErrorNotice3(), and PQresultVerboseErrorMessage().

987 {
988  const char *val;
989  const char *querytext = NULL;
990  int querypos = 0;
991 
992  /* If we couldn't allocate a PGresult, just say "out of memory" */
993  if (res == NULL)
994  {
995  appendPQExpBufferStr(msg, libpq_gettext("out of memory\n"));
996  return;
997  }
998 
999  /*
1000  * If we don't have any broken-down fields, just return the base message.
1001  * This mainly applies if we're given a libpq-generated error result.
1002  */
1003  if (res->errFields == NULL)
1004  {
1005  if (res->errMsg && res->errMsg[0])
1006  appendPQExpBufferStr(msg, res->errMsg);
1007  else
1008  appendPQExpBufferStr(msg, libpq_gettext("no error message available\n"));
1009  return;
1010  }
1011 
1012  /* Else build error message from relevant fields */
1014  if (val)
1015  appendPQExpBuffer(msg, "%s: ", val);
1016 
1017  if (verbosity == PQERRORS_SQLSTATE)
1018  {
1019  /*
1020  * If we have a SQLSTATE, print that and nothing else. If not (which
1021  * shouldn't happen for server-generated errors, but might possibly
1022  * happen for libpq-generated ones), fall back to TERSE format, as
1023  * that seems better than printing nothing at all.
1024  */
1026  if (val)
1027  {
1028  appendPQExpBuffer(msg, "%s\n", val);
1029  return;
1030  }
1031  verbosity = PQERRORS_TERSE;
1032  }
1033 
1034  if (verbosity == PQERRORS_VERBOSE)
1035  {
1037  if (val)
1038  appendPQExpBuffer(msg, "%s: ", val);
1039  }
1041  if (val)
1042  appendPQExpBufferStr(msg, val);
1044  if (val)
1045  {
1046  if (verbosity != PQERRORS_TERSE && res->errQuery != NULL)
1047  {
1048  /* emit position as a syntax cursor display */
1049  querytext = res->errQuery;
1050  querypos = atoi(val);
1051  }
1052  else
1053  {
1054  /* emit position as text addition to primary message */
1055  /* translator: %s represents a digit string */
1056  appendPQExpBuffer(msg, libpq_gettext(" at character %s"),
1057  val);
1058  }
1059  }
1060  else
1061  {
1063  if (val)
1064  {
1065  querytext = PQresultErrorField(res, PG_DIAG_INTERNAL_QUERY);
1066  if (verbosity != PQERRORS_TERSE && querytext != NULL)
1067  {
1068  /* emit position as a syntax cursor display */
1069  querypos = atoi(val);
1070  }
1071  else
1072  {
1073  /* emit position as text addition to primary message */
1074  /* translator: %s represents a digit string */
1075  appendPQExpBuffer(msg, libpq_gettext(" at character %s"),
1076  val);
1077  }
1078  }
1079  }
1080  appendPQExpBufferChar(msg, '\n');
1081  if (verbosity != PQERRORS_TERSE)
1082  {
1083  if (querytext && querypos > 0)
1084  reportErrorPosition(msg, querytext, querypos,
1085  res->client_encoding);
1087  if (val)
1088  appendPQExpBuffer(msg, libpq_gettext("DETAIL: %s\n"), val);
1090  if (val)
1091  appendPQExpBuffer(msg, libpq_gettext("HINT: %s\n"), val);
1093  if (val)
1094  appendPQExpBuffer(msg, libpq_gettext("QUERY: %s\n"), val);
1095  if (show_context == PQSHOW_CONTEXT_ALWAYS ||
1096  (show_context == PQSHOW_CONTEXT_ERRORS &&
1098  {
1099  val = PQresultErrorField(res, PG_DIAG_CONTEXT);
1100  if (val)
1101  appendPQExpBuffer(msg, libpq_gettext("CONTEXT: %s\n"),
1102  val);
1103  }
1104  }
1105  if (verbosity == PQERRORS_VERBOSE)
1106  {
1108  if (val)
1109  appendPQExpBuffer(msg,
1110  libpq_gettext("SCHEMA NAME: %s\n"), val);
1112  if (val)
1113  appendPQExpBuffer(msg,
1114  libpq_gettext("TABLE NAME: %s\n"), val);
1116  if (val)
1117  appendPQExpBuffer(msg,
1118  libpq_gettext("COLUMN NAME: %s\n"), val);
1120  if (val)
1121  appendPQExpBuffer(msg,
1122  libpq_gettext("DATATYPE NAME: %s\n"), val);
1124  if (val)
1125  appendPQExpBuffer(msg,
1126  libpq_gettext("CONSTRAINT NAME: %s\n"), val);
1127  }
1128  if (verbosity == PQERRORS_VERBOSE)
1129  {
1130  const char *valf;
1131  const char *vall;
1132 
1136  if (val || valf || vall)
1137  {
1138  appendPQExpBufferStr(msg, libpq_gettext("LOCATION: "));
1139  if (val)
1140  appendPQExpBuffer(msg, libpq_gettext("%s, "), val);
1141  if (valf && vall) /* unlikely we'd have just one */
1142  appendPQExpBuffer(msg, libpq_gettext("%s:%s"),
1143  valf, vall);
1144  appendPQExpBufferChar(msg, '\n');
1145  }
1146  }
1147 }
PGMessageField * errFields
Definition: libpq-int.h:197
#define PG_DIAG_MESSAGE_PRIMARY
Definition: postgres_ext.h:58
#define PG_DIAG_SCHEMA_NAME
Definition: postgres_ext.h:65
#define PG_DIAG_MESSAGE_DETAIL
Definition: postgres_ext.h:59
#define PG_DIAG_COLUMN_NAME
Definition: postgres_ext.h:67
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
#define PG_DIAG_TABLE_NAME
Definition: postgres_ext.h:66
#define PG_DIAG_SOURCE_LINE
Definition: postgres_ext.h:71
#define PG_DIAG_INTERNAL_POSITION
Definition: postgres_ext.h:62
#define PG_DIAG_SQLSTATE
Definition: postgres_ext.h:57
char * errMsg
Definition: libpq-int.h:196
#define PG_DIAG_SOURCE_FILE
Definition: postgres_ext.h:70
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
static void reportErrorPosition(PQExpBuffer msg, const char *query, int loc, int encoding)
#define PG_DIAG_SEVERITY
Definition: postgres_ext.h:55
#define PG_DIAG_STATEMENT_POSITION
Definition: postgres_ext.h:61
char * errQuery
Definition: libpq-int.h:198
void appendPQExpBufferChar(PQExpBuffer str, char ch)
Definition: pqexpbuffer.c:380
#define PG_DIAG_DATATYPE_NAME
Definition: postgres_ext.h:68
#define PG_DIAG_CONSTRAINT_NAME
Definition: postgres_ext.h:69
#define PG_DIAG_INTERNAL_QUERY
Definition: postgres_ext.h:63
#define PG_DIAG_MESSAGE_HINT
Definition: postgres_ext.h:60
char * PQresultErrorField(const PGresult *res, int fieldcode)
Definition: fe-exec.c:2754
#define PG_DIAG_SOURCE_FUNCTION
Definition: postgres_ext.h:72
ExecStatusType resultStatus
Definition: libpq-int.h:177
long val
Definition: informix.c:664
#define PG_DIAG_CONTEXT
Definition: postgres_ext.h:64
#define libpq_gettext(x)
Definition: libpq-int.h:805
int client_encoding
Definition: libpq-int.h:189

◆ pqBuildStartupPacket2()

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

Definition at line 1589 of file fe-protocol2.c.

References StartupPacket::database, pg_conn::dbName, malloc, MemSet, StartupPacket::options, pg_hton32, pg_conn::pgoptions, pg_conn::pgtty, pg_conn::pguser, StartupPacket::protoVersion, pg_conn::pversion, SM_DATABASE, SM_OPTIONS, SM_TTY, SM_USER, StartupPacket::tty, and StartupPacket::user.

Referenced by PQconnectPoll().

1591 {
1592  StartupPacket *startpacket;
1593 
1594  *packetlen = sizeof(StartupPacket);
1595  startpacket = (StartupPacket *) malloc(sizeof(StartupPacket));
1596  if (!startpacket)
1597  return NULL;
1598 
1599  MemSet(startpacket, 0, sizeof(StartupPacket));
1600 
1601  startpacket->protoVersion = pg_hton32(conn->pversion);
1602 
1603  /* strncpy is safe here: postmaster will handle full fields correctly */
1604  strncpy(startpacket->user, conn->pguser, SM_USER);
1605  strncpy(startpacket->database, conn->dbName, SM_DATABASE);
1606  strncpy(startpacket->tty, conn->pgtty, SM_TTY);
1607 
1608  if (conn->pgoptions)
1609  strncpy(startpacket->options, conn->pgoptions, SM_OPTIONS);
1610 
1611  return (char *) startpacket;
1612 }
char tty[SM_TTY]
Definition: pqcomm.h:149
struct StartupPacket StartupPacket
char * dbName
Definition: libpq-int.h:345
#define MemSet(start, val, len)
Definition: c.h:950
#define SM_USER
Definition: pqcomm.h:134
char options[SM_OPTIONS]
Definition: pqcomm.h:147
#define malloc(a)
Definition: header.h:50
#define SM_TTY
Definition: pqcomm.h:139
#define pg_hton32(x)
Definition: pg_bswap.h:121
char * pguser
Definition: libpq-int.h:347
char database[SM_DATABASE]
Definition: pqcomm.h:144
char * pgoptions
Definition: libpq-int.h:342
ProtocolVersion pversion
Definition: libpq-int.h:414
char user[SM_USER]
Definition: pqcomm.h:146
ProtocolVersion protoVersion
Definition: pqcomm.h:143
#define SM_OPTIONS
Definition: pqcomm.h:137
#define SM_DATABASE
Definition: pqcomm.h:133
char * pgtty
Definition: libpq-int.h:337

◆ pqBuildStartupPacket3()

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

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

References build_startup_packet(), and malloc.

Referenced by PQconnectPoll().

2126 {
2127  char *startpacket;
2128 
2129  *packetlen = build_startup_packet(conn, NULL, options);
2130  startpacket = (char *) malloc(*packetlen);
2131  if (!startpacket)
2132  return NULL;
2133  *packetlen = build_startup_packet(conn, startpacket, options);
2134  return startpacket;
2135 }
static int build_startup_packet(const PGconn *conn, char *packet, const PQEnvironmentOption *options)
#define malloc(a)
Definition: header.h:50

◆ pqCatenateResultError()

void pqCatenateResultError ( PGresult res,
const char *  msg 
)

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

References appendPQExpBufferStr(), PQExpBufferData::data, pg_result::errMsg, initPQExpBuffer(), pqSetResultError(), and termPQExpBuffer().

Referenced by PQexecFinish(), pqSaveErrorResult(), and pqSaveWriteError().

676 {
677  PQExpBufferData errorBuf;
678 
679  if (!res || !msg)
680  return;
681  initPQExpBuffer(&errorBuf);
682  if (res->errMsg)
683  appendPQExpBufferStr(&errorBuf, res->errMsg);
684  appendPQExpBufferStr(&errorBuf, msg);
685  pqSetResultError(res, errorBuf.data);
686  termPQExpBuffer(&errorBuf);
687 }
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:131
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
char * errMsg
Definition: libpq-int.h:196
void pqSetResultError(PGresult *res, const char *msg)
Definition: fe-exec.c:660
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92

◆ pqCheckInBufferSpace()

int pqCheckInBufferSpace ( size_t  bytes_needed,
PGconn conn 
)

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

References pg_conn::errorMessage, pg_conn::inBuffer, pg_conn::inBufSize, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, printfPQExpBuffer(), and realloc.

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

395 {
396  int newsize = conn->inBufSize;
397  char *newbuf;
398 
399  /* Quick exit if we have enough space */
400  if (bytes_needed <= (size_t) newsize)
401  return 0;
402 
403  /*
404  * Before concluding that we need to enlarge the buffer, left-justify
405  * whatever is in it and recheck. The caller's value of bytes_needed
406  * includes any data to the left of inStart, but we can delete that in
407  * preference to enlarging the buffer. It's slightly ugly to have this
408  * function do this, but it's better than making callers worry about it.
409  */
410  bytes_needed -= conn->inStart;
411 
412  if (conn->inStart < conn->inEnd)
413  {
414  if (conn->inStart > 0)
415  {
416  memmove(conn->inBuffer, conn->inBuffer + conn->inStart,
417  conn->inEnd - conn->inStart);
418  conn->inEnd -= conn->inStart;
419  conn->inCursor -= conn->inStart;
420  conn->inStart = 0;
421  }
422  }
423  else
424  {
425  /* buffer is logically empty, reset it */
426  conn->inStart = conn->inCursor = conn->inEnd = 0;
427  }
428 
429  /* Recheck whether we have enough space */
430  if (bytes_needed <= (size_t) newsize)
431  return 0;
432 
433  /*
434  * If we need to enlarge the buffer, we first try to double it in size; if
435  * that doesn't work, enlarge in multiples of 8K. This avoids thrashing
436  * the malloc pool by repeated small enlargements.
437  *
438  * Note: tests for newsize > 0 are to catch integer overflow.
439  */
440  do
441  {
442  newsize *= 2;
443  } while (newsize > 0 && bytes_needed > (size_t) newsize);
444 
445  if (newsize > 0 && bytes_needed <= (size_t) newsize)
446  {
447  newbuf = realloc(conn->inBuffer, newsize);
448  if (newbuf)
449  {
450  /* realloc succeeded */
451  conn->inBuffer = newbuf;
452  conn->inBufSize = newsize;
453  return 0;
454  }
455  }
456 
457  newsize = conn->inBufSize;
458  do
459  {
460  newsize += 8192;
461  } while (newsize > 0 && bytes_needed > (size_t) newsize);
462 
463  if (newsize > 0 && bytes_needed <= (size_t) newsize)
464  {
465  newbuf = realloc(conn->inBuffer, newsize);
466  if (newbuf)
467  {
468  /* realloc succeeded */
469  conn->inBuffer = newbuf;
470  conn->inBufSize = newsize;
471  return 0;
472  }
473  }
474 
475  /* realloc failed. Probably out of memory */
477  "cannot allocate memory for input buffer\n");
478  return EOF;
479 }
int inEnd
Definition: libpq-int.h:448
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
int inStart
Definition: libpq-int.h:446
int inBufSize
Definition: libpq-int.h:445
char * inBuffer
Definition: libpq-int.h:444
PQExpBufferData errorMessage
Definition: libpq-int.h:526
#define realloc(a, b)
Definition: header.h:60
int inCursor
Definition: libpq-int.h:447

◆ pqCheckOutBufferSpace()

int pqCheckOutBufferSpace ( size_t  bytes_needed,
PGconn conn 
)

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

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

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

331 {
332  int newsize = conn->outBufSize;
333  char *newbuf;
334 
335  /* Quick exit if we have enough space */
336  if (bytes_needed <= (size_t) newsize)
337  return 0;
338 
339  /*
340  * If we need to enlarge the buffer, we first try to double it in size; if
341  * that doesn't work, enlarge in multiples of 8K. This avoids thrashing
342  * the malloc pool by repeated small enlargements.
343  *
344  * Note: tests for newsize > 0 are to catch integer overflow.
345  */
346  do
347  {
348  newsize *= 2;
349  } while (newsize > 0 && bytes_needed > (size_t) newsize);
350 
351  if (newsize > 0 && bytes_needed <= (size_t) newsize)
352  {
353  newbuf = realloc(conn->outBuffer, newsize);
354  if (newbuf)
355  {
356  /* realloc succeeded */
357  conn->outBuffer = newbuf;
358  conn->outBufSize = newsize;
359  return 0;
360  }
361  }
362 
363  newsize = conn->outBufSize;
364  do
365  {
366  newsize += 8192;
367  } while (newsize > 0 && bytes_needed > (size_t) newsize);
368 
369  if (newsize > 0 && bytes_needed <= (size_t) newsize)
370  {
371  newbuf = realloc(conn->outBuffer, newsize);
372  if (newbuf)
373  {
374  /* realloc succeeded */
375  conn->outBuffer = newbuf;
376  conn->outBufSize = newsize;
377  return 0;
378  }
379  }
380 
381  /* realloc failed. Probably out of memory */
383  "cannot allocate memory for output buffer\n");
384  return EOF;
385 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
PQExpBufferData errorMessage
Definition: libpq-int.h:526
int outBufSize
Definition: libpq-int.h:452
#define realloc(a, b)
Definition: header.h:60
char * outBuffer
Definition: libpq-int.h:451

◆ pqClearAsyncResult()

void pqClearAsyncResult ( PGconn conn)

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

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

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

750 {
751  if (conn->result)
752  PQclear(conn->result);
753  conn->result = NULL;
754  if (conn->next_result)
755  PQclear(conn->next_result);
756  conn->next_result = NULL;
757 }
PGresult * result
Definition: libpq-int.h:465
PGresult * next_result
Definition: libpq-int.h:466
void PQclear(PGresult *res)
Definition: fe-exec.c:694

◆ pqDropConnection()

void pqDropConnection ( PGconn conn,
bool  flushInput 
)

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

References closesocket, free, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, pg_conn::outCount, pg_fe_scram_free(), PGINVALID_SOCKET, pqsecure_close(), pg_conn::sasl_state, and pg_conn::sock.

Referenced by closePGconn(), connectDBStart(), handleSyncLoss(), PQconnectPoll(), and pqReadData().

460 {
461  /* Drop any SSL state */
462  pqsecure_close(conn);
463 
464  /* Close the socket itself */
465  if (conn->sock != PGINVALID_SOCKET)
466  closesocket(conn->sock);
467  conn->sock = PGINVALID_SOCKET;
468 
469  /* Optionally discard any unread data */
470  if (flushInput)
471  conn->inStart = conn->inCursor = conn->inEnd = 0;
472 
473  /* Always discard any unsent data */
474  conn->outCount = 0;
475 
476  /* Free authentication/encryption state */
477 #ifdef ENABLE_GSS
478  {
479  OM_uint32 min_s;
480 
481  if (conn->gcred != GSS_C_NO_CREDENTIAL)
482  {
483  gss_release_cred(&min_s, &conn->gcred);
484  conn->gcred = GSS_C_NO_CREDENTIAL;
485  }
486  if (conn->gctx)
487  gss_delete_sec_context(&min_s, &conn->gctx, GSS_C_NO_BUFFER);
488  if (conn->gtarg_nam)
489  gss_release_name(&min_s, &conn->gtarg_nam);
490  if (conn->gss_SendBuffer)
491  {
492  free(conn->gss_SendBuffer);
493  conn->gss_SendBuffer = NULL;
494  }
495  if (conn->gss_RecvBuffer)
496  {
497  free(conn->gss_RecvBuffer);
498  conn->gss_RecvBuffer = NULL;
499  }
500  if (conn->gss_ResultBuffer)
501  {
502  free(conn->gss_ResultBuffer);
503  conn->gss_ResultBuffer = NULL;
504  }
505  conn->gssenc = false;
506  }
507 #endif
508 #ifdef ENABLE_SSPI
509  if (conn->sspitarget)
510  {
511  free(conn->sspitarget);
512  conn->sspitarget = NULL;
513  }
514  if (conn->sspicred)
515  {
516  FreeCredentialsHandle(conn->sspicred);
517  free(conn->sspicred);
518  conn->sspicred = NULL;
519  }
520  if (conn->sspictx)
521  {
522  DeleteSecurityContext(conn->sspictx);
523  free(conn->sspictx);
524  conn->sspictx = NULL;
525  }
526  conn->usesspi = 0;
527 #endif
528  if (conn->sasl_state)
529  {
530  /*
531  * XXX: if support for more authentication mechanisms is added, this
532  * needs to call the right 'free' function.
533  */
535  conn->sasl_state = NULL;
536  }
537 }
int inEnd
Definition: libpq-int.h:448
int inStart
Definition: libpq-int.h:446
void pg_fe_scram_free(void *opaq)
#define closesocket
Definition: port.h:331
int outCount
Definition: libpq-int.h:453
void pqsecure_close(PGconn *conn)
Definition: fe-secure.c:197
void * sasl_state
Definition: libpq-int.h:469
pgsocket sock
Definition: libpq-int.h:410
#define PGINVALID_SOCKET
Definition: port.h:33
#define free(a)
Definition: header.h:65
int inCursor
Definition: libpq-int.h:447

◆ pqEndcopy2()

int pqEndcopy2 ( PGconn conn)

Definition at line 1345 of file fe-protocol2.c.

References pg_conn::asyncStatus, PQExpBufferData::data, pg_conn::errorMessage, PQExpBufferData::len, libpq_gettext, pg_conn::noticeHooks, PGASYNC_BUSY, PGASYNC_COPY_IN, PGASYNC_COPY_OUT, PGRES_COMMAND_OK, PQclear(), pqFlush(), PQgetResult(), pqInternalNotice(), PQisBusy(), pqIsnonblocking, PQreset(), PQresetStart(), printfPQExpBuffer(), resetPQExpBuffer(), and pg_result::resultStatus.

Referenced by PQendcopy().

1346 {
1347  PGresult *result;
1348 
1349  if (conn->asyncStatus != PGASYNC_COPY_IN &&
1350  conn->asyncStatus != PGASYNC_COPY_OUT)
1351  {
1353  libpq_gettext("no COPY in progress\n"));
1354  return 1;
1355  }
1356 
1357  /*
1358  * make sure no data is waiting to be sent, abort if we are non-blocking
1359  * and the flush fails
1360  */
1361  if (pqFlush(conn) && pqIsnonblocking(conn))
1362  return 1;
1363 
1364  /* non blocking connections may have to abort at this point. */
1365  if (pqIsnonblocking(conn) && PQisBusy(conn))
1366  return 1;
1367 
1368  /* Return to active duty */
1369  conn->asyncStatus = PGASYNC_BUSY;
1371 
1372  /* Wait for the completion response */
1373  result = PQgetResult(conn);
1374 
1375  /* Expecting a successful result */
1376  if (result && result->resultStatus == PGRES_COMMAND_OK)
1377  {
1378  PQclear(result);
1379  return 0;
1380  }
1381 
1382  /*
1383  * Trouble. For backwards-compatibility reasons, we issue the error
1384  * message as if it were a notice (would be nice to get rid of this
1385  * silliness, but too many apps probably don't handle errors from
1386  * PQendcopy reasonably). Note that the app can still obtain the error
1387  * status from the PGconn object.
1388  */
1389  if (conn->errorMessage.len > 0)
1390  {
1391  /* We have to strip the trailing newline ... pain in neck... */
1392  char svLast = conn->errorMessage.data[conn->errorMessage.len - 1];
1393 
1394  if (svLast == '\n')
1395  conn->errorMessage.data[conn->errorMessage.len - 1] = '\0';
1396  pqInternalNotice(&conn->noticeHooks, "%s", conn->errorMessage.data);
1397  conn->errorMessage.data[conn->errorMessage.len - 1] = svLast;
1398  }
1399 
1400  PQclear(result);
1401 
1402  /*
1403  * The worst case is that we've lost sync with the backend entirely due to
1404  * application screwup of the copy in/out protocol. To recover, reset the
1405  * connection (talk about using a sledgehammer...)
1406  */
1408  "lost synchronization with server, resetting connection");
1409 
1410  /*
1411  * Users doing non-blocking connections need to handle the reset
1412  * themselves, they'll need to check the connection status if we return an
1413  * error.
1414  */
1415  if (pqIsnonblocking(conn))
1416  PQresetStart(conn);
1417  else
1418  PQreset(conn);
1419 
1420  return 1;
1421 }
int pqFlush(PGconn *conn)
Definition: fe-misc.c:1012
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
int PQresetStart(PGconn *conn)
Definition: fe-connect.c:4229
#define pqIsnonblocking(conn)
Definition: libpq-int.h:799
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:389
PGNoticeHooks noticeHooks
Definition: libpq-int.h:380
void pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt,...)
Definition: fe-exec.c:871
PQExpBufferData errorMessage
Definition: libpq-int.h:526
void PQclear(PGresult *res)
Definition: fe-exec.c:694
int PQisBusy(PGconn *conn)
Definition: fe-exec.c:1754
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:148
ExecStatusType resultStatus
Definition: libpq-int.h:177
PGresult * PQgetResult(PGconn *conn)
Definition: fe-exec.c:1778
#define libpq_gettext(x)
Definition: libpq-int.h:805
void PQreset(PGconn *conn)
Definition: fe-connect.c:4188

◆ pqEndcopy3()

int pqEndcopy3 ( PGconn conn)

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

References pg_conn::asyncStatus, 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(), printfPQExpBuffer(), pg_conn::queryclass, resetPQExpBuffer(), and pg_result::resultStatus.

Referenced by PQendcopy().

1830 {
1831  PGresult *result;
1832 
1833  if (conn->asyncStatus != PGASYNC_COPY_IN &&
1834  conn->asyncStatus != PGASYNC_COPY_OUT &&
1835  conn->asyncStatus != PGASYNC_COPY_BOTH)
1836  {
1838  libpq_gettext("no COPY in progress\n"));
1839  return 1;
1840  }
1841 
1842  /* Send the CopyDone message if needed */
1843  if (conn->asyncStatus == PGASYNC_COPY_IN ||
1844  conn->asyncStatus == PGASYNC_COPY_BOTH)
1845  {
1846  if (pqPutMsgStart('c', false, conn) < 0 ||
1847  pqPutMsgEnd(conn) < 0)
1848  return 1;
1849 
1850  /*
1851  * If we sent the COPY command in extended-query mode, we must issue a
1852  * Sync as well.
1853  */
1854  if (conn->queryclass != PGQUERY_SIMPLE)
1855  {
1856  if (pqPutMsgStart('S', false, conn) < 0 ||
1857  pqPutMsgEnd(conn) < 0)
1858  return 1;
1859  }
1860  }
1861 
1862  /*
1863  * make sure no data is waiting to be sent, abort if we are non-blocking
1864  * and the flush fails
1865  */
1866  if (pqFlush(conn) && pqIsnonblocking(conn))
1867  return 1;
1868 
1869  /* Return to active duty */
1870  conn->asyncStatus = PGASYNC_BUSY;
1872 
1873  /*
1874  * Non blocking connections may have to abort at this point. If everyone
1875  * played the game there should be no problem, but in error scenarios the
1876  * expected messages may not have arrived yet. (We are assuming that the
1877  * backend's packetizing will ensure that CommandComplete arrives along
1878  * with the CopyDone; are there corner cases where that doesn't happen?)
1879  */
1880  if (pqIsnonblocking(conn) && PQisBusy(conn))
1881  return 1;
1882 
1883  /* Wait for the completion response */
1884  result = PQgetResult(conn);
1885 
1886  /* Expecting a successful result */
1887  if (result && result->resultStatus == PGRES_COMMAND_OK)
1888  {
1889  PQclear(result);
1890  return 0;
1891  }
1892 
1893  /*
1894  * Trouble. For backwards-compatibility reasons, we issue the error
1895  * message as if it were a notice (would be nice to get rid of this
1896  * silliness, but too many apps probably don't handle errors from
1897  * PQendcopy reasonably). Note that the app can still obtain the error
1898  * status from the PGconn object.
1899  */
1900  if (conn->errorMessage.len > 0)
1901  {
1902  /* We have to strip the trailing newline ... pain in neck... */
1903  char svLast = conn->errorMessage.data[conn->errorMessage.len - 1];
1904 
1905  if (svLast == '\n')
1906  conn->errorMessage.data[conn->errorMessage.len - 1] = '\0';
1907  pqInternalNotice(&conn->noticeHooks, "%s", conn->errorMessage.data);
1908  conn->errorMessage.data[conn->errorMessage.len - 1] = svLast;
1909  }
1910 
1911  PQclear(result);
1912 
1913  return 1;
1914 }
int pqFlush(PGconn *conn)
Definition: fe-misc.c:1012
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
#define pqIsnonblocking(conn)
Definition: libpq-int.h:799
PGQueryClass queryclass
Definition: libpq-int.h:391
int pqPutMsgStart(char msg_type, bool force_len, PGconn *conn)
Definition: fe-misc.c:505
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:389
PGNoticeHooks noticeHooks
Definition: libpq-int.h:380
void pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt,...)
Definition: fe-exec.c:871
PQExpBufferData errorMessage
Definition: libpq-int.h:526
void PQclear(PGresult *res)
Definition: fe-exec.c:694
int PQisBusy(PGconn *conn)
Definition: fe-exec.c:1754
int pqPutMsgEnd(PGconn *conn)
Definition: fe-misc.c:573
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:148
ExecStatusType resultStatus
Definition: libpq-int.h:177
PGresult * PQgetResult(PGconn *conn)
Definition: fe-exec.c:1778
#define libpq_gettext(x)
Definition: libpq-int.h:805

◆ pqFlush()

int pqFlush ( PGconn conn)

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

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

Referenced by pg_SASL_init(), PQconnectPoll(), PQconsumeInput(), pqEndcopy2(), pqEndcopy3(), PQflush(), pqFunctionCall2(), pqFunctionCall3(), PQgetResult(), pqPacketSend(), PQputCopyData(), PQputCopyEnd(), PQsendDescribe(), PQsendPrepare(), PQsendQuery(), PQsendQueryGuts(), PQsetnonblocking(), and sendTerminateConn().

1013 {
1014  if (conn->Pfdebug)
1015  fflush(conn->Pfdebug);
1016 
1017  if (conn->outCount > 0)
1018  return pqSendSome(conn, conn->outCount);
1019 
1020  return 0;
1021 }
int outCount
Definition: libpq-int.h:453
FILE * Pfdebug
Definition: libpq-int.h:377
static int pqSendSome(PGconn *conn, int len)
Definition: fe-misc.c:835

◆ pqFunctionCall2()

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

Definition at line 1430 of file fe-protocol2.c.

References pg_conn::errorMessage, getNotify(), i, pg_conn::inCursor, pg_conn::inStart, PQArgBlock::integer, PQArgBlock::len, libpq_gettext, PGRES_COMMAND_OK, PGRES_FATAL_ERROR, pqFlush(), pqGetc(), pqGetErrorNotice2(), pqGetInt(), pqGetnchar(), PQmakeEmptyPGresult(), pqPrepareAsyncResult(), pqPutInt(), pqPutMsgEnd(), pqPutMsgStart(), pqPutnchar(), pqPuts(), pqReadData(), pqSaveErrorResult(), pqWait(), printfPQExpBuffer(), PQArgBlock::ptr, pg_conn::result, and status().

Referenced by PQfn().

1434 {
1435  bool needInput = false;
1437  char id;
1438  int i;
1439 
1440  /* PQfn already validated connection state */
1441 
1442  if (pqPutMsgStart('F', false, conn) < 0 || /* function call msg */
1443  pqPuts(" ", conn) < 0 || /* dummy string */
1444  pqPutInt(fnid, 4, conn) != 0 || /* function id */
1445  pqPutInt(nargs, 4, conn) != 0) /* # of args */
1446  {
1447  /* error message should be set up already */
1448  return NULL;
1449  }
1450 
1451  for (i = 0; i < nargs; ++i)
1452  { /* len.int4 + contents */
1453  if (pqPutInt(args[i].len, 4, conn))
1454  return NULL;
1455 
1456  if (args[i].isint)
1457  {
1458  if (pqPutInt(args[i].u.integer, 4, conn))
1459  return NULL;
1460  }
1461  else
1462  {
1463  if (pqPutnchar((char *) args[i].u.ptr, args[i].len, conn))
1464  return NULL;
1465  }
1466  }
1467 
1468  if (pqPutMsgEnd(conn) < 0 ||
1469  pqFlush(conn))
1470  return NULL;
1471 
1472  for (;;)
1473  {
1474  if (needInput)
1475  {
1476  /* Wait for some data to arrive (or for the channel to close) */
1477  if (pqWait(true, false, conn) ||
1478  pqReadData(conn) < 0)
1479  break;
1480  }
1481 
1482  /*
1483  * Scan the message. If we run out of data, loop around to try again.
1484  */
1485  conn->inCursor = conn->inStart;
1486  needInput = true;
1487 
1488  if (pqGetc(&id, conn))
1489  continue;
1490 
1491  /*
1492  * We should see V or E response to the command, but might get N
1493  * and/or A notices first. We also need to swallow the final Z before
1494  * returning.
1495  */
1496  switch (id)
1497  {
1498  case 'V': /* function result */
1499  if (pqGetc(&id, conn))
1500  continue;
1501  if (id == 'G')
1502  {
1503  /* function returned nonempty value */
1504  if (pqGetInt(actual_result_len, 4, conn))
1505  continue;
1506  if (result_is_int)
1507  {
1508  if (pqGetInt(result_buf, 4, conn))
1509  continue;
1510  }
1511  else
1512  {
1513  if (pqGetnchar((char *) result_buf,
1514  *actual_result_len,
1515  conn))
1516  continue;
1517  }
1518  if (pqGetc(&id, conn)) /* get the last '0' */
1519  continue;
1520  }
1521  if (id == '0')
1522  {
1523  /* correctly finished function result message */
1524  status = PGRES_COMMAND_OK;
1525  }
1526  else
1527  {
1528  /* The backend violates the protocol. */
1530  libpq_gettext("protocol error: id=0x%x\n"),
1531  id);
1532  pqSaveErrorResult(conn);
1533  conn->inStart = conn->inCursor;
1534  return pqPrepareAsyncResult(conn);
1535  }
1536  break;
1537  case 'E': /* error return */
1538  if (pqGetErrorNotice2(conn, true))
1539  continue;
1540  status = PGRES_FATAL_ERROR;
1541  break;
1542  case 'A': /* notify message */
1543  /* handle notify and go back to processing return values */
1544  if (getNotify(conn))
1545  continue;
1546  break;
1547  case 'N': /* notice */
1548  /* handle notice and go back to processing return values */
1549  if (pqGetErrorNotice2(conn, false))
1550  continue;
1551  break;
1552  case 'Z': /* backend is ready for new query */
1553  /* consume the message and exit */
1554  conn->inStart = conn->inCursor;
1555  /* if we saved a result object (probably an error), use it */
1556  if (conn->result)
1557  return pqPrepareAsyncResult(conn);
1558  return PQmakeEmptyPGresult(conn, status);
1559  default:
1560  /* The backend violates the protocol. */
1562  libpq_gettext("protocol error: id=0x%x\n"),
1563  id);
1564  pqSaveErrorResult(conn);
1565  conn->inStart = conn->inCursor;
1566  return pqPrepareAsyncResult(conn);
1567  }
1568  /* Completed this message, keep going */
1569  conn->inStart = conn->inCursor;
1570  needInput = false;
1571  }
1572 
1573  /*
1574  * We fall out of the loop only upon failing to read data.
1575  * conn->errorMessage has been set by pqWait or pqReadData. We want to
1576  * append it to any already-received error message.
1577  */
1578  pqSaveErrorResult(conn);
1579  return pqPrepareAsyncResult(conn);
1580 }
int pqFlush(PGconn *conn)
Definition: fe-misc.c:1012
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
int inStart
Definition: libpq-int.h:446
int pqPutMsgStart(char msg_type, bool force_len, PGconn *conn)
Definition: fe-misc.c:505
int pqGetInt(int *result, size_t bytes, PGconn *conn)
Definition: fe-misc.c:253
ExecStatusType
Definition: libpq-fe.h:84
int pqGetnchar(char *s, size_t len, PGconn *conn)
Definition: fe-misc.c:181
PGresult * pqPrepareAsyncResult(PGconn *conn)
Definition: fe-exec.c:826
PGresult * result
Definition: libpq-int.h:465
int pqPutInt(int value, size_t bytes, PGconn *conn)
Definition: fe-misc.c:293
int pqReadData(PGconn *conn)
Definition: fe-misc.c:615
int pqWait(int forRead, int forWrite, PGconn *conn)
Definition: fe-misc.c:1035
PGresult * PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
Definition: fe-exec.c:141
int pqPuts(const char *s, PGconn *conn)
Definition: fe-misc.c:165
int pqGetc(char *result, PGconn *conn)
Definition: fe-misc.c:80
static int getNotify(PGconn *conn)
PQExpBufferData errorMessage
Definition: libpq-int.h:526
int pqPutnchar(const char *s, size_t len, PGconn *conn)
Definition: fe-misc.c:232
int pqPutMsgEnd(PGconn *conn)
Definition: fe-misc.c:573
int i
void pqSaveErrorResult(PGconn *conn)
Definition: fe-exec.c:772
int inCursor
Definition: libpq-int.h:447
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227
int * ptr
Definition: libpq-fe.h:229
#define libpq_gettext(x)
Definition: libpq-int.h:805
int integer
Definition: libpq-fe.h:230
static int pqGetErrorNotice2(PGconn *conn, bool isError)
Definition: fe-protocol2.c:956

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

References pg_conn::errorMessage, getNotify(), getParameterStatus(), getReadyForQuery(), handleSyncLoss(), i, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, PQArgBlock::integer, PQArgBlock::len, libpq_gettext, PGRES_COMMAND_OK, PGRES_FATAL_ERROR, pqCheckInBufferSpace(), pqFlush(), pqGetc(), pqGetErrorNotice3(), pqGetInt(), pqGetnchar(), PQmakeEmptyPGresult(), pqPrepareAsyncResult(), pqPutInt(), pqPutMsgEnd(), pqPutMsgStart(), pqPutnchar(), pqReadData(), pqSaveErrorResult(), pqWait(), printfPQExpBuffer(), PQArgBlock::ptr, pg_conn::result, status(), and VALID_LONG_MESSAGE_TYPE.

Referenced by PQfn().

1927 {
1928  bool needInput = false;
1930  char id;
1931  int msgLength;
1932  int avail;
1933  int i;
1934 
1935  /* PQfn already validated connection state */
1936 
1937  if (pqPutMsgStart('F', false, conn) < 0 || /* function call msg */
1938  pqPutInt(fnid, 4, conn) < 0 || /* function id */
1939  pqPutInt(1, 2, conn) < 0 || /* # of format codes */
1940  pqPutInt(1, 2, conn) < 0 || /* format code: BINARY */
1941  pqPutInt(nargs, 2, conn) < 0) /* # of args */
1942  {
1943  /* error message should be set up already */
1944  return NULL;
1945  }
1946 
1947  for (i = 0; i < nargs; ++i)
1948  { /* len.int4 + contents */
1949  if (pqPutInt(args[i].len, 4, conn))
1950  return NULL;
1951  if (args[i].len == -1)
1952  continue; /* it's NULL */
1953 
1954  if (args[i].isint)
1955  {
1956  if (pqPutInt(args[i].u.integer, args[i].len, conn))
1957  return NULL;
1958  }
1959  else
1960  {
1961  if (pqPutnchar((char *) args[i].u.ptr, args[i].len, conn))
1962  return NULL;
1963  }
1964  }
1965 
1966  if (pqPutInt(1, 2, conn) < 0) /* result format code: BINARY */
1967  return NULL;
1968 
1969  if (pqPutMsgEnd(conn) < 0 ||
1970  pqFlush(conn))
1971  return NULL;
1972 
1973  for (;;)
1974  {
1975  if (needInput)
1976  {
1977  /* Wait for some data to arrive (or for the channel to close) */
1978  if (pqWait(true, false, conn) ||
1979  pqReadData(conn) < 0)
1980  break;
1981  }
1982 
1983  /*
1984  * Scan the message. If we run out of data, loop around to try again.
1985  */
1986  needInput = true;
1987 
1988  conn->inCursor = conn->inStart;
1989  if (pqGetc(&id, conn))
1990  continue;
1991  if (pqGetInt(&msgLength, 4, conn))
1992  continue;
1993 
1994  /*
1995  * Try to validate message type/length here. A length less than 4 is
1996  * definitely broken. Large lengths should only be believed for a few
1997  * message types.
1998  */
1999  if (msgLength < 4)
2000  {
2001  handleSyncLoss(conn, id, msgLength);
2002  break;
2003  }
2004  if (msgLength > 30000 && !VALID_LONG_MESSAGE_TYPE(id))
2005  {
2006  handleSyncLoss(conn, id, msgLength);
2007  break;
2008  }
2009 
2010  /*
2011  * Can't process if message body isn't all here yet.
2012  */
2013  msgLength -= 4;
2014  avail = conn->inEnd - conn->inCursor;
2015  if (avail < msgLength)
2016  {
2017  /*
2018  * Before looping, enlarge the input buffer if needed to hold the
2019  * whole message. See notes in parseInput.
2020  */
2021  if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength,
2022  conn))
2023  {
2024  /*
2025  * XXX add some better recovery code... plan is to skip over
2026  * the message using its length, then report an error. For the
2027  * moment, just treat this like loss of sync (which indeed it
2028  * might be!)
2029  */
2030  handleSyncLoss(conn, id, msgLength);
2031  break;
2032  }
2033  continue;
2034  }
2035 
2036  /*
2037  * We should see V or E response to the command, but might get N
2038  * and/or A notices first. We also need to swallow the final Z before
2039  * returning.
2040  */
2041  switch (id)
2042  {
2043  case 'V': /* function result */
2044  if (pqGetInt(actual_result_len, 4, conn))
2045  continue;
2046  if (*actual_result_len != -1)
2047  {
2048  if (result_is_int)
2049  {
2050  if (pqGetInt(result_buf, *actual_result_len, conn))
2051  continue;
2052  }
2053  else
2054  {
2055  if (pqGetnchar((char *) result_buf,
2056  *actual_result_len,
2057  conn))
2058  continue;
2059  }
2060  }
2061  /* correctly finished function result message */
2062  status = PGRES_COMMAND_OK;
2063  break;
2064  case 'E': /* error return */
2065  if (pqGetErrorNotice3(conn, true))
2066  continue;
2067  status = PGRES_FATAL_ERROR;
2068  break;
2069  case 'A': /* notify message */
2070  /* handle notify and go back to processing return values */
2071  if (getNotify(conn))
2072  continue;
2073  break;
2074  case 'N': /* notice */
2075  /* handle notice and go back to processing return values */
2076  if (pqGetErrorNotice3(conn, false))
2077  continue;
2078  break;
2079  case 'Z': /* backend is ready for new query */
2080  if (getReadyForQuery(conn))
2081  continue;
2082  /* consume the message and exit */
2083  conn->inStart += 5 + msgLength;
2084  /* if we saved a result object (probably an error), use it */
2085  if (conn->result)
2086  return pqPrepareAsyncResult(conn);
2087  return PQmakeEmptyPGresult(conn, status);
2088  case 'S': /* parameter status */
2089  if (getParameterStatus(conn))
2090  continue;
2091  break;
2092  default:
2093  /* The backend violates the protocol. */
2095  libpq_gettext("protocol error: id=0x%x\n"),
2096  id);
2097  pqSaveErrorResult(conn);
2098  /* trust the specified message length as what to skip */
2099  conn->inStart += 5 + msgLength;
2100  return pqPrepareAsyncResult(conn);
2101  }
2102  /* Completed this message, keep going */
2103  /* trust the specified message length as what to skip */
2104  conn->inStart += 5 + msgLength;
2105  needInput = false;
2106  }
2107 
2108  /*
2109  * We fall out of the loop only upon failing to read data.
2110  * conn->errorMessage has been set by pqWait or pqReadData. We want to
2111  * append it to any already-received error message.
2112  */
2113  pqSaveErrorResult(conn);
2114  return pqPrepareAsyncResult(conn);
2115 }
int pqFlush(PGconn *conn)
Definition: fe-misc.c:1012
int inEnd
Definition: libpq-int.h:448
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
int inStart
Definition: libpq-int.h:446
int pqCheckInBufferSpace(size_t bytes_needed, PGconn *conn)
Definition: fe-misc.c:394
int pqPutMsgStart(char msg_type, bool force_len, PGconn *conn)
Definition: fe-misc.c:505
int pqGetInt(int *result, size_t bytes, PGconn *conn)
Definition: fe-misc.c:253
ExecStatusType
Definition: libpq-fe.h:84
int pqGetnchar(char *s, size_t len, PGconn *conn)
Definition: fe-misc.c:181
PGresult * pqPrepareAsyncResult(PGconn *conn)
Definition: fe-exec.c:826
PGresult * result
Definition: libpq-int.h:465
int pqPutInt(int value, size_t bytes, PGconn *conn)
Definition: fe-misc.c:293
int pqGetErrorNotice3(PGconn *conn, bool isError)
Definition: fe-protocol3.c:871
int pqReadData(PGconn *conn)
Definition: fe-misc.c:615
int pqWait(int forRead, int forWrite, PGconn *conn)
Definition: fe-misc.c:1035
PGresult * PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
Definition: fe-exec.c:141
int pqGetc(char *result, PGconn *conn)
Definition: fe-misc.c:80
#define VALID_LONG_MESSAGE_TYPE(id)
Definition: fe-protocol3.c:38
PQExpBufferData errorMessage
Definition: libpq-int.h:526
int pqPutnchar(const char *s, size_t len, PGconn *conn)
Definition: fe-misc.c:232
static int getReadyForQuery(PGconn *conn)
int pqPutMsgEnd(PGconn *conn)
Definition: fe-misc.c:573
static int getParameterStatus(PGconn *conn)
static int getNotify(PGconn *conn)
int i
static void handleSyncLoss(PGconn *conn, char id, int msgLength)
Definition: fe-protocol3.c:446
void pqSaveErrorResult(PGconn *conn)
Definition: fe-exec.c:772
int inCursor
Definition: libpq-int.h:447
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227
int * ptr
Definition: libpq-fe.h:229
#define libpq_gettext(x)
Definition: libpq-int.h:805
int integer
Definition: libpq-fe.h:230

◆ pqGetc()

int pqGetc ( char *  result,
PGconn conn 
)

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

References fprintf, pg_conn::inBuffer, pg_conn::inCursor, pg_conn::inEnd, and pg_conn::Pfdebug.

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

81 {
82  if (conn->inCursor >= conn->inEnd)
83  return EOF;
84 
85  *result = conn->inBuffer[conn->inCursor++];
86 
87  if (conn->Pfdebug)
88  fprintf(conn->Pfdebug, "From backend> %c\n", *result);
89 
90  return 0;
91 }
int inEnd
Definition: libpq-int.h:448
#define fprintf
Definition: port.h:219
FILE * Pfdebug
Definition: libpq-int.h:377
char * inBuffer
Definition: libpq-int.h:444
int inCursor
Definition: libpq-int.h:447

◆ pqGetCopyData2()

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

Definition at line 1162 of file fe-protocol2.c.

References pg_conn::asyncStatus, pg_conn::errorMessage, pg_conn::inBuffer, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, libpq_gettext, malloc, PGASYNC_BUSY, pqReadData(), pqWait(), and printfPQExpBuffer().

Referenced by PQgetCopyData().

1163 {
1164  bool found;
1165  int msgLength;
1166 
1167  for (;;)
1168  {
1169  /*
1170  * Do we have a complete line of data?
1171  */
1172  conn->inCursor = conn->inStart;
1173  found = false;
1174  while (conn->inCursor < conn->inEnd)
1175  {
1176  char c = conn->inBuffer[conn->inCursor++];
1177 
1178  if (c == '\n')
1179  {
1180  found = true;
1181  break;
1182  }
1183  }
1184  if (!found)
1185  goto nodata;
1186  msgLength = conn->inCursor - conn->inStart;
1187 
1188  /*
1189  * If it's the end-of-data marker, consume it, exit COPY_OUT mode, and
1190  * let caller read status with PQgetResult().
1191  */
1192  if (msgLength == 3 &&
1193  strncmp(&conn->inBuffer[conn->inStart], "\\.\n", 3) == 0)
1194  {
1195  conn->inStart = conn->inCursor;
1196  conn->asyncStatus = PGASYNC_BUSY;
1197  return -1;
1198  }
1199 
1200  /*
1201  * Pass the line back to the caller.
1202  */
1203  *buffer = (char *) malloc(msgLength + 1);
1204  if (*buffer == NULL)
1205  {
1207  libpq_gettext("out of memory\n"));
1208  return -2;
1209  }
1210  memcpy(*buffer, &conn->inBuffer[conn->inStart], msgLength);
1211  (*buffer)[msgLength] = '\0'; /* Add terminating null */
1212 
1213  /* Mark message consumed */
1214  conn->inStart = conn->inCursor;
1215 
1216  return msgLength;
1217 
1218 nodata:
1219  /* Don't block if async read requested */
1220  if (async)
1221  return 0;
1222  /* Need to load more data */
1223  if (pqWait(true, false, conn) ||
1224  pqReadData(conn) < 0)
1225  return -2;
1226  }
1227 }
int inEnd
Definition: libpq-int.h:448
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
int inStart
Definition: libpq-int.h:446
#define malloc(a)
Definition: header.h:50
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:389
int pqReadData(PGconn *conn)
Definition: fe-misc.c:615
char * c
int pqWait(int forRead, int forWrite, PGconn *conn)
Definition: fe-misc.c:1035
char * inBuffer
Definition: libpq-int.h:444
PQExpBufferData errorMessage
Definition: libpq-int.h:526
int inCursor
Definition: libpq-int.h:447
#define libpq_gettext(x)
Definition: libpq-int.h:805

◆ pqGetCopyData3()

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

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

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

Referenced by PQgetCopyData().

1663 {
1664  int msgLength;
1665 
1666  for (;;)
1667  {
1668  /*
1669  * Collect the next input message. To make life simpler for async
1670  * callers, we keep returning 0 until the next message is fully
1671  * available, even if it is not Copy Data.
1672  */
1673  msgLength = getCopyDataMessage(conn);
1674  if (msgLength < 0)
1675  return msgLength; /* end-of-copy or error */
1676  if (msgLength == 0)
1677  {
1678  /* Don't block if async read requested */
1679  if (async)
1680  return 0;
1681  /* Need to load more data */
1682  if (pqWait(true, false, conn) ||
1683  pqReadData(conn) < 0)
1684  return -2;
1685  continue;
1686  }
1687 
1688  /*
1689  * Drop zero-length messages (shouldn't happen anyway). Otherwise
1690  * pass the data back to the caller.
1691  */
1692  msgLength -= 4;
1693  if (msgLength > 0)
1694  {
1695  *buffer = (char *) malloc(msgLength + 1);
1696  if (*buffer == NULL)
1697  {
1699  libpq_gettext("out of memory\n"));
1700  return -2;
1701  }
1702  memcpy(*buffer, &conn->inBuffer[conn->inCursor], msgLength);
1703  (*buffer)[msgLength] = '\0'; /* Add terminating null */
1704 
1705  /* Mark message consumed */
1706  conn->inStart = conn->inCursor + msgLength;
1707 
1708  return msgLength;
1709  }
1710 
1711  /* Empty, so drop it and loop around for another */
1712  conn->inStart = conn->inCursor;
1713  }
1714 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
int inStart
Definition: libpq-int.h:446
#define malloc(a)
Definition: header.h:50
int pqReadData(PGconn *conn)
Definition: fe-misc.c:615
int pqWait(int forRead, int forWrite, PGconn *conn)
Definition: fe-misc.c:1035
char * inBuffer
Definition: libpq-int.h:444
static int getCopyDataMessage(PGconn *conn)
PQExpBufferData errorMessage
Definition: libpq-int.h:526
int inCursor
Definition: libpq-int.h:447
#define libpq_gettext(x)
Definition: libpq-int.h:805

◆ pqGetErrorNotice3()

int pqGetErrorNotice3 ( PGconn conn,
bool  isError 
)

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

References appendPQExpBufferStr(), PQExpBufferData::data, pg_result::errMsg, pg_conn::errorMessage, pg_result::errQuery, initPQExpBuffer(), pg_conn::last_query, 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, pqBuildErrorMessage3(), PQclear(), pqClearAsyncResult(), PQExpBufferDataBroken, pqGetc(), pqGets(), PQmakeEmptyPGresult(), pqResultStrdup(), pqSaveMessageField(), printfPQExpBuffer(), resetPQExpBuffer(), pg_conn::result, pg_result::resultStatus, pg_conn::show_context, strlcpy(), termPQExpBuffer(), and pg_conn::verbosity.

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

872 {
873  PGresult *res = NULL;
874  bool have_position = false;
875  PQExpBufferData workBuf;
876  char id;
877 
878  /*
879  * If this is an error message, pre-emptively clear any incomplete query
880  * result we may have. We'd just throw it away below anyway, and
881  * releasing it before collecting the error might avoid out-of-memory.
882  */
883  if (isError)
884  pqClearAsyncResult(conn);
885 
886  /*
887  * Since the fields might be pretty long, we create a temporary
888  * PQExpBuffer rather than using conn->workBuffer. workBuffer is intended
889  * for stuff that is expected to be short. We shouldn't use
890  * conn->errorMessage either, since this might be only a notice.
891  */
892  initPQExpBuffer(&workBuf);
893 
894  /*
895  * Make a PGresult to hold the accumulated fields. We temporarily lie
896  * about the result status, so that PQmakeEmptyPGresult doesn't uselessly
897  * copy conn->errorMessage.
898  *
899  * NB: This allocation can fail, if you run out of memory. The rest of the
900  * function handles that gracefully, and we still try to set the error
901  * message as the connection's error message.
902  */
904  if (res)
906 
907  /*
908  * Read the fields and save into res.
909  *
910  * While at it, save the SQLSTATE in conn->last_sqlstate, and note whether
911  * we saw a PG_DIAG_STATEMENT_POSITION field.
912  */
913  for (;;)
914  {
915  if (pqGetc(&id, conn))
916  goto fail;
917  if (id == '\0')
918  break; /* terminator found */
919  if (pqGets(&workBuf, conn))
920  goto fail;
921  pqSaveMessageField(res, id, workBuf.data);
922  if (id == PG_DIAG_SQLSTATE)
923  strlcpy(conn->last_sqlstate, workBuf.data,
924  sizeof(conn->last_sqlstate));
925  else if (id == PG_DIAG_STATEMENT_POSITION)
926  have_position = true;
927  }
928 
929  /*
930  * Save the active query text, if any, into res as well; but only if we
931  * might need it for an error cursor display, which is only true if there
932  * is a PG_DIAG_STATEMENT_POSITION field.
933  */
934  if (have_position && conn->last_query && res)
935  res->errQuery = pqResultStrdup(res, conn->last_query);
936 
937  /*
938  * Now build the "overall" error message for PQresultErrorMessage.
939  */
940  resetPQExpBuffer(&workBuf);
941  pqBuildErrorMessage3(&workBuf, res, conn->verbosity, conn->show_context);
942 
943  /*
944  * Either save error as current async result, or just emit the notice.
945  */
946  if (isError)
947  {
948  if (res)
949  res->errMsg = pqResultStrdup(res, workBuf.data);
950  pqClearAsyncResult(conn); /* redundant, but be safe */
951  conn->result = res;
952  if (PQExpBufferDataBroken(workBuf))
954  libpq_gettext("out of memory"));
955  else
956  appendPQExpBufferStr(&conn->errorMessage, workBuf.data);
957  }
958  else
959  {
960  /* if we couldn't allocate the result set, just discard the NOTICE */
961  if (res)
962  {
963  /* We can cheat a little here and not copy the message. */
964  res->errMsg = workBuf.data;
965  if (res->noticeHooks.noticeRec != NULL)
967  PQclear(res);
968  }
969  }
970 
971  termPQExpBuffer(&workBuf);
972  return 0;
973 
974 fail:
975  PQclear(res);
976  termPQExpBuffer(&workBuf);
977  return EOF;
978 }
PGContextVisibility show_context
Definition: libpq-int.h:440
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
int pqGets(PQExpBuffer buf, PGconn *conn)
Definition: fe-misc.c:149
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:131
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
#define PG_DIAG_SQLSTATE
Definition: postgres_ext.h:57
char * errMsg
Definition: libpq-int.h:196
PGresult * result
Definition: libpq-int.h:465
PGNoticeHooks noticeHooks
Definition: libpq-int.h:186
PGVerbosity verbosity
Definition: libpq-int.h:439
PQnoticeReceiver noticeRec
Definition: libpq-int.h:152
PGresult * PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
Definition: fe-exec.c:141
char * last_query
Definition: libpq-int.h:392
#define PG_DIAG_STATEMENT_POSITION
Definition: postgres_ext.h:61
char * errQuery
Definition: libpq-int.h:198
int pqGetc(char *result, PGconn *conn)
Definition: fe-misc.c:80
void pqSaveMessageField(PGresult *res, char code, const char *value)
Definition: fe-exec.c:993
PQExpBufferData errorMessage
Definition: libpq-int.h:526
void PQclear(PGresult *res)
Definition: fe-exec.c:694
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
#define PQExpBufferDataBroken(buf)
Definition: pqexpbuffer.h:67
void pqBuildErrorMessage3(PQExpBuffer msg, const PGresult *res, PGVerbosity verbosity, PGContextVisibility show_context)
Definition: fe-protocol3.c:985
void pqClearAsyncResult(PGconn *conn)
Definition: fe-exec.c:749
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:148
ExecStatusType resultStatus
Definition: libpq-int.h:177
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92
#define libpq_gettext(x)
Definition: libpq-int.h:805
char * pqResultStrdup(PGresult *res, const char *str)
Definition: fe-exec.c:646
void * noticeRecArg
Definition: libpq-int.h:153
char last_sqlstate[6]
Definition: libpq-int.h:393

◆ pqGetHomeDirectory()

bool pqGetHomeDirectory ( char *  buf,
int  bufsize 
)

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

References pqGetpwuid(), snprintf, and strlcpy().

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

7176 {
7177 #ifndef WIN32
7178  char pwdbuf[BUFSIZ];
7179  struct passwd pwdstr;
7180  struct passwd *pwd = NULL;
7181 
7182  (void) pqGetpwuid(geteuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd);
7183  if (pwd == NULL)
7184  return false;
7185  strlcpy(buf, pwd->pw_dir, bufsize);
7186  return true;
7187 #else
7188  char tmppath[MAX_PATH];
7189 
7190  ZeroMemory(tmppath, sizeof(tmppath));
7191  if (SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, tmppath) != S_OK)
7192  return false;
7193  snprintf(buf, bufsize, "%s/postgresql", tmppath);
7194  return true;
7195 #endif
7196 }
static char * buf
Definition: pg_test_fsync.c:68
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
int pqGetpwuid(uid_t uid, struct passwd *resultbuf, char *buffer, size_t buflen, struct passwd **result)
Definition: thread.c:65
#define snprintf
Definition: port.h:215

◆ pqGetInt()

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

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

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

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

254 {
255  uint16 tmp2;
256  uint32 tmp4;
257 
258  switch (bytes)
259  {
260  case 2:
261  if (conn->inCursor + 2 > conn->inEnd)
262  return EOF;
263  memcpy(&tmp2, conn->inBuffer + conn->inCursor, 2);
264  conn->inCursor += 2;
265  *result = (int) pg_ntoh16(tmp2);
266  break;
267  case 4:
268  if (conn->inCursor + 4 > conn->inEnd)
269  return EOF;
270  memcpy(&tmp4, conn->inBuffer + conn->inCursor, 4);
271  conn->inCursor += 4;
272  *result = (int) pg_ntoh32(tmp4);
273  break;
274  default:
276  "integer of size %lu not supported by pqGetInt",
277  (unsigned long) bytes);
278  return EOF;
279  }
280 
281  if (conn->Pfdebug)
282  fprintf(conn->Pfdebug, "From backend (#%lu)> %d\n", (unsigned long) bytes, *result);
283 
284  return 0;
285 }
int inEnd
Definition: libpq-int.h:448
def bytes(source, encoding='ascii', errors='strict')
#define pg_ntoh16(x)
Definition: pg_bswap.h:124
#define fprintf
Definition: port.h:219
FILE * Pfdebug
Definition: libpq-int.h:377
unsigned short uint16
Definition: c.h:374
#define pg_ntoh32(x)
Definition: pg_bswap.h:125
PGNoticeHooks noticeHooks
Definition: libpq-int.h:380
void pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt,...)
Definition: fe-exec.c:871
unsigned int uint32
Definition: c.h:375
char * inBuffer
Definition: libpq-int.h:444
int inCursor
Definition: libpq-int.h:447

◆ pqGetline2()

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

Definition at line 1236 of file fe-protocol2.c.

References pg_conn::asyncStatus, pg_conn::inBuffer, pg_conn::inEnd, pg_conn::inStart, PGASYNC_COPY_OUT, PGINVALID_SOCKET, pqReadData(), pqWait(), and pg_conn::sock.

Referenced by PQgetline().

1237 {
1238  int result = 1; /* return value if buffer overflows */
1239 
1240  if (conn->sock == PGINVALID_SOCKET ||
1241  conn->asyncStatus != PGASYNC_COPY_OUT)
1242  {
1243  *s = '\0';
1244  return EOF;
1245  }
1246 
1247  /*
1248  * Since this is a purely synchronous routine, we don't bother to maintain
1249  * conn->inCursor; there is no need to back up.
1250  */
1251  while (maxlen > 1)
1252  {
1253  if (conn->inStart < conn->inEnd)
1254  {
1255  char c = conn->inBuffer[conn->inStart++];
1256 
1257  if (c == '\n')
1258  {
1259  result = 0; /* success exit */
1260  break;
1261  }
1262  *s++ = c;
1263  maxlen--;
1264  }
1265  else
1266  {
1267  /* need to load more data */
1268  if (pqWait(true, false, conn) ||
1269  pqReadData(conn) < 0)
1270  {
1271  result = EOF;
1272  break;
1273  }
1274  }
1275  }
1276  *s = '\0';
1277 
1278  return result;
1279 }
int inEnd
Definition: libpq-int.h:448
int inStart
Definition: libpq-int.h:446
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:389
int pqReadData(PGconn *conn)
Definition: fe-misc.c:615
char * c
int pqWait(int forRead, int forWrite, PGconn *conn)
Definition: fe-misc.c:1035
pgsocket sock
Definition: libpq-int.h:410
#define PGINVALID_SOCKET
Definition: port.h:33
char * inBuffer
Definition: libpq-int.h:444

◆ pqGetline3()

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

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

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

Referenced by PQgetline().

1723 {
1724  int status;
1725 
1726  if (conn->sock == PGINVALID_SOCKET ||
1727  (conn->asyncStatus != PGASYNC_COPY_OUT &&
1728  conn->asyncStatus != PGASYNC_COPY_BOTH) ||
1729  conn->copy_is_binary)
1730  {
1732  libpq_gettext("PQgetline: not doing text COPY OUT\n"));
1733  *s = '\0';
1734  return EOF;
1735  }
1736 
1737  while ((status = PQgetlineAsync(conn, s, maxlen - 1)) == 0)
1738  {
1739  /* need to load more data */
1740  if (pqWait(true, false, conn) ||
1741  pqReadData(conn) < 0)
1742  {
1743  *s = '\0';
1744  return EOF;
1745  }
1746  }
1747 
1748  if (status < 0)
1749  {
1750  /* End of copy detected; gin up old-style terminator */
1751  strcpy(s, "\\.");
1752  return 0;
1753  }
1754 
1755  /* Add null terminator, and strip trailing \n if present */
1756  if (s[status - 1] == '\n')
1757  {
1758  s[status - 1] = '\0';
1759  return 0;
1760  }
1761  else
1762  {
1763  s[status] = '\0';
1764  return 1;
1765  }
1766 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
int PQgetlineAsync(PGconn *conn, char *buffer, int bufsize)
Definition: fe-exec.c:2565
char copy_is_binary
Definition: libpq-int.h:398
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:389
int pqReadData(PGconn *conn)
Definition: fe-misc.c:615
int pqWait(int forRead, int forWrite, PGconn *conn)
Definition: fe-misc.c:1035
pgsocket sock
Definition: libpq-int.h:410
#define PGINVALID_SOCKET
Definition: port.h:33
PQExpBufferData errorMessage
Definition: libpq-int.h:526
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227
#define libpq_gettext(x)
Definition: libpq-int.h:805

◆ pqGetlineAsync2()

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

Definition at line 1287 of file fe-protocol2.c.

References pg_conn::asyncStatus, pg_conn::inBuffer, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, and PGASYNC_COPY_OUT.

Referenced by PQgetlineAsync().

1288 {
1289  int avail;
1290 
1291  if (conn->asyncStatus != PGASYNC_COPY_OUT)
1292  return -1; /* we are not doing a copy... */
1293 
1294  /*
1295  * Move data from libpq's buffer to the caller's. We want to accept data
1296  * only in units of whole lines, not partial lines. This ensures that we
1297  * can recognize the terminator line "\\.\n". (Otherwise, if it happened
1298  * to cross a packet/buffer boundary, we might hand the first one or two
1299  * characters off to the caller, which we shouldn't.)
1300  */
1301 
1302  conn->inCursor = conn->inStart;
1303 
1304  avail = bufsize;
1305  while (avail > 0 && conn->inCursor < conn->inEnd)
1306  {
1307  char c = conn->inBuffer[conn->inCursor++];
1308 
1309  *buffer++ = c;
1310  --avail;
1311  if (c == '\n')
1312  {
1313  /* Got a complete line; mark the data removed from libpq */
1314  conn->inStart = conn->inCursor;
1315  /* Is it the endmarker line? */
1316  if (bufsize - avail == 3 && buffer[-3] == '\\' && buffer[-2] == '.')
1317  return -1;
1318  /* No, return the data line to the caller */
1319  return bufsize - avail;
1320  }
1321  }
1322 
1323  /*
1324  * We don't have a complete line. We'd prefer to leave it in libpq's
1325  * buffer until the rest arrives, but there is a special case: what if the
1326  * line is longer than the buffer the caller is offering us? In that case
1327  * we'd better hand over a partial line, else we'd get into an infinite
1328  * loop. Do this in a way that ensures we can't misrecognize a terminator
1329  * line later: leave last 3 characters in libpq buffer.
1330  */
1331  if (avail == 0 && bufsize > 3)
1332  {
1333  conn->inStart = conn->inCursor - 3;
1334  return bufsize - 3;
1335  }
1336  return 0;
1337 }
int inEnd
Definition: libpq-int.h:448
int inStart
Definition: libpq-int.h:446
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:389
char * c
char * inBuffer
Definition: libpq-int.h:444
int inCursor
Definition: libpq-int.h:447

◆ pqGetlineAsync3()

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

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

References pg_conn::asyncStatus, 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().

1775 {
1776  int msgLength;
1777  int avail;
1778 
1779  if (conn->asyncStatus != PGASYNC_COPY_OUT
1780  && conn->asyncStatus != PGASYNC_COPY_BOTH)
1781  return -1; /* we are not doing a copy... */
1782 
1783  /*
1784  * Recognize the next input message. To make life simpler for async
1785  * callers, we keep returning 0 until the next message is fully available
1786  * even if it is not Copy Data. This should keep PQendcopy from blocking.
1787  * (Note: unlike pqGetCopyData3, we do not change asyncStatus here.)
1788  */
1789  msgLength = getCopyDataMessage(conn);
1790  if (msgLength < 0)
1791  return -1; /* end-of-copy or error */
1792  if (msgLength == 0)
1793  return 0; /* no data yet */
1794 
1795  /*
1796  * Move data from libpq's buffer to the caller's. In the case where a
1797  * prior call found the caller's buffer too small, we use
1798  * conn->copy_already_done to remember how much of the row was already
1799  * returned to the caller.
1800  */
1801  conn->inCursor += conn->copy_already_done;
1802  avail = msgLength - 4 - conn->copy_already_done;
1803  if (avail <= bufsize)
1804  {
1805  /* Able to consume the whole message */
1806  memcpy(buffer, &conn->inBuffer[conn->inCursor], avail);
1807  /* Mark message consumed */
1808  conn->inStart = conn->inCursor + avail;
1809  /* Reset state for next time */
1810  conn->copy_already_done = 0;
1811  return avail;
1812  }
1813  else
1814  {
1815  /* We must return a partial message */
1816  memcpy(buffer, &conn->inBuffer[conn->inCursor], bufsize);
1817  /* The message is NOT consumed from libpq's buffer */
1818  conn->copy_already_done += bufsize;
1819  return bufsize;
1820  }
1821 }
int inStart
Definition: libpq-int.h:446
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:389
char * inBuffer
Definition: libpq-int.h:444
static int getCopyDataMessage(PGconn *conn)
int copy_already_done
Definition: libpq-int.h:399
int inCursor
Definition: libpq-int.h:447

◆ pqGetnchar()

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

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

References fprintf, pg_conn::inBuffer, pg_conn::inCursor, pg_conn::inEnd, and pg_conn::Pfdebug.

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

182 {
183  if (len > (size_t) (conn->inEnd - conn->inCursor))
184  return EOF;
185 
186  memcpy(s, conn->inBuffer + conn->inCursor, len);
187  /* no terminating null */
188 
189  conn->inCursor += len;
190 
191  if (conn->Pfdebug)
192  {
193  fprintf(conn->Pfdebug, "From backend (%lu)> ", (unsigned long) len);
194  fwrite(s, 1, len, conn->Pfdebug);
195  fprintf(conn->Pfdebug, "\n");
196  }
197 
198  return 0;
199 }
int inEnd
Definition: libpq-int.h:448
#define fprintf
Definition: port.h:219
FILE * Pfdebug
Definition: libpq-int.h:377
char * inBuffer
Definition: libpq-int.h:444
int inCursor
Definition: libpq-int.h:447

◆ pqGets()

int pqGets ( PQExpBuffer  buf,
PGconn conn 
)

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

References pqGets_internal().

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

150 {
151  return pqGets_internal(buf, conn, true);
152 }
static int pqGets_internal(PQExpBuffer buf, PGconn *conn, bool resetbuffer)
Definition: fe-misc.c:118

◆ pqGets_append()

int pqGets_append ( PQExpBuffer  buf,
PGconn conn 
)

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

References pqGets_internal().

Referenced by PQconnectPoll().

156 {
157  return pqGets_internal(buf, conn, false);
158 }
static int pqGets_internal(PQExpBuffer buf, PGconn *conn, bool resetbuffer)
Definition: fe-misc.c:118

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

References DefaultHost, free, hostname, i, _internalPQconninfoOption::keyword, _PQconninfoOption::keyword, libpq_gettext, malloc, pg_strcasecmp(), pg_strncasecmp(), port, pqFlush(), pqPutMsgEnd(), pqPutMsgStart(), pqPutnchar(), printfPQExpBuffer(), STATUS_ERROR, STATUS_OK, _internalPQconninfoOption::val, _PQconninfoOption::val, and values.

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

4521 {
4522  /* Start the message. */
4523  if (pqPutMsgStart(pack_type, true, conn))
4524  return STATUS_ERROR;
4525 
4526  /* Send the message body. */
4527  if (pqPutnchar(buf, buf_len, conn))
4528  return STATUS_ERROR;
4529 
4530  /* Finish the message. */
4531  if (pqPutMsgEnd(conn))
4532  return STATUS_ERROR;
4533 
4534  /* Flush to ensure backend gets it. */
4535  if (pqFlush(conn))
4536  return STATUS_ERROR;
4537 
4538  return STATUS_OK;
4539 }
int pqFlush(PGconn *conn)
Definition: fe-misc.c:1012
int pqPutMsgStart(char msg_type, bool force_len, PGconn *conn)
Definition: fe-misc.c:505
#define STATUS_ERROR
Definition: c.h:1113
static char * buf
Definition: pg_test_fsync.c:68
#define STATUS_OK
Definition: c.h:1112
int pqPutnchar(const char *s, size_t len, PGconn *conn)
Definition: fe-misc.c:232
int pqPutMsgEnd(PGconn *conn)
Definition: fe-misc.c:573

◆ pqParseInput2()

void pqParseInput2 ( PGconn conn)

Definition at line 405 of file fe-protocol2.c.

References pg_conn::asyncStatus, pg_conn::be_key, pg_conn::be_pid, checkXactStatus(), pg_result::cmdStatus, CMDSTATUS_LEN, PQExpBufferData::data, pg_conn::errorMessage, getAnotherTuple(), getNotify(), getRowDescriptions(), pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, libpq_gettext, pg_conn::noticeHooks, PGASYNC_BUSY, PGASYNC_COPY_IN, PGASYNC_COPY_OUT, PGASYNC_IDLE, PGASYNC_READY, PGRES_COMMAND_OK, PGRES_EMPTY_QUERY, pqGetc(), pqGetErrorNotice2(), pqGetInt(), pqGets(), pqInternalNotice(), PQmakeEmptyPGresult(), pqSaveErrorResult(), printfPQExpBuffer(), pg_conn::result, strlcpy(), and pg_conn::workBuffer.

Referenced by parseInput().

406 {
407  char id;
408 
409  /*
410  * Loop to parse successive complete messages available in the buffer.
411  */
412  for (;;)
413  {
414  /*
415  * Quit if in COPY_OUT state: we expect raw data from the server until
416  * PQendcopy is called. Don't try to parse it according to the normal
417  * protocol. (This is bogus. The data lines ought to be part of the
418  * protocol and have identifying leading characters.)
419  */
420  if (conn->asyncStatus == PGASYNC_COPY_OUT)
421  return;
422 
423  /*
424  * OK to try to read a message type code.
425  */
426  conn->inCursor = conn->inStart;
427  if (pqGetc(&id, conn))
428  return;
429 
430  /*
431  * NOTIFY and NOTICE messages can happen in any state besides COPY
432  * OUT; always process them right away.
433  *
434  * Most other messages should only be processed while in BUSY state.
435  * (In particular, in READY state we hold off further parsing until
436  * the application collects the current PGresult.)
437  *
438  * However, if the state is IDLE then we got trouble; we need to deal
439  * with the unexpected message somehow.
440  */
441  if (id == 'A')
442  {
443  if (getNotify(conn))
444  return;
445  }
446  else if (id == 'N')
447  {
448  if (pqGetErrorNotice2(conn, false))
449  return;
450  }
451  else if (conn->asyncStatus != PGASYNC_BUSY)
452  {
453  /* If not IDLE state, just wait ... */
454  if (conn->asyncStatus != PGASYNC_IDLE)
455  return;
456 
457  /*
458  * Unexpected message in IDLE state; need to recover somehow.
459  * ERROR messages are displayed using the notice processor;
460  * anything else is just dropped on the floor after displaying a
461  * suitable warning notice. (An ERROR is very possibly the
462  * backend telling us why it is about to close the connection, so
463  * we don't want to just discard it...)
464  */
465  if (id == 'E')
466  {
467  if (pqGetErrorNotice2(conn, false /* treat as notice */ ))
468  return;
469  }
470  else
471  {
473  "message type 0x%02x arrived from server while idle",
474  id);
475  /* Discard the unexpected message; good idea?? */
476  conn->inStart = conn->inEnd;
477  break;
478  }
479  }
480  else
481  {
482  /*
483  * In BUSY state, we can process everything.
484  */
485  switch (id)
486  {
487  case 'C': /* command complete */
488  if (pqGets(&conn->workBuffer, conn))
489  return;
490  if (conn->result == NULL)
491  {
492  conn->result = PQmakeEmptyPGresult(conn,
494  if (!conn->result)
495  {
497  libpq_gettext("out of memory"));
498  pqSaveErrorResult(conn);
499  }
500  }
501  if (conn->result)
502  {
503  strlcpy(conn->result->cmdStatus, conn->workBuffer.data,
504  CMDSTATUS_LEN);
505  }
506  checkXactStatus(conn, conn->workBuffer.data);
507  conn->asyncStatus = PGASYNC_READY;
508  break;
509  case 'E': /* error return */
510  if (pqGetErrorNotice2(conn, true))
511  return;
512  conn->asyncStatus = PGASYNC_READY;
513  break;
514  case 'Z': /* backend is ready for new query */
515  conn->asyncStatus = PGASYNC_IDLE;
516  break;
517  case 'I': /* empty query */
518  /* read and throw away the closing '\0' */
519  if (pqGetc(&id, conn))
520  return;
521  if (id != '\0')
523  "unexpected character %c following empty query response (\"I\" message)",
524  id);
525  if (conn->result == NULL)
526  {
527  conn->result = PQmakeEmptyPGresult(conn,
529  if (!conn->result)
530  {
532  libpq_gettext("out of memory"));
533  pqSaveErrorResult(conn);
534  }
535  }
536  conn->asyncStatus = PGASYNC_READY;
537  break;
538  case 'K': /* secret key data from the backend */
539 
540  /*
541  * This is expected only during backend startup, but it's
542  * just as easy to handle it as part of the main loop.
543  * Save the data and continue processing.
544  */
545  if (pqGetInt(&(conn->be_pid), 4, conn))
546  return;
547  if (pqGetInt(&(conn->be_key), 4, conn))
548  return;
549  break;
550  case 'P': /* synchronous (normal) portal */
551  if (pqGets(&conn->workBuffer, conn))
552  return;
553  /* We pretty much ignore this message type... */
554  break;
555  case 'T': /* row descriptions (start of query results) */
556  if (conn->result == NULL)
557  {
558  /* First 'T' in a query sequence */
559  if (getRowDescriptions(conn))
560  return;
561  /* getRowDescriptions() moves inStart itself */
562  continue;
563  }
564  else
565  {
566  /*
567  * A new 'T' message is treated as the start of
568  * another PGresult. (It is not clear that this is
569  * really possible with the current backend.) We stop
570  * parsing until the application accepts the current
571  * result.
572  */
573  conn->asyncStatus = PGASYNC_READY;
574  return;
575  }
576  break;
577  case 'D': /* ASCII data tuple */
578  if (conn->result != NULL)
579  {
580  /* Read another tuple of a normal query response */
581  if (getAnotherTuple(conn, false))
582  return;
583  /* getAnotherTuple() moves inStart itself */
584  continue;
585  }
586  else
587  {
589  "server sent data (\"D\" message) without prior row description (\"T\" message)");
590  /* Discard the unexpected message; good idea?? */
591  conn->inStart = conn->inEnd;
592  return;
593  }
594  break;
595  case 'B': /* Binary data tuple */
596  if (conn->result != NULL)
597  {
598  /* Read another tuple of a normal query response */
599  if (getAnotherTuple(conn, true))
600  return;
601  /* getAnotherTuple() moves inStart itself */
602  continue;
603  }
604  else
605  {
607  "server sent binary data (\"B\" message) without prior row description (\"T\" message)");
608  /* Discard the unexpected message; good idea?? */
609  conn->inStart = conn->inEnd;
610  return;
611  }
612  break;
613  case 'G': /* Start Copy In */
615  break;
616  case 'H': /* Start Copy Out */
618  break;
619 
620  /*
621  * Don't need to process CopyBothResponse here because it
622  * never arrives from the server during protocol 2.0.
623  */
624  default:
626  libpq_gettext("unexpected response from server; first received character was \"%c\"\n"),
627  id);
628  /* build an error result holding the error message */
629  pqSaveErrorResult(conn);
630  /* Discard the unexpected message; good idea?? */
631  conn->inStart = conn->inEnd;
632  conn->asyncStatus = PGASYNC_READY;
633  return;
634  } /* switch on protocol character */
635  }
636  /* Successfully consumed this message */
637  conn->inStart = conn->inCursor;
638  }
639 }
static void checkXactStatus(PGconn *conn, const char *cmdTag)
int inEnd
Definition: libpq-int.h:448
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
int inStart
Definition: libpq-int.h:446
static int getRowDescriptions(PGconn *conn)
Definition: fe-protocol2.c:652
int pqGets(PQExpBuffer buf, PGconn *conn)
Definition: fe-misc.c:149
PQExpBufferData workBuffer
Definition: libpq-int.h:529
int pqGetInt(int *result, size_t bytes, PGconn *conn)
Definition: fe-misc.c:253
#define CMDSTATUS_LEN
Definition: libpq-int.h:86
PGresult * result
Definition: libpq-int.h:465
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:389
PGNoticeHooks noticeHooks
Definition: libpq-int.h:380
static int getAnotherTuple(PGconn *conn, bool binary)
Definition: fe-protocol2.c:783
void pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt,...)
Definition: fe-exec.c:871
PGresult * PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
Definition: fe-exec.c:141
int pqGetc(char *result, PGconn *conn)
Definition: fe-misc.c:80
static int getNotify(PGconn *conn)
PQExpBufferData errorMessage
Definition: libpq-int.h:526
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
char cmdStatus[CMDSTATUS_LEN]
Definition: libpq-int.h:178
int be_key
Definition: libpq-int.h:435
void pqSaveErrorResult(PGconn *conn)
Definition: fe-exec.c:772
int inCursor
Definition: libpq-int.h:447
int be_pid
Definition: libpq-int.h:434
#define libpq_gettext(x)
Definition: libpq-int.h:805
static int pqGetErrorNotice2(PGconn *conn, bool isError)
Definition: fe-protocol2.c:956

◆ pqParseInput3()

void pqParseInput3 ( PGconn conn)

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

References pg_conn::asyncStatus, pg_conn::be_key, pg_conn::be_pid, pg_result::cmdStatus, CMDSTATUS_LEN, pg_conn::copy_already_done, PQExpBufferData::data, pg_conn::errorMessage, getAnotherTuple(), getCopyStart(), getNotify(), getParamDescriptions(), getParameterStatus(), getReadyForQuery(), getRowDescriptions(), handleSyncLoss(), pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, libpq_gettext, pg_conn::noticeHooks, PGASYNC_BUSY, PGASYNC_COPY_BOTH, PGASYNC_COPY_IN, PGASYNC_COPY_OUT, PGASYNC_IDLE, PGASYNC_READY, PGQUERY_DESCRIBE, PGQUERY_PREPARE, PGRES_COMMAND_OK, PGRES_COPY_BOTH, PGRES_COPY_IN, PGRES_COPY_OUT, PGRES_EMPTY_QUERY, PGRES_FATAL_ERROR, PGRES_TUPLES_OK, pqCheckInBufferSpace(), pqGetc(), pqGetErrorNotice3(), pqGetInt(), pqGets(), pqInternalNotice(), PQmakeEmptyPGresult(), pqSaveErrorResult(), printfPQExpBuffer(), pg_conn::queryclass, pg_conn::result, pg_result::resultStatus, strlcpy(), VALID_LONG_MESSAGE_TYPE, and pg_conn::workBuffer.

Referenced by parseInput().

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  */
78  conn->inCursor = conn->inStart;
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  {
177  if (getParameterStatus(conn))
178  return;
179  }
180  else
181  {
183  "message type 0x%02x arrived from server while idle",
184  id);
185  /* Discard the unexpected message */
186  conn->inCursor += msgLength;
187  }
188  }
189  else
190  {
191  /*
192  * In BUSY state, we can process everything.
193  */
194  switch (id)
195  {
196  case 'C': /* command complete */
197  if (pqGets(&conn->workBuffer, conn))
198  return;
199  if (conn->result == NULL)
200  {
201  conn->result = PQmakeEmptyPGresult(conn,
203  if (!conn->result)
204  {
206  libpq_gettext("out of memory"));
207  pqSaveErrorResult(conn);
208  }
209  }
210  if (conn->result)
211  strlcpy(conn->result->cmdStatus, conn->workBuffer.data,
212  CMDSTATUS_LEN);
213  conn->asyncStatus = PGASYNC_READY;
214  break;
215  case 'E': /* error return */
216  if (pqGetErrorNotice3(conn, true))
217  return;
218  conn->asyncStatus = PGASYNC_READY;
219  break;
220  case 'Z': /* backend is ready for new query */
221  if (getReadyForQuery(conn))
222  return;
223  conn->asyncStatus = PGASYNC_IDLE;
224  break;
225  case 'I': /* empty query */
226  if (conn->result == NULL)
227  {
228  conn->result = PQmakeEmptyPGresult(conn,
230  if (!conn->result)
231  {
233  libpq_gettext("out of memory"));
234  pqSaveErrorResult(conn);
235  }
236  }
237  conn->asyncStatus = PGASYNC_READY;
238  break;
239  case '1': /* Parse Complete */
240  /* If we're doing PQprepare, we're done; else ignore */
241  if (conn->queryclass == PGQUERY_PREPARE)
242  {
243  if (conn->result == NULL)
244  {
245  conn->result = PQmakeEmptyPGresult(conn,
247  if (!conn->result)
248  {
250  libpq_gettext("out of memory"));
251  pqSaveErrorResult(conn);
252  }
253  }
254  conn->asyncStatus = PGASYNC_READY;
255  }
256  break;
257  case '2': /* Bind Complete */
258  case '3': /* Close Complete */
259  /* Nothing to do for these message types */
260  break;
261  case 'S': /* parameter status */
262  if (getParameterStatus(conn))
263  return;
264  break;
265  case 'K': /* secret key data from the backend */
266 
267  /*
268  * This is expected only during backend startup, but it's
269  * just as easy to handle it as part of the main loop.
270  * Save the data and continue processing.
271  */
272  if (pqGetInt(&(conn->be_pid), 4, conn))
273  return;
274  if (pqGetInt(&(conn->be_key), 4, conn))
275  return;
276  break;
277  case 'T': /* Row Description */
278  if (conn->result != NULL &&
280  {
281  /*
282  * We've already choked for some reason. Just discard
283  * the data till we get to the end of the query.
284  */
285  conn->inCursor += msgLength;
286  }
287  else if (conn->result == NULL ||
288  conn->queryclass == PGQUERY_DESCRIBE)
289  {
290  /* First 'T' in a query sequence */
291  if (getRowDescriptions(conn, msgLength))
292  return;
293  /* getRowDescriptions() moves inStart itself */
294  continue;
295  }
296  else
297  {
298  /*
299  * A new 'T' message is treated as the start of
300  * another PGresult. (It is not clear that this is
301  * really possible with the current backend.) We stop
302  * parsing until the application accepts the current
303  * result.
304  */
305  conn->asyncStatus = PGASYNC_READY;
306  return;
307  }
308  break;
309  case 'n': /* No Data */
310 
311  /*
312  * NoData indicates that we will not be seeing a
313  * RowDescription message because the statement or portal
314  * inquired about doesn't return rows.
315  *
316  * If we're doing a Describe, we have to pass something
317  * back to the client, so set up a COMMAND_OK result,
318  * instead of PGRES_TUPLES_OK. Otherwise we can just
319  * ignore this message.
320  */
321  if (conn->queryclass == PGQUERY_DESCRIBE)
322  {
323  if (conn->result == NULL)
324  {
325  conn->result = PQmakeEmptyPGresult(conn,
327  if (!conn->result)
328  {
330  libpq_gettext("out of memory"));
331  pqSaveErrorResult(conn);
332  }
333  }
334  conn->asyncStatus = PGASYNC_READY;
335  }
336  break;
337  case 't': /* Parameter Description */
338  if (getParamDescriptions(conn, msgLength))
339  return;
340  /* getParamDescriptions() moves inStart itself */
341  continue;
342  case 'D': /* Data Row */
343  if (conn->result != NULL &&
345  {
346  /* Read another tuple of a normal query response */
347  if (getAnotherTuple(conn, msgLength))
348  return;
349  /* getAnotherTuple() moves inStart itself */
350  continue;
351  }
352  else if (conn->result != NULL &&
354  {
355  /*
356  * We've already choked for some reason. Just discard
357  * tuples till we get to the end of the query.
358  */
359  conn->inCursor += msgLength;
360  }
361  else
362  {
363  /* Set up to report error at end of query */
365  libpq_gettext("server sent data (\"D\" message) without prior row description (\"T\" message)\n"));
366  pqSaveErrorResult(conn);
367  /* Discard the unexpected message */
368  conn->inCursor += msgLength;
369  }
370  break;
371  case 'G': /* Start Copy In */
372  if (getCopyStart(conn, PGRES_COPY_IN))
373  return;
375  break;
376  case 'H': /* Start Copy Out */
377  if (getCopyStart(conn, PGRES_COPY_OUT))
378  return;
380  conn->copy_already_done = 0;
381  break;
382  case 'W': /* Start Copy Both */
383  if (getCopyStart(conn, PGRES_COPY_BOTH))
384  return;
386  conn->copy_already_done = 0;
387  break;
388  case 'd': /* Copy Data */
389 
390  /*
391  * If we see Copy Data, just silently drop it. This would
392  * only occur if application exits COPY OUT mode too
393  * early.
394  */
395  conn->inCursor += msgLength;
396  break;
397  case 'c': /* Copy Done */
398 
399  /*
400  * If we see Copy Done, just silently drop it. This is
401  * the normal case during PQendcopy. We will keep
402  * swallowing data, expecting to see command-complete for
403  * the COPY command.
404  */
405  break;
406  default:
408  libpq_gettext("unexpected response from server; first received character was \"%c\"\n"),
409  id);
410  /* build an error result holding the error message */
411  pqSaveErrorResult(conn);
412  /* not sure if we will see more, so go to ready state */
413  conn->asyncStatus = PGASYNC_READY;
414  /* Discard the unexpected message */
415  conn->inCursor += msgLength;
416  break;
417  } /* switch on protocol character */
418  }
419  /* Successfully consumed this message */
420  if (conn->inCursor == conn->inStart + 5 + msgLength)
421  {
422  /* Normal case: parsing agrees with specified length */
423  conn->inStart = conn->inCursor;
424  }
425  else
426  {
427  /* Trouble --- report it */
429  libpq_gettext("message contents do not agree with length in message type \"%c\"\n"),
430  id);
431  /* build an error result holding the error message */
432  pqSaveErrorResult(conn);
433  conn->asyncStatus = PGASYNC_READY;
434  /* trust the specified message length as what to skip */
435  conn->inStart += 5 + msgLength;
436  }
437  }
438 }
int inEnd
Definition: libpq-int.h:448
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
int inStart
Definition: libpq-int.h:446
int pqGets(PQExpBuffer buf, PGconn *conn)
Definition: fe-misc.c:149
PQExpBufferData workBuffer
Definition: libpq-int.h:529
int pqCheckInBufferSpace(size_t bytes_needed, PGconn *conn)
Definition: fe-misc.c:394
PGQueryClass queryclass
Definition: libpq-int.h:391
int pqGetInt(int *result, size_t bytes, PGconn *conn)
Definition: fe-misc.c:253
static int getParamDescriptions(PGconn *conn, int msgLength)
Definition: fe-protocol3.c:646
#define CMDSTATUS_LEN
Definition: libpq-int.h:86
PGresult * result
Definition: libpq-int.h:465
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:389
static int getRowDescriptions(PGconn *conn, int msgLength)
Definition: fe-protocol3.c:468
int pqGetErrorNotice3(PGconn *conn, bool isError)
Definition: fe-protocol3.c:871
PGNoticeHooks noticeHooks
Definition: libpq-int.h:380
static int getAnotherTuple(PGconn *conn, int msgLength)
Definition: fe-protocol3.c:743
void pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt,...)
Definition: fe-exec.c:871
PGresult * PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
Definition: fe-exec.c:141
int pqGetc(char *result, PGconn *conn)
Definition: fe-misc.c:80
#define VALID_LONG_MESSAGE_TYPE(id)
Definition: fe-protocol3.c:38
PQExpBufferData errorMessage
Definition: libpq-int.h:526
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
static int getReadyForQuery(PGconn *conn)
static int getCopyStart(PGconn *conn, ExecStatusType copytype)
char cmdStatus[CMDSTATUS_LEN]
Definition: libpq-int.h:178
int be_key
Definition: libpq-int.h:435
int copy_already_done
Definition: libpq-int.h:399
static int getParameterStatus(PGconn *conn)
static int getNotify(PGconn *conn)
static void handleSyncLoss(PGconn *conn, char id, int msgLength)
Definition: fe-protocol3.c:446
void pqSaveErrorResult(PGconn *conn)
Definition: fe-exec.c:772
int inCursor
Definition: libpq-int.h:447
int be_pid
Definition: libpq-int.h:434
ExecStatusType resultStatus
Definition: libpq-int.h:177
#define libpq_gettext(x)
Definition: libpq-int.h:805

◆ pqPrepareAsyncResult()

PGresult* pqPrepareAsyncResult ( PGconn conn)

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

References appendPQExpBufferStr(), pg_conn::errorMessage, pg_conn::next_result, PGRES_FATAL_ERROR, PQmakeEmptyPGresult(), PQresultErrorMessage(), resetPQExpBuffer(), and pg_conn::result.

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

827 {
828  PGresult *res;
829 
830  /*
831  * conn->result is the PGresult to return. If it is NULL (which probably
832  * shouldn't happen) we assume there is an appropriate error message in
833  * conn->errorMessage.
834  */
835  res = conn->result;
836  if (!res)
838  else
839  {
840  /*
841  * Make sure PQerrorMessage agrees with result; it could be different
842  * if we have concatenated messages.
843  */
846  PQresultErrorMessage(res));
847  }
848 
849  /*
850  * Replace conn->result with next_result, if any. In the normal case
851  * there isn't a next result and we're just dropping ownership of the
852  * current result. In single-row mode this restores the situation to what
853  * it was before we created the current single-row result.
854  */
855  conn->result = conn->next_result;
856  conn->next_result = NULL;
857 
858  return res;
859 }
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
PGresult * result
Definition: libpq-int.h:465
PGresult * next_result
Definition: libpq-int.h:466
PGresult * PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
Definition: fe-exec.c:141
PQExpBufferData errorMessage
Definition: libpq-int.h:526
char * PQresultErrorMessage(const PGresult *res)
Definition: fe-exec.c:2708
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:148

◆ pqPutc()

int pqPutc ( char  c,
PGconn conn 
)

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

References fprintf, pg_conn::Pfdebug, and pqPutMsgBytes().

Referenced by PQsendDescribe(), and PQsendQueryGuts().

99 {
100  if (pqPutMsgBytes(&c, 1, conn))
101  return EOF;
102 
103  if (conn->Pfdebug)
104  fprintf(conn->Pfdebug, "To backend> %c\n", c);
105 
106  return 0;
107 }
#define fprintf
Definition: port.h:219
FILE * Pfdebug
Definition: libpq-int.h:377
static int pqPutMsgBytes(const void *buf, size_t len, PGconn *conn)
Definition: fe-misc.c:550
char * c

◆ pqPutInt()

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

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

References fprintf, pg_conn::noticeHooks, pg_conn::Pfdebug, pg_hton16, pg_hton32, pqInternalNotice(), and pqPutMsgBytes().

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

294 {
295  uint16 tmp2;
296  uint32 tmp4;
297 
298  switch (bytes)
299  {
300  case 2:
301  tmp2 = pg_hton16((uint16) value);
302  if (pqPutMsgBytes((const char *) &tmp2, 2, conn))
303  return EOF;
304  break;
305  case 4:
306  tmp4 = pg_hton32((uint32) value);
307  if (pqPutMsgBytes((const char *) &tmp4, 4, conn))
308  return EOF;
309  break;
310  default:
312  "integer of size %lu not supported by pqPutInt",
313  (unsigned long) bytes);
314  return EOF;
315  }
316 
317  if (conn->Pfdebug)
318  fprintf(conn->Pfdebug, "To backend (%lu#)> %d\n", (unsigned long) bytes, value);
319 
320  return 0;
321 }
def bytes(source, encoding='ascii', errors='strict')
#define pg_hton16(x)
Definition: pg_bswap.h:120
#define fprintf
Definition: port.h:219
FILE * Pfdebug
Definition: libpq-int.h:377
unsigned short uint16
Definition: c.h:374
#define pg_hton32(x)
Definition: pg_bswap.h:121
PGNoticeHooks noticeHooks
Definition: libpq-int.h:380
static int pqPutMsgBytes(const void *buf, size_t len, PGconn *conn)
Definition: fe-misc.c:550
void pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt,...)
Definition: fe-exec.c:871
unsigned int uint32
Definition: c.h:375
static struct @143 value

◆ pqPutMsgEnd()

int pqPutMsgEnd ( PGconn conn)

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

References fprintf, pg_conn::outBuffer, pg_conn::outCount, pg_conn::outMsgEnd, pg_conn::outMsgStart, pg_conn::Pfdebug, pg_hton32, and pqSendSome().

Referenced by pg_SASL_init(), pqEndcopy3(), pqFunctionCall2(), pqFunctionCall3(), pqPacketSend(), PQputCopyData(), PQputCopyEnd(), PQsendDescribe(), PQsendPrepare(), PQsendQuery(), PQsendQueryGuts(), and sendTerminateConn().

574 {
575  if (conn->Pfdebug)
576  fprintf(conn->Pfdebug, "To backend> Msg complete, length %u\n",
577  conn->outMsgEnd - conn->outCount);
578 
579  /* Fill in length word if needed */
580  if (conn->outMsgStart >= 0)
581  {
582  uint32 msgLen = conn->outMsgEnd - conn->outMsgStart;
583 
584  msgLen = pg_hton32(msgLen);
585  memcpy(conn->outBuffer + conn->outMsgStart, &msgLen, 4);
586  }
587 
588  /* Make message eligible to send */
589  conn->outCount = conn->outMsgEnd;
590 
591  if (conn->outCount >= 8192)
592  {
593  int toSend = conn->outCount - (conn->outCount % 8192);
594 
595  if (pqSendSome(conn, toSend) < 0)
596  return EOF;
597  /* in nonblock mode, don't complain if unable to send it all */
598  }
599 
600  return 0;
601 }
int outCount
Definition: libpq-int.h:453
int outMsgEnd
Definition: libpq-int.h:458
#define fprintf
Definition: port.h:219
FILE * Pfdebug
Definition: libpq-int.h:377
#define pg_hton32(x)
Definition: pg_bswap.h:121
unsigned int uint32
Definition: c.h:375
int outMsgStart
Definition: libpq-int.h:456
char * outBuffer
Definition: libpq-int.h:451
static int pqSendSome(PGconn *conn, int len)
Definition: fe-misc.c:835

◆ pqPutMsgStart()

int pqPutMsgStart ( char  msg_type,
bool  force_len,
PGconn conn 
)

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

References fprintf, pg_conn::outBuffer, pg_conn::outCount, pg_conn::outMsgEnd, pg_conn::outMsgStart, pg_conn::Pfdebug, PG_PROTOCOL_MAJOR, pqCheckOutBufferSpace(), and pg_conn::pversion.

Referenced by pg_SASL_init(), pqEndcopy3(), pqFunctionCall2(), pqFunctionCall3(), pqPacketSend(), PQputCopyData(), PQputCopyEnd(), PQsendDescribe(), PQsendPrepare(), PQsendQuery(), PQsendQueryGuts(), and sendTerminateConn().

506 {
507  int lenPos;
508  int endPos;
509 
510  /* allow room for message type byte */
511  if (msg_type)
512  endPos = conn->outCount + 1;
513  else
514  endPos = conn->outCount;
515 
516  /* do we want a length word? */
517  if (force_len || PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
518  {
519  lenPos = endPos;
520  /* allow room for message length */
521  endPos += 4;
522  }
523  else
524  lenPos = -1;
525 
526  /* make sure there is room for message header */
527  if (pqCheckOutBufferSpace(endPos, conn))
528  return EOF;
529  /* okay, save the message type byte if any */
530  if (msg_type)
531  conn->outBuffer[conn->outCount] = msg_type;
532  /* set up the message pointers */
533  conn->outMsgStart = lenPos;
534  conn->outMsgEnd = endPos;
535  /* length word, if needed, will be filled in by pqPutMsgEnd */
536 
537  if (conn->Pfdebug)
538  fprintf(conn->Pfdebug, "To backend> Msg %c\n",
539  msg_type ? msg_type : ' ');
540 
541  return 0;
542 }
int pqCheckOutBufferSpace(size_t bytes_needed, PGconn *conn)
Definition: fe-misc.c:330
int outCount
Definition: libpq-int.h:453
int outMsgEnd
Definition: libpq-int.h:458
#define PG_PROTOCOL_MAJOR(v)
Definition: pqcomm.h:104
#define fprintf
Definition: port.h:219
FILE * Pfdebug
Definition: libpq-int.h:377
int outMsgStart
Definition: libpq-int.h:456
ProtocolVersion pversion
Definition: libpq-int.h:414
char * outBuffer
Definition: libpq-int.h:451

◆ pqPutnchar()

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

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

References fprintf, pg_conn::Pfdebug, and pqPutMsgBytes().

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

233 {
234  if (pqPutMsgBytes(s, len, conn))
235  return EOF;
236 
237  if (conn->Pfdebug)
238  {
239  fprintf(conn->Pfdebug, "To backend> ");
240  fwrite(s, 1, len, conn->Pfdebug);
241  fprintf(conn->Pfdebug, "\n");
242  }
243 
244  return 0;
245 }
#define fprintf
Definition: port.h:219
FILE * Pfdebug
Definition: libpq-int.h:377
static int pqPutMsgBytes(const void *buf, size_t len, PGconn *conn)
Definition: fe-misc.c:550

◆ pqPuts()

int pqPuts ( const char *  s,
PGconn conn 
)

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

References fprintf, pg_conn::Pfdebug, and pqPutMsgBytes().

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

166 {
167  if (pqPutMsgBytes(s, strlen(s) + 1, conn))
168  return EOF;
169 
170  if (conn->Pfdebug)
171  fprintf(conn->Pfdebug, "To backend> \"%s\"\n", s);
172 
173  return 0;
174 }
#define fprintf
Definition: port.h:219
FILE * Pfdebug
Definition: libpq-int.h:377
static int pqPutMsgBytes(const void *buf, size_t len, PGconn *conn)
Definition: fe-misc.c:550

◆ pqReadData()

int pqReadData ( PGconn conn)

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

References ALL_CONNECTION_FAILURE_ERRNOS, 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(), printfPQExpBuffer(), pg_conn::sock, SOCK_ERRNO, pg_conn::ssl_in_use, and pg_conn::status.

Referenced by PQconnectPoll(), PQconsumeInput(), pqFunctionCall2(), pqFunctionCall3(), pqGetCopyData2(), pqGetCopyData3(), pqGetline2(), pqGetline3(), PQgetResult(), pqSendSome(), and pqSetenvPoll().

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

◆ pqReadReady()

int pqReadReady ( PGconn conn)

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

References pqSocketCheck().

Referenced by gss_read(), and pqReadData().

1073 {
1074  return pqSocketCheck(conn, 1, 0, (time_t) 0);
1075 }
static int pqSocketCheck(PGconn *conn, int forRead, int forWrite, time_t end_time)
Definition: fe-misc.c:1096

◆ pqResultAlloc()

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

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

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, pgresult_data::space, and pg_result::spaceLeft.

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

535 {
536  char *space;
537  PGresult_data *block;
538 
539  if (!res)
540  return NULL;
541 
542  if (nBytes <= 0)
543  return res->null_field;
544 
545  /*
546  * If alignment is needed, round up the current position to an alignment
547  * boundary.
548  */
549  if (isBinary)
550  {
551  int offset = res->curOffset % PGRESULT_ALIGN_BOUNDARY;
552 
553  if (offset)
554  {
555  res->curOffset += PGRESULT_ALIGN_BOUNDARY - offset;
556  res->spaceLeft -= PGRESULT_ALIGN_BOUNDARY - offset;
557  }
558  }
559 
560  /* If there's enough space in the current block, no problem. */
561  if (nBytes <= (size_t) res->spaceLeft)
562  {
563  space = res->curBlock->space + res->curOffset;
564  res->curOffset += nBytes;
565  res->spaceLeft -= nBytes;
566  return space;
567  }
568 
569  /*
570  * If the requested object is very large, give it its own block; this
571  * avoids wasting what might be most of the current block to start a new
572  * block. (We'd have to special-case requests bigger than the block size
573  * anyway.) The object is always given binary alignment in this case.
574  */
575  if (nBytes >= PGRESULT_SEP_ALLOC_THRESHOLD)
576  {
577  size_t alloc_size = nBytes + PGRESULT_BLOCK_OVERHEAD;
578 
579  block = (PGresult_data *) malloc(alloc_size);
580  if (!block)
581  return NULL;
582  res->memorySize += alloc_size;
583  space = block->space + PGRESULT_BLOCK_OVERHEAD;
584  if (res->curBlock)
585  {
586  /*
587  * Tuck special block below the active block, so that we don't
588  * have to waste the free space in the active block.
589  */
590  block->next = res->curBlock->next;
591  res->curBlock->next = block;
592  }
593  else
594  {
595  /* Must set up the new block as the first active block. */
596  block->next = NULL;
597  res->curBlock = block;
598  res->spaceLeft = 0; /* be sure it's marked full */
599  }
600  return space;
601  }
602 
603  /* Otherwise, start a new block. */
605  if (!block)
606  return NULL;
608  block->next = res->curBlock;
609  res->curBlock = block;
610  if (isBinary)
611  {
612  /* object needs full alignment */
615  }
616  else
617  {
618  /* we can cram it right after the overhead pointer */
619  res->curOffset = sizeof(PGresult_data);
621  }
622 
623  space = block->space + res->curOffset;
624  res->curOffset += nBytes;
625  res->spaceLeft -= nBytes;
626  return space;
627 }
size_t memorySize
Definition: libpq-int.h:212
char space[1]
Definition: libpq-int.h:106
PGresult_data * next
Definition: libpq-int.h:105
union pgresult_data PGresult_data
Definition: libpq-int.h:101
int spaceLeft
Definition: libpq-int.h:210
char null_field[1]
Definition: libpq-int.h:201
#define malloc(a)
Definition: header.h:50
#define PGRESULT_ALIGN_BOUNDARY
Definition: fe-exec.c:129
int curOffset
Definition: libpq-int.h:209
#define PGRESULT_BLOCK_OVERHEAD
Definition: fe-exec.c:130
PGresult_data * curBlock
Definition: libpq-int.h:208
#define PGRESULT_SEP_ALLOC_THRESHOLD
Definition: fe-exec.c:131
#define PGRESULT_DATA_BLOCKSIZE
Definition: fe-exec.c:128

◆ pqResultStrdup()

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

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

References pqResultAlloc().

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

647 {
648  char *space = (char *) pqResultAlloc(res, strlen(str) + 1, false);
649 
650  if (space)
651  strcpy(space, str);
652  return space;
653 }
void * pqResultAlloc(PGresult *res, size_t nBytes, bool isBinary)
Definition: fe-exec.c:534

◆ pqRowProcessor()

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

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

References pg_conn::asyncStatus, pg_result::attDescs, 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, PGRES_SINGLE_TUPLE, pqAddTuple(), PQclear(), PQcopyResult(), pqResultAlloc(), pg_conn::result, pg_result::resultStatus, pg_conn::rowBuf, pg_conn::singleRowMode, val, pgresAttValue::value, and value.

Referenced by getAnotherTuple().

1133 {
1134  PGresult *res = conn->result;
1135  int nfields = res->numAttributes;
1136  const PGdataValue *columns = conn->rowBuf;
1137  PGresAttValue *tup;
1138  int i;
1139 
1140  /*
1141  * In single-row mode, make a new PGresult that will hold just this one
1142  * row; the original conn->result is left unchanged so that it can be used
1143  * again as the template for future rows.
1144  */
1145  if (conn->singleRowMode)
1146  {
1147  /* Copy everything that should be in the result at this point */
1148  res = PQcopyResult(res,
1151  if (!res)
1152  return 0;
1153  }
1154 
1155  /*
1156  * Basically we just allocate space in the PGresult for each field and
1157  * copy the data over.
1158  *
1159  * Note: on malloc failure, we return 0 leaving *errmsgp still NULL, which
1160  * caller will take to mean "out of memory". This is preferable to trying
1161  * to set up such a message here, because evidently there's not enough
1162  * memory for gettext() to do anything.
1163  */
1164  tup = (PGresAttValue *)
1165  pqResultAlloc(res, nfields * sizeof(PGresAttValue), true);
1166  if (tup == NULL)
1167  goto fail;
1168 
1169  for (i = 0; i < nfields; i++)
1170  {
1171  int clen = columns[i].len;
1172 
1173  if (clen < 0)
1174  {
1175  /* null field */
1176  tup[i].len = NULL_LEN;
1177  tup[i].value = res->null_field;
1178  }
1179  else
1180  {
1181  bool isbinary = (res->attDescs[i].format != 0);
1182  char *val;
1183 
1184  val = (char *) pqResultAlloc(res, clen + 1, isbinary);
1185  if (val == NULL)
1186  goto fail;
1187 
1188  /* copy and zero-terminate the data (even if it's binary) */
1189  memcpy(val, columns[i].value, clen);
1190  val[clen] = '\0';
1191 
1192  tup[i].len = clen;
1193  tup[i].value = val;
1194  }
1195  }
1196 
1197  /* And add the tuple to the PGresult's tuple array */
1198  if (!pqAddTuple(res, tup, errmsgp))
1199  goto fail;
1200 
1201  /*
1202  * Success. In single-row mode, make the result available to the client
1203  * immediately.
1204  */
1205  if (conn->singleRowMode)
1206  {
1207  /* Change result status to special single-row value */
1209  /* Stash old result for re-use later */
1210  conn->next_result = conn->result;
1211  conn->result = res;
1212  /* And mark the result ready to return */
1213  conn->asyncStatus = PGASYNC_READY;
1214  }
1215 
1216  return 1;
1217 
1218 fail:
1219  /* release locally allocated PGresult, if we made one */
1220  if (res != conn->result)
1221  PQclear(res);
1222  return 0;
1223 }
bool singleRowMode
Definition: libpq-int.h:397
PGresult * PQcopyResult(const PGresult *src, int flags)
Definition: fe-exec.c:294
#define NULL_LEN
Definition: libpq-int.h:133
char null_field[1]
Definition: libpq-int.h:201
PGresAttDesc * attDescs
Definition: libpq-int.h:171
PGresult * result
Definition: libpq-int.h:465
PGresult * next_result
Definition: libpq-int.h:466
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:389
#define PG_COPYRES_EVENTS
Definition: libpq-fe.h:36
static bool pqAddTuple(PGresult *res, PGresAttValue *tup, const char **errmsgp)
Definition: fe-exec.c:926
#define PG_COPYRES_NOTICEHOOKS
Definition: libpq-fe.h:37
PGdataValue * rowBuf
Definition: libpq-int.h:461
int numAttributes
Definition: libpq-int.h:170
#define PG_COPYRES_ATTRS
Definition: libpq-fe.h:34
static struct @143 value
void PQclear(PGresult *res)
Definition: fe-exec.c:694
void * pqResultAlloc(PGresult *res, size_t nBytes, bool isBinary)
Definition: fe-exec.c:534
int i
char * value
Definition: libpq-int.h:138
ExecStatusType resultStatus
Definition: libpq-int.h:177
long val
Definition: informix.c:664

◆ pqSaveErrorResult()

void pqSaveErrorResult ( PGconn conn)

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

References PQExpBufferData::data, pg_result::errMsg, pg_conn::errorMessage, PGRES_FATAL_ERROR, pqCatenateResultError(), pqClearAsyncResult(), PQmakeEmptyPGresult(), pg_conn::result, and pg_result::resultStatus.

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

773 {
774  /*
775  * If no old async result, just let PQmakeEmptyPGresult make one. Likewise
776  * if old result is not an error message.
777  */
778  if (conn->result == NULL ||
780  conn->result->errMsg == NULL)
781  {
782  pqClearAsyncResult(conn);
784  }
785  else
786  {
787  /* Else, concatenate error message to existing async result. */
789  }
790 }
char * errMsg
Definition: libpq-int.h:196
PGresult * result
Definition: libpq-int.h:465
PGresult * PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
Definition: fe-exec.c:141
PQExpBufferData errorMessage
Definition: libpq-int.h:526
void pqCatenateResultError(PGresult *res, const char *msg)
Definition: fe-exec.c:675
void pqClearAsyncResult(PGconn *conn)
Definition: fe-exec.c:749
ExecStatusType resultStatus
Definition: libpq-int.h:177

◆ pqSaveMessageField()

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

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

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

Referenced by pqGetErrorNotice2(), pqGetErrorNotice3(), and pqInternalNotice().

994 {
995  PGMessageField *pfield;
996 
997  pfield = (PGMessageField *)
998  pqResultAlloc(res,
999  offsetof(PGMessageField, contents) +
1000  strlen(value) + 1,
1001  true);
1002  if (!pfield)
1003  return; /* out of memory? */
1004  pfield->code = code;
1005  strcpy(pfield->contents, value);
1006  pfield->next = res->errFields;
1007  res->errFields = pfield;
1008 }
PGMessageField * errFields
Definition: libpq-int.h:197
struct pgMessageField * next
Definition: libpq-int.h:144
static struct @143 value
void * pqResultAlloc(PGresult *res, size_t nBytes, bool isBinary)
Definition: fe-exec.c:534
char contents[FLEXIBLE_ARRAY_MEMBER]
Definition: libpq-int.h:146
#define offsetof(type, field)
Definition: c.h:669

◆ pqSaveParameterStatus()

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

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

References pg_conn::client_encoding, fprintf, free, malloc, pgParameterStatus::name, pgParameterStatus::next, pg_conn::Pfdebug, pg_char_to_encoding(), PG_SQL_ASCII, pg_conn::pstatus, static_client_encoding, static_std_strings, pg_conn::std_strings, pg_conn::sversion, and pgParameterStatus::value.

Referenced by getParameterStatus(), PQsetClientEncoding(), and pqSetenvPoll().

1015 {
1016  pgParameterStatus *pstatus;
1017  pgParameterStatus *prev;
1018 
1019  if (conn->Pfdebug)
1020  fprintf(conn->Pfdebug, "pqSaveParameterStatus: '%s' = '%s'\n",
1021  name, value);
1022 
1023  /*
1024  * Forget any old information about the parameter
1025  */
1026  for (pstatus = conn->pstatus, prev = NULL;
1027  pstatus != NULL;
1028  prev = pstatus, pstatus = pstatus->next)
1029  {
1030  if (strcmp(pstatus->name, name) == 0)
1031  {
1032  if (prev)
1033  prev->next = pstatus->next;
1034  else
1035  conn->pstatus = pstatus->next;
1036  free(pstatus); /* frees name and value strings too */
1037  break;
1038  }
1039  }
1040 
1041  /*
1042  * Store new info as a single malloc block
1043  */
1044  pstatus = (pgParameterStatus *) malloc(sizeof(pgParameterStatus) +
1045  strlen(name) + strlen(value) + 2);
1046  if (pstatus)
1047  {
1048  char *ptr;
1049 
1050  ptr = ((char *) pstatus) + sizeof(pgParameterStatus);
1051  pstatus->name = ptr;
1052  strcpy(ptr, name);
1053  ptr += strlen(name) + 1;
1054  pstatus->value = ptr;
1055  strcpy(ptr, value);
1056  pstatus->next = conn->pstatus;
1057  conn->pstatus = pstatus;
1058  }
1059 
1060  /*
1061  * Special hacks: remember client_encoding and
1062  * standard_conforming_strings, and convert server version to a numeric
1063  * form. We keep the first two of these in static variables as well, so
1064  * that PQescapeString and PQescapeBytea can behave somewhat sanely (at
1065  * least in single-connection-using programs).
1066  */
1067  if (strcmp(name, "client_encoding") == 0)
1068  {
1070  /* if we don't recognize the encoding name, fall back to SQL_ASCII */
1071  if (conn->client_encoding < 0)
1072  conn->client_encoding = PG_SQL_ASCII;
1074  }
1075  else if (strcmp(name, "standard_conforming_strings") == 0)
1076  {
1077  conn->std_strings = (strcmp(value, "on") == 0);
1079  }
1080  else if (strcmp(name, "server_version") == 0)
1081  {
1082  int cnt;
1083  int vmaj,
1084  vmin,
1085  vrev;
1086 
1087  cnt = sscanf(value, "%d.%d.%d", &vmaj, &vmin, &vrev);
1088 
1089  if (cnt == 3)
1090  {
1091  /* old style, e.g. 9.6.1 */
1092  conn->sversion = (100 * vmaj + vmin) * 100 + vrev;
1093  }
1094  else if (cnt == 2)
1095  {
1096  if (vmaj >= 10)
1097  {
1098  /* new style, e.g. 10.1 */
1099  conn->sversion = 100 * 100 * vmaj + vmin;
1100  }
1101  else
1102  {
1103  /* old style without minor version, e.g. 9.6devel */
1104  conn->sversion = (100 * vmaj + vmin) * 100;
1105  }
1106  }
1107  else if (cnt == 1)
1108  {
1109  /* new style without minor version, e.g. 10devel */
1110  conn->sversion = 100 * 100 * vmaj;
1111  }
1112  else
1113  conn->sversion = 0; /* unknown */
1114  }
1115 }
static bool static_std_strings
Definition: fe-exec.c:50
int pg_char_to_encoding(const char *name)
Definition: encnames.c:550
#define fprintf
Definition: port.h:219
FILE * Pfdebug
Definition: libpq-int.h:377
#define malloc(a)
Definition: header.h:50
int sversion
Definition: libpq-int.h:415
struct pgParameterStatus pgParameterStatus
static int static_client_encoding
Definition: fe-exec.c:49
pgParameterStatus * pstatus
Definition: libpq-int.h:436
bool std_strings
Definition: libpq-int.h:438
static struct @143 value
#define free(a)
Definition: header.h:65
struct pgParameterStatus * next
Definition: libpq-int.h:261
const char * name
Definition: encode.c:561
int client_encoding
Definition: libpq-int.h:437

◆ pqsecure_close()

void pqsecure_close ( PGconn )

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

References pgtls_close(), and pg_conn::ssl_in_use.

Referenced by pqDropConnection().

198 {
199 #ifdef USE_SSL
200  if (conn->ssl_in_use)
201  pgtls_close(conn);
202 #endif
203 }
PGconn * conn
Definition: streamutil.c:54
bool ssl_in_use
Definition: libpq-int.h:472
void pgtls_close(PGconn *conn)

◆ pqsecure_initialize()

int pqsecure_initialize ( PGconn )

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

References pgtls_init().

Referenced by PQconnectPoll().

169 {
170  int r = 0;
171 
172 #ifdef USE_SSL
173  r = pgtls_init(conn);
174 #endif
175 
176  return r;
177 }
PGconn * conn
Definition: streamutil.c:54
int pgtls_init(PGconn *conn)

◆ pqsecure_open_client()

PostgresPollingStatusType pqsecure_open_client ( PGconn )

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

References PGRES_POLLING_FAILED, and pgtls_open_client().

Referenced by PQconnectPoll().

184 {
185 #ifdef USE_SSL
186  return pgtls_open_client(conn);
187 #else
188  /* shouldn't get here */
189  return PGRES_POLLING_FAILED;
190 #endif
191 }
PostgresPollingStatusType pgtls_open_client(PGconn *conn)
PGconn * conn
Definition: streamutil.c:54

◆ pqsecure_raw_read()

ssize_t pqsecure_raw_read ( PGconn ,
void *  ptr,
size_t  len 
)

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

References EAGAIN, ECONNRESET, EINTR, pg_conn::errorMessage, EWOULDBLOCK, libpq_gettext, PG_STRERROR_R_BUFLEN, printfPQExpBuffer(), 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().

240 {
241  ssize_t n;
242  int result_errno = 0;
243  char sebuf[PG_STRERROR_R_BUFLEN];
244 
245  n = recv(conn->sock, ptr, len, 0);
246 
247  if (n < 0)
248  {
249  result_errno = SOCK_ERRNO;
250 
251  /* Set error message if appropriate */
252  switch (result_errno)
253  {
254 #ifdef EAGAIN
255  case EAGAIN:
256 #endif
257 #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
258  case EWOULDBLOCK:
259 #endif
260  case EINTR:
261  /* no error message, caller is expected to retry */
262  break;
263 
264  case EPIPE:
265  case ECONNRESET:
267  libpq_gettext("server closed the connection unexpectedly\n"
268  "\tThis probably means the server terminated abnormally\n"
269  "\tbefore or while processing the request.\n"));
270  break;
271 
272  default:
274  libpq_gettext("could not receive data from server: %s\n"),
275  SOCK_STRERROR(result_errno,
276  sebuf, sizeof(sebuf)));
277  break;
278  }
279  }
280 
281  /* ensure we return the intended errno to caller */
282  SOCK_ERRNO_SET(result_errno);
283 
284  return n;
285 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
#define EAGAIN
Definition: win32_port.h:341
#define PG_STRERROR_R_BUFLEN
Definition: port.h:233
#define recv(s, buf, len, flags)
Definition: win32_port.h:465
#define SOCK_STRERROR
Definition: libpq-int.h:819
#define SOCK_ERRNO
Definition: libpq-int.h:818
PGconn * conn
Definition: streamutil.c:54
#define SOCK_ERRNO_SET(e)
Definition: libpq-int.h:820
pgsocket sock
Definition: libpq-int.h:410
PQExpBufferData errorMessage
Definition: libpq-int.h:526
#define ECONNRESET
Definition: win32_port.h:353
#define EWOULDBLOCK
Definition: win32_port.h:349
#define EINTR
Definition: win32_port.h:343
#define libpq_gettext(x)
Definition: libpq-int.h:805

◆ pqsecure_raw_write()

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

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

References DECLARE_SIGPIPE_INFO, DISABLE_SIGPIPE, EAGAIN, ECONNRESET, EINTR, pg_conn::errorMessage, EWOULDBLOCK, libpq_gettext, PG_STRERROR_R_BUFLEN, printfPQExpBuffer(), REMEMBER_EPIPE, RESTORE_SIGPIPE, send, pg_conn::sigpipe_flag, pg_conn::sock, SOCK_ERRNO, SOCK_ERRNO_SET, and SOCK_STRERROR.

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

322 {
323  ssize_t n;
324  int flags = 0;
325  int result_errno = 0;
326  char sebuf[PG_STRERROR_R_BUFLEN];
327 
328  DECLARE_SIGPIPE_INFO(spinfo);
329 
330 #ifdef MSG_NOSIGNAL
331  if (conn->sigpipe_flag)
332  flags |= MSG_NOSIGNAL;
333 
334 retry_masked:
335 #endif /* MSG_NOSIGNAL */
336 
337  DISABLE_SIGPIPE(conn, spinfo, return -1);
338 
339  n = send(conn->sock, ptr, len, flags);
340 
341  if (n < 0)
342  {
343  result_errno = SOCK_ERRNO;
344 
345  /*
346  * If we see an EINVAL, it may be because MSG_NOSIGNAL isn't available
347  * on this machine. So, clear sigpipe_flag so we don't try the flag
348  * again, and retry the send().
349  */
350 #ifdef MSG_NOSIGNAL
351  if (flags != 0 && result_errno == EINVAL)
352  {
353  conn->sigpipe_flag = false;
354  flags = 0;
355  goto retry_masked;
356  }
357 #endif /* MSG_NOSIGNAL */
358 
359  /* Set error message if appropriate */
360  switch (result_errno)
361  {
362 #ifdef EAGAIN
363  case EAGAIN:
364 #endif
365 #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
366  case EWOULDBLOCK:
367 #endif
368  case EINTR:
369  /* no error message, caller is expected to retry */
370  break;
371 
372  case EPIPE:
373  /* Set flag for EPIPE */
374  REMEMBER_EPIPE(spinfo, true);
375 
376  /* FALL THRU */
377 
378  case ECONNRESET:
380  libpq_gettext("server closed the connection unexpectedly\n"
381  "\tThis probably means the server terminated abnormally\n"
382  "\tbefore or while processing the request.\n"));
383  break;
384 
385  default:
387  libpq_gettext("could not send data to server: %s\n"),
388  SOCK_STRERROR(result_errno,
389  sebuf, sizeof(sebuf)));
390  break;
391  }
392  }
393 
394  RESTORE_SIGPIPE(conn, spinfo);
395 
396  /* ensure we return the intended errno to caller */
397  SOCK_ERRNO_SET(result_errno);
398 
399  return n;
400 }
bool sigpipe_flag
Definition: libpq-int.h:419
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
#define EAGAIN
Definition: win32_port.h:341
#define DECLARE_SIGPIPE_INFO(spinfo)
Definition: fe-secure.c:103