Commits

Anonymous committed bc43331

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.

Comments (0)

Files changed (1)

src/interfaces/libpq/fe-lobj.c

 	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;
 	}
 
 	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;
 	}
 
 	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;
 	}
 
 	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;
 	}
 
 	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;
 	}
 
 	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;
 	}
 
 
 	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);
 	 */
 	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;
 	}
 
 		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;
 		}
 	}
 		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"),