{
if (inputlen == 0)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("malformed SCRAM message (empty message)\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("malformed SCRAM message (empty message)\n"));
goto error;
}
if (inputlen != strlen(input))
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("malformed SCRAM message (length mismatch)\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("malformed SCRAM message (length mismatch)\n"));
goto error;
}
}
*/
if (!verify_server_signature(state, success))
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could not verify server signature\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("could not verify server signature\n"));
goto error;
}
if (!*success)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("incorrect server signature\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("incorrect server signature\n"));
}
*done = true;
state->state = FE_SCRAM_FINISHED;
default:
/* shouldn't happen */
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("invalid SCRAM exchange state\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("invalid SCRAM exchange state\n"));
goto error;
}
return;
/*
* Read value for an attribute part of a SCRAM message.
+ *
+ * The buffer at **input is destructively modified, and *input is
+ * advanced over the "attr=value" string and any following comma.
+ *
+ * On failure, append an error message to *errorMessage and return NULL.
*/
static char *
read_attr_value(char **input, char attr, PQExpBuffer errorMessage)
if (*begin != attr)
{
- printfPQExpBuffer(errorMessage,
+ appendPQExpBuffer(errorMessage,
libpq_gettext("malformed SCRAM message (attribute \"%c\" expected)\n"),
attr);
return NULL;
if (*begin != '=')
{
- printfPQExpBuffer(errorMessage,
+ appendPQExpBuffer(errorMessage,
libpq_gettext("malformed SCRAM message (expected character \"=\" for attribute \"%c\")\n"),
attr);
return NULL;
*/
if (!pg_strong_random(raw_nonce, SCRAM_RAW_NONCE_LEN))
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could not generate nonce\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("could not generate nonce\n"));
return NULL;
}
state->client_nonce = malloc(encoded_len + 1);
if (state->client_nonce == NULL)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("out of memory\n"));
return NULL;
}
encoded_len = pg_b64_encode(raw_nonce, SCRAM_RAW_NONCE_LEN,
state->client_nonce, encoded_len);
if (encoded_len < 0)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could not encode nonce\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("could not encode nonce\n"));
return NULL;
}
state->client_nonce[encoded_len] = '\0';
oom_error:
termPQExpBuffer(&buf);
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("out of memory\n"));
return NULL;
}
free(cbind_data);
free(cbind_input);
termPQExpBuffer(&buf);
- printfPQExpBuffer(&conn->errorMessage,
- "could not encode cbind data for channel binding\n");
+ appendPQExpBufferStr(&conn->errorMessage,
+ "could not encode cbind data for channel binding\n");
return NULL;
}
buf.len += encoded_cbind_len;
* Shouldn't happen.
*/
termPQExpBuffer(&buf);
- printfPQExpBuffer(&conn->errorMessage,
- "channel binding not supported by this build\n");
+ appendPQExpBufferStr(&conn->errorMessage,
+ "channel binding not supported by this build\n");
return NULL;
#endif /* HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH */
}
client_proof))
{
termPQExpBuffer(&buf);
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could not calculate client proof\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("could not calculate client proof\n"));
return NULL;
}
if (encoded_len < 0)
{
termPQExpBuffer(&buf);
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could not encode client proof\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("could not encode client proof\n"));
return NULL;
}
buf.len += encoded_len;
oom_error:
termPQExpBuffer(&buf);
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("out of memory\n"));
return NULL;
}
state->server_first_message = strdup(input);
if (state->server_first_message == NULL)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("out of memory\n"));
return false;
}
&conn->errorMessage);
if (nonce == NULL)
{
- /* read_attr_value() has generated an error string */
+ /* read_attr_value() has appended an error string */
return false;
}
if (strlen(nonce) < strlen(state->client_nonce) ||
memcmp(nonce, state->client_nonce, strlen(state->client_nonce)) != 0)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("invalid SCRAM response (nonce mismatch)\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("invalid SCRAM response (nonce mismatch)\n"));
return false;
}
state->nonce = strdup(nonce);
if (state->nonce == NULL)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("out of memory\n"));
return false;
}
encoded_salt = read_attr_value(&input, 's', &conn->errorMessage);
if (encoded_salt == NULL)
{
- /* read_attr_value() has generated an error string */
+ /* read_attr_value() has appended an error string */
return false;
}
decoded_salt_len = pg_b64_dec_len(strlen(encoded_salt));
state->salt = malloc(decoded_salt_len);
if (state->salt == NULL)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("out of memory\n"));
return false;
}
state->saltlen = pg_b64_decode(encoded_salt,
decoded_salt_len);
if (state->saltlen < 0)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("malformed SCRAM message (invalid salt)\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("malformed SCRAM message (invalid salt)\n"));
return false;
}
iterations_str = read_attr_value(&input, 'i', &conn->errorMessage);
if (iterations_str == NULL)
{
- /* read_attr_value() has generated an error string */
+ /* read_attr_value() has appended an error string */
return false;
}
state->iterations = strtol(iterations_str, &endptr, 10);
if (*endptr != '\0' || state->iterations < 1)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("malformed SCRAM message (invalid iteration count)\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("malformed SCRAM message (invalid iteration count)\n"));
return false;
}
if (*input != '\0')
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("malformed SCRAM message (garbage at end of server-first-message)\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("malformed SCRAM message (garbage at end of server-first-message)\n"));
return true;
}
state->server_final_message = strdup(input);
if (!state->server_final_message)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("out of memory\n"));
return false;
}
char *errmsg = read_attr_value(&input, 'e',
&conn->errorMessage);
- printfPQExpBuffer(&conn->errorMessage,
+ if (errmsg == NULL)
+ {
+ /* read_attr_value() has appended an error message */
+ return false;
+ }
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("error received from server in SCRAM exchange: %s\n"),
errmsg);
return false;
&conn->errorMessage);
if (encoded_server_signature == NULL)
{
- /* read_attr_value() has generated an error message */
+ /* read_attr_value() has appended an error message */
return false;
}
if (*input != '\0')
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("malformed SCRAM message (garbage at end of server-final-message)\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("malformed SCRAM message (garbage at end of server-final-message)\n"));
server_signature_len = pg_b64_dec_len(strlen(encoded_server_signature));
decoded_server_signature = malloc(server_signature_len);
if (!decoded_server_signature)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("out of memory\n"));
return false;
}
if (server_signature_len != SCRAM_KEY_LEN)
{
free(decoded_server_signature);
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("malformed SCRAM message (invalid server signature)\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("malformed SCRAM message (invalid server signature)\n"));
return false;
}
memcpy(state->ServerSignature, decoded_server_signature, SCRAM_KEY_LEN);
ginbuf.value = malloc(payloadlen);
if (!ginbuf.value)
{
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory allocating GSSAPI buffer (%d)\n"),
payloadlen);
return STATUS_ERROR;
if (!(host && host[0] != '\0'))
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("host name must be specified\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("host name must be specified\n"));
return STATUS_ERROR;
}
if (conn->gctx)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("duplicate GSS authentication request\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("duplicate GSS authentication request\n"));
return STATUS_ERROR;
}
FORMAT_MESSAGE_FROM_SYSTEM,
NULL, r, 0,
sysmsg, sizeof(sysmsg), NULL) == 0)
- printfPQExpBuffer(&conn->errorMessage, "%s: SSPI error %x\n",
+ appendPQExpBuffer(&conn->errorMessage, "%s: SSPI error %x\n",
mprefix, (unsigned int) r);
else
- printfPQExpBuffer(&conn->errorMessage, "%s: %s (%x)\n",
+ appendPQExpBuffer(&conn->errorMessage, "%s: %s (%x)\n",
mprefix, sysmsg, (unsigned int) r);
}
inputbuf = malloc(payloadlen);
if (!inputbuf)
{
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory allocating SSPI buffer (%d)\n"),
payloadlen);
return STATUS_ERROR;
conn->sspictx = malloc(sizeof(CtxtHandle));
if (conn->sspictx == NULL)
{
- printfPQExpBuffer(&conn->errorMessage, libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("out of memory\n"));
return STATUS_ERROR;
}
memcpy(conn->sspictx, &newContext, sizeof(CtxtHandle));
* authentication. Keep check in case it shows up with other
* authentication methods later.
*/
- printfPQExpBuffer(&conn->errorMessage, "SSPI returned invalid number of output buffers\n");
+ appendPQExpBufferStr(&conn->errorMessage,
+ "SSPI returned invalid number of output buffers\n");
return STATUS_ERROR;
}
if (conn->sspictx)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("duplicate SSPI authentication request\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("duplicate SSPI authentication request\n"));
return STATUS_ERROR;
}
conn->sspicred = malloc(sizeof(CredHandle));
if (conn->sspicred == NULL)
{
- printfPQExpBuffer(&conn->errorMessage, libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("out of memory\n"));
return STATUS_ERROR;
}
*/
if (!(host && host[0] != '\0'))
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("host name must be specified\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("host name must be specified\n"));
return STATUS_ERROR;
}
conn->sspitarget = malloc(strlen(conn->krbsrvname) + strlen(host) + 2);
if (!conn->sspitarget)
{
- printfPQExpBuffer(&conn->errorMessage, libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("out of memory\n"));
return STATUS_ERROR;
}
sprintf(conn->sspitarget, "%s/%s", conn->krbsrvname, host);
if (conn->channel_binding[0] == 'r' && /* require */
!conn->ssl_in_use)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("channel binding required, but SSL not in use\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("channel binding required, but SSL not in use\n"));
goto error;
}
if (conn->sasl_state)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("duplicate SASL authentication request\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("duplicate SASL authentication request\n"));
goto error;
}
{
if (pqGets(&mechanism_buf, conn))
{
- printfPQExpBuffer(&conn->errorMessage,
- "fe_sendauth: invalid authentication request from server: invalid list of authentication mechanisms\n");
+ appendPQExpBufferStr(&conn->errorMessage,
+ "fe_sendauth: invalid authentication request from server: invalid list of authentication mechanisms\n");
goto error;
}
if (PQExpBufferDataBroken(mechanism_buf))
*/
if (conn->channel_binding[0] == 'r') /* require */
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("channel binding is required, but client does not support it\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("channel binding is required, but client does not support it\n"));
goto error;
}
#endif
* the client and server supported it. The SCRAM exchange
* checks for that, to prevent downgrade attacks.
*/
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("server offered SCRAM-SHA-256-PLUS authentication over a non-SSL connection\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("server offered SCRAM-SHA-256-PLUS authentication over a non-SSL connection\n"));
goto error;
}
}
if (!selected_mechanism)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("none of the server's SASL authentication mechanisms are supported\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("none of the server's SASL authentication mechanisms are supported\n"));
goto error;
}
if (conn->channel_binding[0] == 'r' && /* require */
strcmp(selected_mechanism, SCRAM_SHA_256_PLUS_NAME) != 0)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("channel binding is required, but server did not offer an authentication method that supports channel binding\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("channel binding is required, but server did not offer an authentication method that supports channel binding\n"));
goto error;
}
password = conn->pgpass;
if (password == NULL || password[0] == '\0')
{
- printfPQExpBuffer(&conn->errorMessage,
- PQnoPasswordSupplied);
+ appendPQExpBufferStr(&conn->errorMessage,
+ PQnoPasswordSupplied);
goto error;
}
termPQExpBuffer(&mechanism_buf);
if (initialresponse)
free(initialresponse);
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("out of memory\n"));
return STATUS_ERROR;
}
challenge = malloc(payloadlen + 1);
if (!challenge)
{
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory allocating SASL buffer (%d)\n"),
payloadlen);
return STATUS_ERROR;
if (outputlen != 0)
free(output);
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("AuthenticationSASLFinal received from server, but SASL authentication was not completed\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("AuthenticationSASLFinal received from server, but SASL authentication was not completed\n"));
return STATUS_ERROR;
}
if (outputlen != 0)
{
char sebuf[PG_STRERROR_R_BUFLEN];
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
"pg_local_sendauth: sendmsg: %s\n",
strerror_r(errno, sebuf, sizeof(sebuf)));
return STATUS_ERROR;
}
return STATUS_OK;
#else
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("SCM_CRED authentication method not supported\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("SCM_CRED authentication method not supported\n"));
return STATUS_ERROR;
#endif
}
crypt_pwd = malloc(2 * (MD5_PASSWD_LEN + 1));
if (!crypt_pwd)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("out of memory\n"));
return STATUS_ERROR;
}
case AUTH_REQ_OK:
if (!pg_fe_scram_channel_bound(conn->sasl_state))
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("channel binding required, but server authenticated client without channel binding\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("channel binding required, but server authenticated client without channel binding\n"));
result = false;
}
break;
default:
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("channel binding required but not supported by server's authentication request\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("channel binding required but not supported by server's authentication request\n"));
result = false;
break;
}
int
pg_fe_sendauth(AuthRequest areq, int payloadlen, PGconn *conn)
{
+ int oldmsglen;
+
if (!check_expected_areq(areq, conn))
return STATUS_ERROR;
break;
case AUTH_REQ_KRB4:
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("Kerberos 4 authentication not supported\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("Kerberos 4 authentication not supported\n"));
return STATUS_ERROR;
case AUTH_REQ_KRB5:
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("Kerberos 5 authentication not supported\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("Kerberos 5 authentication not supported\n"));
return STATUS_ERROR;
#if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
/* No GSSAPI *or* SSPI support */
case AUTH_REQ_GSS:
case AUTH_REQ_GSS_CONT:
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("GSSAPI authentication not supported\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("GSSAPI authentication not supported\n"));
return STATUS_ERROR;
#endif /* defined(ENABLE_GSS) || defined(ENABLE_SSPI) */
*/
#if !defined(ENABLE_GSS)
case AUTH_REQ_SSPI:
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("SSPI authentication not supported\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("SSPI authentication not supported\n"));
return STATUS_ERROR;
#endif /* !define(ENABLE_GSS) */
#endif /* ENABLE_SSPI */
case AUTH_REQ_CRYPT:
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("Crypt authentication not supported\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("Crypt authentication not supported\n"));
return STATUS_ERROR;
case AUTH_REQ_MD5:
password = conn->pgpass;
if (password == NULL || password[0] == '\0')
{
- printfPQExpBuffer(&conn->errorMessage,
- PQnoPasswordSupplied);
+ appendPQExpBufferStr(&conn->errorMessage,
+ PQnoPasswordSupplied);
return STATUS_ERROR;
}
if (pg_password_sendauth(conn, password, areq) != STATUS_OK)
{
- printfPQExpBuffer(&conn->errorMessage,
- "fe_sendauth: error sending password authentication\n");
+ appendPQExpBufferStr(&conn->errorMessage,
+ "fe_sendauth: error sending password authentication\n");
return STATUS_ERROR;
}
break;
case AUTH_REQ_SASL_FIN:
if (conn->sasl_state == NULL)
{
- printfPQExpBuffer(&conn->errorMessage,
- "fe_sendauth: invalid authentication request from server: AUTH_REQ_SASL_CONT without AUTH_REQ_SASL\n");
+ appendPQExpBufferStr(&conn->errorMessage,
+ "fe_sendauth: invalid authentication request from server: AUTH_REQ_SASL_CONT without AUTH_REQ_SASL\n");
return STATUS_ERROR;
}
+ oldmsglen = conn->errorMessage.len;
if (pg_SASL_continue(conn, payloadlen,
(areq == AUTH_REQ_SASL_FIN)) != STATUS_OK)
{
- /* Use error message, if set already */
- if (conn->errorMessage.len == 0)
- printfPQExpBuffer(&conn->errorMessage,
- "fe_sendauth: error in SASL authentication\n");
+ /* Use this message if pg_SASL_continue didn't supply one */
+ if (conn->errorMessage.len == oldmsglen)
+ appendPQExpBufferStr(&conn->errorMessage,
+ "fe_sendauth: error in SASL authentication\n");
return STATUS_ERROR;
}
break;
break;
default:
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("authentication method %u not supported\n"), areq);
return STATUS_ERROR;
}
*
* Returns a pointer to malloc'd space containing whatever name the user
* has authenticated to the system. If there is an error, return NULL,
- * and put a suitable error message in *errorMessage if that's not NULL.
+ * and append a suitable error message to *errorMessage if that's not NULL.
*/
char *
pg_fe_getauthname(PQExpBuffer errorMessage)
if (GetUserName(username, &namesize))
name = username;
else if (errorMessage)
- printfPQExpBuffer(errorMessage,
+ appendPQExpBuffer(errorMessage,
libpq_gettext("user name lookup failure: error code %lu\n"),
GetLastError());
#else
else if (errorMessage)
{
if (pwerr != 0)
- printfPQExpBuffer(errorMessage,
+ appendPQExpBuffer(errorMessage,
libpq_gettext("could not look up local user ID %d: %s\n"),
(int) user_id,
strerror_r(pwerr, pwdbuf, sizeof(pwdbuf)));
else
- printfPQExpBuffer(errorMessage,
+ appendPQExpBuffer(errorMessage,
libpq_gettext("local user with ID %d does not exist\n"),
(int) user_id);
}
{
result = strdup(name);
if (result == NULL && errorMessage)
- printfPQExpBuffer(errorMessage,
- libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(errorMessage,
+ libpq_gettext("out of memory\n"));
}
pgunlock_thread();
if (!conn)
return NULL;
+ resetPQExpBuffer(&conn->errorMessage);
+
/* If no algorithm was given, ask the server. */
if (algorithm == NULL)
{
if (PQntuples(res) != 1 || PQnfields(res) != 1)
{
PQclear(res);
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("unexpected shape of result set returned for SHOW\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("unexpected shape of result set returned for SHOW\n"));
return NULL;
}
val = PQgetvalue(res, 0, 0);
if (strlen(val) > MAX_ALGORITHM_NAME_LEN)
{
PQclear(res);
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("password_encryption value too long\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("password_encryption value too long\n"));
return NULL;
}
strcpy(algobuf, val);
}
else
{
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("unrecognized password encryption algorithm \"%s\"\n"),
algorithm);
return NULL;
}
if (!crypt_pwd)
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("out of memory\n"));
return crypt_pwd;
}
PQconninfoOption *connOptions;
/*
- * Allocate memory for the conn structure
+ * Allocate memory for the conn structure. Note that we also expect this
+ * to initialize conn->errorMessage to empty. All subsequent steps during
+ * connection initialization will only append to that buffer.
*/
conn = makeEmptyPGconn();
if (conn == NULL)
PGconn *conn;
/*
- * Allocate memory for the conn structure
+ * Allocate memory for the conn structure. Note that we also expect this
+ * to initialize conn->errorMessage to empty. All subsequent steps during
+ * connection initialization will only append to that buffer.
*/
conn = makeEmptyPGconn();
if (conn == NULL)
*connmember = strdup(tmp);
if (*connmember == NULL)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("out of memory\n"));
return false;
}
}
if (more || i != conn->nconnhost)
{
conn->status = CONNECTION_BAD;
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not match %d host names to %d hostaddr values\n"),
count_comma_separated_elems(conn->pghost), conn->nconnhost);
return false;
else if (more || i != conn->nconnhost)
{
conn->status = CONNECTION_BAD;
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not match %d port numbers to %d hosts\n"),
count_comma_separated_elems(conn->pgport), conn->nconnhost);
return false;
&& strcmp(conn->channel_binding, "require") != 0)
{
conn->status = CONNECTION_BAD;
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("invalid %s value: \"%s\"\n"),
"channel_binding", conn->channel_binding);
return false;
&& strcmp(conn->sslmode, "verify-full") != 0)
{
conn->status = CONNECTION_BAD;
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("invalid %s value: \"%s\"\n"),
"sslmode", conn->sslmode);
return false;
case 'r': /* "require" */
case 'v': /* "verify-ca" or "verify-full" */
conn->status = CONNECTION_BAD;
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("sslmode value \"%s\" invalid when SSL support is not compiled in\n"),
conn->sslmode);
return false;
if (!sslVerifyProtocolVersion(conn->ssl_min_protocol_version))
{
conn->status = CONNECTION_BAD;
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("invalid %s value: \"%s\"\n"),
"ssl_min_protocol_version",
conn->ssl_min_protocol_version);
if (!sslVerifyProtocolVersion(conn->ssl_max_protocol_version))
{
conn->status = CONNECTION_BAD;
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("invalid %s value: \"%s\"\n"),
"ssl_max_protocol_version",
conn->ssl_max_protocol_version);
conn->ssl_max_protocol_version))
{
conn->status = CONNECTION_BAD;
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("invalid SSL protocol version range\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("invalid SSL protocol version range\n"));
return false;
}
strcmp(conn->gssencmode, "require") != 0)
{
conn->status = CONNECTION_BAD;
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("invalid %s value: \"%s\"\n"),
"gssencmode",
conn->gssencmode);
if (strcmp(conn->gssencmode, "require") == 0)
{
conn->status = CONNECTION_BAD;
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("gssencmode value \"%s\" invalid when GSSAPI support is not compiled in\n"),
conn->gssencmode);
return false;
&& strcmp(conn->target_session_attrs, "read-write") != 0)
{
conn->status = CONNECTION_BAD;
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("invalid %s value: \"%s\"\n"),
"target_settion_attrs",
conn->target_session_attrs);
oom_error:
conn->status = CONNECTION_BAD;
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("out of memory\n"));
return false;
}
PGconn *conn;
/*
- * Allocate memory for the conn structure
+ * Allocate memory for the conn structure. Note that we also expect this
+ * to initialize conn->errorMessage to empty. All subsequent steps during
+ * connection initialization will only append to that buffer.
*/
conn = makeEmptyPGconn();
if (conn == NULL)
oom_error:
conn->status = CONNECTION_BAD;
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("out of memory\n"));
return conn;
}
*/
if (!pg_link_canary_is_frontend())
{
- printfPQExpBuffer(&conn->errorMessage,
- "libpq is incorrectly linked to backend functions\n");
+ appendPQExpBufferStr(&conn->errorMessage,
+ "libpq is incorrectly linked to backend functions\n");
goto connect_errReturn;
}
conn->inStart = conn->inCursor = conn->inEnd = 0;
conn->outCount = 0;
- /*
- * Ensure errorMessage is empty, too. PQconnectPoll will append messages
- * to it in the process of scanning for a working server. Thus, if we
- * fail to connect to multiple hosts, the final error message will include
- * details about each failure.
- */
- resetPQExpBuffer(&conn->errorMessage);
-
/*
* Set up to try to connect to the first host. (Setting whichhost = -1 is
* a bit of a cheat, but PQconnectPoll will advance it to 0 before
switch (flag)
{
case PGRES_POLLING_OK:
-
- /*
- * Reset stored error messages since we now have a working
- * connection
- */
- resetPQExpBuffer(&conn->errorMessage);
return 1; /* success! */
case PGRES_POLLING_READING:
}
}
-/*
- * This subroutine saves conn->errorMessage, which will be restored back by
- * restoreErrorMessage subroutine. Returns false on OOM failure.
- */
-static bool
-saveErrorMessage(PGconn *conn, PQExpBuffer savedMessage)
-{
- initPQExpBuffer(savedMessage);
- appendPQExpBufferStr(savedMessage,
- conn->errorMessage.data);
- if (PQExpBufferBroken(savedMessage))
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory\n"));
- return false;
- }
- /* Clear whatever is in errorMessage now */
- resetPQExpBuffer(&conn->errorMessage);
- return true;
-}
-
-/*
- * Restores saved error messages back to conn->errorMessage, prepending them
- * to whatever is in conn->errorMessage already. (This does the right thing
- * if anything's been added to conn->errorMessage since saveErrorMessage.)
- */
-static void
-restoreErrorMessage(PGconn *conn, PQExpBuffer savedMessage)
-{
- appendPQExpBufferStr(savedMessage, conn->errorMessage.data);
- resetPQExpBuffer(&conn->errorMessage);
- appendPQExpBufferStr(&conn->errorMessage, savedMessage->data);
- /* If any step above hit OOM, just report that */
- if (PQExpBufferBroken(savedMessage) ||
- PQExpBufferBroken(&conn->errorMessage))
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory\n"));
- termPQExpBuffer(savedMessage);
-}
-
/* ----------------
* PQconnectPoll
*
PGresult *res;
char sebuf[PG_STRERROR_R_BUFLEN];
int optval;
- PQExpBufferData savedMessage;
if (conn == NULL)
return PGRES_POLLING_FAILED;
EnvironmentOptions);
if (!startpacket)
{
- /*
- * will not appendbuffer here, since it's likely to also
- * run out of memory
- */
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("out of memory\n"));
goto error_return;
}
* avoid the Kerberos code doing a hostname look-up.
*/
res = pg_fe_sendauth(areq, msgLength, conn);
- conn->errorMessage.len = strlen(conn->errorMessage.data);
/* OK, we have processed the message; mark data consumed */
conn->inStart = conn->inCursor;
strcmp(conn->target_session_attrs, "read-write") == 0)
{
/*
- * Save existing error messages across the PQsendQuery
- * attempt. This is necessary because PQsendQuery is
- * going to reset conn->errorMessage, so we would lose
- * error messages related to previous hosts we have tried
- * and failed to connect to.
+ * We use PQsendQueryContinue so that conn->errorMessage
+ * does not get cleared. We need to preserve any error
+ * messages related to previous hosts we have tried and
+ * failed to connect to.
*/
- if (!saveErrorMessage(conn, &savedMessage))
- goto error_return;
-
conn->status = CONNECTION_OK;
- if (!PQsendQuery(conn,
- "SHOW transaction_read_only"))
- {
- restoreErrorMessage(conn, &savedMessage);
+ if (!PQsendQueryContinue(conn,
+ "SHOW transaction_read_only"))
goto error_return;
- }
conn->status = CONNECTION_CHECK_WRITABLE;
- restoreErrorMessage(conn, &savedMessage);
return PGRES_POLLING_READING;
}
const char *displayed_host;
const char *displayed_port;
- if (!saveErrorMessage(conn, &savedMessage))
- goto error_return;
-
conn->status = CONNECTION_OK;
if (!PQconsumeInput(conn))
- {
- restoreErrorMessage(conn, &savedMessage);
goto error_return;
- }
if (PQisBusy(conn))
{
conn->status = CONNECTION_CHECK_WRITABLE;
- restoreErrorMessage(conn, &savedMessage);
return PGRES_POLLING_READING;
}
{
/* Not writable; fail this connection. */
PQclear(res);
- restoreErrorMessage(conn, &savedMessage);
/* Append error report to conn->errorMessage. */
if (conn->connhost[conn->whichhost].type == CHT_HOST_ADDRESS)
/* Session is read-write, so we're good. */
PQclear(res);
- termPQExpBuffer(&savedMessage);
/*
* Finish reading any remaining messages before being
*/
if (res)
PQclear(res);
- restoreErrorMessage(conn, &savedMessage);
/* Append error report to conn->errorMessage. */
if (conn->connhost[conn->whichhost].type == CHT_HOST_ADDRESS)
/*
* Close the connection, reset all transient state, flush I/O buffers.
+ * Note that this includes clearing conn->errorMessage; we're no longer
+ * interested in any failures associated with the old connection, and we
+ * want a clean slate for any new connection attempt.
*/
pqDropConnection(conn, true);
conn->status = CONNECTION_BAD; /* Well, not really _bad_ - just absent */
conn->events[i].passThrough))
{
conn->status = CONNECTION_BAD;
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("PGEventProc \"%s\" failed during PGEVT_CONNRESET event\n"),
conn->events[i].name);
break;
conn->events[i].passThrough))
{
conn->status = CONNECTION_BAD;
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("PGEventProc \"%s\" failed during PGEVT_CONNRESET event\n"),
conn->events[i].name);
return PGRES_POLLING_FAILED;
* 2 if a connection could not be established, and
* 3 if a fatal error occurred.
*
- * An error message is returned in the third argument for return codes 1 and 3.
+ * An error message is appended to *errorMessage for return codes 1 and 3.
*/
static int
ldapServiceLookup(const char *purl, PQconninfoOption *options,
if ((url = strdup(purl)) == NULL)
{
- printfPQExpBuffer(errorMessage, libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(errorMessage, libpq_gettext("out of memory\n"));
return 3;
}
if (pg_strncasecmp(url, LDAP_URL, strlen(LDAP_URL)) != 0)
{
- printfPQExpBuffer(errorMessage,
+ appendPQExpBuffer(errorMessage,
libpq_gettext("invalid LDAP URL \"%s\": scheme must be ldap://\n"), purl);
free(url);
return 3;
p = strchr(url + strlen(LDAP_URL), '/');
if (p == NULL || *(p + 1) == '\0' || *(p + 1) == '?')
{
- printfPQExpBuffer(errorMessage,
+ appendPQExpBuffer(errorMessage,
libpq_gettext("invalid LDAP URL \"%s\": missing distinguished name\n"),
purl);
free(url);
/* attribute */
if ((p = strchr(dn, '?')) == NULL || *(p + 1) == '\0' || *(p + 1) == '?')
{
- printfPQExpBuffer(errorMessage,
+ appendPQExpBuffer(errorMessage,
libpq_gettext("invalid LDAP URL \"%s\": must have exactly one attribute\n"),
purl);
free(url);
/* scope */
if ((p = strchr(attrs[0], '?')) == NULL || *(p + 1) == '\0' || *(p + 1) == '?')
{
- printfPQExpBuffer(errorMessage, libpq_gettext("invalid LDAP URL \"%s\": must have search scope (base/one/sub)\n"), purl);
+ appendPQExpBuffer(errorMessage,
+ libpq_gettext("invalid LDAP URL \"%s\": must have search scope (base/one/sub)\n"),
+ purl);
free(url);
return 3;
}
/* filter */
if ((p = strchr(scopestr, '?')) == NULL || *(p + 1) == '\0' || *(p + 1) == '?')
{
- printfPQExpBuffer(errorMessage,
- libpq_gettext("invalid LDAP URL \"%s\": no filter\n"), purl);
+ appendPQExpBuffer(errorMessage,
+ libpq_gettext("invalid LDAP URL \"%s\": no filter\n"),
+ purl);
free(url);
return 3;
}
lport = strtol(portstr, &endptr, 10);
if (*portstr == '\0' || *endptr != '\0' || errno || lport < 0 || lport > 65535)
{
- printfPQExpBuffer(errorMessage,
+ appendPQExpBuffer(errorMessage,
libpq_gettext("invalid LDAP URL \"%s\": invalid port number\n"),
purl);
free(url);
/* Allow only one attribute */
if (strchr(attrs[0], ',') != NULL)
{
- printfPQExpBuffer(errorMessage,
+ appendPQExpBuffer(errorMessage,
libpq_gettext("invalid LDAP URL \"%s\": must have exactly one attribute\n"),
purl);
free(url);
scope = LDAP_SCOPE_SUBTREE;
else
{
- printfPQExpBuffer(errorMessage, libpq_gettext("invalid LDAP URL \"%s\": must have search scope (base/one/sub)\n"), purl);
+ appendPQExpBuffer(errorMessage,
+ libpq_gettext("invalid LDAP URL \"%s\": must have search scope (base/one/sub)\n"),
+ purl);
free(url);
return 3;
}
/* initialize LDAP structure */
if ((ld = ldap_init(hostname, port)) == NULL)
{
- printfPQExpBuffer(errorMessage,
- libpq_gettext("could not create LDAP structure\n"));
+ appendPQExpBufferStr(errorMessage,
+ libpq_gettext("could not create LDAP structure\n"));
free(url);
return 3;
}
{
if (res != NULL)
ldap_msgfree(res);
- printfPQExpBuffer(errorMessage,
+ appendPQExpBuffer(errorMessage,
libpq_gettext("lookup on LDAP server failed: %s\n"),
ldap_err2string(rc));
ldap_unbind(ld);
/* complain if there was not exactly one result */
if ((rc = ldap_count_entries(ld, res)) != 1)
{
- printfPQExpBuffer(errorMessage,
- rc ? libpq_gettext("more than one entry found on LDAP lookup\n")
- : libpq_gettext("no entry found on LDAP lookup\n"));
+ appendPQExpBufferStr(errorMessage,
+ rc ? libpq_gettext("more than one entry found on LDAP lookup\n")
+ : libpq_gettext("no entry found on LDAP lookup\n"));
ldap_msgfree(res);
ldap_unbind(ld);
free(url);
if ((entry = ldap_first_entry(ld, res)) == NULL)
{
/* should never happen */
- printfPQExpBuffer(errorMessage,
- libpq_gettext("no entry found on LDAP lookup\n"));
+ appendPQExpBufferStr(errorMessage,
+ libpq_gettext("no entry found on LDAP lookup\n"));
ldap_msgfree(res);
ldap_unbind(ld);
free(url);
/* get values */
if ((values = ldap_get_values_len(ld, entry, attrs[0])) == NULL)
{
- printfPQExpBuffer(errorMessage,
- libpq_gettext("attribute has no values on LDAP lookup\n"));
+ appendPQExpBufferStr(errorMessage,
+ libpq_gettext("attribute has no values on LDAP lookup\n"));
ldap_msgfree(res);
ldap_unbind(ld);
free(url);
if (values[0] == NULL)
{
- printfPQExpBuffer(errorMessage,
- libpq_gettext("attribute has no values on LDAP lookup\n"));
+ appendPQExpBufferStr(errorMessage,
+ libpq_gettext("attribute has no values on LDAP lookup\n"));
ldap_value_free_len(values);
ldap_unbind(ld);
return 1;
size += values[i]->bv_len + 1;
if ((result = malloc(size)) == NULL)
{
- printfPQExpBuffer(errorMessage,
- libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(errorMessage,
+ libpq_gettext("out of memory\n"));
ldap_value_free_len(values);
ldap_unbind(ld);
return 3;
}
else if (ld_is_nl_cr(*p))
{
- printfPQExpBuffer(errorMessage,
+ appendPQExpBuffer(errorMessage,
libpq_gettext("missing \"=\" after \"%s\" in connection info string\n"),
optname);
free(result);
}
else if (!ld_is_sp_tab(*p))
{
- printfPQExpBuffer(errorMessage,
+ appendPQExpBuffer(errorMessage,
libpq_gettext("missing \"=\" after \"%s\" in connection info string\n"),
optname);
free(result);
options[i].val = strdup(optval);
if (!options[i].val)
{
- printfPQExpBuffer(errorMessage,
- libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(errorMessage,
+ libpq_gettext("out of memory\n"));
free(result);
return 3;
}
}
if (!found_keyword)
{
- printfPQExpBuffer(errorMessage,
+ appendPQExpBuffer(errorMessage,
libpq_gettext("invalid connection option \"%s\"\n"),
optname);
free(result);
if (state == 5 || state == 6)
{
- printfPQExpBuffer(errorMessage,
- libpq_gettext("unterminated quoted string in connection info string\n"));
+ appendPQExpBufferStr(errorMessage,
+ libpq_gettext("unterminated quoted string in connection info string\n"));
return 3;
}
last_file:
if (!group_found)
{
- printfPQExpBuffer(errorMessage,
+ appendPQExpBuffer(errorMessage,
libpq_gettext("definition of service \"%s\" not found\n"), service);
return 3;
}
f = fopen(serviceFile, "r");
if (f == NULL)
{
- printfPQExpBuffer(errorMessage, libpq_gettext("service file \"%s\" not found\n"),
+ appendPQExpBuffer(errorMessage, libpq_gettext("service file \"%s\" not found\n"),
serviceFile);
return 1;
}
val = strchr(line, '=');
if (val == NULL)
{
- printfPQExpBuffer(errorMessage,
+ appendPQExpBuffer(errorMessage,
libpq_gettext("syntax error in service file \"%s\", line %d\n"),
serviceFile,
linenr);
if (strcmp(key, "service") == 0)
{
- printfPQExpBuffer(errorMessage,
+ appendPQExpBuffer(errorMessage,
libpq_gettext("nested service specifications not supported in service file \"%s\", line %d\n"),
serviceFile,
linenr);
options[i].val = strdup(val);
if (!options[i].val)
{
- printfPQExpBuffer(errorMessage,
- libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(errorMessage,
+ libpq_gettext("out of memory\n"));
result = 3;
goto exit;
}
if (!found_keyword)
{
- printfPQExpBuffer(errorMessage,
+ appendPQExpBuffer(errorMessage,
libpq_gettext("syntax error in service file \"%s\", line %d\n"),
serviceFile,
linenr);
options = (PQconninfoOption *) malloc(sizeof(PQconninfoOption) * sizeof(PQconninfoOptions) / sizeof(PQconninfoOptions[0]));
if (options == NULL)
{
- printfPQExpBuffer(errorMessage,
- libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(errorMessage,
+ libpq_gettext("out of memory\n"));
return NULL;
}
opt_dest = options;
* Connection string parser
*
* Returns a malloc'd PQconninfoOption array, if parsing is successful.
- * Otherwise, NULL is returned and an error message is left in errorMessage.
+ * Otherwise, NULL is returned and an error message is added to errorMessage.
*
* If use_defaults is true, default values are filled in (from a service file,
* environment variables, etc).
/* Need a modifiable copy of the input string */
if ((buf = strdup(conninfo)) == NULL)
{
- printfPQExpBuffer(errorMessage,
- libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(errorMessage,
+ libpq_gettext("out of memory\n"));
PQconninfoFree(options);
return NULL;
}
/* Check that there is a following '=' */
if (*cp != '=')
{
- printfPQExpBuffer(errorMessage,
+ appendPQExpBuffer(errorMessage,
libpq_gettext("missing \"=\" after \"%s\" in connection info string\n"),
pname);
PQconninfoFree(options);
{
if (*cp == '\0')
{
- printfPQExpBuffer(errorMessage,
- libpq_gettext("unterminated quoted string in connection info string\n"));
+ appendPQExpBufferStr(errorMessage,
+ libpq_gettext("unterminated quoted string in connection info string\n"));
PQconninfoFree(options);
free(buf);
return NULL;
*
* If successful, a malloc'd PQconninfoOption array is returned.
* If not successful, NULL is returned and an error message is
- * left in errorMessage.
+ * appended to errorMessage.
* Defaults are supplied (from a service file, environment variables, etc)
* for unspecified options, but only if use_defaults is true.
*
/* Check for invalid connection option */
if (option->keyword == NULL)
{
- printfPQExpBuffer(errorMessage,
+ appendPQExpBuffer(errorMessage,
libpq_gettext("invalid connection option \"%s\"\n"),
pname);
PQconninfoFree(options);
options[k].val = strdup(str_option->val);
if (!options[k].val)
{
- printfPQExpBuffer(errorMessage,
- libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(errorMessage,
+ libpq_gettext("out of memory\n"));
PQconninfoFree(options);
PQconninfoFree(dbname_options);
return NULL;
option->val = strdup(pvalue);
if (!option->val)
{
- printfPQExpBuffer(errorMessage,
- libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(errorMessage,
+ libpq_gettext("out of memory\n"));
PQconninfoFree(options);
PQconninfoFree(dbname_options);
return NULL;
if (!option->val)
{
if (errorMessage)
- printfPQExpBuffer(errorMessage,
- libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(errorMessage,
+ libpq_gettext("out of memory\n"));
return false;
}
continue;
if (!option->val)
{
if (errorMessage)
- printfPQExpBuffer(errorMessage,
- libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(errorMessage,
+ libpq_gettext("out of memory\n"));
return false;
}
continue;
if (!option->val)
{
if (errorMessage)
- printfPQExpBuffer(errorMessage,
- libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(errorMessage,
+ libpq_gettext("out of memory\n"));
return false;
}
continue;
initPQExpBuffer(&portbuf);
if (PQExpBufferDataBroken(hostbuf) || PQExpBufferDataBroken(portbuf))
{
- printfPQExpBuffer(errorMessage,
- libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(errorMessage,
+ libpq_gettext("out of memory\n"));
goto cleanup;
}
buf = strdup(uri);
if (buf == NULL)
{
- printfPQExpBuffer(errorMessage,
- libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(errorMessage,
+ libpq_gettext("out of memory\n"));
goto cleanup;
}
start = buf;
if (prefix_len == 0)
{
/* Should never happen */
- printfPQExpBuffer(errorMessage,
+ appendPQExpBuffer(errorMessage,
libpq_gettext("invalid URI propagated to internal parser routine: \"%s\"\n"),
uri);
goto cleanup;
++p;
if (!*p)
{
- printfPQExpBuffer(errorMessage,
+ appendPQExpBuffer(errorMessage,
libpq_gettext("end of string reached when looking for matching \"]\" in IPv6 host address in URI: \"%s\"\n"),
uri);
goto cleanup;
}
if (p == host)
{
- printfPQExpBuffer(errorMessage,
+ appendPQExpBuffer(errorMessage,
libpq_gettext("IPv6 host address may not be empty in URI: \"%s\"\n"),
uri);
goto cleanup;
*/
if (*p && *p != ':' && *p != '/' && *p != '?' && *p != ',')
{
- printfPQExpBuffer(errorMessage,
+ appendPQExpBuffer(errorMessage,
libpq_gettext("unexpected character \"%c\" at position %d in URI (expected \":\" or \"/\"): \"%s\"\n"),
*p, (int) (p - buf + 1), uri);
goto cleanup;
char *value = NULL;
char *p = params;
bool malloced = false;
+ int oldmsglen;
/*
* Scan the params string for '=' and '&', marking the end of keyword
/* Was there '=' already? */
if (value != NULL)
{
- printfPQExpBuffer(errorMessage,
+ appendPQExpBuffer(errorMessage,
libpq_gettext("extra key/value separator \"=\" in URI query parameter: \"%s\"\n"),
keyword);
return false;
/* Was there '=' at all? */
if (value == NULL)
{
- printfPQExpBuffer(errorMessage,
+ appendPQExpBuffer(errorMessage,
libpq_gettext("missing key/value separator \"=\" in URI query parameter: \"%s\"\n"),
keyword);
return false;
* otherwise. At this point both keyword and value are not
* URI-encoded.
*/
+ oldmsglen = errorMessage->len;
if (!conninfo_storeval(connOptions, keyword, value,
errorMessage, true, false))
{
/* Insert generic message if conninfo_storeval didn't give one. */
- if (errorMessage->len == 0)
- printfPQExpBuffer(errorMessage,
+ if (errorMessage->len == oldmsglen)
+ appendPQExpBuffer(errorMessage,
libpq_gettext("invalid URI query parameter: \"%s\"\n"),
keyword);
/* And fail. */
buf = malloc(strlen(str) + 1);
if (buf == NULL)
{
- printfPQExpBuffer(errorMessage, libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(errorMessage, libpq_gettext("out of memory\n"));
return NULL;
}
p = buf;
*/
if (!(get_hexdigit(*q++, &hi) && get_hexdigit(*q++, &lo)))
{
- printfPQExpBuffer(errorMessage,
+ appendPQExpBuffer(errorMessage,
libpq_gettext("invalid percent-encoded token: \"%s\"\n"),
str);
free(buf);
c = (hi << 4) | lo;
if (c == 0)
{
- printfPQExpBuffer(errorMessage,
+ appendPQExpBuffer(errorMessage,
libpq_gettext("forbidden value %%00 in percent-encoded value: \"%s\"\n"),
str);
free(buf);
if (option == NULL)
{
if (!ignoreMissing)
- printfPQExpBuffer(errorMessage,
+ appendPQExpBuffer(errorMessage,
libpq_gettext("invalid connection option \"%s\"\n"),
keyword);
return NULL;
value_copy = strdup(value);
if (value_copy == NULL)
{
- printfPQExpBuffer(errorMessage, libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(errorMessage, libpq_gettext("out of memory\n"));
return NULL;
}
}
if (conn == NULL)
return NULL;
- /* We don't actually report any errors here, but callees want a buffer */
+ /*
+ * We don't actually report any errors here, but callees want a buffer,
+ * and we prefer not to trash the conn's errorMessage.
+ */
initPQExpBuffer(&errorBuf);
if (PQExpBufferDataBroken(errorBuf))
return NULL; /* out of memory already :-( */
static PGEvent *dupEvents(PGEvent *events, int count, size_t *memSize);
static bool pqAddTuple(PGresult *res, PGresAttValue *tup,
const char **errmsgp);
-static bool PQsendQueryStart(PGconn *conn);
+static int PQsendQueryInternal(PGconn *conn, const char *query, bool newQuery);
+static bool PQsendQueryStart(PGconn *conn, bool newQuery);
static int PQsendQueryGuts(PGconn *conn,
const char *command,
const char *stmtName,
res->errMsg = NULL;
}
-/*
- * pqCatenateResultError -
- * concatenate a new error message to the one already in a PGresult
- */
-void
-pqCatenateResultError(PGresult *res, const char *msg)
-{
- PQExpBufferData errorBuf;
-
- if (!res || !msg)
- return;
- initPQExpBuffer(&errorBuf);
- if (res->errMsg)
- appendPQExpBufferStr(&errorBuf, res->errMsg);
- appendPQExpBufferStr(&errorBuf, msg);
- pqSetResultError(res, errorBuf.data);
- termPQExpBuffer(&errorBuf);
-}
-
/*
* PQclear -
* free's the memory associated with a PGresult
/*
* This subroutine deletes any existing async result, sets conn->result
* to a PGresult with status PGRES_FATAL_ERROR, and stores the current
- * contents of conn->errorMessage into that result. It differs from a
- * plain call on PQmakeEmptyPGresult() in that if there is already an
- * async result with status PGRES_FATAL_ERROR, the current error message
- * is APPENDED to the old error message instead of replacing it. This
- * behavior lets us report multiple error conditions properly, if necessary.
- * (An example where this is needed is when the backend sends an 'E' message
- * and immediately closes the connection --- we want to report both the
- * backend error and the connection closure error.)
+ * contents of conn->errorMessage into that result.
*/
void
pqSaveErrorResult(PGconn *conn)
{
- /*
- * If no old async result, just let PQmakeEmptyPGresult make one. Likewise
- * if old result is not an error message.
- */
- if (conn->result == NULL ||
- conn->result->resultStatus != PGRES_FATAL_ERROR ||
- conn->result->errMsg == NULL)
- {
- pqClearAsyncResult(conn);
- conn->result = PQmakeEmptyPGresult(conn, PGRES_FATAL_ERROR);
- }
- else
- {
- /* Else, concatenate error message to existing async result. */
- pqCatenateResultError(conn->result, conn->errorMessage.data);
- }
+ pqClearAsyncResult(conn);
+ conn->result = PQmakeEmptyPGresult(conn, PGRES_FATAL_ERROR);
}
/*
- * As above, and append conn->write_err_msg to whatever other error we have.
- * This is used when we've detected a write failure and have exhausted our
- * chances of reporting something else instead.
+ * As above, after appending conn->write_err_msg to whatever other error we
+ * have. This is used when we've detected a write failure and have exhausted
+ * our chances of reporting something else instead.
*/
static void
pqSaveWriteError(PGconn *conn)
{
/*
- * Ensure conn->result is an error result, and add anything in
- * conn->errorMessage to it.
+ * If write_err_msg is null because of previous strdup failure, do what we
+ * can. (It's likely our machinations here will get OOM failures as well,
+ * but might as well try.)
*/
- pqSaveErrorResult(conn);
-
- /*
- * Now append write_err_msg to that. If it's null because of previous
- * strdup failure, do what we can. (It's likely our machinations here are
- * all getting OOM failures as well, but ...)
- */
- if (conn->write_err_msg && conn->write_err_msg[0] != '\0')
- pqCatenateResultError(conn->result, conn->write_err_msg);
+ if (conn->write_err_msg)
+ {
+ appendPQExpBufferStr(&conn->errorMessage, conn->write_err_msg);
+ /* Avoid possibly appending the same message twice */
+ conn->write_err_msg[0] = '\0';
+ }
else
- pqCatenateResultError(conn->result,
- libpq_gettext("write to server failed\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("write to server failed\n"));
+
+ pqSaveErrorResult(conn);
}
/*
* This subroutine prepares an async result object for return to the caller.
* If there is not already an async result object, build an error object
* using whatever is in conn->errorMessage. In any case, clear the async
- * result storage and make sure PQerrorMessage will agree with the result's
- * error string.
+ * result storage.
*/
PGresult *
pqPrepareAsyncResult(PGconn *conn)
res = conn->result;
if (!res)
res = PQmakeEmptyPGresult(conn, PGRES_FATAL_ERROR);
- else
- {
- /*
- * Make sure PQerrorMessage agrees with result; it could be different
- * if we have concatenated messages.
- */
- resetPQExpBuffer(&conn->errorMessage);
- appendPQExpBufferStr(&conn->errorMessage,
- PQresultErrorMessage(res));
- }
/*
* Replace conn->result with next_result, if any. In the normal case
*
* Returns: 1 if successfully submitted
* 0 if error (conn->errorMessage is set)
+ *
+ * PQsendQueryContinue is a non-exported version that behaves identically
+ * except that it doesn't reset conn->errorMessage.
*/
int
PQsendQuery(PGconn *conn, const char *query)
{
- if (!PQsendQueryStart(conn))
+ return PQsendQueryInternal(conn, query, true);
+}
+
+int
+PQsendQueryContinue(PGconn *conn, const char *query)
+{
+ return PQsendQueryInternal(conn, query, false);
+}
+
+static int
+PQsendQueryInternal(PGconn *conn, const char *query, bool newQuery)
+{
+ if (!PQsendQueryStart(conn, newQuery))
return 0;
/* check the argument */
if (!query)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("command string is a null pointer\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("command string is a null pointer\n"));
return 0;
}
const int *paramFormats,
int resultFormat)
{
- if (!PQsendQueryStart(conn))
+ if (!PQsendQueryStart(conn, true))
return 0;
/* check the arguments */
if (!command)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("command string is a null pointer\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("command string is a null pointer\n"));
return 0;
}
if (nParams < 0 || nParams > 65535)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("number of parameters must be between 0 and 65535\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("number of parameters must be between 0 and 65535\n"));
return 0;
}
const char *stmtName, const char *query,
int nParams, const Oid *paramTypes)
{
- if (!PQsendQueryStart(conn))
+ if (!PQsendQueryStart(conn, true))
return 0;
/* check the arguments */
if (!stmtName)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("statement name is a null pointer\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("statement name is a null pointer\n"));
return 0;
}
if (!query)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("command string is a null pointer\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("command string is a null pointer\n"));
return 0;
}
if (nParams < 0 || nParams > 65535)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("number of parameters must be between 0 and 65535\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("number of parameters must be between 0 and 65535\n"));
return 0;
}
/* This isn't gonna work on a 2.0 server */
if (PG_PROTOCOL_MAJOR(conn->pversion) < 3)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("function requires at least protocol version 3.0\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("function requires at least protocol version 3.0\n"));
return 0;
}
const int *paramFormats,
int resultFormat)
{
- if (!PQsendQueryStart(conn))
+ if (!PQsendQueryStart(conn, true))
return 0;
/* check the arguments */
if (!stmtName)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("statement name is a null pointer\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("statement name is a null pointer\n"));
return 0;
}
if (nParams < 0 || nParams > 65535)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("number of parameters must be between 0 and 65535\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("number of parameters must be between 0 and 65535\n"));
return 0;
}
* Common startup code for PQsendQuery and sibling routines
*/
static bool
-PQsendQueryStart(PGconn *conn)
+PQsendQueryStart(PGconn *conn, bool newQuery)
{
if (!conn)
return false;
- /* clear the error string */
- resetPQExpBuffer(&conn->errorMessage);
+ /*
+ * If this is the beginning of a query cycle, reset the error buffer.
+ */
+ if (newQuery)
+ resetPQExpBuffer(&conn->errorMessage);
/* Don't try to send if we know there's no live connection. */
if (conn->status != CONNECTION_OK)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("no connection to the server\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("no connection to the server\n"));
return false;
}
/* Can't send while already busy, either. */
if (conn->asyncStatus != PGASYNC_IDLE)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("another command is already in progress\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("another command is already in progress\n"));
return false;
}
/* This isn't gonna work on a 2.0 server */
if (PG_PROTOCOL_MAJOR(conn->pversion) < 3)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("function requires at least protocol version 3.0\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("function requires at least protocol version 3.0\n"));
return 0;
}
nbytes = paramLengths[i];
else
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("length must be given for binary parameter\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("length must be given for binary parameter\n"));
goto sendFailed;
}
}
res = getCopyResult(conn, PGRES_COPY_BOTH);
break;
default:
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("unexpected asyncStatus: %d\n"),
(int) conn->asyncStatus);
res = PQmakeEmptyPGresult(conn, PGRES_FATAL_ERROR);
if (!res->events[i].proc(PGEVT_RESULTCREATE, &evt,
res->events[i].passThrough))
{
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("PGEventProc \"%s\" failed during PGEVT_RESULTCREATE event\n"),
res->events[i].name);
pqSetResultError(res, conn->errorMessage.data);
if (!conn)
return false;
+ /*
+ * Since this is the beginning of a query cycle, reset the error buffer.
+ */
+ resetPQExpBuffer(&conn->errorMessage);
+
/*
* Silently discard any prior query result that application didn't eat.
* This is probably poor design, but it's here for backward compatibility.
else
{
/* In older protocols we have to punt */
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("COPY IN state must be terminated first\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("COPY IN state must be terminated first\n"));
return false;
}
}
else
{
/* In older protocols we have to punt */
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("COPY OUT state must be terminated first\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("COPY OUT state must be terminated first\n"));
return false;
}
}
else if (resultStatus == PGRES_COPY_BOTH)
{
/* We don't allow PQexec during COPY BOTH */
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("PQexec not allowed during COPY BOTH\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("PQexec not allowed during COPY BOTH\n"));
return false;
}
/* check for loss of connection, too */
/*
* For backwards compatibility, return the last result if there are more
- * than one --- but merge error messages if we get more than one error
- * result.
+ * than one. (We used to have logic here to concatenate successive error
+ * messages, but now that happens automatically, since conn->errorMessage
+ * will continue to accumulate errors throughout this loop.)
*
* We have to stop if we see copy in/out/both, however. We will resume
* parsing after application performs the data transfer.
while ((result = PQgetResult(conn)) != NULL)
{
if (lastResult)
- {
- if (lastResult->resultStatus == PGRES_FATAL_ERROR &&
- result->resultStatus == PGRES_FATAL_ERROR)
- {
- pqCatenateResultError(lastResult, result->errMsg);
- PQclear(result);
- result = lastResult;
-
- /*
- * Make sure PQerrorMessage agrees with concatenated result
- */
- resetPQExpBuffer(&conn->errorMessage);
- appendPQExpBufferStr(&conn->errorMessage, result->errMsg);
- }
- else
- PQclear(lastResult);
- }
+ PQclear(lastResult);
lastResult = result;
if (result->resultStatus == PGRES_COPY_IN ||
result->resultStatus == PGRES_COPY_OUT ||
if (!desc_target)
desc_target = "";
- if (!PQsendQueryStart(conn))
+ if (!PQsendQueryStart(conn, true))
return 0;
/* This isn't gonna work on a 2.0 server */
if (PG_PROTOCOL_MAJOR(conn->pversion) < 3)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("function requires at least protocol version 3.0\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("function requires at least protocol version 3.0\n"));
return 0;
}
if (conn->asyncStatus != PGASYNC_COPY_IN &&
conn->asyncStatus != PGASYNC_COPY_BOTH)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("no COPY in progress\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("no COPY in progress\n"));
return -1;
}
if (conn->asyncStatus != PGASYNC_COPY_IN &&
conn->asyncStatus != PGASYNC_COPY_BOTH)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("no COPY in progress\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("no COPY in progress\n"));
return -1;
}
if (errormsg)
{
/* Oops, no way to do this in 2.0 */
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("function requires at least protocol version 3.0\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("function requires at least protocol version 3.0\n"));
return -1;
}
else
conn->asyncStatus = PGASYNC_COPY_OUT;
else
conn->asyncStatus = PGASYNC_BUSY;
- resetPQExpBuffer(&conn->errorMessage);
/* Try to flush data */
if (pqFlush(conn) < 0)
if (conn->asyncStatus != PGASYNC_COPY_OUT &&
conn->asyncStatus != PGASYNC_COPY_BOTH)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("no COPY in progress\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("no COPY in progress\n"));
return -2;
}
if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
if (!conn)
return NULL;
- /* clear the error string */
+ /*
+ * Since this is the beginning of a query cycle, reset the error buffer.
+ */
resetPQExpBuffer(&conn->errorMessage);
if (conn->sock == PGINVALID_SOCKET || conn->asyncStatus != PGASYNC_IDLE ||
conn->result != NULL)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("connection in wrong state\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("connection in wrong state\n"));
return NULL;
}
* need to flush the send queue at this point in order to guarantee proper
* behavior. this is ok because either they are making a transition _from_
* or _to_ blocking mode, either way we can block them.
+ *
+ * Clear errorMessage in case pqFlush adds to it.
*/
+ resetPQExpBuffer(&conn->errorMessage);
+
/* if we are going from blocking to non-blocking flush here */
if (pqFlush(conn))
return -1;
if (error)
*error = 1;
if (conn)
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("incomplete multibyte character\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("incomplete multibyte character\n"));
for (; i < len; i++)
{
if (((size_t) (target - to)) / 2 >= length)
*error = 1;
return 0;
}
+
+ resetPQExpBuffer(&conn->errorMessage);
+
return PQescapeStringInternal(conn, to, from, length, error,
conn->client_encoding,
conn->std_strings);
if (!conn)
return NULL;
+ resetPQExpBuffer(&conn->errorMessage);
+
/* Scan the string for characters that must be escaped. */
for (s = str; (s - str) < len && *s != '\0'; ++s)
{
/* Multibyte character overruns allowable length. */
if ((s - str) + charlen > len || memchr(s, 0, charlen) != NULL)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("incomplete multibyte character\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("incomplete multibyte character\n"));
return NULL;
}
result = rp = (char *) malloc(result_size);
if (rp == NULL)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("out of memory\n"));
return NULL;
}
if (rp == NULL)
{
if (conn)
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("out of memory\n"));
return NULL;
}
{
if (!conn)
return NULL;
+
+ resetPQExpBuffer(&conn->errorMessage);
+
return PQescapeByteaInternal(conn, from, from_length, to_length,
conn->std_strings,
(conn->sversion >= 90000));
pg_GSS_error(const char *mprefix, PGconn *conn,
OM_uint32 maj_stat, OM_uint32 min_stat)
{
- resetPQExpBuffer(&conn->errorMessage);
appendPQExpBuffer(&conn->errorMessage, "%s:", mprefix);
pg_GSS_error_int(&conn->errorMessage, maj_stat, GSS_C_GSS_CODE);
appendPQExpBufferChar(&conn->errorMessage, ':');
host = PQhost(conn);
if (!(host && host[0] != '\0'))
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("host name must be specified\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("host name must be specified\n"));
return STATUS_ERROR;
}
temp_gbuf.value = (char *) malloc(maxlen);
if (!temp_gbuf.value)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("out of memory\n"));
return STATUS_ERROR;
}
snprintf(temp_gbuf.value, maxlen, "%s@%s",
PQArgBlock argv[2];
PGresult *res;
- if (conn == NULL || conn->lobjfuncs == NULL)
- {
- if (lo_initialize(conn) < 0)
- return -1;
- }
+ if (lo_initialize(conn) < 0)
+ return -1;
argv[0].isint = 1;
argv[0].len = 4;
int retval;
int result_len;
- if (conn == NULL || conn->lobjfuncs == NULL)
- {
- if (lo_initialize(conn) < 0)
- return -1;
- }
+ if (lo_initialize(conn) < 0)
+ return -1;
argv[0].isint = 1;
argv[0].len = 4;
int retval;
int result_len;
- if (conn == NULL || conn->lobjfuncs == NULL)
- {
- if (lo_initialize(conn) < 0)
- return -1;
- }
+ if (lo_initialize(conn) < 0)
+ return -1;
/* Must check this on-the-fly because it's not there pre-8.3 */
if (conn->lobjfuncs->fn_lo_truncate == 0)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("cannot determine OID of function lo_truncate\n"));
+ appendPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("cannot determine OID of function %s\n"),
+ "lo_truncate");
return -1;
}
*/
if (len > (size_t) INT_MAX)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("argument of lo_truncate exceeds integer range\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("argument of lo_truncate exceeds integer range\n"));
return -1;
}
int retval;
int result_len;
- if (conn == NULL || conn->lobjfuncs == NULL)
- {
- if (lo_initialize(conn) < 0)
- return -1;
- }
+ if (lo_initialize(conn) < 0)
+ return -1;
if (conn->lobjfuncs->fn_lo_truncate64 == 0)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("cannot determine OID of function lo_truncate64\n"));
+ appendPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("cannot determine OID of function %s\n"),
+ "lo_truncate64");
return -1;
}
PGresult *res;
int result_len;
- if (conn == NULL || conn->lobjfuncs == NULL)
- {
- if (lo_initialize(conn) < 0)
- return -1;
- }
+ if (lo_initialize(conn) < 0)
+ return -1;
/*
* Long ago, somebody thought it'd be a good idea to declare this function
*/
if (len > (size_t) INT_MAX)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("argument of lo_read exceeds integer range\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("argument of lo_read exceeds integer range\n"));
return -1;
}
int result_len;
int retval;
- if (conn == NULL || conn->lobjfuncs == NULL)
- {
- if (lo_initialize(conn) < 0)
- return -1;
- }
+ if (lo_initialize(conn) < 0)
+ return -1;
/*
* Long ago, somebody thought it'd be a good idea to declare this function
*/
if (len > (size_t) INT_MAX)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("argument of lo_write exceeds integer range\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("argument of lo_write exceeds integer range\n"));
return -1;
}
int retval;
int result_len;
- if (conn == NULL || conn->lobjfuncs == NULL)
- {
- if (lo_initialize(conn) < 0)
- return -1;
- }
+ if (lo_initialize(conn) < 0)
+ return -1;
argv[0].isint = 1;
argv[0].len = 4;
pg_int64 retval;
int result_len;
- if (conn == NULL || conn->lobjfuncs == NULL)
- {
- if (lo_initialize(conn) < 0)
- return -1;
- }
+ if (lo_initialize(conn) < 0)
+ return -1;
if (conn->lobjfuncs->fn_lo_lseek64 == 0)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("cannot determine OID of function lo_lseek64\n"));
+ appendPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("cannot determine OID of function %s\n"),
+ "lo_lseek64");
return -1;
}
int retval;
int result_len;
- if (conn == NULL || conn->lobjfuncs == NULL)
- {
- if (lo_initialize(conn) < 0)
- return InvalidOid;
- }
+ if (lo_initialize(conn) < 0)
+ return InvalidOid;
argv[0].isint = 1;
argv[0].len = 4;
int retval;
int result_len;
- if (conn == NULL || conn->lobjfuncs == NULL)
- {
- if (lo_initialize(conn) < 0)
- return InvalidOid;
- }
+ if (lo_initialize(conn) < 0)
+ return InvalidOid;
/* Must check this on-the-fly because it's not there pre-8.1 */
if (conn->lobjfuncs->fn_lo_create == 0)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("cannot determine OID of function lo_create\n"));
+ appendPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("cannot determine OID of function %s\n"),
+ "lo_create");
return InvalidOid;
}
PGresult *res;
int result_len;
- if (conn == NULL || conn->lobjfuncs == NULL)
- {
- if (lo_initialize(conn) < 0)
- return -1;
- }
+ if (lo_initialize(conn) < 0)
+ return -1;
argv[0].isint = 1;
argv[0].len = 4;
PGresult *res;
int result_len;
- if (conn == NULL || conn->lobjfuncs == NULL)
- {
- if (lo_initialize(conn) < 0)
- return -1;
- }
+ if (lo_initialize(conn) < 0)
+ return -1;
if (conn->lobjfuncs->fn_lo_tell64 == 0)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("cannot determine OID of function lo_tell64\n"));
+ appendPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("cannot determine OID of function %s\n"),
+ "lo_tell64");
return -1;
}
int result_len;
int retval;
- if (conn == NULL || conn->lobjfuncs == NULL)
- {
- if (lo_initialize(conn) < 0)
- return -1;
- }
+ if (lo_initialize(conn) < 0)
+ return -1;
argv[0].isint = 1;
argv[0].len = 4;
int lobj;
char sebuf[PG_STRERROR_R_BUFLEN];
+ if (conn == NULL)
+ return InvalidOid;
+
+ /* Since this is the beginning of a query cycle, reset the error buffer */
+ resetPQExpBuffer(&conn->errorMessage);
+
/*
* open the file to be read in
*/
fd = open(filename, O_RDONLY | PG_BINARY, 0666);
if (fd < 0)
{ /* error */
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open file \"%s\": %s\n"),
filename, strerror_r(errno, sebuf, sizeof(sebuf)));
return InvalidOid;
(void) lo_close(conn, lobj);
(void) close(fd);
+ /* deliberately overwrite any error from lo_close */
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not read from file \"%s\": %s\n"),
filename,
int save_errno = errno;
(void) lo_close(conn, lobj);
+ /* deliberately overwrite any error from lo_close */
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open file \"%s\": %s\n"),
filename,
(void) lo_close(conn, lobj);
(void) close(fd);
+ /* deliberately overwrite any error from lo_close */
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not write to file \"%s\": %s\n"),
filename,
/* if we already failed, don't overwrite that msg with a close error */
if (close(fd) != 0 && result >= 0)
{
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not write to file \"%s\": %s\n"),
filename, strerror_r(errno, sebuf, sizeof(sebuf)));
result = -1;
/*
* lo_initialize
*
- * Initialize the large object interface for an existing connection.
- * We ask the backend about the functions OID's in pg_proc for all
- * functions that are required for large object operations.
+ * Initialize for a new large-object operation on an existing connection.
+ * Return 0 if OK, -1 on failure.
+ *
+ * If we haven't previously done so, we collect the function OIDs from
+ * pg_proc for all functions that are required for large object operations.
*/
static int
lo_initialize(PGconn *conn)
const char *fname;
Oid foid;
- if (!conn)
+ /* Nothing we can do with no connection */
+ if (conn == NULL)
return -1;
+ /* Since this is the beginning of a query cycle, reset the error buffer */
+ resetPQExpBuffer(&conn->errorMessage);
+
+ /* Nothing else to do if we already collected info */
+ if (conn->lobjfuncs != NULL)
+ return 0;
+
/*
- * Allocate the structure to hold the functions OID's
+ * Allocate the structure to hold the function OIDs. We don't store it
+ * into the PGconn until it's successfully filled.
*/
lobjfuncs = (PGlobjfuncs *) malloc(sizeof(PGlobjfuncs));
if (lobjfuncs == NULL)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("out of memory\n"));
return -1;
}
MemSet((char *) lobjfuncs, 0, sizeof(PGlobjfuncs));
{
free(lobjfuncs);
PQclear(res);
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("query to initialize large object functions did not return data\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("query to initialize large object functions did not return data\n"));
return -1;
}
*/
if (lobjfuncs->fn_lo_open == 0)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("cannot determine OID of function lo_open\n"));
+ appendPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("cannot determine OID of function %s\n"),
+ "lo_open");
free(lobjfuncs);
return -1;
}
if (lobjfuncs->fn_lo_close == 0)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("cannot determine OID of function lo_close\n"));
+ appendPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("cannot determine OID of function %s\n"),
+ "lo_close");
free(lobjfuncs);
return -1;
}
if (lobjfuncs->fn_lo_creat == 0)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("cannot determine OID of function lo_creat\n"));
+ appendPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("cannot determine OID of function %s\n"),
+ "lo_creat");
free(lobjfuncs);
return -1;
}
if (lobjfuncs->fn_lo_unlink == 0)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("cannot determine OID of function lo_unlink\n"));
+ appendPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("cannot determine OID of function %s\n"),
+ "lo_unlink");
free(lobjfuncs);
return -1;
}
if (lobjfuncs->fn_lo_lseek == 0)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("cannot determine OID of function lo_lseek\n"));
+ appendPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("cannot determine OID of function %s\n"),
+ "lo_lseek");
free(lobjfuncs);
return -1;
}
if (lobjfuncs->fn_lo_tell == 0)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("cannot determine OID of function lo_tell\n"));
+ appendPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("cannot determine OID of function %s\n"),
+ "lo_tell");
free(lobjfuncs);
return -1;
}
if (lobjfuncs->fn_lo_read == 0)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("cannot determine OID of function loread\n"));
+ appendPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("cannot determine OID of function %s\n"),
+ "loread");
free(lobjfuncs);
return -1;
}
if (lobjfuncs->fn_lo_write == 0)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("cannot determine OID of function lowrite\n"));
+ appendPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("cannot determine OID of function %s\n"),
+ "lowrite");
free(lobjfuncs);
return -1;
}
}
/* realloc failed. Probably out of memory */
- printfPQExpBuffer(&conn->errorMessage,
- "cannot allocate memory for output buffer\n");
+ appendPQExpBufferStr(&conn->errorMessage,
+ "cannot allocate memory for output buffer\n");
return EOF;
}
}
/* realloc failed. Probably out of memory */
- printfPQExpBuffer(&conn->errorMessage,
- "cannot allocate memory for input buffer\n");
+ appendPQExpBufferStr(&conn->errorMessage,
+ "cannot allocate memory for input buffer\n");
return EOF;
}
if (conn->sock == PGINVALID_SOCKET)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("connection not open\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("connection not open\n"));
return -1;
}
* means the connection has been closed. Cope.
*/
definitelyEOF:
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("server closed the connection unexpectedly\n"
- "\tThis probably means the server terminated abnormally\n"
- "\tbefore or while processing the request.\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("server closed the connection unexpectedly\n"
+ "\tThis probably means the server terminated abnormally\n"
+ "\tbefore or while processing the request.\n"));
/* Come here if lower-level code already set a suitable errorMessage */
definitelyFailed:
{
char *ptr = conn->outBuffer;
int remaining = conn->outCount;
+ int oldmsglen = conn->errorMessage.len;
int result = 0;
/*
if (conn->sock == PGINVALID_SOCKET)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("connection not open\n"));
conn->write_failed = true;
- /* Transfer error message to conn->write_err_msg, if possible */
+ /* Insert error message into conn->write_err_msg, if possible */
/* (strdup failure is OK, we'll cope later) */
- conn->write_err_msg = strdup(conn->errorMessage.data);
- resetPQExpBuffer(&conn->errorMessage);
+ conn->write_err_msg = strdup(libpq_gettext("connection not open\n"));
/* Discard queued data; no chance it'll ever be sent */
conn->outCount = 0;
return 0;
* Transfer error message to conn->write_err_msg, if
* possible (strdup failure is OK, we'll cope later).
*
- * Note: this assumes that pqsecure_write and its children
- * will overwrite not append to conn->errorMessage. If
- * that's ever changed, we could remember the length of
- * conn->errorMessage at entry to this routine, and then
- * save and delete just what was appended.
+ * We only want to transfer whatever has been appended to
+ * conn->errorMessage since we entered this routine.
*/
- conn->write_err_msg = strdup(conn->errorMessage.data);
- resetPQExpBuffer(&conn->errorMessage);
+ if (!PQExpBufferBroken(&conn->errorMessage))
+ {
+ conn->write_err_msg = strdup(conn->errorMessage.data +
+ oldmsglen);
+ conn->errorMessage.len = oldmsglen;
+ conn->errorMessage.data[oldmsglen] = '\0';
+ }
/* Discard queued data; no chance it'll ever be sent */
conn->outCount = 0;
if (result == 0)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("timeout expired\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("timeout expired\n"));
return 1;
}
return -1;
if (conn->sock == PGINVALID_SOCKET)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("invalid socket\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("invalid socket\n"));
return -1;
}
{
char sebuf[PG_STRERROR_R_BUFLEN];
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("select() failed: %s\n"),
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
}
return PGRES_POLLING_OK;
default:
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("invalid setenv state %c, probably indicative of memory corruption\n"),
conn->setenv_state);
goto error_return;
}
default:
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("invalid state %c, "
"probably indicative of memory corruption\n"),
conn->setenv_state);
PGRES_COMMAND_OK);
if (!conn->result)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("out of memory"));
pqSaveErrorResult(conn);
}
}
PGRES_EMPTY_QUERY);
if (!conn->result)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("out of memory"));
pqSaveErrorResult(conn);
}
}
* never arrives from the server during protocol 2.0.
*/
default:
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("unexpected response from server; first received character was \"%c\"\n"),
id);
/* build an error result holding the error message */
if (!errmsg)
errmsg = libpq_gettext("out of memory for query result");
- printfPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
+ appendPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
/*
* XXX: if PQmakeEmptyPGresult() fails, there's probably not much we can
if (!errmsg)
errmsg = libpq_gettext("out of memory for query result");
- printfPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
+ appendPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
/*
* XXX: if PQmakeEmptyPGresult() fails, there's probably not much we can
{
pqClearAsyncResult(conn); /* redundant, but be safe */
conn->result = res;
- resetPQExpBuffer(&conn->errorMessage);
if (res && !PQExpBufferDataBroken(workBuf) && res->errMsg)
appendPQExpBufferStr(&conn->errorMessage, res->errMsg);
else
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("out of memory"));
if (conn->xactStatus == PQTRANS_INTRANS)
conn->xactStatus = PQTRANS_INERROR;
}
*buffer = (char *) malloc(msgLength + 1);
if (*buffer == NULL)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("out of memory\n"));
return -2;
}
memcpy(*buffer, &conn->inBuffer[conn->inStart], msgLength);
if (conn->asyncStatus != PGASYNC_COPY_IN &&
conn->asyncStatus != PGASYNC_COPY_OUT)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("no COPY in progress\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("no COPY in progress\n"));
return 1;
}
/* Return to active duty */
conn->asyncStatus = PGASYNC_BUSY;
- resetPQExpBuffer(&conn->errorMessage);
/* Wait for the completion response */
result = PQgetResult(conn);
else
{
/* The backend violates the protocol. */
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("protocol error: id=0x%x\n"),
id);
pqSaveErrorResult(conn);
return PQmakeEmptyPGresult(conn, status);
default:
/* The backend violates the protocol. */
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("protocol error: id=0x%x\n"),
id);
pqSaveErrorResult(conn);
PGRES_COMMAND_OK);
if (!conn->result)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("out of memory"));
pqSaveErrorResult(conn);
}
}
PGRES_EMPTY_QUERY);
if (!conn->result)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("out of memory"));
pqSaveErrorResult(conn);
}
}
PGRES_COMMAND_OK);
if (!conn->result)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("out of memory"));
pqSaveErrorResult(conn);
}
}
PGRES_COMMAND_OK);
if (!conn->result)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("out of memory"));
pqSaveErrorResult(conn);
}
}
else
{
/* Set up to report error at end of query */
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("server sent data (\"D\" message) without prior row description (\"T\" message)\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("server sent data (\"D\" message) without prior row description (\"T\" message)\n"));
pqSaveErrorResult(conn);
/* Discard the unexpected message */
conn->inCursor += msgLength;
*/
break;
default:
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("unexpected response from server; first received character was \"%c\"\n"),
id);
/* build an error result holding the error message */
else
{
/* Trouble --- report it */
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("message contents do not agree with length in message type \"%c\"\n"),
id);
/* build an error result holding the error message */
static void
handleSyncLoss(PGconn *conn, char id, int msgLength)
{
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("lost synchronization with server: got message type \"%c\", length %d\n"),
id, msgLength);
/* build an error result holding the error message */
if (!errmsg)
errmsg = libpq_gettext("out of memory for query result");
- printfPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
+ appendPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
pqSaveErrorResult(conn);
/*
*/
if (!errmsg)
errmsg = libpq_gettext("out of memory");
- printfPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
+ appendPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
pqSaveErrorResult(conn);
/*
if (!errmsg)
errmsg = libpq_gettext("out of memory for query result");
- printfPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
+ appendPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
pqSaveErrorResult(conn);
/*
pqClearAsyncResult(conn); /* redundant, but be safe */
conn->result = res;
if (PQExpBufferDataBroken(workBuf))
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("out of memory"));
else
appendPQExpBufferStr(&conn->errorMessage, workBuf.data);
}
*buffer = (char *) malloc(msgLength + 1);
if (*buffer == NULL)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("out of memory\n"));
return -2;
}
memcpy(*buffer, &conn->inBuffer[conn->inCursor], msgLength);
conn->asyncStatus != PGASYNC_COPY_BOTH) ||
conn->copy_is_binary)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("PQgetline: not doing text COPY OUT\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("PQgetline: not doing text COPY OUT\n"));
*s = '\0';
return EOF;
}
conn->asyncStatus != PGASYNC_COPY_OUT &&
conn->asyncStatus != PGASYNC_COPY_BOTH)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("no COPY in progress\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("no COPY in progress\n"));
return 1;
}
/* Return to active duty */
conn->asyncStatus = PGASYNC_BUSY;
- resetPQExpBuffer(&conn->errorMessage);
/*
* Non blocking connections may have to abort at this point. If everyone
break;
default:
/* The backend violates the protocol. */
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("protocol error: id=0x%x\n"),
id);
pqSaveErrorResult(conn);
if (!(host && host[0] != '\0'))
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("host name must be specified\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("host name must be specified\n"));
return -1;
}
name = malloc(namelen + 1);
if (name == NULL)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("out of memory\n"));
return -1;
}
memcpy(name, namedata, namelen);
if (namelen != strlen(name))
{
free(name);
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("SSL certificate's name contains embedded null\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("SSL certificate's name contains embedded null\n"));
return -1;
}
/* Check that we have a hostname to compare with. */
if (!(host && host[0] != '\0'))
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("host name must be specified for a verified SSL connection\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("host name must be specified for a verified SSL connection\n"));
return false;
}
*/
if (names_examined > 1)
{
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_ngettext("server certificate for \"%s\" (and %d other name) does not match host name \"%s\"\n",
"server certificate for \"%s\" (and %d other names) does not match host name \"%s\"\n",
names_examined - 1),
}
else if (names_examined == 1)
{
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("server certificate for \"%s\" does not match host name \"%s\"\n"),
first_name, host);
}
else
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could not get server's host name from server certificate\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("could not get server's host name from server certificate\n"));
}
}
*
* On success, returns the number of data bytes consumed (possibly less than
* len). On failure, returns -1 with errno set appropriately. If the errno
- * indicates a non-retryable error, a message is put into conn->errorMessage.
+ * indicates a non-retryable error, a message is added to conn->errorMessage.
* For retryable errors, caller should call again (passing the same data)
* once the socket is ready.
*/
*/
if (len < PqGSSSendConsumed)
{
- printfPQExpBuffer(&conn->errorMessage,
- "GSSAPI caller failed to retransmit all data needing to be retried\n");
+ appendPQExpBufferStr(&conn->errorMessage,
+ "GSSAPI caller failed to retransmit all data needing to be retried\n");
errno = EINVAL;
return -1;
}
if (conf_state == 0)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("outgoing GSSAPI message would not use confidentiality\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("outgoing GSSAPI message would not use confidentiality\n"));
errno = EIO; /* for lack of a better idea */
goto cleanup;
}
if (output.length > PQ_GSS_SEND_BUFFER_SIZE - sizeof(uint32))
{
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("client tried to send oversize GSSAPI packet (%zu > %zu)\n"),
(size_t) output.length,
PQ_GSS_SEND_BUFFER_SIZE - sizeof(uint32));
*
* Returns the number of data bytes read, or on failure, returns -1
* with errno set appropriately. If the errno indicates a non-retryable
- * error, a message is put into conn->errorMessage. For retryable errors,
+ * error, a message is added to conn->errorMessage. For retryable errors,
* caller should call again once the socket is ready.
*/
ssize_t
if (input.length > PQ_GSS_RECV_BUFFER_SIZE - sizeof(uint32))
{
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("oversize GSSAPI packet sent by the server (%zu > %zu)\n"),
(size_t) input.length,
PQ_GSS_RECV_BUFFER_SIZE - sizeof(uint32));
if (conf_state == 0)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("incoming GSSAPI message did not use confidentiality\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("incoming GSSAPI message did not use confidentiality\n"));
ret = -1;
errno = EIO; /* for lack of a better idea */
goto cleanup;
PqGSSResultBuffer = malloc(PQ_GSS_RECV_BUFFER_SIZE);
if (!PqGSSSendBuffer || !PqGSSRecvBuffer || !PqGSSResultBuffer)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("out of memory\n"));
return PGRES_POLLING_FAILED;
}
PqGSSSendLength = PqGSSSendNext = PqGSSSendConsumed = 0;
PqGSSRecvLength += ret;
- printfPQExpBuffer(&conn->errorMessage, "%s\n", PqGSSRecvBuffer + 1);
+ appendPQExpBuffer(&conn->errorMessage, "%s\n", PqGSSRecvBuffer + 1);
return PGRES_POLLING_FAILED;
}
input.length = pg_ntoh32(*(uint32 *) PqGSSRecvBuffer);
if (input.length > PQ_GSS_RECV_BUFFER_SIZE - sizeof(uint32))
{
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("oversize GSSAPI packet sent by the server (%zu > %zu)\n"),
(size_t) input.length,
PQ_GSS_RECV_BUFFER_SIZE - sizeof(uint32));
if (n < 0)
{
/* Not supposed to happen, so we don't translate the msg */
- printfPQExpBuffer(&conn->errorMessage,
- "SSL_read failed but did not provide error information\n");
+ appendPQExpBufferStr(&conn->errorMessage,
+ "SSL_read failed but did not provide error information\n");
/* assume the connection is broken */
result_errno = ECONNRESET;
}
result_errno = SOCK_ERRNO;
if (result_errno == EPIPE ||
result_errno == ECONNRESET)
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("server closed the connection unexpectedly\n"
- "\tThis probably means the server terminated abnormally\n"
- "\tbefore or while processing the request.\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("server closed the connection unexpectedly\n"
+ "\tThis probably means the server terminated abnormally\n"
+ "\tbefore or while processing the request.\n"));
else
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSL SYSCALL error: %s\n"),
SOCK_STRERROR(result_errno,
sebuf, sizeof(sebuf)));
}
else
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("SSL SYSCALL error: EOF detected\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("SSL SYSCALL error: EOF detected\n"));
/* assume the connection is broken */
result_errno = ECONNRESET;
n = -1;
{
char *errm = SSLerrmessage(ecode);
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSL error: %s\n"), errm);
SSLerrfree(errm);
/* assume the connection is broken */
* a clean connection closure, so we should not report it as a
* server crash.
*/
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("SSL connection has been closed unexpectedly\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("SSL connection has been closed unexpectedly\n"));
result_errno = ECONNRESET;
n = -1;
break;
default:
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("unrecognized SSL error code: %d\n"),
err);
/* assume the connection is broken */
if (n < 0)
{
/* Not supposed to happen, so we don't translate the msg */
- printfPQExpBuffer(&conn->errorMessage,
- "SSL_write failed but did not provide error information\n");
+ appendPQExpBufferStr(&conn->errorMessage,
+ "SSL_write failed but did not provide error information\n");
/* assume the connection is broken */
result_errno = ECONNRESET;
}
{
result_errno = SOCK_ERRNO;
if (result_errno == EPIPE || result_errno == ECONNRESET)
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("server closed the connection unexpectedly\n"
- "\tThis probably means the server terminated abnormally\n"
- "\tbefore or while processing the request.\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("server closed the connection unexpectedly\n"
+ "\tThis probably means the server terminated abnormally\n"
+ "\tbefore or while processing the request.\n"));
else
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSL SYSCALL error: %s\n"),
SOCK_STRERROR(result_errno,
sebuf, sizeof(sebuf)));
}
else
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("SSL SYSCALL error: EOF detected\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("SSL SYSCALL error: EOF detected\n"));
/* assume the connection is broken */
result_errno = ECONNRESET;
n = -1;
{
char *errm = SSLerrmessage(ecode);
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSL error: %s\n"), errm);
SSLerrfree(errm);
/* assume the connection is broken */
* a clean connection closure, so we should not report it as a
* server crash.
*/
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("SSL connection has been closed unexpectedly\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("SSL connection has been closed unexpectedly\n"));
result_errno = ECONNRESET;
n = -1;
break;
default:
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("unrecognized SSL error code: %d\n"),
err);
/* assume the connection is broken */
if (!OBJ_find_sigid_algs(X509_get_signature_nid(peer_cert),
&algo_nid, NULL))
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could not determine server certificate signature algorithm\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("could not determine server certificate signature algorithm\n"));
return NULL;
}
algo_type = EVP_get_digestbynid(algo_nid);
if (algo_type == NULL)
{
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not find digest for NID %s\n"),
OBJ_nid2sn(algo_nid));
return NULL;
if (!X509_digest(peer_cert, algo_type, hash, &hash_size))
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could not generate peer certificate hash\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("could not generate peer certificate hash\n"));
return NULL;
}
cert_hash = malloc(hash_size);
if (cert_hash == NULL)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("out of memory\n"));
return NULL;
}
memcpy(cert_hash, hash, hash_size);
/* Should not happen... */
if (name_entry == NULL)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("SSL certificate's name entry is missing\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("SSL certificate's name entry is missing\n"));
return -1;
}
{
char *err = SSLerrmessage(ERR_get_error());
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not create SSL context: %s\n"),
err);
SSLerrfree(err);
if (ssl_min_ver == -1)
{
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("invalid value \"%s\" for minimum SSL protocol version\n"),
conn->ssl_min_protocol_version);
SSL_CTX_free(SSL_context);
{
char *err = SSLerrmessage(ERR_get_error());
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not set minimum SSL protocol version: %s\n"),
err);
SSLerrfree(err);
if (ssl_max_ver == -1)
{
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("invalid value \"%s\" for maximum SSL protocol version\n"),
conn->ssl_max_protocol_version);
SSL_CTX_free(SSL_context);
{
char *err = SSLerrmessage(ERR_get_error());
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not set maximum SSL protocol version: %s\n"),
err);
SSLerrfree(err);
{
char *err = SSLerrmessage(ERR_get_error());
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not read root certificate file \"%s\": %s\n"),
fnbuf, err);
SSLerrfree(err);
* that it seems worth having a specialized error message for it.
*/
if (fnbuf[0] == '\0')
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not get home directory to locate root certificate file\n"
"Either provide the file or change sslmode to disable server certificate verification.\n"));
else
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("root certificate file \"%s\" does not exist\n"
"Either provide the file or change sslmode to disable server certificate verification.\n"), fnbuf);
SSL_CTX_free(SSL_context);
*/
if (errno != ENOENT && errno != ENOTDIR)
{
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open certificate file \"%s\": %s\n"),
fnbuf, strerror_r(errno, sebuf, sizeof(sebuf)));
SSL_CTX_free(SSL_context);
{
char *err = SSLerrmessage(ERR_get_error());
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not read certificate file \"%s\": %s\n"),
fnbuf, err);
SSLerrfree(err);
{
char *err = SSLerrmessage(ERR_get_error());
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not establish SSL connection: %s\n"),
err);
SSLerrfree(err);
if (engine_str == NULL)
{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("out of memory\n"));
return -1;
}
{
char *err = SSLerrmessage(ERR_get_error());
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not load SSL engine \"%s\": %s\n"),
engine_str, err);
SSLerrfree(err);
{
char *err = SSLerrmessage(ERR_get_error());
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not initialize SSL engine \"%s\": %s\n"),
engine_str, err);
SSLerrfree(err);
{
char *err = SSLerrmessage(ERR_get_error());
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not read private SSL key \"%s\" from engine \"%s\": %s\n"),
engine_colon, engine_str, err);
SSLerrfree(err);
{
char *err = SSLerrmessage(ERR_get_error());
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not load private SSL key \"%s\" from engine \"%s\": %s\n"),
engine_colon, engine_str, err);
SSLerrfree(err);
if (stat(fnbuf, &buf) != 0)
{
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("certificate present, but not private key file \"%s\"\n"),
fnbuf);
return -1;
#ifndef WIN32
if (!S_ISREG(buf.st_mode) || buf.st_mode & (S_IRWXG | S_IRWXO))
{
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("private key file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n"),
fnbuf);
return -1;
*/
if (SSL_use_PrivateKey_file(conn->ssl, fnbuf, SSL_FILETYPE_ASN1) != 1)
{
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not load private key file \"%s\": %s\n"),
fnbuf, err);
SSLerrfree(err);
{
char *err = SSLerrmessage(ERR_get_error());
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("certificate does not match private key file \"%s\": %s\n"),
fnbuf, err);
SSLerrfree(err);
char sebuf[PG_STRERROR_R_BUFLEN];
if (r == -1)
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSL SYSCALL error: %s\n"),
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
else
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("SSL SYSCALL error: EOF detected\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("SSL SYSCALL error: EOF detected\n"));
pgtls_close(conn);
return PGRES_POLLING_FAILED;
}
{
char *err = SSLerrmessage(ecode);
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSL error: %s\n"),
err);
SSLerrfree(err);
}
default:
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("unrecognized SSL error code: %d\n"),
err);
pgtls_close(conn);
{
char *err = SSLerrmessage(ERR_get_error());
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("certificate could not be obtained: %s\n"),
err);
SSLerrfree(err);
/*
* Read data from a secure connection.
*
- * On failure, this function is responsible for putting a suitable message
- * into conn->errorMessage. The caller must still inspect errno, but only
+ * On failure, this function is responsible for appending a suitable message
+ * to conn->errorMessage. The caller must still inspect errno, but only
* to determine whether to continue/retry after error.
*/
ssize_t
case EPIPE:
case ECONNRESET:
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("server closed the connection unexpectedly\n"
- "\tThis probably means the server terminated abnormally\n"
- "\tbefore or while processing the request.\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("server closed the connection unexpectedly\n"
+ "\tThis probably means the server terminated abnormally\n"
+ "\tbefore or while processing the request.\n"));
break;
default:
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not receive data from server: %s\n"),
SOCK_STRERROR(result_errno,
sebuf, sizeof(sebuf)));
/*
* Write data to a secure connection.
*
- * On failure, this function is responsible for putting a suitable message
- * into conn->errorMessage. The caller must still inspect errno, but only
+ * On failure, this function is responsible for appending a suitable message
+ * to conn->errorMessage. The caller must still inspect errno, but only
* to determine whether to continue/retry after error.
*/
ssize_t
/* FALL THRU */
case ECONNRESET:
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("server closed the connection unexpectedly\n"
- "\tThis probably means the server terminated abnormally\n"
- "\tbefore or while processing the request.\n"));
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("server closed the connection unexpectedly\n"
+ "\tThis probably means the server terminated abnormally\n"
+ "\tbefore or while processing the request.\n"));
break;
default:
- printfPQExpBuffer(&conn->errorMessage,
+ appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not send data to server: %s\n"),
SOCK_STRERROR(result_errno,
sebuf, sizeof(sebuf)));
* connection */
#endif
- /* Buffer for current error message */
+ /*
+ * Buffer for current error message. This is cleared at the start of any
+ * connection attempt or query cycle; after that, all code should append
+ * messages to it, never overwrite.
+ */
PQExpBufferData errorMessage; /* expansible string */
/* Buffer for receiving various parts of messages */
/* === in fe-exec.c === */
extern void pqSetResultError(PGresult *res, const char *msg);
-extern void pqCatenateResultError(PGresult *res, const char *msg);
extern void *pqResultAlloc(PGresult *res, size_t nBytes, bool isBinary);
extern char *pqResultStrdup(PGresult *res, const char *str);
extern void pqClearAsyncResult(PGconn *conn);
extern void pqSaveParameterStatus(PGconn *conn, const char *name,
const char *value);
extern int pqRowProcessor(PGconn *conn, const char **errmsgp);
+extern int PQsendQueryContinue(PGconn *conn, const char *query);
/* === in fe-protocol2.c === */
* The conn parameter is only used to be able to pass back an error
* message - no connection-local setup is made here.
*
- * Returns 0 if OK, -1 on failure (with a message in conn->errorMessage).
+ * Returns 0 if OK, -1 on failure (adding a message to conn->errorMessage).
*/
extern int pgtls_init(PGconn *conn);
/*
* Read data from a secure connection.
*
- * On failure, this function is responsible for putting a suitable message
- * into conn->errorMessage. The caller must still inspect errno, but only
+ * On failure, this function is responsible for appending a suitable message
+ * to conn->errorMessage. The caller must still inspect errno, but only
* to determine whether to continue/retry after error.
*/
extern ssize_t pgtls_read(PGconn *conn, void *ptr, size_t len);
/*
* Write data to a secure connection.
*
- * On failure, this function is responsible for putting a suitable message
- * into conn->errorMessage. The caller must still inspect errno, but only
+ * On failure, this function is responsible for appending a suitable message
+ * to conn->errorMessage. The caller must still inspect errno, but only
* to determine whether to continue/retry after error.
*/
extern ssize_t pgtls_write(PGconn *conn, const void *ptr, size_t len);