Skip to content

Commit ace9335

Browse files
committed
Improve error detection and recovery in lo_import()/lo_export().
Problems noted while experimenting with new control-C code for psql.
1 parent 067e40c commit ace9335

File tree

1 file changed

+55
-28
lines changed

1 file changed

+55
-28
lines changed

src/interfaces/libpq/fe-lobj.c

Lines changed: 55 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-lobj.c,v 1.56 2006/03/05 15:59:09 momjian Exp $
11+
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-lobj.c,v 1.57 2006/06/14 01:28:55 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -58,6 +58,12 @@ lo_open(PGconn *conn, Oid lobjId, int mode)
5858
PQArgBlock argv[2];
5959
PGresult *res;
6060

61+
if (conn->lobjfuncs == NULL)
62+
{
63+
if (lo_initialize(conn) < 0)
64+
return -1;
65+
}
66+
6167
argv[0].isint = 1;
6268
argv[0].len = 4;
6369
argv[0].u.integer = lobjId;
@@ -66,12 +72,6 @@ lo_open(PGconn *conn, Oid lobjId, int mode)
6672
argv[1].len = 4;
6773
argv[1].u.integer = mode;
6874

69-
if (conn->lobjfuncs == NULL)
70-
{
71-
if (lo_initialize(conn) < 0)
72-
return -1;
73-
}
74-
7575
res = PQfn(conn, conn->lobjfuncs->fn_lo_open, &fd, &result_len, 1, argv, 2);
7676
if (PQresultStatus(res) == PGRES_COMMAND_OK)
7777
{
@@ -438,23 +438,22 @@ lo_import(PGconn *conn, const char *filename)
438438
char buf[LO_BUFSIZE];
439439
Oid lobjOid;
440440
int lobj;
441+
char sebuf[256];
441442

442443
/*
443444
* open the file to be read in
444445
*/
445446
fd = open(filename, O_RDONLY | PG_BINARY, 0666);
446447
if (fd < 0)
447448
{ /* error */
448-
char sebuf[256];
449-
450449
printfPQExpBuffer(&conn->errorMessage,
451450
libpq_gettext("could not open file \"%s\": %s\n"),
452451
filename, pqStrerror(errno, sebuf, sizeof(sebuf)));
453452
return InvalidOid;
454453
}
455454

456455
/*
457-
* create an inversion "object"
456+
* create an inversion object
458457
*/
459458
lobjOid = lo_creat(conn, INV_READ | INV_WRITE);
460459
if (lobjOid == InvalidOid)
@@ -477,41 +476,65 @@ lo_import(PGconn *conn, const char *filename)
477476
}
478477

479478
/*
480-
* read in from the Unix file and write to the inversion file
479+
* read in from the file and write to the large object
481480
*/
482481
while ((nbytes = read(fd, buf, LO_BUFSIZE)) > 0)
483482
{
484483
tmp = lo_write(conn, lobj, buf, nbytes);
485-
if (tmp < nbytes)
484+
if (tmp != nbytes)
486485
{
486+
/*
487+
* If the lo_write failed, we are probably in an aborted
488+
* transaction and so lo_close will fail. Try it anyway for
489+
* cleanliness, but don't let it determine the returned error
490+
* message.
491+
*/
492+
(void) lo_close(conn, lobj);
493+
487494
printfPQExpBuffer(&conn->errorMessage,
488-
libpq_gettext("error while reading file \"%s\"\n"),
489-
filename);
495+
libpq_gettext("error while writing large object %u\n"),
496+
lobjOid);
490497
(void) close(fd);
491-
(void) lo_close(conn, lobj);
492498
return InvalidOid;
493499
}
494500
}
495501

502+
if (nbytes < 0)
503+
{
504+
printfPQExpBuffer(&conn->errorMessage,
505+
libpq_gettext("could not read from file \"%s\": %s\n"),
506+
filename, pqStrerror(errno, sebuf, sizeof(sebuf)));
507+
lobjOid = InvalidOid;
508+
}
509+
496510
(void) close(fd);
497-
(void) lo_close(conn, lobj);
511+
512+
if (lo_close(conn, lobj) != 0)
513+
{
514+
printfPQExpBuffer(&conn->errorMessage,
515+
libpq_gettext("error while writing large object %u\n"),
516+
lobjOid);
517+
return InvalidOid;
518+
}
498519

499520
return lobjOid;
500521
}
501522

502523
/*
503524
* lo_export -
504525
* exports an (inversion) large object.
505-
* returns -1 upon failure, 1 otherwise
526+
* returns -1 upon failure, 1 if OK
506527
*/
507528
int
508529
lo_export(PGconn *conn, Oid lobjId, const char *filename)
509530
{
531+
int result = 1;
510532
int fd;
511533
int nbytes,
512534
tmp;
513535
char buf[LO_BUFSIZE];
514536
int lobj;
537+
char sebuf[256];
515538

516539
/*
517540
* open the large object.
@@ -530,8 +553,6 @@ lo_export(PGconn *conn, Oid lobjId, const char *filename)
530553
fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC | PG_BINARY, 0666);
531554
if (fd < 0)
532555
{ /* error */
533-
char sebuf[256];
534-
535556
printfPQExpBuffer(&conn->errorMessage,
536557
libpq_gettext("could not open file \"%s\": %s\n"),
537558
filename, pqStrerror(errno, sebuf, sizeof(sebuf)));
@@ -540,33 +561,39 @@ lo_export(PGconn *conn, Oid lobjId, const char *filename)
540561
}
541562

542563
/*
543-
* read in from the inversion file and write to the Unix file
564+
* read in from the large object and write to the file
544565
*/
545566
while ((nbytes = lo_read(conn, lobj, buf, LO_BUFSIZE)) > 0)
546567
{
547568
tmp = write(fd, buf, nbytes);
548-
if (tmp < nbytes)
569+
if (tmp != nbytes)
549570
{
550571
printfPQExpBuffer(&conn->errorMessage,
551-
libpq_gettext("error while writing to file \"%s\"\n"),
552-
filename);
572+
libpq_gettext("error while writing to file \"%s\": %s\n"),
573+
filename, pqStrerror(errno, sebuf, sizeof(sebuf)));
553574
(void) lo_close(conn, lobj);
554575
(void) close(fd);
555576
return -1;
556577
}
557578
}
558579

559-
(void) lo_close(conn, lobj);
580+
if (lo_close(conn, lobj) != 0 || nbytes < 0)
581+
{
582+
printfPQExpBuffer(&conn->errorMessage,
583+
libpq_gettext("error while reading large object %u\n"),
584+
lobjId);
585+
result = -1;
586+
}
560587

561588
if (close(fd))
562589
{
563590
printfPQExpBuffer(&conn->errorMessage,
564-
libpq_gettext("error while writing to file \"%s\"\n"),
565-
filename);
566-
return -1;
591+
libpq_gettext("error while writing to file \"%s\": %s\n"),
592+
filename, pqStrerror(errno, sebuf, sizeof(sebuf)));
593+
result = -1;
567594
}
568595

569-
return 1;
596+
return result;
570597
}
571598

572599

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