aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2006-06-14 01:28:55 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2006-06-14 01:28:55 +0000
commitace93353eadf1316364bcb76f52952c413779083 (patch)
tree0bb4f3ad4ac903fd9122ed70660351097dc312ca /src
parent067e40cc6d1c9254c68e7ad29e7a07f14daa7eaa (diff)
downloadpostgresql-ace93353eadf1316364bcb76f52952c413779083.tar.gz
postgresql-ace93353eadf1316364bcb76f52952c413779083.zip
Improve error detection and recovery in lo_import()/lo_export().
Problems noted while experimenting with new control-C code for psql.
Diffstat (limited to 'src')
-rw-r--r--src/interfaces/libpq/fe-lobj.c83
1 files changed, 55 insertions, 28 deletions
diff --git a/src/interfaces/libpq/fe-lobj.c b/src/interfaces/libpq/fe-lobj.c
index 5d81a6ea339..5e11b0e3059 100644
--- a/src/interfaces/libpq/fe-lobj.c
+++ b/src/interfaces/libpq/fe-lobj.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/interfaces/libpq/fe-lobj.c,v 1.56 2006/03/05 15:59:09 momjian Exp $
+ * $PostgreSQL: pgsql/src/interfaces/libpq/fe-lobj.c,v 1.57 2006/06/14 01:28:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -58,6 +58,12 @@ lo_open(PGconn *conn, Oid lobjId, int mode)
PQArgBlock argv[2];
PGresult *res;
+ if (conn->lobjfuncs == NULL)
+ {
+ if (lo_initialize(conn) < 0)
+ return -1;
+ }
+
argv[0].isint = 1;
argv[0].len = 4;
argv[0].u.integer = lobjId;
@@ -66,12 +72,6 @@ lo_open(PGconn *conn, Oid lobjId, int mode)
argv[1].len = 4;
argv[1].u.integer = mode;
- if (conn->lobjfuncs == NULL)
- {
- if (lo_initialize(conn) < 0)
- return -1;
- }
-
res = PQfn(conn, conn->lobjfuncs->fn_lo_open, &fd, &result_len, 1, argv, 2);
if (PQresultStatus(res) == PGRES_COMMAND_OK)
{
@@ -438,6 +438,7 @@ lo_import(PGconn *conn, const char *filename)
char buf[LO_BUFSIZE];
Oid lobjOid;
int lobj;
+ char sebuf[256];
/*
* open the file to be read in
@@ -445,8 +446,6 @@ lo_import(PGconn *conn, const char *filename)
fd = open(filename, O_RDONLY | PG_BINARY, 0666);
if (fd < 0)
{ /* error */
- char sebuf[256];
-
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open file \"%s\": %s\n"),
filename, pqStrerror(errno, sebuf, sizeof(sebuf)));
@@ -454,7 +453,7 @@ lo_import(PGconn *conn, const char *filename)
}
/*
- * create an inversion "object"
+ * create an inversion object
*/
lobjOid = lo_creat(conn, INV_READ | INV_WRITE);
if (lobjOid == InvalidOid)
@@ -477,24 +476,46 @@ lo_import(PGconn *conn, const char *filename)
}
/*
- * read in from the Unix file and write to the inversion file
+ * read in from the file and write to the large object
*/
while ((nbytes = read(fd, buf, LO_BUFSIZE)) > 0)
{
tmp = lo_write(conn, lobj, buf, nbytes);
- if (tmp < nbytes)
+ if (tmp != nbytes)
{
+ /*
+ * If the lo_write failed, we are probably in an aborted
+ * transaction and so lo_close will fail. Try it anyway for
+ * cleanliness, but don't let it determine the returned error
+ * message.
+ */
+ (void) lo_close(conn, lobj);
+
printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("error while reading file \"%s\"\n"),
- filename);
+ libpq_gettext("error while writing large object %u\n"),
+ lobjOid);
(void) close(fd);
- (void) lo_close(conn, lobj);
return InvalidOid;
}
}
+ if (nbytes < 0)
+ {
+ printfPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("could not read from file \"%s\": %s\n"),
+ filename, pqStrerror(errno, sebuf, sizeof(sebuf)));
+ lobjOid = InvalidOid;
+ }
+
(void) close(fd);
- (void) lo_close(conn, lobj);
+
+ if (lo_close(conn, lobj) != 0)
+ {
+ printfPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("error while writing large object %u\n"),
+ lobjOid);
+ return InvalidOid;
+ }
return lobjOid;
}
@@ -502,16 +523,18 @@ lo_import(PGconn *conn, const char *filename)
/*
* lo_export -
* exports an (inversion) large object.
- * returns -1 upon failure, 1 otherwise
+ * returns -1 upon failure, 1 if OK
*/
int
lo_export(PGconn *conn, Oid lobjId, const char *filename)
{
+ int result = 1;
int fd;
int nbytes,
tmp;
char buf[LO_BUFSIZE];
int lobj;
+ char sebuf[256];
/*
* open the large object.
@@ -530,8 +553,6 @@ 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 */
- char sebuf[256];
-
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open file \"%s\": %s\n"),
filename, pqStrerror(errno, sebuf, sizeof(sebuf)));
@@ -540,33 +561,39 @@ lo_export(PGconn *conn, Oid lobjId, const char *filename)
}
/*
- * read in from the inversion file and write to the Unix file
+ * read in from the large object and write to the file
*/
while ((nbytes = lo_read(conn, lobj, buf, LO_BUFSIZE)) > 0)
{
tmp = write(fd, buf, nbytes);
- if (tmp < nbytes)
+ if (tmp != nbytes)
{
printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("error while writing to file \"%s\"\n"),
- filename);
+ libpq_gettext("error while writing to file \"%s\": %s\n"),
+ filename, pqStrerror(errno, sebuf, sizeof(sebuf)));
(void) lo_close(conn, lobj);
(void) close(fd);
return -1;
}
}
- (void) lo_close(conn, lobj);
+ if (lo_close(conn, lobj) != 0 || nbytes < 0)
+ {
+ printfPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("error while reading large object %u\n"),
+ lobjId);
+ result = -1;
+ }
if (close(fd))
{
printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("error while writing to file \"%s\"\n"),
- filename);
- return -1;
+ libpq_gettext("error while writing to file \"%s\": %s\n"),
+ filename, pqStrerror(errno, sebuf, sizeof(sebuf)));
+ result = -1;
}
- return 1;
+ return result;
}