summaryrefslogtreecommitdiff
path: root/src/interfaces/libpq/fe-lobj.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/interfaces/libpq/fe-lobj.c')
-rw-r--r--src/interfaces/libpq/fe-lobj.c661
1 files changed, 0 insertions, 661 deletions
diff --git a/src/interfaces/libpq/fe-lobj.c b/src/interfaces/libpq/fe-lobj.c
deleted file mode 100644
index dd2d76867df..00000000000
--- a/src/interfaces/libpq/fe-lobj.c
+++ /dev/null
@@ -1,661 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * fe-lobj.c
- * Front-end large object interface
- *
- * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-lobj.c,v 1.41 2002/06/20 20:29:54 momjian Exp $
- *
- *-------------------------------------------------------------------------
- */
-#include "postgres_fe.h"
-
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <errno.h>
-
-#ifdef WIN32
-#include "win32.h"
-#include "io.h"
-#else
-#include <unistd.h>
-#endif
-
-#include "libpq-fe.h"
-#include "libpq-int.h"
-#include "libpq/libpq-fs.h" /* must come after sys/stat.h */
-
-
-#define LO_BUFSIZE 8192
-
-static int lo_initialize(PGconn *conn);
-
-
-/*
- * lo_open
- * opens an existing large object
- *
- * returns the file descriptor for use in later lo_* calls
- * return -1 upon failure.
- */
-int
-lo_open(PGconn *conn, Oid lobjId, int mode)
-{
- int fd;
- int result_len;
- PQArgBlock argv[2];
- PGresult *res;
-
- argv[0].isint = 1;
- argv[0].len = 4;
- argv[0].u.integer = lobjId;
-
- argv[1].isint = 1;
- argv[1].len = 4;
- argv[1].u.integer = mode;
-
- if (conn->lobjfuncs == (PGlobjfuncs *) 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)
- {
- PQclear(res);
-
- /* have to do this to reset offset in shared fd cache */
- /* but only if fd is valid */
- if (fd >= 0 && lo_lseek(conn, fd, 0L, SEEK_SET) < 0)
- return -1;
- return fd;
- }
- else
- {
- PQclear(res);
- return -1;
- }
-}
-
-/*
- * lo_close
- * closes an existing large object
- *
- * returns 0 upon success
- * returns -1 upon failure.
- */
-int
-lo_close(PGconn *conn, int fd)
-{
- PQArgBlock argv[1];
- PGresult *res;
- int retval;
- int result_len;
-
- if (conn->lobjfuncs == (PGlobjfuncs *) NULL)
- {
- if (lo_initialize(conn) < 0)
- return -1;
- }
-
- argv[0].isint = 1;
- argv[0].len = 4;
- argv[0].u.integer = fd;
- res = PQfn(conn, conn->lobjfuncs->fn_lo_close,
- &retval, &result_len, 1, argv, 1);
- if (PQresultStatus(res) == PGRES_COMMAND_OK)
- {
- PQclear(res);
- return retval;
- }
- else
- {
- PQclear(res);
- return -1;
- }
-}
-
-/*
- * lo_read
- * read len bytes of the large object into buf
- *
- * returns the number of bytes read, or -1 on failure.
- * the CALLER must have allocated enough space to hold the result returned
- */
-
-int
-lo_read(PGconn *conn, int fd, char *buf, size_t len)
-{
- PQArgBlock argv[2];
- PGresult *res;
- int result_len;
-
- if (conn->lobjfuncs == (PGlobjfuncs *) NULL)
- {
- if (lo_initialize(conn) < 0)
- return -1;
- }
-
- argv[0].isint = 1;
- argv[0].len = 4;
- argv[0].u.integer = fd;
-
- argv[1].isint = 1;
- argv[1].len = 4;
- argv[1].u.integer = len;
-
- res = PQfn(conn, conn->lobjfuncs->fn_lo_read,
- (int *) buf, &result_len, 0, argv, 2);
- if (PQresultStatus(res) == PGRES_COMMAND_OK)
- {
- PQclear(res);
- return result_len;
- }
- else
- {
- PQclear(res);
- return -1;
- }
-}
-
-/*
- * lo_write
- * write len bytes of buf into the large object fd
- *
- * returns the number of bytes written, or -1 on failure.
- */
-int
-lo_write(PGconn *conn, int fd, char *buf, size_t len)
-{
- PQArgBlock argv[2];
- PGresult *res;
- int result_len;
- int retval;
-
- if (conn->lobjfuncs == (PGlobjfuncs *) NULL)
- {
- if (lo_initialize(conn) < 0)
- return -1;
- }
-
- if (len <= 0)
- return 0;
-
- argv[0].isint = 1;
- argv[0].len = 4;
- argv[0].u.integer = fd;
-
- argv[1].isint = 0;
- argv[1].len = len;
- argv[1].u.ptr = (int *) buf;
-
- res = PQfn(conn, conn->lobjfuncs->fn_lo_write,
- &retval, &result_len, 1, argv, 2);
- if (PQresultStatus(res) == PGRES_COMMAND_OK)
- {
- PQclear(res);
- return retval;
- }
- else
- {
- PQclear(res);
- return -1;
- }
-}
-
-/*
- * lo_lseek
- * change the current read or write location on a large object
- * currently, only L_SET is a legal value for whence
- *
- */
-
-int
-lo_lseek(PGconn *conn, int fd, int offset, int whence)
-{
- PQArgBlock argv[3];
- PGresult *res;
- int retval;
- int result_len;
-
- if (conn->lobjfuncs == (PGlobjfuncs *) NULL)
- {
- if (lo_initialize(conn) < 0)
- return -1;
- }
-
- argv[0].isint = 1;
- argv[0].len = 4;
- argv[0].u.integer = fd;
-
- argv[1].isint = 1;
- argv[1].len = 4;
- argv[1].u.integer = offset;
-
- argv[2].isint = 1;
- argv[2].len = 4;
- argv[2].u.integer = whence;
-
- res = PQfn(conn, conn->lobjfuncs->fn_lo_lseek,
- &retval, &result_len, 1, argv, 3);
- if (PQresultStatus(res) == PGRES_COMMAND_OK)
- {
- PQclear(res);
- return retval;
- }
- else
- {
- PQclear(res);
- return -1;
- }
-}
-
-/*
- * lo_creat
- * create a new large object
- * the mode is a bitmask describing different attributes of the new object
- *
- * returns the oid of the large object created or
- * InvalidOid upon failure
- */
-
-Oid
-lo_creat(PGconn *conn, int mode)
-{
- PQArgBlock argv[1];
- PGresult *res;
- int retval;
- int result_len;
-
- if (conn->lobjfuncs == (PGlobjfuncs *) NULL)
- {
- if (lo_initialize(conn) < 0)
- return InvalidOid;
- }
-
- argv[0].isint = 1;
- argv[0].len = 4;
- argv[0].u.integer = mode;
- res = PQfn(conn, conn->lobjfuncs->fn_lo_creat,
- &retval, &result_len, 1, argv, 1);
- if (PQresultStatus(res) == PGRES_COMMAND_OK)
- {
- PQclear(res);
- return (Oid) retval;
- }
- else
- {
- PQclear(res);
- return InvalidOid;
- }
-}
-
-
-/*
- * lo_tell
- * returns the current seek location of the large object
- *
- */
-
-int
-lo_tell(PGconn *conn, int fd)
-{
- int retval;
- PQArgBlock argv[1];
- PGresult *res;
- int result_len;
-
- if (conn->lobjfuncs == (PGlobjfuncs *) NULL)
- {
- if (lo_initialize(conn) < 0)
- return -1;
- }
-
- argv[0].isint = 1;
- argv[0].len = 4;
- argv[0].u.integer = fd;
-
- res = PQfn(conn, conn->lobjfuncs->fn_lo_tell,
- &retval, &result_len, 1, argv, 1);
- if (PQresultStatus(res) == PGRES_COMMAND_OK)
- {
- PQclear(res);
- return retval;
- }
- else
- {
- PQclear(res);
- return -1;
- }
-}
-
-/*
- * lo_unlink
- * delete a file
- *
- */
-
-int
-lo_unlink(PGconn *conn, Oid lobjId)
-{
- PQArgBlock argv[1];
- PGresult *res;
- int result_len;
- int retval;
-
- if (conn->lobjfuncs == (PGlobjfuncs *) NULL)
- {
- if (lo_initialize(conn) < 0)
- return -1;
- }
-
- argv[0].isint = 1;
- argv[0].len = 4;
- argv[0].u.integer = lobjId;
-
- res = PQfn(conn, conn->lobjfuncs->fn_lo_unlink,
- &retval, &result_len, 1, argv, 1);
- if (PQresultStatus(res) == PGRES_COMMAND_OK)
- {
- PQclear(res);
- return retval;
- }
- else
- {
- PQclear(res);
- return -1;
- }
-}
-
-/*
- * lo_import -
- * imports a file as an (inversion) large object.
- *
- * returns the oid of that object upon success,
- * returns InvalidOid upon failure
- */
-
-Oid
-lo_import(PGconn *conn, const char *filename)
-{
- int fd;
- int nbytes,
- tmp;
- char buf[LO_BUFSIZE];
- Oid lobjOid;
- int lobj;
-
- /*
- * open the file to be read in
- */
- fd = open(filename, O_RDONLY | PG_BINARY, 0666);
- if (fd < 0)
- { /* error */
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could not open file \"%s\": %s\n"),
- filename, strerror(errno));
- return InvalidOid;
- }
-
- /*
- * create an inversion "object"
- */
- lobjOid = lo_creat(conn, INV_READ | INV_WRITE);
- if (lobjOid == InvalidOid)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could not create large object for file \"%s\"\n"),
- filename);
- (void) close(fd);
- return InvalidOid;
- }
-
- lobj = lo_open(conn, lobjOid, INV_WRITE);
- if (lobj == -1)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could not open large object %u\n"),
- lobjOid);
- (void) close(fd);
- return InvalidOid;
- }
-
- /*
- * read in from the Unix file and write to the inversion file
- */
- while ((nbytes = read(fd, buf, LO_BUFSIZE)) > 0)
- {
- tmp = lo_write(conn, lobj, buf, nbytes);
- if (tmp < nbytes)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("error while reading file \"%s\"\n"),
- filename);
- (void) close(fd);
- (void) lo_close(conn, lobj);
- return InvalidOid;
- }
- }
-
- (void) close(fd);
- (void) lo_close(conn, lobj);
-
- return lobjOid;
-}
-
-/*
- * lo_export -
- * exports an (inversion) large object.
- * returns -1 upon failure, 1 otherwise
- */
-int
-lo_export(PGconn *conn, Oid lobjId, const char *filename)
-{
- int fd;
- int nbytes,
- tmp;
- char buf[LO_BUFSIZE];
- int lobj;
-
- /*
- * open the large object.
- */
- lobj = lo_open(conn, lobjId, INV_READ);
- if (lobj == -1)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could not open large object %u\n"), lobjId);
- return -1;
- }
-
- /*
- * create the file to be written to
- */
- fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC | PG_BINARY, 0666);
- if (fd < 0)
- { /* error */
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could not open file \"%s\": %s\n"),
- filename, strerror(errno));
- (void) lo_close(conn, lobj);
- return -1;
- }
-
- /*
- * read in from the Unix file and write to the inversion file
- */
- while ((nbytes = lo_read(conn, lobj, buf, LO_BUFSIZE)) > 0)
- {
- tmp = write(fd, buf, nbytes);
- if (tmp < nbytes)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("error while writing to file \"%s\"\n"),
- filename);
- (void) lo_close(conn, lobj);
- (void) close(fd);
- return -1;
- }
- }
-
- (void) lo_close(conn, lobj);
- (void) close(fd);
-
- return 1;
-}
-
-
-/*
- * lo_initialize
- *
- * Initialize the large object interface for an existing connection.
- * We ask the backend about the functions OID's in pg_proc for all
- * functions that are required for large object operations.
- */
-static int
-lo_initialize(PGconn *conn)
-{
- PGresult *res;
- PGlobjfuncs *lobjfuncs;
- int n;
- const char *fname;
- Oid foid;
-
- /*
- * Allocate the structure to hold the functions OID's
- */
- lobjfuncs = (PGlobjfuncs *) malloc(sizeof(PGlobjfuncs));
- if (lobjfuncs == (PGlobjfuncs *) NULL)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory\n"));
- return -1;
- }
- MemSet((char *) lobjfuncs, 0, sizeof(PGlobjfuncs));
-
- /*
- * Execute the query to get all the functions at once
- */
- res = PQexec(conn, "select proname, oid from pg_proc \
- where proname = 'lo_open' \
- or proname = 'lo_close' \
- or proname = 'lo_creat' \
- or proname = 'lo_unlink' \
- or proname = 'lo_lseek' \
- or proname = 'lo_tell' \
- or proname = 'loread' \
- or proname = 'lowrite'");
- if (res == (PGresult *) NULL)
- {
- free(lobjfuncs);
- return -1;
- }
-
- if (res->resultStatus != PGRES_TUPLES_OK)
- {
- free(lobjfuncs);
- PQclear(res);
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("query to initialize large object functions did not return data\n"));
- return -1;
- }
-
- /*
- * Examine the result and put the OID's into the struct
- */
- for (n = 0; n < PQntuples(res); n++)
- {
- fname = PQgetvalue(res, n, 0);
- foid = (Oid) atoi(PQgetvalue(res, n, 1));
- if (!strcmp(fname, "lo_open"))
- lobjfuncs->fn_lo_open = foid;
- else if (!strcmp(fname, "lo_close"))
- lobjfuncs->fn_lo_close = foid;
- else if (!strcmp(fname, "lo_creat"))
- lobjfuncs->fn_lo_creat = foid;
- else if (!strcmp(fname, "lo_unlink"))
- lobjfuncs->fn_lo_unlink = foid;
- else if (!strcmp(fname, "lo_lseek"))
- lobjfuncs->fn_lo_lseek = foid;
- else if (!strcmp(fname, "lo_tell"))
- lobjfuncs->fn_lo_tell = foid;
- else if (!strcmp(fname, "loread"))
- lobjfuncs->fn_lo_read = foid;
- else if (!strcmp(fname, "lowrite"))
- lobjfuncs->fn_lo_write = foid;
- }
-
- PQclear(res);
-
- /*
- * Finally check that we really got all large object interface
- * functions.
- */
- if (lobjfuncs->fn_lo_open == 0)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("cannot determine OID of function lo_open\n"));
- free(lobjfuncs);
- return -1;
- }
- if (lobjfuncs->fn_lo_close == 0)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("cannot determine OID of function lo_close\n"));
- free(lobjfuncs);
- return -1;
- }
- if (lobjfuncs->fn_lo_creat == 0)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("cannot determine OID of function lo_creat\n"));
- free(lobjfuncs);
- return -1;
- }
- if (lobjfuncs->fn_lo_unlink == 0)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("cannot determine OID of function lo_unlink\n"));
- free(lobjfuncs);
- return -1;
- }
- if (lobjfuncs->fn_lo_lseek == 0)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("cannot determine OID of function lo_lseek\n"));
- free(lobjfuncs);
- return -1;
- }
- if (lobjfuncs->fn_lo_tell == 0)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("cannot determine OID of function lo_tell\n"));
- free(lobjfuncs);
- return -1;
- }
- if (lobjfuncs->fn_lo_read == 0)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("cannot determine OID of function loread\n"));
- free(lobjfuncs);
- return -1;
- }
- if (lobjfuncs->fn_lo_write == 0)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("cannot determine OID of function lowrite\n"));
- free(lobjfuncs);
- return -1;
- }
-
- /*
- * Put the structure into the connection control
- */
- conn->lobjfuncs = lobjfuncs;
- return 0;
-}