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 792 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(), 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 793 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 583 of file libpq-int.h.

Referenced by pg_fe_getauthname(), and pg_fe_sendauth().

◆ pgunlock_thread

#define pgunlock_thread ( )    ((void) 0)

Definition at line 584 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 1299 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().

1300 {
1301  bool destroy_needed = false;
1302 
1303  if (conn->ssl)
1304  {
1305  /*
1306  * We can't destroy everything SSL-related here due to the possible
1307  * later calls to OpenSSL routines which may need our thread
1308  * callbacks, so set a flag here and check at the end.
1309  */
1310  destroy_needed = true;
1311 
1312  SSL_shutdown(conn->ssl);
1313  SSL_free(conn->ssl);
1314  conn->ssl = NULL;
1315  conn->ssl_in_use = false;
1316  }
1317 
1318  if (conn->peer)
1319  {
1320  X509_free(conn->peer);
1321  conn->peer = NULL;
1322  }
1323 
1324 #ifdef USE_SSL_ENGINE
1325  if (conn->engine)
1326  {
1327  ENGINE_finish(conn->engine);
1328  ENGINE_free(conn->engine);
1329  conn->engine = NULL;
1330  }
1331 #endif
1332 
1333  /*
1334  * This will remove our SSL locking hooks, if this is the last SSL
1335  * connection, which means we must wait to call it until after all SSL
1336  * calls have been made, otherwise we can end up with a race condition and
1337  * possible deadlocks.
1338  *
1339  * See comments above destroy_ssl_system().
1340  */
1341  if (destroy_needed)
1343 }
bool ssl_in_use
Definition: libpq-int.h:469
static void destroy_ssl_system(void)

◆ pgtls_init()

int pgtls_init ( PGconn conn)

Definition at line 640 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().

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

References pq_init_crypto_lib, and pq_init_ssl_lib.

Referenced by PQinitOpenSSL(), and PQinitSSL().

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

◆ pgtls_open_client()

PostgresPollingStatusType pgtls_open_client ( PGconn conn)

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

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

Referenced by pqsecure_open_client().

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

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

◆ pgtls_read_pending()

bool pgtls_read_pending ( PGconn conn)

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

Referenced by pqSocketCheck().

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

◆ 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_free(peer_san);
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  conn,
581  X509_NAME_ENTRY_get_data(
582  X509_NAME_get_entry(subject_name, cn_index)),
583  first_name);
584  }
585  }
586  }
587 
588  return rc;
589 }
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:521
int i

◆ pgtls_write()

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

Definition at line 273 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().

274 {
275  ssize_t n;
276  int result_errno = 0;
277  char sebuf[PG_STRERROR_R_BUFLEN];
278  int err;
279  unsigned long ecode;
280 
281  SOCK_ERRNO_SET(0);
282  ERR_clear_error();
283  n = SSL_write(conn->ssl, ptr, len);
284  err = SSL_get_error(conn->ssl, n);
285  ecode = (err != SSL_ERROR_NONE || n < 0) ? ERR_get_error() : 0;
286  switch (err)
287  {
288  case SSL_ERROR_NONE:
289  if (n < 0)
290  {
291  /* Not supposed to happen, so we don't translate the msg */
293  "SSL_write failed but did not provide error information\n");
294  /* assume the connection is broken */
295  result_errno = ECONNRESET;
296  }
297  break;
298  case SSL_ERROR_WANT_READ:
299 
300  /*
301  * Returning 0 here causes caller to wait for write-ready, which
302  * is not really the right thing, but it's the best we can do.
303  */
304  n = 0;
305  break;
306  case SSL_ERROR_WANT_WRITE:
307  n = 0;
308  break;
309  case SSL_ERROR_SYSCALL:
310  if (n < 0)
311  {
312  result_errno = SOCK_ERRNO;
313  if (result_errno == EPIPE || result_errno == ECONNRESET)
316  "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:210
#define SOCK_STRERROR
Definition: libpq-int.h:806
#define SOCK_ERRNO
Definition: libpq-int.h:805
#define SOCK_ERRNO_SET(e)
Definition: libpq-int.h:807
static void SSLerrfree(char *buf)
PQExpBufferData errorMessage
Definition: libpq-int.h:511
#define ECONNRESET
Definition: win32_port.h:333
static char * SSLerrmessage(unsigned long ecode)
#define libpq_gettext(x)
Definition: libpq-int.h:792

◆ pqBuildErrorMessage3()

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

Definition at line 987 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().

989 {
990  const char *val;
991  const char *querytext = NULL;
992  int querypos = 0;
993 
994  /* If we couldn't allocate a PGresult, just say "out of memory" */
995  if (res == NULL)
996  {
997  appendPQExpBufferStr(msg, libpq_gettext("out of memory\n"));
998  return;
999  }
1000 
1001  /*
1002  * If we don't have any broken-down fields, just return the base message.
1003  * This mainly applies if we're given a libpq-generated error result.
1004  */
1005  if (res->errFields == NULL)
1006  {
1007  if (res->errMsg && res->errMsg[0])
1008  appendPQExpBufferStr(msg, res->errMsg);
1009  else
1010  appendPQExpBufferStr(msg, libpq_gettext("no error message available\n"));
1011  return;
1012  }
1013 
1014  /* Else build error message from relevant fields */
1016  if (val)
1017  appendPQExpBuffer(msg, "%s: ", val);
1018 
1019  if (verbosity == PQERRORS_SQLSTATE)
1020  {
1021  /*
1022  * If we have a SQLSTATE, print that and nothing else. If not (which
1023  * shouldn't happen for server-generated errors, but might possibly
1024  * happen for libpq-generated ones), fall back to TERSE format, as
1025  * that seems better than printing nothing at all.
1026  */
1028  if (val)
1029  {
1030  appendPQExpBuffer(msg, "%s\n", val);
1031  return;
1032  }
1033  verbosity = PQERRORS_TERSE;
1034  }
1035 
1036  if (verbosity == PQERRORS_VERBOSE)
1037  {
1039  if (val)
1040  appendPQExpBuffer(msg, "%s: ", val);
1041  }
1043  if (val)
1044  appendPQExpBufferStr(msg, val);
1046  if (val)
1047  {
1048  if (verbosity != PQERRORS_TERSE && res->errQuery != NULL)
1049  {
1050  /* emit position as a syntax cursor display */
1051  querytext = res->errQuery;
1052  querypos = atoi(val);
1053  }
1054  else
1055  {
1056  /* emit position as text addition to primary message */
1057  /* translator: %s represents a digit string */
1058  appendPQExpBuffer(msg, libpq_gettext(" at character %s"),
1059  val);
1060  }
1061  }
1062  else
1063  {
1065  if (val)
1066  {
1067  querytext = PQresultErrorField(res, PG_DIAG_INTERNAL_QUERY);
1068  if (verbosity != PQERRORS_TERSE && querytext != NULL)
1069  {
1070  /* emit position as a syntax cursor display */
1071  querypos = atoi(val);
1072  }
1073  else
1074  {
1075  /* emit position as text addition to primary message */
1076  /* translator: %s represents a digit string */
1077  appendPQExpBuffer(msg, libpq_gettext(" at character %s"),
1078  val);
1079  }
1080  }
1081  }
1082  appendPQExpBufferChar(msg, '\n');
1083  if (verbosity != PQERRORS_TERSE)
1084  {
1085  if (querytext && querypos > 0)
1086  reportErrorPosition(msg, querytext, querypos,
1087  res->client_encoding);
1089  if (val)
1090  appendPQExpBuffer(msg, libpq_gettext("DETAIL: %s\n"), val);
1092  if (val)
1093  appendPQExpBuffer(msg, libpq_gettext("HINT: %s\n"), val);
1095  if (val)
1096  appendPQExpBuffer(msg, libpq_gettext("QUERY: %s\n"), val);
1097  if (show_context == PQSHOW_CONTEXT_ALWAYS ||
1098  (show_context == PQSHOW_CONTEXT_ERRORS &&
1100  {
1101  val = PQresultErrorField(res, PG_DIAG_CONTEXT);
1102  if (val)
1103  appendPQExpBuffer(msg, libpq_gettext("CONTEXT: %s\n"),
1104  val);
1105  }
1106  }
1107  if (verbosity == PQERRORS_VERBOSE)
1108  {
1110  if (val)
1111  appendPQExpBuffer(msg,
1112  libpq_gettext("SCHEMA NAME: %s\n"), val);
1114  if (val)
1115  appendPQExpBuffer(msg,
1116  libpq_gettext("TABLE NAME: %s\n"), val);
1118  if (val)
1119  appendPQExpBuffer(msg,
1120  libpq_gettext("COLUMN NAME: %s\n"), val);
1122  if (val)
1123  appendPQExpBuffer(msg,
1124  libpq_gettext("DATATYPE NAME: %s\n"), val);
1126  if (val)
1127  appendPQExpBuffer(msg,
1128  libpq_gettext("CONSTRAINT NAME: %s\n"), val);
1129  }
1130  if (verbosity == PQERRORS_VERBOSE)
1131  {
1132  const char *valf;
1133  const char *vall;
1134 
1138  if (val || valf || vall)
1139  {
1140  appendPQExpBufferStr(msg, libpq_gettext("LOCATION: "));
1141  if (val)
1142  appendPQExpBuffer(msg, libpq_gettext("%s, "), val);
1143  if (valf && vall) /* unlikely we'd have just one */
1144  appendPQExpBuffer(msg, libpq_gettext("%s:%s"),
1145  valf, vall);
1146  appendPQExpBufferChar(msg, '\n');
1147  }
1148  }
1149 }
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:792
int client_encoding
Definition: libpq-int.h:189

◆ pqBuildStartupPacket2()

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

Definition at line 1593 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().

1595 {
1596  StartupPacket *startpacket;
1597 
1598  *packetlen = sizeof(StartupPacket);
1599  startpacket = (StartupPacket *) malloc(sizeof(StartupPacket));
1600  if (!startpacket)
1601  return NULL;
1602 
1603  MemSet(startpacket, 0, sizeof(StartupPacket));
1604 
1605  startpacket->protoVersion = pg_hton32(conn->pversion);
1606 
1607  /* strncpy is safe here: postmaster will handle full fields correctly */
1608  strncpy(startpacket->user, conn->pguser, SM_USER);
1609  strncpy(startpacket->database, conn->dbName, SM_DATABASE);
1610  strncpy(startpacket->tty, conn->pgtty, SM_TTY);
1611 
1612  if (conn->pgoptions)
1613  strncpy(startpacket->options, conn->pgoptions, SM_OPTIONS);
1614 
1615  return (char *) startpacket;
1616 }
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:962
#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:411
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 2126 of file fe-protocol3.c.

References build_startup_packet(), and malloc.

Referenced by PQconnectPoll().

2128 {
2129  char *startpacket;
2130 
2131  *packetlen = build_startup_packet(conn, NULL, options);
2132  startpacket = (char *) malloc(*packetlen);
2133  if (!startpacket)
2134  return NULL;
2135  *packetlen = build_startup_packet(conn, startpacket, options);
2136  return startpacket;
2137 }
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 407 of file fe-misc.c.

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

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

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

◆ pqCheckOutBufferSpace()

int pqCheckOutBufferSpace ( size_t  bytes_needed,
PGconn conn 
)

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

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

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

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

◆ 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:462
PGresult * next_result
Definition: libpq-int.h:463
void PQclear(PGresult *res)
Definition: fe-exec.c:694

◆ pqDropConnection()

void pqDropConnection ( PGconn conn,
bool  flushInput 
)

Definition at line 457 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().

458 {
459  /* Drop any SSL state */
460  pqsecure_close(conn);
461 
462  /* Close the socket itself */
463  if (conn->sock != PGINVALID_SOCKET)
464  closesocket(conn->sock);
465  conn->sock = PGINVALID_SOCKET;
466 
467  /* Optionally discard any unread data */
468  if (flushInput)
469  conn->inStart = conn->inCursor = conn->inEnd = 0;
470 
471  /* Always discard any unsent data */
472  conn->outCount = 0;
473 
474  /* Free authentication state */
475 #ifdef ENABLE_GSS
476  {
477  OM_uint32 min_s;
478 
479  if (conn->gctx)
480  gss_delete_sec_context(&min_s, &conn->gctx, GSS_C_NO_BUFFER);
481  if (conn->gtarg_nam)
482  gss_release_name(&min_s, &conn->gtarg_nam);
483  }
484 #endif
485 #ifdef ENABLE_SSPI
486  if (conn->sspitarget)
487  {
488  free(conn->sspitarget);
489  conn->sspitarget = NULL;
490  }
491  if (conn->sspicred)
492  {
493  FreeCredentialsHandle(conn->sspicred);
494  free(conn->sspicred);
495  conn->sspicred = NULL;
496  }
497  if (conn->sspictx)
498  {
499  DeleteSecurityContext(conn->sspictx);
500  free(conn->sspictx);
501  conn->sspictx = NULL;
502  }
503  conn->usesspi = 0;
504 #endif
505  if (conn->sasl_state)
506  {
507  /*
508  * XXX: if support for more authentication mechanisms is added, this
509  * needs to call the right 'free' function.
510  */
512  conn->sasl_state = NULL;
513  }
514 }
int inEnd
Definition: libpq-int.h:445
int inStart
Definition: libpq-int.h:443
void pg_fe_scram_free(void *opaq)
#define closesocket
Definition: port.h:312
int outCount
Definition: libpq-int.h:450
void pqsecure_close(PGconn *conn)
Definition: fe-secure.c:197
void * sasl_state
Definition: libpq-int.h:466
pgsocket sock
Definition: libpq-int.h:407
#define PGINVALID_SOCKET
Definition: port.h:33
#define free(a)
Definition: header.h:65
int inCursor
Definition: libpq-int.h:444

◆ pqEndcopy2()

int pqEndcopy2 ( PGconn conn)

Definition at line 1349 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().

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

◆ pqEndcopy3()

int pqEndcopy3 ( PGconn conn)

Definition at line 1831 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().

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

◆ pqFlush()

int pqFlush ( PGconn conn)

Definition at line 997 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().

998 {
999  if (conn->Pfdebug)
1000  fflush(conn->Pfdebug);
1001 
1002  if (conn->outCount > 0)
1003  return pqSendSome(conn, conn->outCount);
1004 
1005  return 0;
1006 }
int outCount
Definition: libpq-int.h:450
FILE * Pfdebug
Definition: libpq-int.h:374
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 1434 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().

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

◆ 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 1925 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().

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

◆ pqGetc()

int pqGetc ( char *  result,
PGconn conn 
)

Definition at line 93 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().

94 {
95  if (conn->inCursor >= conn->inEnd)
96  return EOF;
97 
98  *result = conn->inBuffer[conn->inCursor++];
99 
100  if (conn->Pfdebug)
101  fprintf(conn->Pfdebug, "From backend> %c\n", *result);
102 
103  return 0;
104 }
int inEnd
Definition: libpq-int.h:445
#define fprintf
Definition: port.h:196
FILE * Pfdebug
Definition: libpq-int.h:374
char * inBuffer
Definition: libpq-int.h:441
int inCursor
Definition: libpq-int.h:444

◆ pqGetCopyData2()

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

Definition at line 1166 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().

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

◆ pqGetCopyData3()

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

Definition at line 1664 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().

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

◆ pqGetErrorNotice3()

int pqGetErrorNotice3 ( PGconn conn,
bool  isError 
)

Definition at line 873 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().

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

◆ pqGetHomeDirectory()

bool pqGetHomeDirectory ( char *  buf,
int  bufsize 
)

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

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

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

7047 {
7048 #ifndef WIN32
7049  char pwdbuf[BUFSIZ];
7050  struct passwd pwdstr;
7051  struct passwd *pwd = NULL;
7052 
7053  (void) pqGetpwuid(geteuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd);
7054  if (pwd == NULL)
7055  return false;
7056  strlcpy(buf, pwd->pw_dir, bufsize);
7057  return true;
7058 #else
7059  char tmppath[MAX_PATH];
7060 
7061  ZeroMemory(tmppath, sizeof(tmppath));
7062  if (SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, tmppath) != S_OK)
7063  return false;
7064  snprintf(buf, bufsize, "%s/postgresql", tmppath);
7065  return true;
7066 #endif
7067 }
static char * buf
Definition: pg_test_fsync.c:67
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:68
#define snprintf
Definition: port.h:192

◆ pqGetInt()

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

Definition at line 266 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().

267 {
268  uint16 tmp2;
269  uint32 tmp4;
270 
271  switch (bytes)
272  {
273  case 2:
274  if (conn->inCursor + 2 > conn->inEnd)
275  return EOF;
276  memcpy(&tmp2, conn->inBuffer + conn->inCursor, 2);
277  conn->inCursor += 2;
278  *result = (int) pg_ntoh16(tmp2);
279  break;
280  case 4:
281  if (conn->inCursor + 4 > conn->inEnd)
282  return EOF;
283  memcpy(&tmp4, conn->inBuffer + conn->inCursor, 4);
284  conn->inCursor += 4;
285  *result = (int) pg_ntoh32(tmp4);
286  break;
287  default:
289  "integer of size %lu not supported by pqGetInt",
290  (unsigned long) bytes);
291  return EOF;
292  }
293 
294  if (conn->Pfdebug)
295  fprintf(conn->Pfdebug, "From backend (#%lu)> %d\n", (unsigned long) bytes, *result);
296 
297  return 0;
298 }
int inEnd
Definition: libpq-int.h:445
def bytes(source, encoding='ascii', errors='strict')
#define pg_ntoh16(x)
Definition: pg_bswap.h:124
#define fprintf
Definition: port.h:196
FILE * Pfdebug
Definition: libpq-int.h:374
unsigned short uint16
Definition: c.h:358
#define pg_ntoh32(x)
Definition: pg_bswap.h:125
PGNoticeHooks noticeHooks
Definition: libpq-int.h:377
void pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt,...)
Definition: fe-exec.c:871
unsigned int uint32
Definition: c.h:359
char * inBuffer
Definition: libpq-int.h:441
int inCursor
Definition: libpq-int.h:444

◆ pqGetline2()

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

Definition at line 1240 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().

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

◆ pqGetline3()

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

Definition at line 1724 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().

1725 {
1726  int status;
1727 
1728  if (conn->sock == PGINVALID_SOCKET ||
1729  (conn->asyncStatus != PGASYNC_COPY_OUT &&
1730  conn->asyncStatus != PGASYNC_COPY_BOTH) ||
1731  conn->copy_is_binary)
1732  {
1734  libpq_gettext("PQgetline: not doing text COPY OUT\n"));
1735  *s = '\0';
1736  return EOF;
1737  }
1738 
1739  while ((status = PQgetlineAsync(conn, s, maxlen - 1)) == 0)
1740  {
1741  /* need to load more data */
1742  if (pqWait(true, false, conn) ||
1743  pqReadData(conn) < 0)
1744  {
1745  *s = '\0';
1746  return EOF;
1747  }
1748  }
1749 
1750  if (status < 0)
1751  {
1752  /* End of copy detected; gin up old-style terminator */
1753  strcpy(s, "\\.");
1754  return 0;
1755  }
1756 
1757  /* Add null terminator, and strip trailing \n if present */
1758  if (s[status - 1] == '\n')
1759  {
1760  s[status - 1] = '\0';
1761  return 0;
1762  }
1763  else
1764  {
1765  s[status] = '\0';
1766  return 1;
1767  }
1768 }
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:395
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:386
int pqReadData(PGconn *conn)
Definition: fe-misc.c:628
int pqWait(int forRead, int forWrite, PGconn *conn)
Definition: fe-misc.c:1020
pgsocket sock
Definition: libpq-int.h:407
#define PGINVALID_SOCKET
Definition: port.h:33
PQExpBufferData errorMessage
Definition: libpq-int.h:511
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:226
#define libpq_gettext(x)
Definition: libpq-int.h:792

◆ pqGetlineAsync2()

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

Definition at line 1291 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().

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

◆ pqGetlineAsync3()

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

Definition at line 1776 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().

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

◆ pqGetnchar()

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

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

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

195 {
196  if (len > (size_t) (conn->inEnd - conn->inCursor))
197  return EOF;
198 
199  memcpy(s, conn->inBuffer + conn->inCursor, len);
200  /* no terminating null */
201 
202  conn->inCursor += len;
203 
204  if (conn->Pfdebug)
205  {
206  fprintf(conn->Pfdebug, "From backend (%lu)> ", (unsigned long) len);
207  fputnbytes(conn->Pfdebug, s, len);
208  fprintf(conn->Pfdebug, "\n");
209  }
210 
211  return 0;
212 }
int inEnd
Definition: libpq-int.h:445
#define fprintf
Definition: port.h:196
FILE * Pfdebug
Definition: libpq-int.h:374
char * inBuffer
Definition: libpq-int.h:441
static void fputnbytes(FILE *f, const char *str, size_t n)
Definition: fe-misc.c:78
int inCursor
Definition: libpq-int.h:444

◆ pqGets()

int pqGets ( PQExpBuffer  buf,
PGconn conn 
)

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

References pqGets_internal().

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

163 {
164  return pqGets_internal(buf, conn, true);
165 }
static int pqGets_internal(PQExpBuffer buf, PGconn *conn, bool resetbuffer)
Definition: fe-misc.c:131

