Skip to content

Commit bc43331

Browse files
committed
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.
1 parent f52c516 commit bc43331

File tree

1 file changed

+30
-15
lines changed

1 file changed

+30
-15
lines changed

src/interfaces/libpq/fe-lobj.c

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ lo_truncate(PGconn *conn, int fd, size_t len)
168168
if (len > (size_t) INT_MAX)
169169
{
170170
printfPQExpBuffer(&conn->errorMessage,
171-
libpq_gettext("argument of lo_truncate exceeds integer range\n"));
171+
libpq_gettext("argument of lo_truncate exceeds integer range\n"));
172172
return -1;
173173
}
174174

@@ -219,7 +219,7 @@ lo_truncate64(PGconn *conn, int fd, pg_int64 len)
219219
if (conn->lobjfuncs->fn_lo_truncate64 == 0)
220220
{
221221
printfPQExpBuffer(&conn->errorMessage,
222-
libpq_gettext("cannot determine OID of function lo_truncate64\n"));
222+
libpq_gettext("cannot determine OID of function lo_truncate64\n"));
223223
return -1;
224224
}
225225

@@ -277,7 +277,7 @@ lo_read(PGconn *conn, int fd, char *buf, size_t len)
277277
if (len > (size_t) INT_MAX)
278278
{
279279
printfPQExpBuffer(&conn->errorMessage,
280-
libpq_gettext("argument of lo_read exceeds integer range\n"));
280+
libpq_gettext("argument of lo_read exceeds integer range\n"));
281281
return -1;
282282
}
283283

@@ -332,7 +332,7 @@ lo_write(PGconn *conn, int fd, const char *buf, size_t len)
332332
if (len > (size_t) INT_MAX)
333333
{
334334
printfPQExpBuffer(&conn->errorMessage,
335-
libpq_gettext("argument of lo_write exceeds integer range\n"));
335+
libpq_gettext("argument of lo_write exceeds integer range\n"));
336336
return -1;
337337
}
338338

@@ -423,7 +423,7 @@ lo_lseek64(PGconn *conn, int fd, pg_int64 offset, int whence)
423423
if (conn->lobjfuncs->fn_lo_lseek64 == 0)
424424
{
425425
printfPQExpBuffer(&conn->errorMessage,
426-
libpq_gettext("cannot determine OID of function lo_lseek64\n"));
426+
libpq_gettext("cannot determine OID of function lo_lseek64\n"));
427427
return -1;
428428
}
429429

@@ -598,7 +598,7 @@ lo_tell64(PGconn *conn, int fd)
598598
if (conn->lobjfuncs->fn_lo_tell64 == 0)
599599
{
600600
printfPQExpBuffer(&conn->errorMessage,
601-
libpq_gettext("cannot determine OID of function lo_tell64\n"));
601+
libpq_gettext("cannot determine OID of function lo_tell64\n"));
602602
return -1;
603603
}
604604

@@ -753,10 +753,16 @@ lo_import_internal(PGconn *conn, const char *filename, Oid oid)
753753

754754
if (nbytes < 0)
755755
{
756+
/* We must do lo_close before setting the errorMessage */
757+
int save_errno = errno;
758+
759+
(void) lo_close(conn, lobj);
760+
(void) close(fd);
756761
printfPQExpBuffer(&conn->errorMessage,
757762
libpq_gettext("could not read from file \"%s\": %s\n"),
758-
filename, pqStrerror(errno, sebuf, sizeof(sebuf)));
759-
lobjOid = InvalidOid;
763+
filename,
764+
pqStrerror(save_errno, sebuf, sizeof(sebuf)));
765+
return InvalidOid;
760766
}
761767

762768
(void) close(fd);
@@ -801,11 +807,15 @@ lo_export(PGconn *conn, Oid lobjId, const char *filename)
801807
*/
802808
fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC | PG_BINARY, 0666);
803809
if (fd < 0)
804-
{ /* error */
810+
{
811+
/* We must do lo_close before setting the errorMessage */
812+
int save_errno = errno;
813+
814+
(void) lo_close(conn, lobj);
805815
printfPQExpBuffer(&conn->errorMessage,
806816
libpq_gettext("could not open file \"%s\": %s\n"),
807-
filename, pqStrerror(errno, sebuf, sizeof(sebuf)));
808-
(void) lo_close(conn, lobj);
817+
filename,
818+
pqStrerror(save_errno, sebuf, sizeof(sebuf)));
809819
return -1;
810820
}
811821

@@ -817,11 +827,15 @@ lo_export(PGconn *conn, Oid lobjId, const char *filename)
817827
tmp = write(fd, buf, nbytes);
818828
if (tmp != nbytes)
819829
{
820-
printfPQExpBuffer(&conn->errorMessage,
821-
libpq_gettext("could not write to file \"%s\": %s\n"),
822-
filename, pqStrerror(errno, sebuf, sizeof(sebuf)));
830+
/* We must do lo_close before setting the errorMessage */
831+
int save_errno = errno;
832+
823833
(void) lo_close(conn, lobj);
824834
(void) close(fd);
835+
printfPQExpBuffer(&conn->errorMessage,
836+
libpq_gettext("could not write to file \"%s\": %s\n"),
837+
filename,
838+
pqStrerror(save_errno, sebuf, sizeof(sebuf)));
825839
return -1;
826840
}
827841
}
@@ -839,7 +853,8 @@ lo_export(PGconn *conn, Oid lobjId, const char *filename)
839853
result = -1;
840854
}
841855

842-
if (close(fd))
856+
/* if we already failed, don't overwrite that msg with a close error */
857+
if (close(fd) && result >= 0)
843858
{
844859
printfPQExpBuffer(&conn->errorMessage,
845860
libpq_gettext("could not write to file \"%s\": %s\n"),

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy