Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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)