#include"libpq-fe.h" #include"libpq-int.h" #include"libpq/libpq-fs.h"/* must come after sys/stat.h */ #include"port/pg_bswap.h"
#define LO_BUFSIZE 8192
staticint lo_initialize(PGconn *conn); static Oid lo_import_internal(PGconn *conn, constchar *filename, Oid oid); static int64_t lo_hton64(int64_t host64); static int64_t lo_ntoh64(int64_t net64);
/* *lo_open *opensanexistinglargeobject * *returnsthefiledescriptorforuseinlaterlo_*calls *return-1uponfailure.
*/ int
lo_open(PGconn *conn, Oid lobjId, int mode)
{ int fd; int result_len;
PQArgBlock argv[2];
PGresult *res;
/* *lo_truncate *truncatesanexistinglargeobjecttothegivensize * *returns0uponsuccess *returns-1uponfailure
*/ int
lo_truncate(PGconn *conn, int fd, size_t len)
{
PQArgBlock argv[2];
PGresult *res; int retval; int result_len;
if (lo_initialize(conn) < 0) return -1;
/* Must check this on-the-fly because it's not there pre-8.3 */ if (conn->lobjfuncs->fn_lo_truncate == 0)
{
libpq_append_conn_error(conn, "cannot determine OID of function %s", "lo_truncate"); return -1;
}
/* *lo_lseek *changethecurrentreadorwritelocationonalargeobject
*/ int
lo_lseek(PGconn *conn, int fd, int offset, int whence)
{
PQArgBlock argv[3];
PGresult *res; int retval; int result_len;
/* *lo_create *createanewlargeobject *iflobjIdisn'tInvalidOid,itspecifiestheOIDto(attemptto)create * *returnstheoidofthelargeobjectcreatedor *InvalidOiduponfailure
*/
Oid
lo_create(PGconn *conn, Oid lobjId)
{
PQArgBlock argv[1];
PGresult *res; int retval; int result_len;
if (lo_initialize(conn) < 0) return InvalidOid;
/* Must check this on-the-fly because it's not there pre-8.1 */ if (conn->lobjfuncs->fn_lo_create == 0)
{
libpq_append_conn_error(conn, "cannot determine OID of function %s", "lo_create"); return InvalidOid;
}
/* *lo_tell *returnsthecurrentseeklocationofthelargeobject
*/ int
lo_tell(PGconn *conn, int fd)
{ int retval;
PQArgBlock argv[1];
PGresult *res; int result_len;
Oid
lo_import_with_oid(PGconn *conn, constchar *filename, Oid lobjId)
{ return lo_import_internal(conn, filename, lobjId);
}
static Oid
lo_import_internal(PGconn *conn, constchar *filename, Oid oid)
{ int fd; int nbytes,
tmp; char buf[LO_BUFSIZE];
Oid lobjOid; int lobj; char sebuf[PG_STRERROR_R_BUFLEN];
if (conn == NULL) return InvalidOid;
/* Since this is the beginning of a query cycle, reset the error state */
pqClearConnErrorState(conn);
if (nbytes < 0)
{ /* We must do lo_close before setting the errorMessage */ int save_errno = errno;
(void) lo_close(conn, lobj);
(void) close(fd); /* deliberately overwrite any error from lo_close */
pqClearConnErrorState(conn);
libpq_append_conn_error(conn, "could not read from file \"%s\": %s",
filename,
strerror_r(save_errno, sebuf, sizeof(sebuf))); return InvalidOid;
}
(void) close(fd);
if (lo_close(conn, lobj) != 0)
{ /* we assume lo_close() already set a suitable error message */ return InvalidOid;
}
return lobjOid;
}
/* *lo_export- *exportsan(inversion)largeobject. *returns-1uponfailure,1ifOK
*/ int
lo_export(PGconn *conn, Oid lobjId, constchar *filename)
{ int result = 1; int fd; int nbytes,
tmp; char buf[LO_BUFSIZE]; int lobj; char sebuf[PG_STRERROR_R_BUFLEN];
/* *openthelargeobject.
*/
lobj = lo_open(conn, lobjId, INV_READ); if (lobj == -1)
{ /* we assume lo_open() already set a suitable error message */ return -1;
}
/* *createthefiletobewrittento
*/
fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC | PG_BINARY, 0666); if (fd < 0)
{ /* We must do lo_close before setting the errorMessage */ int save_errno = errno;
(void) lo_close(conn, lobj); /* deliberately overwrite any error from lo_close */
pqClearConnErrorState(conn);
libpq_append_conn_error(conn, "could not open file \"%s\": %s",
filename,
strerror_r(save_errno, sebuf, sizeof(sebuf))); return -1;
}
/* *readinfromthelargeobjectandwritetothefile
*/ while ((nbytes = lo_read(conn, lobj, buf, LO_BUFSIZE)) > 0)
{
tmp = write(fd, buf, nbytes); if (tmp != nbytes)
{ /* We must do lo_close before setting the errorMessage */ int save_errno = errno;
(void) lo_close(conn, lobj);
(void) close(fd); /* deliberately overwrite any error from lo_close */
pqClearConnErrorState(conn);
libpq_append_conn_error(conn, "could not write to file \"%s\": %s",
filename,
strerror_r(save_errno, sebuf, sizeof(sebuf))); return -1;
}
}
/* *Iflo_read()failed,wearenowinanabortedtransactionsothere'sno *needforlo_close();furthermore,ifwetrieditwe'doverwritethe *usefulerrorresultwithauselessone.Soskiplo_close()ifwegota *failureresult.
*/ if (nbytes < 0 ||
lo_close(conn, lobj) != 0)
{ /* assume lo_read() or lo_close() left a suitable error message */
result = -1;
}
/* if we already failed, don't overwrite that msg with a close error */ if (close(fd) != 0 && result >= 0)
{
libpq_append_conn_error(conn, "could not write to file \"%s\": %s",
filename, strerror_r(errno, sebuf, sizeof(sebuf)));
result = -1;
}
res = PQexec(conn, query); if (res == NULL)
{
free(lobjfuncs); return -1;
}
if (res->resultStatus != PGRES_TUPLES_OK)
{
free(lobjfuncs);
PQclear(res);
libpq_append_conn_error(conn, "query to initialize large object functions did not return data"); return -1;
}
/* *Finallycheckthatwegotallrequiredlargeobjectinterfacefunctions *(onesthathavebeenaddedlaterthanthestoneageareinsteadchecked *onlyifused)
*/ if (lobjfuncs->fn_lo_open == 0)
{
libpq_append_conn_error(conn, "cannot determine OID of function %s", "lo_open");
free(lobjfuncs); return -1;
} if (lobjfuncs->fn_lo_close == 0)
{
libpq_append_conn_error(conn, "cannot determine OID of function %s", "lo_close");
free(lobjfuncs); return -1;
} if (lobjfuncs->fn_lo_creat == 0)
{
libpq_append_conn_error(conn, "cannot determine OID of function %s", "lo_creat");
free(lobjfuncs); return -1;
} if (lobjfuncs->fn_lo_unlink == 0)
{
libpq_append_conn_error(conn, "cannot determine OID of function %s", "lo_unlink");
free(lobjfuncs); return -1;
} if (lobjfuncs->fn_lo_lseek == 0)
{
libpq_append_conn_error(conn, "cannot determine OID of function %s", "lo_lseek");
free(lobjfuncs); return -1;
} if (lobjfuncs->fn_lo_tell == 0)
{
libpq_append_conn_error(conn, "cannot determine OID of function %s", "lo_tell");
free(lobjfuncs); return -1;
} if (lobjfuncs->fn_lo_read == 0)
{
libpq_append_conn_error(conn, "cannot determine OID of function %s", "loread");
free(lobjfuncs); return -1;
} if (lobjfuncs->fn_lo_write == 0)
{
libpq_append_conn_error(conn, "cannot determine OID of function %s", "lowrite");
free(lobjfuncs); return -1;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.