Commit bc433317 authored by Tom Lane's avatar Tom Lane

Fix lo_import and lo_export to return useful error messages more often.

I found that these functions tend to return -1 while leaving an empty error
message string in the PGconn, if they suffer some kind of I/O error on the
file.  The reason is that lo_close, which thinks it's executed a perfectly
fine SQL command, clears the errorMessage.  The minimum-change workaround
is to reorder operations here so that we don't fill the errorMessage until
after lo_close.
parent f52c5165
...@@ -168,7 +168,7 @@ lo_truncate(PGconn *conn, int fd, size_t len) ...@@ -168,7 +168,7 @@ lo_truncate(PGconn *conn, int fd, size_t len)
if (len > (size_t) INT_MAX) if (len > (size_t) INT_MAX)
{ {
printfPQExpBuffer(&conn->errorMessage, printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("argument of lo_truncate exceeds integer range\n")); libpq_gettext("argument of lo_truncate exceeds integer range\n"));
return -1; return -1;
} }
...@@ -219,7 +219,7 @@ lo_truncate64(PGconn *conn, int fd, pg_int64 len) ...@@ -219,7 +219,7 @@ lo_truncate64(PGconn *conn, int fd, pg_int64 len)
if (conn->lobjfuncs->fn_lo_truncate64 == 0) if (conn->lobjfuncs->fn_lo_truncate64 == 0)
{ {
printfPQExpBuffer(&conn->errorMessage, printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("cannot determine OID of function lo_truncate64\n")); libpq_gettext("cannot determine OID of function lo_truncate64\n"));
return -1; return -1;
} }
...@@ -277,7 +277,7 @@ lo_read(PGconn *conn, int fd, char *buf, size_t len) ...@@ -277,7 +277,7 @@ lo_read(PGconn *conn, int fd, char *buf, size_t len)
if (len > (size_t) INT_MAX) if (len > (size_t) INT_MAX)
{ {
printfPQExpBuffer(&conn->errorMessage, printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("argument of lo_read exceeds integer range\n")); libpq_gettext("argument of lo_read exceeds integer range\n"));
return -1; return -1;
} }
...@@ -332,7 +332,7 @@ lo_write(PGconn *conn, int fd, const char *buf, size_t len) ...@@ -332,7 +332,7 @@ lo_write(PGconn *conn, int fd, const char *buf, size_t len)
if (len > (size_t) INT_MAX) if (len > (size_t) INT_MAX)
{ {
printfPQExpBuffer(&conn->errorMessage, printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("argument of lo_write exceeds integer range\n")); libpq_gettext("argument of lo_write exceeds integer range\n"));
return -1; return -1;
} }
...@@ -423,7 +423,7 @@ lo_lseek64(PGconn *conn, int fd, pg_int64 offset, int whence) ...@@ -423,7 +423,7 @@ lo_lseek64(PGconn *conn, int fd, pg_int64 offset, int whence)
if (conn->lobjfuncs->fn_lo_lseek64 == 0) if (conn->lobjfuncs->fn_lo_lseek64 == 0)
{ {
printfPQExpBuffer(&conn->errorMessage, printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("cannot determine OID of function lo_lseek64\n")); libpq_gettext("cannot determine OID of function lo_lseek64\n"));
return -1; return -1;
} }
...@@ -598,7 +598,7 @@ lo_tell64(PGconn *conn, int fd) ...@@ -598,7 +598,7 @@ lo_tell64(PGconn *conn, int fd)
if (conn->lobjfuncs->fn_lo_tell64 == 0) if (conn->lobjfuncs->fn_lo_tell64 == 0)
{ {
printfPQExpBuffer(&conn->errorMessage, printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("cannot determine OID of function lo_tell64\n")); libpq_gettext("cannot determine OID of function lo_tell64\n"));
return -1; return -1;
} }
...@@ -753,10 +753,16 @@ lo_import_internal(PGconn *conn, const char *filename, Oid oid) ...@@ -753,10 +753,16 @@ lo_import_internal(PGconn *conn, const char *filename, Oid oid)
if (nbytes < 0) if (nbytes < 0)
{ {
/* We must do lo_close before setting the errorMessage */
int save_errno = errno;
(void) lo_close(conn, lobj);
(void) close(fd);
printfPQExpBuffer(&conn->errorMessage, printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not read from file \"%s\": %s\n"), libpq_gettext("could not read from file \"%s\": %s\n"),
filename, pqStrerror(errno, sebuf, sizeof(sebuf))); filename,
lobjOid = InvalidOid; pqStrerror(save_errno, sebuf, sizeof(sebuf)));
return InvalidOid;
} }
(void) close(fd); (void) close(fd);
...@@ -801,11 +807,15 @@ lo_export(PGconn *conn, Oid lobjId, const char *filename) ...@@ -801,11 +807,15 @@ lo_export(PGconn *conn, Oid lobjId, const char *filename)
*/ */
fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC | PG_BINARY, 0666); fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC | PG_BINARY, 0666);
if (fd < 0) if (fd < 0)
{ /* error */ {
/* We must do lo_close before setting the errorMessage */
int save_errno = errno;
(void) lo_close(conn, lobj);
printfPQExpBuffer(&conn->errorMessage, printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open file \"%s\": %s\n"), libpq_gettext("could not open file \"%s\": %s\n"),
filename, pqStrerror(errno, sebuf, sizeof(sebuf))); filename,
(void) lo_close(conn, lobj); pqStrerror(save_errno, sebuf, sizeof(sebuf)));
return -1; return -1;
} }
...@@ -817,11 +827,15 @@ lo_export(PGconn *conn, Oid lobjId, const char *filename) ...@@ -817,11 +827,15 @@ lo_export(PGconn *conn, Oid lobjId, const char *filename)
tmp = write(fd, buf, nbytes); tmp = write(fd, buf, nbytes);
if (tmp != nbytes) if (tmp != nbytes)
{ {
printfPQExpBuffer(&conn->errorMessage, /* We must do lo_close before setting the errorMessage */
libpq_gettext("could not write to file \"%s\": %s\n"), int save_errno = errno;
filename, pqStrerror(errno, sebuf, sizeof(sebuf)));
(void) lo_close(conn, lobj); (void) lo_close(conn, lobj);
(void) close(fd); (void) close(fd);
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not write to file \"%s\": %s\n"),
filename,
pqStrerror(save_errno, sebuf, sizeof(sebuf)));
return -1; return -1;
} }
} }
...@@ -839,7 +853,8 @@ lo_export(PGconn *conn, Oid lobjId, const char *filename) ...@@ -839,7 +853,8 @@ lo_export(PGconn *conn, Oid lobjId, const char *filename)
result = -1; result = -1;
} }
if (close(fd)) /* if we already failed, don't overwrite that msg with a close error */
if (close(fd) && result >= 0)
{ {
printfPQExpBuffer(&conn->errorMessage, printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not write to file \"%s\": %s\n"), libpq_gettext("could not write to file \"%s\": %s\n"),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment