1 /*-------------------------------------------------------------------------
4 * Front-end large object interface
6 * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * $PostgreSQL: pgsql/src/interfaces/libpq/fe-lobj.c,v 1.52 2004/12/31 22:03:50 pgsql Exp $
13 *-------------------------------------------------------------------------
18 * As unlink/rename are #define'd in port.h (via postgres_fe.h), io.h
19 * must be included first on MS C. Might as well do it for all WIN32's
25 #include "postgres_fe.h"
38 #include "libpq-int.h"
39 #include "libpq/libpq-fs.h" /* must come after sys/stat.h */
41 #define LO_BUFSIZE 8192
43 static int lo_initialize(PGconn *conn);
48 * opens an existing large object
50 * returns the file descriptor for use in later lo_* calls
51 * return -1 upon failure.
54 lo_open(PGconn *conn, Oid lobjId, int mode)
63 argv[0].u.integer = lobjId;
67 argv[1].u.integer = mode;
69 if (conn->lobjfuncs == NULL)
71 if (lo_initialize(conn) < 0)
75 res = PQfn(conn, conn->lobjfuncs->fn_lo_open, &fd, &result_len, 1, argv, 2);
76 if (PQresultStatus(res) == PGRES_COMMAND_OK)
80 /* have to do this to reset offset in shared fd cache */
81 /* but only if fd is valid */
82 if (fd >= 0 && lo_lseek(conn, fd, 0L, SEEK_SET) < 0)
95 * closes an existing large object
97 * returns 0 upon success
98 * returns -1 upon failure.
101 lo_close(PGconn *conn, int fd)
108 if (conn->lobjfuncs == NULL)
110 if (lo_initialize(conn) < 0)
116 argv[0].u.integer = fd;
117 res = PQfn(conn, conn->lobjfuncs->fn_lo_close,
118 &retval, &result_len, 1, argv, 1);
119 if (PQresultStatus(res) == PGRES_COMMAND_OK)
133 * read len bytes of the large object into buf
135 * returns the number of bytes read, or -1 on failure.
136 * the CALLER must have allocated enough space to hold the result returned
140 lo_read(PGconn *conn, int fd, char *buf, size_t len)
146 if (conn->lobjfuncs == NULL)
148 if (lo_initialize(conn) < 0)
154 argv[0].u.integer = fd;
158 argv[1].u.integer = len;
160 res = PQfn(conn, conn->lobjfuncs->fn_lo_read,
161 (int *) buf, &result_len, 0, argv, 2);
162 if (PQresultStatus(res) == PGRES_COMMAND_OK)
176 * write len bytes of buf into the large object fd
178 * returns the number of bytes written, or -1 on failure.
181 lo_write(PGconn *conn, int fd, char *buf, size_t len)
188 if (conn->lobjfuncs == NULL)
190 if (lo_initialize(conn) < 0)
199 argv[0].u.integer = fd;
203 argv[1].u.ptr = (int *) buf;
205 res = PQfn(conn, conn->lobjfuncs->fn_lo_write,
206 &retval, &result_len, 1, argv, 2);
207 if (PQresultStatus(res) == PGRES_COMMAND_OK)
221 * change the current read or write location on a large object
222 * currently, only L_SET is a legal value for whence
227 lo_lseek(PGconn *conn, int fd, int offset, int whence)
234 if (conn->lobjfuncs == NULL)
236 if (lo_initialize(conn) < 0)
242 argv[0].u.integer = fd;
246 argv[1].u.integer = offset;
250 argv[2].u.integer = whence;
252 res = PQfn(conn, conn->lobjfuncs->fn_lo_lseek,
253 &retval, &result_len, 1, argv, 3);
254 if (PQresultStatus(res) == PGRES_COMMAND_OK)
268 * create a new large object
269 * the mode is a bitmask describing different attributes of the new object
271 * returns the oid of the large object created or
272 * InvalidOid upon failure
276 lo_creat(PGconn *conn, int mode)
283 if (conn->lobjfuncs == NULL)
285 if (lo_initialize(conn) < 0)
291 argv[0].u.integer = mode;
292 res = PQfn(conn, conn->lobjfuncs->fn_lo_creat,
293 &retval, &result_len, 1, argv, 1);
294 if (PQresultStatus(res) == PGRES_COMMAND_OK)
309 * returns the current seek location of the large object
314 lo_tell(PGconn *conn, int fd)
321 if (conn->lobjfuncs == NULL)
323 if (lo_initialize(conn) < 0)
329 argv[0].u.integer = fd;
331 res = PQfn(conn, conn->lobjfuncs->fn_lo_tell,
332 &retval, &result_len, 1, argv, 1);
333 if (PQresultStatus(res) == PGRES_COMMAND_OK)
352 lo_unlink(PGconn *conn, Oid lobjId)
359 if (conn->lobjfuncs == NULL)
361 if (lo_initialize(conn) < 0)
367 argv[0].u.integer = lobjId;
369 res = PQfn(conn, conn->lobjfuncs->fn_lo_unlink,
370 &retval, &result_len, 1, argv, 1);
371 if (PQresultStatus(res) == PGRES_COMMAND_OK)
385 * imports a file as an (inversion) large object.
387 * returns the oid of that object upon success,
388 * returns InvalidOid upon failure
392 lo_import(PGconn *conn, const char *filename)
397 char buf[LO_BUFSIZE];
402 * open the file to be read in
404 fd = open(filename, O_RDONLY | PG_BINARY, 0666);
409 printfPQExpBuffer(&conn->errorMessage,
410 libpq_gettext("could not open file \"%s\": %s\n"),
411 filename, pqStrerror(errno, sebuf, sizeof(sebuf)));
416 * create an inversion "object"
418 lobjOid = lo_creat(conn, INV_READ | INV_WRITE);
419 if (lobjOid == InvalidOid)
421 printfPQExpBuffer(&conn->errorMessage,
422 libpq_gettext("could not create large object for file \"%s\"\n"),
428 lobj = lo_open(conn, lobjOid, INV_WRITE);
431 printfPQExpBuffer(&conn->errorMessage,
432 libpq_gettext("could not open large object %u\n"),
439 * read in from the Unix file and write to the inversion file
441 while ((nbytes = read(fd, buf, LO_BUFSIZE)) > 0)
443 tmp = lo_write(conn, lobj, buf, nbytes);
446 printfPQExpBuffer(&conn->errorMessage,
447 libpq_gettext("error while reading file \"%s\"\n"),
450 (void) lo_close(conn, lobj);
456 (void) lo_close(conn, lobj);
463 * exports an (inversion) large object.
464 * returns -1 upon failure, 1 otherwise
467 lo_export(PGconn *conn, Oid lobjId, const char *filename)
472 char buf[LO_BUFSIZE];
476 * open the large object.
478 lobj = lo_open(conn, lobjId, INV_READ);
481 printfPQExpBuffer(&conn->errorMessage,
482 libpq_gettext("could not open large object %u\n"), lobjId);
487 * create the file to be written to
489 fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC | PG_BINARY, 0666);
494 printfPQExpBuffer(&conn->errorMessage,
495 libpq_gettext("could not open file \"%s\": %s\n"),
496 filename, pqStrerror(errno, sebuf, sizeof(sebuf)));
497 (void) lo_close(conn, lobj);
502 * read in from the inversion file and write to the Unix file
504 while ((nbytes = lo_read(conn, lobj, buf, LO_BUFSIZE)) > 0)
506 tmp = write(fd, buf, nbytes);
509 printfPQExpBuffer(&conn->errorMessage,
510 libpq_gettext("error while writing to file \"%s\"\n"),
512 (void) lo_close(conn, lobj);
518 (void) lo_close(conn, lobj);
522 printfPQExpBuffer(&conn->errorMessage,
523 libpq_gettext("error while writing to file \"%s\"\n"),
535 * Initialize the large object interface for an existing connection.
536 * We ask the backend about the functions OID's in pg_proc for all
537 * functions that are required for large object operations.
540 lo_initialize(PGconn *conn)
543 PGlobjfuncs *lobjfuncs;
550 * Allocate the structure to hold the functions OID's
552 lobjfuncs = (PGlobjfuncs *) malloc(sizeof(PGlobjfuncs));
553 if (lobjfuncs == NULL)
555 printfPQExpBuffer(&conn->errorMessage,
556 libpq_gettext("out of memory\n"));
559 MemSet((char *) lobjfuncs, 0, sizeof(PGlobjfuncs));
562 * Execute the query to get all the functions at once. In 7.3 and
563 * later we need to be schema-safe.
565 if (conn->sversion >= 70300)
566 query = "select proname, oid from pg_catalog.pg_proc "
576 "and pronamespace = (select oid from pg_catalog.pg_namespace "
577 "where nspname = 'pg_catalog')";
579 query = "select proname, oid from pg_proc "
580 "where proname = 'lo_open' "
581 "or proname = 'lo_close' "
582 "or proname = 'lo_creat' "
583 "or proname = 'lo_unlink' "
584 "or proname = 'lo_lseek' "
585 "or proname = 'lo_tell' "
586 "or proname = 'loread' "
587 "or proname = 'lowrite'";
589 res = PQexec(conn, query);
596 if (res->resultStatus != PGRES_TUPLES_OK)
600 printfPQExpBuffer(&conn->errorMessage,
601 libpq_gettext("query to initialize large object functions did not return data\n"));
606 * Examine the result and put the OID's into the struct
608 for (n = 0; n < PQntuples(res); n++)
610 fname = PQgetvalue(res, n, 0);
611 foid = (Oid) atoi(PQgetvalue(res, n, 1));
612 if (!strcmp(fname, "lo_open"))
613 lobjfuncs->fn_lo_open = foid;
614 else if (!strcmp(fname, "lo_close"))
615 lobjfuncs->fn_lo_close = foid;
616 else if (!strcmp(fname, "lo_creat"))
617 lobjfuncs->fn_lo_creat = foid;
618 else if (!strcmp(fname, "lo_unlink"))
619 lobjfuncs->fn_lo_unlink = foid;
620 else if (!strcmp(fname, "lo_lseek"))
621 lobjfuncs->fn_lo_lseek = foid;
622 else if (!strcmp(fname, "lo_tell"))
623 lobjfuncs->fn_lo_tell = foid;
624 else if (!strcmp(fname, "loread"))
625 lobjfuncs->fn_lo_read = foid;
626 else if (!strcmp(fname, "lowrite"))
627 lobjfuncs->fn_lo_write = foid;
633 * Finally check that we really got all large object interface
636 if (lobjfuncs->fn_lo_open == 0)
638 printfPQExpBuffer(&conn->errorMessage,
639 libpq_gettext("cannot determine OID of function lo_open\n"));
643 if (lobjfuncs->fn_lo_close == 0)
645 printfPQExpBuffer(&conn->errorMessage,
646 libpq_gettext("cannot determine OID of function lo_close\n"));
650 if (lobjfuncs->fn_lo_creat == 0)
652 printfPQExpBuffer(&conn->errorMessage,
653 libpq_gettext("cannot determine OID of function lo_creat\n"));
657 if (lobjfuncs->fn_lo_unlink == 0)
659 printfPQExpBuffer(&conn->errorMessage,
660 libpq_gettext("cannot determine OID of function lo_unlink\n"));
664 if (lobjfuncs->fn_lo_lseek == 0)
666 printfPQExpBuffer(&conn->errorMessage,
667 libpq_gettext("cannot determine OID of function lo_lseek\n"));
671 if (lobjfuncs->fn_lo_tell == 0)
673 printfPQExpBuffer(&conn->errorMessage,
674 libpq_gettext("cannot determine OID of function lo_tell\n"));
678 if (lobjfuncs->fn_lo_read == 0)
680 printfPQExpBuffer(&conn->errorMessage,
681 libpq_gettext("cannot determine OID of function loread\n"));
685 if (lobjfuncs->fn_lo_write == 0)
687 printfPQExpBuffer(&conn->errorMessage,
688 libpq_gettext("cannot determine OID of function lowrite\n"));
694 * Put the structure into the connection control
696 conn->lobjfuncs = lobjfuncs;