]> granicus.if.org Git - postgresql/commitdiff
Fix lo_import and lo_export to return useful error messages more often.
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 9 Oct 2012 01:52:34 +0000 (21:52 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 9 Oct 2012 01:52:34 +0000 (21:52 -0400)
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

index ffe333608c12e13d9a62cbceafc93e6f35217420..1aed2ffeb7de7ca52f282ab030725cf0355e0a98 100644 (file)
@@ -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"),