◆ pqGets_append()

int pqGets_append ( PQExpBuffer  buf,
PGconn conn 
)

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

References pqGets_internal().

Referenced by PQconnectPoll().

169 {
170  return pqGets_internal(buf, conn, false);
171 }
static int pqGets_internal(PQExpBuffer buf, PGconn *conn, bool resetbuffer)
Definition: fe-misc.c:131

◆ 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 4470 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().

4472 {
4473  /* Start the message. */
4474  if (pqPutMsgStart(pack_type, true, conn))
4475  return STATUS_ERROR;
4476 
4477  /* Send the message body. */
4478  if (pqPutnchar(buf, buf_len, conn))
4479  return STATUS_ERROR;
4480 
4481  /* Finish the message. */
4482  if (pqPutMsgEnd(conn))
4483  return STATUS_ERROR;
4484 
4485  /* Flush to ensure backend gets it. */
4486  if (pqFlush(conn))
4487  return STATUS_ERROR;
4488 
4489  return STATUS_OK;
4490 }
int pqFlush(PGconn *conn)
Definition: fe-misc.c:997
int pqPutMsgStart(char msg_type, bool force_len, PGconn *conn)
Definition: fe-misc.c:518
#define STATUS_ERROR
Definition: c.h:1121
static char * buf
Definition: pg_test_fsync.c:67
#define STATUS_OK
Definition: c.h:1120
int pqPutnchar(const char *s, size_t len, PGconn *conn)
Definition: fe-misc.c:245
int pqPutMsgEnd(PGconn *conn)
Definition: fe-misc.c:586

