Move routines to manipulate WAL into PostgreSQL::Test::Cluster
[pgsql.git] / src / interfaces / libpq / fe-lobj.c
blob45edbae6717fe44ce52bdd19b6c3a67d106660c0
1 /*-------------------------------------------------------------------------
3 * fe-lobj.c
4 * Front-end large object interface
6 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
10 * IDENTIFICATION
11 * src/interfaces/libpq/fe-lobj.c
13 *-------------------------------------------------------------------------
16 #ifdef WIN32
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
20 * here.
22 #include <io.h>
23 #endif
25 #include "postgres_fe.h"
27 #ifdef WIN32
28 #include "win32.h"
29 #else
30 #include <unistd.h>
31 #endif
33 #include <fcntl.h>
34 #include <limits.h>
35 #include <sys/stat.h>
37 #include "libpq-fe.h"
38 #include "libpq-int.h"
39 #include "libpq/libpq-fs.h" /* must come after sys/stat.h */
40 #include "port/pg_bswap.h"
42 #define LO_BUFSIZE 8192
44 static int lo_initialize(PGconn *conn);
45 static Oid lo_import_internal(PGconn *conn, const char *filename, Oid oid);
46 static pg_int64 lo_hton64(pg_int64 host64);
47 static pg_int64 lo_ntoh64(pg_int64 net64);
50 * lo_open
51 * opens an existing large object
53 * returns the file descriptor for use in later lo_* calls
54 * return -1 upon failure.
56 int
57 lo_open(PGconn *conn, Oid lobjId, int mode)
59 int fd;
60 int result_len;
61 PQArgBlock argv[2];
62 PGresult *res;
64 if (lo_initialize(conn) < 0)
65 return -1;
67 argv[0].isint = 1;
68 argv[0].len = 4;
69 argv[0].u.integer = lobjId;
71 argv[1].isint = 1;
72 argv[1].len = 4;
73 argv[1].u.integer = mode;
75 res = PQfn(conn, conn->lobjfuncs->fn_lo_open, &fd, &result_len, 1, argv, 2);
76 if (PQresultStatus(res) == PGRES_COMMAND_OK)
78 PQclear(res);
79 return fd;
81 else
83 PQclear(res);
84 return -1;
89 * lo_close
90 * closes an existing large object
92 * returns 0 upon success
93 * returns -1 upon failure.
95 int
96 lo_close(PGconn *conn, int fd)
98 PQArgBlock argv[1];
99 PGresult *res;
100 int retval;
101 int result_len;
103 if (lo_initialize(conn) < 0)
104 return -1;
106 argv[0].isint = 1;
107 argv[0].len = 4;
108 argv[0].u.integer = fd;
109 res = PQfn(conn, conn->lobjfuncs->fn_lo_close,
110 &retval, &result_len, 1, argv, 1);
111 if (PQresultStatus(res) == PGRES_COMMAND_OK)
113 PQclear(res);
114 return retval;
116 else
118 PQclear(res);
119 return -1;
124 * lo_truncate
125 * truncates an existing large object to the given size
127 * returns 0 upon success
128 * returns -1 upon failure
131 lo_truncate(PGconn *conn, int fd, size_t len)
133 PQArgBlock argv[2];
134 PGresult *res;
135 int retval;
136 int result_len;
138 if (lo_initialize(conn) < 0)
139 return -1;
141 /* Must check this on-the-fly because it's not there pre-8.3 */
142 if (conn->lobjfuncs->fn_lo_truncate == 0)
144 libpq_append_conn_error(conn, "cannot determine OID of function %s",
145 "lo_truncate");
146 return -1;
150 * Long ago, somebody thought it'd be a good idea to declare this function
151 * as taking size_t ... but the underlying backend function only accepts a
152 * signed int32 length. So throw error if the given value overflows
153 * int32. (A possible alternative is to automatically redirect the call
154 * to lo_truncate64; but if the caller wanted to rely on that backend
155 * function being available, he could have called lo_truncate64 for
156 * himself.)
158 if (len > (size_t) INT_MAX)
160 libpq_append_conn_error(conn, "argument of lo_truncate exceeds integer range");
161 return -1;
164 argv[0].isint = 1;
165 argv[0].len = 4;
166 argv[0].u.integer = fd;
168 argv[1].isint = 1;
169 argv[1].len = 4;
170 argv[1].u.integer = (int) len;
172 res = PQfn(conn, conn->lobjfuncs->fn_lo_truncate,
173 &retval, &result_len, 1, argv, 2);
175 if (PQresultStatus(res) == PGRES_COMMAND_OK)
177 PQclear(res);
178 return retval;
180 else
182 PQclear(res);
183 return -1;
188 * lo_truncate64
189 * truncates an existing large object to the given size
191 * returns 0 upon success
192 * returns -1 upon failure
195 lo_truncate64(PGconn *conn, int fd, pg_int64 len)
197 PQArgBlock argv[2];
198 PGresult *res;
199 int retval;
200 int result_len;
202 if (lo_initialize(conn) < 0)
203 return -1;
205 if (conn->lobjfuncs->fn_lo_truncate64 == 0)
207 libpq_append_conn_error(conn, "cannot determine OID of function %s",
208 "lo_truncate64");
209 return -1;
212 argv[0].isint = 1;
213 argv[0].len = 4;
214 argv[0].u.integer = fd;
216 len = lo_hton64(len);
217 argv[1].isint = 0;
218 argv[1].len = 8;
219 argv[1].u.ptr = (int *) &len;
221 res = PQfn(conn, conn->lobjfuncs->fn_lo_truncate64,
222 &retval, &result_len, 1, argv, 2);
224 if (PQresultStatus(res) == PGRES_COMMAND_OK)
226 PQclear(res);
227 return retval;
229 else
231 PQclear(res);
232 return -1;
237 * lo_read
238 * read len bytes of the large object into buf
240 * returns the number of bytes read, or -1 on failure.
241 * the CALLER must have allocated enough space to hold the result returned
245 lo_read(PGconn *conn, int fd, char *buf, size_t len)
247 PQArgBlock argv[2];
248 PGresult *res;
249 int result_len;
251 if (lo_initialize(conn) < 0)
252 return -1;
255 * Long ago, somebody thought it'd be a good idea to declare this function
256 * as taking size_t ... but the underlying backend function only accepts a
257 * signed int32 length. So throw error if the given value overflows
258 * int32.
260 if (len > (size_t) INT_MAX)
262 libpq_append_conn_error(conn, "argument of lo_read exceeds integer range");
263 return -1;
266 argv[0].isint = 1;
267 argv[0].len = 4;
268 argv[0].u.integer = fd;
270 argv[1].isint = 1;
271 argv[1].len = 4;
272 argv[1].u.integer = (int) len;
274 res = PQfn(conn, conn->lobjfuncs->fn_lo_read,
275 (void *) buf, &result_len, 0, argv, 2);
276 if (PQresultStatus(res) == PGRES_COMMAND_OK)
278 PQclear(res);
279 return result_len;
281 else
283 PQclear(res);
284 return -1;
289 * lo_write
290 * write len bytes of buf into the large object fd
292 * returns the number of bytes written, or -1 on failure.
295 lo_write(PGconn *conn, int fd, const char *buf, size_t len)
297 PQArgBlock argv[2];
298 PGresult *res;
299 int result_len;
300 int retval;
302 if (lo_initialize(conn) < 0)
303 return -1;
306 * Long ago, somebody thought it'd be a good idea to declare this function
307 * as taking size_t ... but the underlying backend function only accepts a
308 * signed int32 length. So throw error if the given value overflows
309 * int32.
311 if (len > (size_t) INT_MAX)
313 libpq_append_conn_error(conn, "argument of lo_write exceeds integer range");
314 return -1;
317 argv[0].isint = 1;
318 argv[0].len = 4;
319 argv[0].u.integer = fd;
321 argv[1].isint = 0;
322 argv[1].len = (int) len;
323 argv[1].u.ptr = (int *) unconstify(char *, buf);
325 res = PQfn(conn, conn->lobjfuncs->fn_lo_write,
326 &retval, &result_len, 1, argv, 2);
327 if (PQresultStatus(res) == PGRES_COMMAND_OK)
329 PQclear(res);
330 return retval;
332 else
334 PQclear(res);
335 return -1;
340 * lo_lseek
341 * change the current read or write location on a large object
344 lo_lseek(PGconn *conn, int fd, int offset, int whence)
346 PQArgBlock argv[3];
347 PGresult *res;
348 int retval;
349 int result_len;
351 if (lo_initialize(conn) < 0)
352 return -1;
354 argv[0].isint = 1;
355 argv[0].len = 4;
356 argv[0].u.integer = fd;
358 argv[1].isint = 1;
359 argv[1].len = 4;
360 argv[1].u.integer = offset;
362 argv[2].isint = 1;
363 argv[2].len = 4;
364 argv[2].u.integer = whence;
366 res = PQfn(conn, conn->lobjfuncs->fn_lo_lseek,
367 &retval, &result_len, 1, argv, 3);
368 if (PQresultStatus(res) == PGRES_COMMAND_OK)
370 PQclear(res);
371 return retval;
373 else
375 PQclear(res);
376 return -1;
381 * lo_lseek64
382 * change the current read or write location on a large object
384 pg_int64
385 lo_lseek64(PGconn *conn, int fd, pg_int64 offset, int whence)
387 PQArgBlock argv[3];
388 PGresult *res;
389 pg_int64 retval;
390 int result_len;
392 if (lo_initialize(conn) < 0)
393 return -1;
395 if (conn->lobjfuncs->fn_lo_lseek64 == 0)
397 libpq_append_conn_error(conn, "cannot determine OID of function %s",
398 "lo_lseek64");
399 return -1;
402 argv[0].isint = 1;
403 argv[0].len = 4;
404 argv[0].u.integer = fd;
406 offset = lo_hton64(offset);
407 argv[1].isint = 0;
408 argv[1].len = 8;
409 argv[1].u.ptr = (int *) &offset;
411 argv[2].isint = 1;
412 argv[2].len = 4;
413 argv[2].u.integer = whence;
415 res = PQfn(conn, conn->lobjfuncs->fn_lo_lseek64,
416 (void *) &retval, &result_len, 0, argv, 3);
417 if (PQresultStatus(res) == PGRES_COMMAND_OK && result_len == 8)
419 PQclear(res);
420 return lo_ntoh64(retval);
422 else
424 PQclear(res);
425 return -1;
430 * lo_creat
431 * create a new large object
432 * the mode is ignored (once upon a time it had a use)
434 * returns the oid of the large object created or
435 * InvalidOid upon failure
438 lo_creat(PGconn *conn, int mode)
440 PQArgBlock argv[1];
441 PGresult *res;
442 int retval;
443 int result_len;
445 if (lo_initialize(conn) < 0)
446 return InvalidOid;
448 argv[0].isint = 1;
449 argv[0].len = 4;
450 argv[0].u.integer = mode;
451 res = PQfn(conn, conn->lobjfuncs->fn_lo_creat,
452 &retval, &result_len, 1, argv, 1);
453 if (PQresultStatus(res) == PGRES_COMMAND_OK)
455 PQclear(res);
456 return (Oid) retval;
458 else
460 PQclear(res);
461 return InvalidOid;
466 * lo_create
467 * create a new large object
468 * if lobjId isn't InvalidOid, it specifies the OID to (attempt to) create
470 * returns the oid of the large object created or
471 * InvalidOid upon failure
474 lo_create(PGconn *conn, Oid lobjId)
476 PQArgBlock argv[1];
477 PGresult *res;
478 int retval;
479 int result_len;
481 if (lo_initialize(conn) < 0)
482 return InvalidOid;
484 /* Must check this on-the-fly because it's not there pre-8.1 */
485 if (conn->lobjfuncs->fn_lo_create == 0)
487 libpq_append_conn_error(conn, "cannot determine OID of function %s",
488 "lo_create");
489 return InvalidOid;
492 argv[0].isint = 1;
493 argv[0].len = 4;
494 argv[0].u.integer = lobjId;
495 res = PQfn(conn, conn->lobjfuncs->fn_lo_create,
496 &retval, &result_len, 1, argv, 1);
497 if (PQresultStatus(res) == PGRES_COMMAND_OK)
499 PQclear(res);
500 return (Oid) retval;
502 else
504 PQclear(res);
505 return InvalidOid;
511 * lo_tell
512 * returns the current seek location of the large object
515 lo_tell(PGconn *conn, int fd)
517 int retval;
518 PQArgBlock argv[1];
519 PGresult *res;
520 int result_len;
522 if (lo_initialize(conn) < 0)
523 return -1;
525 argv[0].isint = 1;
526 argv[0].len = 4;
527 argv[0].u.integer = fd;
529 res = PQfn(conn, conn->lobjfuncs->fn_lo_tell,
530 &retval, &result_len, 1, argv, 1);
531 if (PQresultStatus(res) == PGRES_COMMAND_OK)
533 PQclear(res);
534 return retval;
536 else
538 PQclear(res);
539 return -1;
544 * lo_tell64
545 * returns the current seek location of the large object
547 pg_int64
548 lo_tell64(PGconn *conn, int fd)
550 pg_int64 retval;
551 PQArgBlock argv[1];
552 PGresult *res;
553 int result_len;
555 if (lo_initialize(conn) < 0)
556 return -1;
558 if (conn->lobjfuncs->fn_lo_tell64 == 0)
560 libpq_append_conn_error(conn, "cannot determine OID of function %s",
561 "lo_tell64");
562 return -1;
565 argv[0].isint = 1;
566 argv[0].len = 4;
567 argv[0].u.integer = fd;
569 res = PQfn(conn, conn->lobjfuncs->fn_lo_tell64,
570 (void *) &retval, &result_len, 0, argv, 1);
571 if (PQresultStatus(res) == PGRES_COMMAND_OK && result_len == 8)
573 PQclear(res);
574 return lo_ntoh64(retval);
576 else
578 PQclear(res);
579 return -1;
584 * lo_unlink
585 * delete a file
589 lo_unlink(PGconn *conn, Oid lobjId)
591 PQArgBlock argv[1];
592 PGresult *res;
593 int result_len;
594 int retval;
596 if (lo_initialize(conn) < 0)
597 return -1;
599 argv[0].isint = 1;
600 argv[0].len = 4;
601 argv[0].u.integer = lobjId;
603 res = PQfn(conn, conn->lobjfuncs->fn_lo_unlink,
604 &retval, &result_len, 1, argv, 1);
605 if (PQresultStatus(res) == PGRES_COMMAND_OK)
607 PQclear(res);
608 return retval;
610 else
612 PQclear(res);
613 return -1;
618 * lo_import -
619 * imports a file as an (inversion) large object.
621 * returns the oid of that object upon success,
622 * returns InvalidOid upon failure
626 lo_import(PGconn *conn, const char *filename)
628 return lo_import_internal(conn, filename, InvalidOid);
632 * lo_import_with_oid -
633 * imports a file as an (inversion) large object.
634 * large object id can be specified.
636 * returns the oid of that object upon success,
637 * returns InvalidOid upon failure
641 lo_import_with_oid(PGconn *conn, const char *filename, Oid lobjId)
643 return lo_import_internal(conn, filename, lobjId);
646 static Oid
647 lo_import_internal(PGconn *conn, const char *filename, Oid oid)
649 int fd;
650 int nbytes,
651 tmp;
652 char buf[LO_BUFSIZE];
653 Oid lobjOid;
654 int lobj;
655 char sebuf[PG_STRERROR_R_BUFLEN];
657 if (conn == NULL)
658 return InvalidOid;
660 /* Since this is the beginning of a query cycle, reset the error state */
661 pqClearConnErrorState(conn);
664 * open the file to be read in
666 fd = open(filename, O_RDONLY | PG_BINARY, 0666);
667 if (fd < 0)
668 { /* error */
669 libpq_append_conn_error(conn, "could not open file \"%s\": %s",
670 filename, strerror_r(errno, sebuf, sizeof(sebuf)));
671 return InvalidOid;
675 * create an inversion object
677 if (oid == InvalidOid)
678 lobjOid = lo_creat(conn, INV_READ | INV_WRITE);
679 else
680 lobjOid = lo_create(conn, oid);
682 if (lobjOid == InvalidOid)
684 /* we assume lo_create() already set a suitable error message */
685 (void) close(fd);
686 return InvalidOid;
689 lobj = lo_open(conn, lobjOid, INV_WRITE);
690 if (lobj == -1)
692 /* we assume lo_open() already set a suitable error message */
693 (void) close(fd);
694 return InvalidOid;
698 * read in from the file and write to the large object
700 while ((nbytes = read(fd, buf, LO_BUFSIZE)) > 0)
702 tmp = lo_write(conn, lobj, buf, nbytes);
703 if (tmp != nbytes)
706 * If lo_write() failed, we are now in an aborted transaction so
707 * there's no need for lo_close(); furthermore, if we tried it
708 * we'd overwrite the useful error result with a useless one. So
709 * just nail the doors shut and get out of town.
711 (void) close(fd);
712 return InvalidOid;
716 if (nbytes < 0)
718 /* We must do lo_close before setting the errorMessage */
719 int save_errno = errno;
721 (void) lo_close(conn, lobj);
722 (void) close(fd);
723 /* deliberately overwrite any error from lo_close */
724 pqClearConnErrorState(conn);
725 libpq_append_conn_error(conn, "could not read from file \"%s\": %s",
726 filename,
727 strerror_r(save_errno, sebuf, sizeof(sebuf)));
728 return InvalidOid;
731 (void) close(fd);
733 if (lo_close(conn, lobj) != 0)
735 /* we assume lo_close() already set a suitable error message */
736 return InvalidOid;
739 return lobjOid;
743 * lo_export -
744 * exports an (inversion) large object.
745 * returns -1 upon failure, 1 if OK
748 lo_export(PGconn *conn, Oid lobjId, const char *filename)
750 int result = 1;
751 int fd;
752 int nbytes,
753 tmp;
754 char buf[LO_BUFSIZE];
755 int lobj;
756 char sebuf[PG_STRERROR_R_BUFLEN];
759 * open the large object.
761 lobj = lo_open(conn, lobjId, INV_READ);
762 if (lobj == -1)
764 /* we assume lo_open() already set a suitable error message */
765 return -1;
769 * create the file to be written to
771 fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC | PG_BINARY, 0666);
772 if (fd < 0)
774 /* We must do lo_close before setting the errorMessage */
775 int save_errno = errno;
777 (void) lo_close(conn, lobj);
778 /* deliberately overwrite any error from lo_close */
779 pqClearConnErrorState(conn);
780 libpq_append_conn_error(conn, "could not open file \"%s\": %s",
781 filename,
782 strerror_r(save_errno, sebuf, sizeof(sebuf)));
783 return -1;
787 * read in from the large object and write to the file
789 while ((nbytes = lo_read(conn, lobj, buf, LO_BUFSIZE)) > 0)
791 tmp = write(fd, buf, nbytes);
792 if (tmp != nbytes)
794 /* We must do lo_close before setting the errorMessage */
795 int save_errno = errno;
797 (void) lo_close(conn, lobj);
798 (void) close(fd);
799 /* deliberately overwrite any error from lo_close */
800 pqClearConnErrorState(conn);
801 libpq_append_conn_error(conn, "could not write to file \"%s\": %s",
802 filename,
803 strerror_r(save_errno, sebuf, sizeof(sebuf)));
804 return -1;
809 * If lo_read() failed, we are now in an aborted transaction so there's no
810 * need for lo_close(); furthermore, if we tried it we'd overwrite the
811 * useful error result with a useless one. So skip lo_close() if we got a
812 * failure result.
814 if (nbytes < 0 ||
815 lo_close(conn, lobj) != 0)
817 /* assume lo_read() or lo_close() left a suitable error message */
818 result = -1;
821 /* if we already failed, don't overwrite that msg with a close error */
822 if (close(fd) != 0 && result >= 0)
824 libpq_append_conn_error(conn, "could not write to file \"%s\": %s",
825 filename, strerror_r(errno, sebuf, sizeof(sebuf)));
826 result = -1;
829 return result;
834 * lo_initialize
836 * Initialize for a new large-object operation on an existing connection.
837 * Return 0 if OK, -1 on failure.
839 * If we haven't previously done so, we collect the function OIDs from
840 * pg_proc for all functions that are required for large object operations.
842 static int
843 lo_initialize(PGconn *conn)
845 PGresult *res;
846 PGlobjfuncs *lobjfuncs;
847 int n;
848 const char *query;
849 const char *fname;
850 Oid foid;
852 /* Nothing we can do with no connection */
853 if (conn == NULL)
854 return -1;
856 /* Since this is the beginning of a query cycle, reset the error state */
857 pqClearConnErrorState(conn);
859 /* Nothing else to do if we already collected info */
860 if (conn->lobjfuncs != NULL)
861 return 0;
864 * Allocate the structure to hold the function OIDs. We don't store it
865 * into the PGconn until it's successfully filled.
867 lobjfuncs = (PGlobjfuncs *) malloc(sizeof(PGlobjfuncs));
868 if (lobjfuncs == NULL)
870 libpq_append_conn_error(conn, "out of memory");
871 return -1;
873 MemSet((char *) lobjfuncs, 0, sizeof(PGlobjfuncs));
876 * Execute the query to get all the functions at once. (Not all of them
877 * may exist in older server versions.)
879 query = "select proname, oid from pg_catalog.pg_proc "
880 "where proname in ("
881 "'lo_open', "
882 "'lo_close', "
883 "'lo_creat', "
884 "'lo_create', "
885 "'lo_unlink', "
886 "'lo_lseek', "
887 "'lo_lseek64', "
888 "'lo_tell', "
889 "'lo_tell64', "
890 "'lo_truncate', "
891 "'lo_truncate64', "
892 "'loread', "
893 "'lowrite') "
894 "and pronamespace = (select oid from pg_catalog.pg_namespace "
895 "where nspname = 'pg_catalog')";
897 res = PQexec(conn, query);
898 if (res == NULL)
900 free(lobjfuncs);
901 return -1;
904 if (res->resultStatus != PGRES_TUPLES_OK)
906 free(lobjfuncs);
907 PQclear(res);
908 libpq_append_conn_error(conn, "query to initialize large object functions did not return data");
909 return -1;
913 * Examine the result and put the OID's into the struct
915 for (n = 0; n < PQntuples(res); n++)
917 fname = PQgetvalue(res, n, 0);
918 foid = (Oid) atoi(PQgetvalue(res, n, 1));
919 if (strcmp(fname, "lo_open") == 0)
920 lobjfuncs->fn_lo_open = foid;
921 else if (strcmp(fname, "lo_close") == 0)
922 lobjfuncs->fn_lo_close = foid;
923 else if (strcmp(fname, "lo_creat") == 0)
924 lobjfuncs->fn_lo_creat = foid;
925 else if (strcmp(fname, "lo_create") == 0)
926 lobjfuncs->fn_lo_create = foid;
927 else if (strcmp(fname, "lo_unlink") == 0)
928 lobjfuncs->fn_lo_unlink = foid;
929 else if (strcmp(fname, "lo_lseek") == 0)
930 lobjfuncs->fn_lo_lseek = foid;
931 else if (strcmp(fname, "lo_lseek64") == 0)
932 lobjfuncs->fn_lo_lseek64 = foid;
933 else if (strcmp(fname, "lo_tell") == 0)
934 lobjfuncs->fn_lo_tell = foid;
935 else if (strcmp(fname, "lo_tell64") == 0)
936 lobjfuncs->fn_lo_tell64 = foid;
937 else if (strcmp(fname, "lo_truncate") == 0)
938 lobjfuncs->fn_lo_truncate = foid;
939 else if (strcmp(fname, "lo_truncate64") == 0)
940 lobjfuncs->fn_lo_truncate64 = foid;
941 else if (strcmp(fname, "loread") == 0)
942 lobjfuncs->fn_lo_read = foid;
943 else if (strcmp(fname, "lowrite") == 0)
944 lobjfuncs->fn_lo_write = foid;
947 PQclear(res);
950 * Finally check that we got all required large object interface functions
951 * (ones that have been added later than the stone age are instead checked
952 * only if used)
954 if (lobjfuncs->fn_lo_open == 0)
956 libpq_append_conn_error(conn, "cannot determine OID of function %s",
957 "lo_open");
958 free(lobjfuncs);
959 return -1;
961 if (lobjfuncs->fn_lo_close == 0)
963 libpq_append_conn_error(conn, "cannot determine OID of function %s",
964 "lo_close");
965 free(lobjfuncs);
966 return -1;
968 if (lobjfuncs->fn_lo_creat == 0)
970 libpq_append_conn_error(conn, "cannot determine OID of function %s",
971 "lo_creat");
972 free(lobjfuncs);
973 return -1;
975 if (lobjfuncs->fn_lo_unlink == 0)
977 libpq_append_conn_error(conn, "cannot determine OID of function %s",
978 "lo_unlink");
979 free(lobjfuncs);
980 return -1;
982 if (lobjfuncs->fn_lo_lseek == 0)
984 libpq_append_conn_error(conn, "cannot determine OID of function %s",
985 "lo_lseek");
986 free(lobjfuncs);
987 return -1;
989 if (lobjfuncs->fn_lo_tell == 0)
991 libpq_append_conn_error(conn, "cannot determine OID of function %s",
992 "lo_tell");
993 free(lobjfuncs);
994 return -1;
996 if (lobjfuncs->fn_lo_read == 0)
998 libpq_append_conn_error(conn, "cannot determine OID of function %s",
999 "loread");
1000 free(lobjfuncs);
1001 return -1;
1003 if (lobjfuncs->fn_lo_write == 0)
1005 libpq_append_conn_error(conn, "cannot determine OID of function %s",
1006 "lowrite");
1007 free(lobjfuncs);
1008 return -1;
1012 * Put the structure into the connection control
1014 conn->lobjfuncs = lobjfuncs;
1015 return 0;
1019 * lo_hton64
1020 * converts a 64-bit integer from host byte order to network byte order
1022 static pg_int64
1023 lo_hton64(pg_int64 host64)
1025 union
1027 pg_int64 i64;
1028 uint32 i32[2];
1029 } swap;
1030 uint32 t;
1032 /* High order half first, since we're doing MSB-first */
1033 t = (uint32) (host64 >> 32);
1034 swap.i32[0] = pg_hton32(t);
1036 /* Now the low order half */
1037 t = (uint32) host64;
1038 swap.i32[1] = pg_hton32(t);
1040 return swap.i64;
1044 * lo_ntoh64
1045 * converts a 64-bit integer from network byte order to host byte order
1047 static pg_int64
1048 lo_ntoh64(pg_int64 net64)
1050 union
1052 pg_int64 i64;
1053 uint32 i32[2];
1054 } swap;
1055 pg_int64 result;
1057 swap.i64 = net64;
1059 result = (uint32) pg_ntoh32(swap.i32[0]);
1060 result <<= 32;
1061 result |= (uint32) pg_ntoh32(swap.i32[1]);
1063 return result;