From bc433317ae2b0494dea4526b89dc7bb90a65d79b Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 8 Oct 2012 21:52:34 -0400 Subject: [PATCH] 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. --- src/interfaces/libpq/fe-lobj.c | 45 ++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/src/interfaces/libpq/fe-lobj.c b/src/interfaces/libpq/fe-lobj.c index ffe333608c..1aed2ffeb7 100644 --- a/src/interfaces/libpq/fe-lobj.c +++ b/src/interfaces/libpq/fe-lobj.c @@ -168,7 +168,7 @@ lo_truncate(PGconn *conn, int fd, size_t len) if (len > (size_t) INT_MAX) { 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; } @@ -219,7 +219,7 @@ lo_truncate64(PGconn *conn, int fd, pg_int64 len) if (conn->lobjfuncs->fn_lo_truncate64 == 0) { 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; } @@ -277,7 +277,7 @@ lo_read(PGconn *conn, int fd, char *buf, size_t len) if (len > (size_t) INT_MAX) { 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; } @@ -332,7 +332,7 @@ lo_write(PGconn *conn, int fd, const char *buf, size_t len) if (len > (size_t) INT_MAX) { 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; } @@ -423,7 +423,7 @@ lo_lseek64(PGconn *conn, int fd, pg_int64 offset, int whence) if (conn->lobjfuncs->fn_lo_lseek64 == 0) { 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; } @@ -598,7 +598,7 @@ lo_tell64(PGconn *conn, int fd) if (conn->lobjfuncs->fn_lo_tell64 == 0) { 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; } @@ -753,10 +753,16 @@ lo_import_internal(PGconn *conn, const char *filename, Oid oid) 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, libpq_gettext("could not read from file \"%s\": %s\n"), - filename, pqStrerror(errno, sebuf, sizeof(sebuf))); - lobjOid = InvalidOid; + filename, + pqStrerror(save_errno, sebuf, sizeof(sebuf))); + return InvalidOid; } (void) close(fd); @@ -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); 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, libpq_gettext("could not open file \"%s\": %s\n"), - filename, pqStrerror(errno, sebuf, sizeof(sebuf))); - (void) lo_close(conn, lobj); + filename, + pqStrerror(save_errno, sebuf, sizeof(sebuf))); return -1; } @@ -817,11 +827,15 @@ lo_export(PGconn *conn, Oid lobjId, const char *filename) tmp = write(fd, buf, nbytes); if (tmp != nbytes) { - printfPQExpBuffer(&conn->errorMessage, - libpq_gettext("could not write to file \"%s\": %s\n"), - filename, pqStrerror(errno, sebuf, sizeof(sebuf))); + /* We must do lo_close before setting the errorMessage */ + int save_errno = errno; + (void) lo_close(conn, lobj); (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; } } @@ -839,7 +853,8 @@ lo_export(PGconn *conn, Oid lobjId, const char *filename) 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, libpq_gettext("could not write to file \"%s\": %s\n"), -- GitLab