◆ pqParseInput2()

void pqParseInput2 ( PGconn conn)

Definition at line 408 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().

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

◆ 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:
409  "unexpected response from server; first received character was \"%c\"\n"),
410  id);
411  /* build an error result holding the error message */
412  pqSaveErrorResult(conn);
413  /* not sure if we will see more, so go to ready state */
414  conn->asyncStatus = PGASYNC_READY;
415  /* Discard the unexpected message */
416  conn->inCursor += msgLength;
417  break;
418  } /* switch on protocol character */
419  }
420  /* Successfully consumed this message */
421  if (conn->inCursor == conn->inStart + 5 + msgLength)
422  {
423  /* Normal case: parsing agrees with specified length */
424  conn->inStart = conn->inCursor;
425  }
426  else
427  {
428  /* Trouble --- report it */
430  libpq_gettext("message contents do not agree with length in message type \"%c\"\n"),
431  id);
432  /* build an error result holding the error message */
433  pqSaveErrorResult(conn);
434  conn->asyncStatus = PGASYNC_READY;
435  /* trust the specified message length as what to skip */
436  conn->inStart += 5 + msgLength;
437  }
438  }
439 }
int inEnd
Definition: libpq-int.h:445
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
int inStart
Definition: libpq-int.h:443
int pqGets(PQExpBuffer buf, PGconn *conn)
Definition: fe-misc.c:162
PQExpBufferData workBuffer
Definition: libpq-int.h:514
int pqCheckInBufferSpace(size_t bytes_needed, PGconn *conn)
Definition: fe-misc.c:407
PGQueryClass queryclass
Definition: libpq-int.h:388
int pqGetInt(int *result, size_t bytes, PGconn *conn)
Definition: fe-misc.c:266
static int getParamDescriptions(PGconn *conn, int msgLength)
Definition: fe-protocol3.c:648
#define CMDSTATUS_LEN
Definition: libpq-int.h:86
PGresult * result
Definition: libpq-int.h:462
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:386
static int getRowDescriptions(PGconn *conn, int msgLength)
Definition: fe-protocol3.c:470
int pqGetErrorNotice3(PGconn *conn, bool isError)
Definition: fe-protocol3.c:873
PGNoticeHooks noticeHooks
Definition: libpq-int.h:377
static int getAnotherTuple(PGconn *conn, int msgLength)
Definition: fe-protocol3.c:745
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:93
#define VALID_LONG_MESSAGE_TYPE(id)
Definition: fe-protocol3.c:38
PQExpBufferData errorMessage
Definition: libpq-int.h:511
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:432
int copy_already_done
Definition: libpq-int.h:396
static int getParameterStatus(PGconn *conn)
static int getNotify(PGconn *conn)
static void handleSyncLoss(PGconn *conn, char id, int msgLength)
Definition: fe-protocol3.c:447
void pqSaveErrorResult(PGconn *conn)
Definition: fe-exec.c:772
int inCursor
Definition: libpq-int.h:444
int be_pid
Definition: libpq-int.h:431
ExecStatusType resultStatus
Definition: libpq-int.h:177
#define libpq_gettext(x)
Definition: libpq-int.h:792

◆ 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:462
PGresult * next_result
Definition: libpq-int.h:463
PGresult * PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
Definition: fe-exec.c:141
PQExpBufferData errorMessage
Definition: libpq-int.h:511
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 111 of file fe-misc.c.

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

Referenced by PQsendDescribe(), and PQsendQueryGuts().

112 {
113  if (pqPutMsgBytes(&c, 1, conn))
114  return EOF;
115 
116  if (conn->Pfdebug)
117  fprintf(conn->Pfdebug, "To backend> %c\n", c);
118 
119  return 0;
120 }
#define fprintf
Definition: port.h:196
FILE * Pfdebug
Definition: libpq-int.h:374
static int pqPutMsgBytes(const void *buf, size_t len, PGconn *conn)
Definition: fe-misc.c:563
char * c

◆ pqPutInt()

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

Definition at line 306 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().

307 {
308  uint16 tmp2;
309  uint32 tmp4;
310 
311  switch (bytes)
312  {
313  case 2:
314  tmp2 = pg_hton16((uint16) value);
315  if (pqPutMsgBytes((const char *) &tmp2, 2, conn))
316  return EOF;
317  break;
318  case 4:
319  tmp4 = pg_hton32((uint32) value);
320  if (pqPutMsgBytes((const char *) &tmp4, 4, conn))
321  return EOF;
322  break;
323  default:
325  "integer of size %lu not supported by pqPutInt",
326  (unsigned long) bytes);
327  return EOF;
328  }
329 
330  if (conn->Pfdebug)
331  fprintf(conn->Pfdebug, "To backend (%lu#)> %d\n", (unsigned long) bytes, value);
332 
333  return 0;
334 }
def bytes(source, encoding='ascii', errors='strict')
#define pg_hton16(x)
Definition: pg_bswap.h:120
static struct @145 value
#define fprintf
Definition: port.h:196
FILE * Pfdebug
Definition: libpq-int.h:374
unsigned short uint16
Definition: c.h:358
#define pg_hton32(x)
Definition: pg_bswap.h:121
PGNoticeHooks noticeHooks
Definition: libpq-int.h:377
static int pqPutMsgBytes(const void *buf, size_t len, PGconn *conn)
Definition: fe-misc.c:563
void pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt,...)
Definition: fe-exec.c:871
unsigned int uint32
Definition: c.h:359

◆ pqPutMsgEnd()

int pqPutMsgEnd ( PGconn conn)

Definition at line 586 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().

587 {
588  if (conn->Pfdebug)
589  fprintf(conn->Pfdebug, "To backend> Msg complete, length %u\n",
590  conn->outMsgEnd - conn->outCount);
591 
592  /* Fill in length word if needed */
593  if (conn->outMsgStart >= 0)
594  {
595  uint32 msgLen = conn->outMsgEnd - conn->outMsgStart;
596 
597  msgLen = pg_hton32(msgLen);
598  memcpy(conn->outBuffer + conn->outMsgStart, &msgLen, 4);
599  }
600 
601  /* Make message eligible to send */
602  conn->outCount = conn->outMsgEnd;
603 
604  if (conn->outCount >= 8192)
605  {
606  int toSend = conn->outCount - (conn->outCount % 8192);
607 
608  if (pqSendSome(conn, toSend) < 0)
609  return EOF;
610  /* in nonblock mode, don't complain if unable to send it all */
611  }
612 
613  return 0;
614 }
int outCount
Definition: libpq-int.h:450
int outMsgEnd
Definition: libpq-int.h:455
#define fprintf
Definition: port.h:196
FILE * Pfdebug
Definition: libpq-int.h:374
#define pg_hton32(x)
Definition: pg_bswap.h:121
unsigned int uint32
Definition: c.h:359
int outMsgStart
Definition: libpq-int.h:453
char * outBuffer
Definition: libpq-int.h:448
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 518 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().

519 {
520  int lenPos;
521  int endPos;
522 
523  /* allow room for message type byte */
524  if (msg_type)
525  endPos = conn->outCount + 1;
526  else
527  endPos = conn->outCount;
528 
529  /* do we want a length word? */
530  if (force_len || PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
531  {
532  lenPos = endPos;
533  /* allow room for message length */
534  endPos += 4;
535  }
536  else
537  lenPos = -1;
538 
539  /* make sure there is room for message header */
540  if (pqCheckOutBufferSpace(endPos, conn))
541  return EOF;
542  /* okay, save the message type byte if any */
543  if (msg_type)
544  conn->outBuffer[conn->outCount] = msg_type;
545  /* set up the message pointers */
546  conn->outMsgStart = lenPos;
547  conn->outMsgEnd = endPos;
548  /* length word, if needed, will be filled in by pqPutMsgEnd */
549 
550  if (conn->Pfdebug)
551  fprintf(conn->Pfdebug, "To backend> Msg %c\n",
552  msg_type ? msg_type : ' ');
553 
554  return 0;
555 }
int pqCheckOutBufferSpace(size_t bytes_needed, PGconn *conn)
Definition: fe-misc.c:343
int outCount
Definition: libpq-int.h:450
int outMsgEnd
Definition: libpq-int.h:455
#define PG_PROTOCOL_MAJOR(v)
Definition: pqcomm.h:104
#define fprintf
Definition: port.h:196
FILE * Pfdebug
Definition: libpq-int.h:374
int outMsgStart
Definition: libpq-int.h:453
ProtocolVersion pversion
Definition: libpq-int.h:411
char * outBuffer
Definition: libpq-int.h:448

◆ pqPutnchar()

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

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

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

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

246 {
247  if (pqPutMsgBytes(s, len, conn))
248  return EOF;
249 
250  if (conn->Pfdebug)
251  {
252  fprintf(conn->Pfdebug, "To backend> ");
253  fputnbytes(conn->Pfdebug, s, len);
254  fprintf(conn->Pfdebug, "\n");
255  }
256 
257  return 0;
258 }
#define fprintf
Definition: port.h:196
FILE * Pfdebug
Definition: libpq-int.h:374
static int pqPutMsgBytes(const void *buf, size_t len, PGconn *conn)
Definition: fe-misc.c:563
static void fputnbytes(FILE *f, const char *str, size_t n)
Definition: fe-misc.c:78

◆ pqPuts()

int pqPuts ( const char *  s,
PGconn conn 
)

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

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

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

179 {
180  if (pqPutMsgBytes(s, strlen(s) + 1, conn))
181  return EOF;
182 
183  if (conn->Pfdebug)
184  fprintf(conn->Pfdebug, "To backend> \"%s\"\n", s);
185 
186  return 0;
187 }
#define fprintf
Definition: port.h:196
FILE * Pfdebug
Definition: libpq-int.h:374
static int pqPutMsgBytes(const void *buf, size_t len, PGconn *conn)
Definition: fe-misc.c:563

◆ pqReadData()

int pqReadData ( PGconn conn)

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

References CONNECTION_BAD, EAGAIN, ECONNRESET, EINTR, pg_conn::errorMessage, EWOULDBLOCK, pg_conn::inBuffer, pg_conn::inBufSize, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, libpq_gettext, memmove, 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().

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

◆ pqReadReady()

int pqReadReady ( PGconn conn)

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

References pqSocketCheck().

Referenced by gss_read(), and pqReadData().

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

◆ 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:394
PGresult * PQcopyResult(const PGresult *src, int flags)
Definition: fe-exec.c:294
static struct @145 value
#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:462
PGresult * next_result
Definition: libpq-int.h:463
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:386
#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:458
int numAttributes
Definition: libpq-int.h:170
#define PG_COPYRES_ATTRS
Definition: libpq-fe.h:34
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:462
PGresult * PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
Definition: fe-exec.c:141
PQExpBufferData errorMessage
Definition: libpq-int.h:511
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
static struct @145 value
struct pgMessageField * next
Definition: libpq-int.h:144
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:662

◆ 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:551
static struct @145 value
#define fprintf
Definition: port.h:196
FILE * Pfdebug
Definition: libpq-int.h:374
#define malloc(a)
Definition: header.h:50
int sversion
Definition: libpq-int.h:412
struct pgParameterStatus pgParameterStatus
static int static_client_encoding
Definition: fe-exec.c:49
pgParameterStatus * pstatus
Definition: libpq-int.h:433
bool std_strings
Definition: libpq-int.h:435
#define free(a)
Definition: header.h:65
struct pgParameterStatus * next
Definition: libpq-int.h:261
const char * name
Definition: encode.c:521
int client_encoding
Definition: libpq-int.h:434

◆ 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:469
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 #ifdef ECONNRESET
265  case ECONNRESET:
268  "server closed the connection unexpectedly\n"
269  "\tThis probably means the server terminated abnormally\n"
270  "\tbefore or while processing the request.\n"));
271  break;
272 #endif
273 
274  default:
276  libpq_gettext("could not receive data from server: %s\n"),
277  SOCK_STRERROR(result_errno,
278  sebuf, sizeof(sebuf)));
279  break;
280  }
281  }
282 
283  /* ensure we return the intended errno to caller */
284  SOCK_ERRNO_SET(result_errno);
285 
286  return n;
287 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
#define EAGAIN
Definition: win32_port.h:321
#define PG_STRERROR_R_BUFLEN
Definition: port.h:210
#define recv(s, buf, len, flags)
Definition: win32_port.h:437
#define SOCK_STRERROR
Definition: libpq-int.h:806
#define SOCK_ERRNO
Definition: libpq-int.h:805
PGconn * conn
Definition: streamutil.c:54
#define SOCK_ERRNO_SET(e)
Definition: libpq-int.h:807
pgsocket sock
Definition: libpq-int.h:407
PQExpBufferData errorMessage
Definition: libpq-int.h:511
#define ECONNRESET
Definition: win32_port.h:333
#define EWOULDBLOCK
Definition: win32_port.h:329
#define EINTR
Definition: win32_port.h:323
#define libpq_gettext(x)
Definition: libpq-int.h:792

◆ pqsecure_raw_write()

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

Definition at line 323 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().

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