PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
fe-lobj.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * fe-lobj.c
4  * Front-end large object interface
5  *
6  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  * src/interfaces/libpq/fe-lobj.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 
16 #ifdef WIN32
17 /*
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.
21  */
22 #include <io.h>
23 #endif
24 
25 #include "postgres_fe.h"
26 
27 #ifdef WIN32
28 #include "win32.h"
29 #else
30 #include <unistd.h>
31 #endif
32 
33 #include <fcntl.h>
34 #include <limits.h>
35 #include <sys/stat.h>
36 
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"
41 
42 #define LO_BUFSIZE 8192
43 
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);
48 
49 /*
50  * lo_open
51  * opens an existing large object
52  *
53  * returns the file descriptor for use in later lo_* calls
54  * return -1 upon failure.
55  */
56 int
57 lo_open(PGconn *conn, Oid lobjId, int mode)
58 {
59  int fd;
60  int result_len;
61  PQArgBlock argv[2];
62  PGresult *res;
63 
64  if (conn == NULL || conn->lobjfuncs == NULL)
65  {
66  if (lo_initialize(conn) < 0)
67  return -1;
68  }
69 
70  argv[0].isint = 1;
71  argv[0].len = 4;
72  argv[0].u.integer = lobjId;
73 
74  argv[1].isint = 1;
75  argv[1].len = 4;
76  argv[1].u.integer = mode;
77 
78  res = PQfn(conn, conn->lobjfuncs->fn_lo_open, &fd, &result_len, 1, argv, 2);
79  if (PQresultStatus(res) == PGRES_COMMAND_OK)
80  {
81  PQclear(res);
82  return fd;
83  }
84  else
85  {
86  PQclear(res);
87  return -1;
88  }
89 }
90 
91 /*
92  * lo_close
93  * closes an existing large object
94  *
95  * returns 0 upon success
96  * returns -1 upon failure.
97  */
98 int
100 {
101  PQArgBlock argv[1];
102  PGresult *res;
103  int retval;
104  int result_len;
105 
106  if (conn == NULL || conn->lobjfuncs == NULL)
107  {
108  if (lo_initialize(conn) < 0)
109  return -1;
110  }
111 
112  argv[0].isint = 1;
113  argv[0].len = 4;
114  argv[0].u.integer = fd;
115  res = PQfn(conn, conn->lobjfuncs->fn_lo_close,
116  &retval, &result_len, 1, argv, 1);
117  if (PQresultStatus(res) == PGRES_COMMAND_OK)
118  {
119  PQclear(res);
120  return retval;
121  }
122  else
123  {
124  PQclear(res);
125  return -1;
126  }
127 }
128 
129 /*
130  * lo_truncate
131  * truncates an existing large object to the given size
132  *
133  * returns 0 upon success
134  * returns -1 upon failure
135  */
136 int
137 lo_truncate(PGconn *conn, int fd, size_t len)
138 {
139  PQArgBlock argv[2];
140  PGresult *res;
141  int retval;
142  int result_len;
143 
144  if (conn == NULL || conn->lobjfuncs == NULL)
145  {
146  if (lo_initialize(conn) < 0)
147  return -1;
148  }
149 
150  /* Must check this on-the-fly because it's not there pre-8.3 */
151  if (conn->lobjfuncs->fn_lo_truncate == 0)
152  {
154  libpq_gettext("cannot determine OID of function lo_truncate\n"));
155  return -1;
156  }
157 
158  /*
159  * Long ago, somebody thought it'd be a good idea to declare this function
160  * as taking size_t ... but the underlying backend function only accepts a
161  * signed int32 length. So throw error if the given value overflows
162  * int32. (A possible alternative is to automatically redirect the call
163  * to lo_truncate64; but if the caller wanted to rely on that backend
164  * function being available, he could have called lo_truncate64 for
165  * himself.)
166  */
167  if (len > (size_t) INT_MAX)
168  {
170  libpq_gettext("argument of lo_truncate exceeds integer range\n"));
171  return -1;
172  }
173 
174  argv[0].isint = 1;
175  argv[0].len = 4;
176  argv[0].u.integer = fd;
177 
178  argv[1].isint = 1;
179  argv[1].len = 4;
180  argv[1].u.integer = (int) len;
181 
182  res = PQfn(conn, conn->lobjfuncs->fn_lo_truncate,
183  &retval, &result_len, 1, argv, 2);
184 
185  if (PQresultStatus(res) == PGRES_COMMAND_OK)
186  {
187  PQclear(res);
188  return retval;
189  }
190  else
191  {
192  PQclear(res);
193  return -1;
194  }
195 }
196 
197 /*
198  * lo_truncate64
199  * truncates an existing large object to the given size
200  *
201  * returns 0 upon success
202  * returns -1 upon failure
203  */
204 int
206 {
207  PQArgBlock argv[2];
208  PGresult *res;
209  int retval;
210  int result_len;
211 
212  if (conn == NULL || conn->lobjfuncs == NULL)
213  {
214  if (lo_initialize(conn) < 0)
215  return -1;
216  }
217 
218  if (conn->lobjfuncs->fn_lo_truncate64 == 0)
219  {
221  libpq_gettext("cannot determine OID of function lo_truncate64\n"));
222  return -1;
223  }
224 
225  argv[0].isint = 1;
226  argv[0].len = 4;
227  argv[0].u.integer = fd;
228 
229  len = lo_hton64(len);
230  argv[1].isint = 0;
231  argv[1].len = 8;
232  argv[1].u.ptr = (int *) &len;
233 
234  res = PQfn(conn, conn->lobjfuncs->fn_lo_truncate64,
235  &retval, &result_len, 1, argv, 2);
236 
237  if (PQresultStatus(res) == PGRES_COMMAND_OK)
238  {
239  PQclear(res);
240  return retval;
241  }
242  else
243  {
244  PQclear(res);
245  return -1;
246  }
247 }
248 
249 /*
250  * lo_read
251  * read len bytes of the large object into buf
252  *
253  * returns the number of bytes read, or -1 on failure.
254  * the CALLER must have allocated enough space to hold the result returned
255  */
256 
257 int
258 lo_read(PGconn *conn, int fd, char *buf, size_t len)
259 {
260  PQArgBlock argv[2];
261  PGresult *res;
262  int result_len;
263 
264  if (conn == NULL || conn->lobjfuncs == NULL)
265  {
266  if (lo_initialize(conn) < 0)
267  return -1;
268  }
269 
270  /*
271  * Long ago, somebody thought it'd be a good idea to declare this function
272  * as taking size_t ... but the underlying backend function only accepts a
273  * signed int32 length. So throw error if the given value overflows
274  * int32.
275  */
276  if (len > (size_t) INT_MAX)
277  {
279  libpq_gettext("argument of lo_read exceeds integer range\n"));
280  return -1;
281  }
282 
283  argv[0].isint = 1;
284  argv[0].len = 4;
285  argv[0].u.integer = fd;
286 
287  argv[1].isint = 1;
288  argv[1].len = 4;
289  argv[1].u.integer = (int) len;
290 
291  res = PQfn(conn, conn->lobjfuncs->fn_lo_read,
292  (void *) buf, &result_len, 0, argv, 2);
293  if (PQresultStatus(res) == PGRES_COMMAND_OK)
294  {
295  PQclear(res);
296  return result_len;
297  }
298  else
299  {
300  PQclear(res);
301  return -1;
302  }
303 }
304 
305 /*
306  * lo_write
307  * write len bytes of buf into the large object fd
308  *
309  * returns the number of bytes written, or -1 on failure.
310  */
311 int
312 lo_write(PGconn *conn, int fd, const char *buf, size_t len)
313 {
314  PQArgBlock argv[2];
315  PGresult *res;
316  int result_len;
317  int retval;
318 
319  if (conn == NULL || conn->lobjfuncs == NULL)
320  {
321  if (lo_initialize(conn) < 0)
322  return -1;
323  }
324 
325  /*
326  * Long ago, somebody thought it'd be a good idea to declare this function
327  * as taking size_t ... but the underlying backend function only accepts a
328  * signed int32 length. So throw error if the given value overflows
329  * int32.
330  */
331  if (len > (size_t) INT_MAX)
332  {
334  libpq_gettext("argument of lo_write exceeds integer range\n"));
335  return -1;
336  }
337 
338  argv[0].isint = 1;
339  argv[0].len = 4;
340  argv[0].u.integer = fd;
341 
342  argv[1].isint = 0;
343  argv[1].len = (int) len;
344  argv[1].u.ptr = (int *) buf;
345 
346  res = PQfn(conn, conn->lobjfuncs->fn_lo_write,
347  &retval, &result_len, 1, argv, 2);
348  if (PQresultStatus(res) == PGRES_COMMAND_OK)
349  {
350  PQclear(res);
351  return retval;
352  }
353  else
354  {
355  PQclear(res);
356  return -1;
357  }
358 }
359 
360 /*
361  * lo_lseek
362  * change the current read or write location on a large object
363  */
364 int
365 lo_lseek(PGconn *conn, int fd, int offset, int whence)
366 {
367  PQArgBlock argv[3];
368  PGresult *res;
369  int retval;
370  int result_len;
371 
372  if (conn == NULL || conn->lobjfuncs == NULL)
373  {
374  if (lo_initialize(conn) < 0)
375  return -1;
376  }
377 
378  argv[0].isint = 1;
379  argv[0].len = 4;
380  argv[0].u.integer = fd;
381 
382  argv[1].isint = 1;
383  argv[1].len = 4;
384  argv[1].u.integer = offset;
385 
386  argv[2].isint = 1;
387  argv[2].len = 4;
388  argv[2].u.integer = whence;
389 
390  res = PQfn(conn, conn->lobjfuncs->fn_lo_lseek,
391  &retval, &result_len, 1, argv, 3);
392  if (PQresultStatus(res) == PGRES_COMMAND_OK)
393  {
394  PQclear(res);
395  return retval;
396  }
397  else
398  {
399  PQclear(res);
400  return -1;
401  }
402 }
403 
404 /*
405  * lo_lseek64
406  * change the current read or write location on a large object
407  */
408 pg_int64
409 lo_lseek64(PGconn *conn, int fd, pg_int64 offset, int whence)
410 {
411  PQArgBlock argv[3];
412  PGresult *res;
413  pg_int64 retval;
414  int result_len;
415 
416  if (conn == NULL || conn->lobjfuncs == NULL)
417  {
418  if (lo_initialize(conn) < 0)
419  return -1;
420  }
421 
422  if (conn->lobjfuncs->fn_lo_lseek64 == 0)
423  {
425  libpq_gettext("cannot determine OID of function lo_lseek64\n"));
426  return -1;
427  }
428 
429  argv[0].isint = 1;
430  argv[0].len = 4;
431  argv[0].u.integer = fd;
432 
433  offset = lo_hton64(offset);
434  argv[1].isint = 0;
435  argv[1].len = 8;
436  argv[1].u.ptr = (int *) &offset;
437 
438  argv[2].isint = 1;
439  argv[2].len = 4;
440  argv[2].u.integer = whence;
441 
442  res = PQfn(conn, conn->lobjfuncs->fn_lo_lseek64,
443  (void *) &retval, &result_len, 0, argv, 3);
444  if (PQresultStatus(res) == PGRES_COMMAND_OK && result_len == 8)
445  {
446  PQclear(res);
447  return lo_ntoh64(retval);
448  }
449  else
450  {
451  PQclear(res);
452  return -1;
453  }
454 }
455 
456 /*
457  * lo_creat
458  * create a new large object
459  * the mode is ignored (once upon a time it had a use)
460  *
461  * returns the oid of the large object created or
462  * InvalidOid upon failure
463  */
464 Oid
465 lo_creat(PGconn *conn, int mode)
466 {
467  PQArgBlock argv[1];
468  PGresult *res;
469  int retval;
470  int result_len;
471 
472  if (conn == NULL || conn->lobjfuncs == NULL)
473  {
474  if (lo_initialize(conn) < 0)
475  return InvalidOid;
476  }
477 
478  argv[0].isint = 1;
479  argv[0].len = 4;
480  argv[0].u.integer = mode;
481  res = PQfn(conn, conn->lobjfuncs->fn_lo_creat,
482  &retval, &result_len, 1, argv, 1);
483  if (PQresultStatus(res) == PGRES_COMMAND_OK)
484  {
485  PQclear(res);
486  return (Oid) retval;
487  }
488  else
489  {
490  PQclear(res);
491  return InvalidOid;
492  }
493 }
494 
495 /*
496  * lo_create
497  * create a new large object
498  * if lobjId isn't InvalidOid, it specifies the OID to (attempt to) create
499  *
500  * returns the oid of the large object created or
501  * InvalidOid upon failure
502  */
503 Oid
505 {
506  PQArgBlock argv[1];
507  PGresult *res;
508  int retval;
509  int result_len;
510 
511  if (conn == NULL || conn->lobjfuncs == NULL)
512  {
513  if (lo_initialize(conn) < 0)
514  return InvalidOid;
515  }
516 
517  /* Must check this on-the-fly because it's not there pre-8.1 */
518  if (conn->lobjfuncs->fn_lo_create == 0)
519  {
521  libpq_gettext("cannot determine OID of function lo_create\n"));
522  return InvalidOid;
523  }
524 
525  argv[0].isint = 1;
526  argv[0].len = 4;
527  argv[0].u.integer = lobjId;
528  res = PQfn(conn, conn->lobjfuncs->fn_lo_create,
529  &retval, &result_len, 1, argv, 1);
530  if (PQresultStatus(res) == PGRES_COMMAND_OK)
531  {
532  PQclear(res);
533  return (Oid) retval;
534  }
535  else
536  {
537  PQclear(res);
538  return InvalidOid;
539  }
540 }
541 
542 
543 /*
544  * lo_tell
545  * returns the current seek location of the large object
546  */
547 int
549 {
550  int retval;
551  PQArgBlock argv[1];
552  PGresult *res;
553  int result_len;
554 
555  if (conn == NULL || conn->lobjfuncs == NULL)
556  {
557  if (lo_initialize(conn) < 0)
558  return -1;
559  }
560 
561  argv[0].isint = 1;
562  argv[0].len = 4;
563  argv[0].u.integer = fd;
564 
565  res = PQfn(conn, conn->lobjfuncs->fn_lo_tell,
566  &retval, &result_len, 1, argv, 1);
567  if (PQresultStatus(res) == PGRES_COMMAND_OK)
568  {
569  PQclear(res);
570  return retval;
571  }
572  else
573  {
574  PQclear(res);
575  return -1;
576  }
577 }
578 
579 /*
580  * lo_tell64
581  * returns the current seek location of the large object
582  */
583 pg_int64
585 {
586  pg_int64 retval;
587  PQArgBlock argv[1];
588  PGresult *res;
589  int result_len;
590 
591  if (conn == NULL || conn->lobjfuncs == NULL)
592  {
593  if (lo_initialize(conn) < 0)
594  return -1;
595  }
596 
597  if (conn->lobjfuncs->fn_lo_tell64 == 0)
598  {
600  libpq_gettext("cannot determine OID of function lo_tell64\n"));
601  return -1;
602  }
603 
604  argv[0].isint = 1;
605  argv[0].len = 4;
606  argv[0].u.integer = fd;
607 
608  res = PQfn(conn, conn->lobjfuncs->fn_lo_tell64,
609  (void *) &retval, &result_len, 0, argv, 1);
610  if (PQresultStatus(res) == PGRES_COMMAND_OK && result_len == 8)
611  {
612  PQclear(res);
613  return lo_ntoh64(retval);
614  }
615  else
616  {
617  PQclear(res);
618  return -1;
619  }
620 }
621 
622 /*
623  * lo_unlink
624  * delete a file
625  */
626 
627 int
629 {
630  PQArgBlock argv[1];
631  PGresult *res;
632  int result_len;
633  int retval;
634 
635  if (conn == NULL || conn->lobjfuncs == NULL)
636  {
637  if (lo_initialize(conn) < 0)
638  return -1;
639  }
640 
641  argv[0].isint = 1;
642  argv[0].len = 4;
643  argv[0].u.integer = lobjId;
644 
645  res = PQfn(conn, conn->lobjfuncs->fn_lo_unlink,
646  &retval, &result_len, 1, argv, 1);
647  if (PQresultStatus(res) == PGRES_COMMAND_OK)
648  {
649  PQclear(res);
650  return retval;
651  }
652  else
653  {
654  PQclear(res);
655  return -1;
656  }
657 }
658 
659 /*
660  * lo_import -
661  * imports a file as an (inversion) large object.
662  *
663  * returns the oid of that object upon success,
664  * returns InvalidOid upon failure
665  */
666 
667 Oid
669 {
670  return lo_import_internal(conn, filename, InvalidOid);
671 }
672 
673 /*
674  * lo_import_with_oid -
675  * imports a file as an (inversion) large object.
676  * large object id can be specified.
677  *
678  * returns the oid of that object upon success,
679  * returns InvalidOid upon failure
680  */
681 
682 Oid
683 lo_import_with_oid(PGconn *conn, const char *filename, Oid lobjId)
684 {
685  return lo_import_internal(conn, filename, lobjId);
686 }
687 
688 static Oid
690 {
691  int fd;
692  int nbytes,
693  tmp;
694  char buf[LO_BUFSIZE];
695  Oid lobjOid;
696  int lobj;
697  char sebuf[256];
698 
699  /*
700  * open the file to be read in
701  */
702  fd = open(filename, O_RDONLY | PG_BINARY, 0666);
703  if (fd < 0)
704  { /* error */
706  libpq_gettext("could not open file \"%s\": %s\n"),
707  filename, pqStrerror(errno, sebuf, sizeof(sebuf)));
708  return InvalidOid;
709  }
710 
711  /*
712  * create an inversion object
713  */
714  if (oid == InvalidOid)
715  lobjOid = lo_creat(conn, INV_READ | INV_WRITE);
716  else
717  lobjOid = lo_create(conn, oid);
718 
719  if (lobjOid == InvalidOid)
720  {
721  /* we assume lo_create() already set a suitable error message */
722  (void) close(fd);
723  return InvalidOid;
724  }
725 
726  lobj = lo_open(conn, lobjOid, INV_WRITE);
727  if (lobj == -1)
728  {
729  /* we assume lo_open() already set a suitable error message */
730  (void) close(fd);
731  return InvalidOid;
732  }
733 
734  /*
735  * read in from the file and write to the large object
736  */
737  while ((nbytes = read(fd, buf, LO_BUFSIZE)) > 0)
738  {
739  tmp = lo_write(conn, lobj, buf, nbytes);
740  if (tmp != nbytes)
741  {
742  /*
743  * If lo_write() failed, we are now in an aborted transaction so
744  * there's no need for lo_close(); furthermore, if we tried it
745  * we'd overwrite the useful error result with a useless one. So
746  * just nail the doors shut and get out of town.
747  */
748  (void) close(fd);
749  return InvalidOid;
750  }
751  }
752 
753  if (nbytes < 0)
754  {
755  /* We must do lo_close before setting the errorMessage */
756  int save_errno = errno;
757 
758  (void) lo_close(conn, lobj);
759  (void) close(fd);
761  libpq_gettext("could not read from file \"%s\": %s\n"),
762  filename,
763  pqStrerror(save_errno, sebuf, sizeof(sebuf)));
764  return InvalidOid;
765  }
766 
767  (void) close(fd);
768 
769  if (lo_close(conn, lobj) != 0)
770  {
771  /* we assume lo_close() already set a suitable error message */
772  return InvalidOid;
773  }
774 
775  return lobjOid;
776 }
777 
778 /*
779  * lo_export -
780  * exports an (inversion) large object.
781  * returns -1 upon failure, 1 if OK
782  */
783 int
784 lo_export(PGconn *conn, Oid lobjId, const char *filename)
785 {
786  int result = 1;
787  int fd;
788  int nbytes,
789  tmp;
790  char buf[LO_BUFSIZE];
791  int lobj;
792  char sebuf[256];
793 
794  /*
795  * open the large object.
796  */
797  lobj = lo_open(conn, lobjId, INV_READ);
798  if (lobj == -1)
799  {
800  /* we assume lo_open() already set a suitable error message */
801  return -1;
802  }
803 
804  /*
805  * create the file to be written to
806  */
807  fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC | PG_BINARY, 0666);
808  if (fd < 0)
809  {
810  /* We must do lo_close before setting the errorMessage */
811  int save_errno = errno;
812 
813  (void) lo_close(conn, lobj);
815  libpq_gettext("could not open file \"%s\": %s\n"),
816  filename,
817  pqStrerror(save_errno, sebuf, sizeof(sebuf)));
818  return -1;
819  }
820 
821  /*
822  * read in from the large object and write to the file
823  */
824  while ((nbytes = lo_read(conn, lobj, buf, LO_BUFSIZE)) > 0)
825  {
826  tmp = write(fd, buf, nbytes);
827  if (tmp != nbytes)
828  {
829  /* We must do lo_close before setting the errorMessage */
830  int save_errno = errno;
831 
832  (void) lo_close(conn, lobj);
833  (void) close(fd);
835  libpq_gettext("could not write to file \"%s\": %s\n"),
836  filename,
837  pqStrerror(save_errno, sebuf, sizeof(sebuf)));
838  return -1;
839  }
840  }
841 
842  /*
843  * If lo_read() failed, we are now in an aborted transaction so there's no
844  * need for lo_close(); furthermore, if we tried it we'd overwrite the
845  * useful error result with a useless one. So skip lo_close() if we got a
846  * failure result.
847  */
848  if (nbytes < 0 ||
849  lo_close(conn, lobj) != 0)
850  {
851  /* assume lo_read() or lo_close() left a suitable error message */
852  result = -1;
853  }
854 
855  /* if we already failed, don't overwrite that msg with a close error */
856  if (close(fd) && result >= 0)
857  {
859  libpq_gettext("could not write to file \"%s\": %s\n"),
860  filename, pqStrerror(errno, sebuf, sizeof(sebuf)));
861  result = -1;
862  }
863 
864  return result;
865 }
866 
867 
868 /*
869  * lo_initialize
870  *
871  * Initialize the large object interface for an existing connection.
872  * We ask the backend about the functions OID's in pg_proc for all
873  * functions that are required for large object operations.
874  */
875 static int
877 {
878  PGresult *res;
879  PGlobjfuncs *lobjfuncs;
880  int n;
881  const char *query;
882  const char *fname;
883  Oid foid;
884 
885  if (!conn)
886  return -1;
887 
888  /*
889  * Allocate the structure to hold the functions OID's
890  */
891  lobjfuncs = (PGlobjfuncs *) malloc(sizeof(PGlobjfuncs));
892  if (lobjfuncs == NULL)
893  {
895  libpq_gettext("out of memory\n"));
896  return -1;
897  }
898  MemSet((char *) lobjfuncs, 0, sizeof(PGlobjfuncs));
899 
900  /*
901  * Execute the query to get all the functions at once. In 7.3 and later
902  * we need to be schema-safe. lo_create only exists in 8.1 and up.
903  * lo_truncate only exists in 8.3 and up.
904  */
905  if (conn->sversion >= 70300)
906  query = "select proname, oid from pg_catalog.pg_proc "
907  "where proname in ("
908  "'lo_open', "
909  "'lo_close', "
910  "'lo_creat', "
911  "'lo_create', "
912  "'lo_unlink', "
913  "'lo_lseek', "
914  "'lo_lseek64', "
915  "'lo_tell', "
916  "'lo_tell64', "
917  "'lo_truncate', "
918  "'lo_truncate64', "
919  "'loread', "
920  "'lowrite') "
921  "and pronamespace = (select oid from pg_catalog.pg_namespace "
922  "where nspname = 'pg_catalog')";
923  else
924  query = "select proname, oid from pg_proc "
925  "where proname = 'lo_open' "
926  "or proname = 'lo_close' "
927  "or proname = 'lo_creat' "
928  "or proname = 'lo_unlink' "
929  "or proname = 'lo_lseek' "
930  "or proname = 'lo_tell' "
931  "or proname = 'loread' "
932  "or proname = 'lowrite'";
933 
934  res = PQexec(conn, query);
935  if (res == NULL)
936  {
937  free(lobjfuncs);
938  return -1;
939  }
940 
941  if (res->resultStatus != PGRES_TUPLES_OK)
942  {
943  free(lobjfuncs);
944  PQclear(res);
946  libpq_gettext("query to initialize large object functions did not return data\n"));
947  return -1;
948  }
949 
950  /*
951  * Examine the result and put the OID's into the struct
952  */
953  for (n = 0; n < PQntuples(res); n++)
954  {
955  fname = PQgetvalue(res, n, 0);
956  foid = (Oid) atoi(PQgetvalue(res, n, 1));
957  if (strcmp(fname, "lo_open") == 0)
958  lobjfuncs->fn_lo_open = foid;
959  else if (strcmp(fname, "lo_close") == 0)
960  lobjfuncs->fn_lo_close = foid;
961  else if (strcmp(fname, "lo_creat") == 0)
962  lobjfuncs->fn_lo_creat = foid;
963  else if (strcmp(fname, "lo_create") == 0)
964  lobjfuncs->fn_lo_create = foid;
965  else if (strcmp(fname, "lo_unlink") == 0)
966  lobjfuncs->fn_lo_unlink = foid;
967  else if (strcmp(fname, "lo_lseek") == 0)
968  lobjfuncs->fn_lo_lseek = foid;
969  else if (strcmp(fname, "lo_lseek64") == 0)
970  lobjfuncs->fn_lo_lseek64 = foid;
971  else if (strcmp(fname, "lo_tell") == 0)
972  lobjfuncs->fn_lo_tell = foid;
973  else if (strcmp(fname, "lo_tell64") == 0)
974  lobjfuncs->fn_lo_tell64 = foid;
975  else if (strcmp(fname, "lo_truncate") == 0)
976  lobjfuncs->fn_lo_truncate = foid;
977  else if (strcmp(fname, "lo_truncate64") == 0)
978  lobjfuncs->fn_lo_truncate64 = foid;
979  else if (strcmp(fname, "loread") == 0)
980  lobjfuncs->fn_lo_read = foid;
981  else if (strcmp(fname, "lowrite") == 0)
982  lobjfuncs->fn_lo_write = foid;
983  }
984 
985  PQclear(res);
986 
987  /*
988  * Finally check that we got all required large object interface functions
989  * (ones that have been added later than the stone age are instead checked
990  * only if used)
991  */
992  if (lobjfuncs->fn_lo_open == 0)
993  {
995  libpq_gettext("cannot determine OID of function lo_open\n"));
996  free(lobjfuncs);
997  return -1;
998  }
999  if (lobjfuncs->fn_lo_close == 0)
1000  {
1002  libpq_gettext("cannot determine OID of function lo_close\n"));
1003  free(lobjfuncs);
1004  return -1;
1005  }
1006  if (lobjfuncs->fn_lo_creat == 0)
1007  {
1009  libpq_gettext("cannot determine OID of function lo_creat\n"));
1010  free(lobjfuncs);
1011  return -1;
1012  }
1013  if (lobjfuncs->fn_lo_unlink == 0)
1014  {
1016  libpq_gettext("cannot determine OID of function lo_unlink\n"));
1017  free(lobjfuncs);
1018  return -1;
1019  }
1020  if (lobjfuncs->fn_lo_lseek == 0)
1021  {
1023  libpq_gettext("cannot determine OID of function lo_lseek\n"));
1024  free(lobjfuncs);
1025  return -1;
1026  }
1027  if (lobjfuncs->fn_lo_tell == 0)
1028  {
1030  libpq_gettext("cannot determine OID of function lo_tell\n"));
1031  free(lobjfuncs);
1032  return -1;
1033  }
1034  if (lobjfuncs->fn_lo_read == 0)
1035  {
1037  libpq_gettext("cannot determine OID of function loread\n"));
1038  free(lobjfuncs);
1039  return -1;
1040  }
1041  if (lobjfuncs->fn_lo_write == 0)
1042  {
1044  libpq_gettext("cannot determine OID of function lowrite\n"));
1045  free(lobjfuncs);
1046  return -1;
1047  }
1048 
1049  /*
1050  * Put the structure into the connection control
1051  */
1052  conn->lobjfuncs = lobjfuncs;
1053  return 0;
1054 }
1055 
1056 /*
1057  * lo_hton64
1058  * converts a 64-bit integer from host byte order to network byte order
1059  */
1060 static pg_int64
1062 {
1063  union
1064  {
1065  pg_int64 i64;
1066  uint32 i32[2];
1067  } swap;
1068  uint32 t;
1069 
1070  /* High order half first, since we're doing MSB-first */
1071  t = (uint32) (host64 >> 32);
1072  swap.i32[0] = pg_hton32(t);
1073 
1074  /* Now the low order half */
1075  t = (uint32) host64;
1076  swap.i32[1] = pg_hton32(t);
1077 
1078  return swap.i64;
1079 }
1080 
1081 /*
1082  * lo_ntoh64
1083  * converts a 64-bit integer from network byte order to host byte order
1084  */
1085 static pg_int64
1087 {
1088  union
1089  {
1090  pg_int64 i64;
1091  uint32 i32[2];
1092  } swap;
1093  pg_int64 result;
1094 
1095  swap.i64 = net64;
1096 
1097  result = (uint32) pg_ntoh32(swap.i32[0]);
1098  result <<= 32;
1099  result |= (uint32) pg_ntoh32(swap.i32[1]);
1100 
1101  return result;
1102 }
int lo_write(PGconn *conn, int fd, const char *buf, size_t len)
Definition: fe-lobj.c:312
union PQArgBlock::@139 u
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
#define swap(a, b)
Definition: qsort.c:94
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3118
pg_int64 lo_lseek64(PGconn *conn, int fd, pg_int64 offset, int whence)
Definition: fe-lobj.c:409
Oid fn_lo_write
Definition: libpq-int.h:279
#define write(a, b, c)
Definition: win32.h:14
int lo_lseek(PGconn *conn, int fd, int offset, int whence)
Definition: fe-lobj.c:365
int lo_unlink(PGconn *conn, Oid lobjId)
Definition: fe-lobj.c:628
Oid fn_lo_create
Definition: libpq-int.h:270
char * pqStrerror(int errnum, char *strerrbuf, size_t buflen)
Definition: thread.c:61
Oid fn_lo_lseek
Definition: libpq-int.h:272
#define MemSet(start, val, len)
Definition: c.h:863
unsigned int Oid
Definition: postgres_ext.h:31
int PQntuples(const PGresult *res)
Definition: fe-exec.c:2724
PGresult * PQfn(PGconn *conn, int fnid, int *result_buf, int *result_len, int result_is_int, const PQArgBlock *args, int nargs)
Definition: fe-exec.c:2607
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define PG_BINARY
Definition: c.h:1044
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:2647
PG_INT64_TYPE pg_int64
Definition: postgres_ext.h:47
pg_int64 lo_tell64(PGconn *conn, int fd)
Definition: fe-lobj.c:584
#define malloc(a)
Definition: header.h:50
int sversion
Definition: libpq-int.h:405
#define INV_READ
Definition: libpq-fs.h:22
int lo_close(PGconn *conn, int fd)
Definition: fe-lobj.c:99
#define pg_ntoh32(x)
Definition: pg_bswap.h:125
#define pg_hton32(x)
Definition: pg_bswap.h:121
PGconn * conn
Definition: streamutil.c:46
Oid fn_lo_read
Definition: libpq-int.h:278
Oid fn_lo_truncate
Definition: libpq-int.h:276
int lo_tell(PGconn *conn, int fd)
Definition: fe-lobj.c:548
int lo_export(PGconn *conn, Oid lobjId, const char *filename)
Definition: fe-lobj.c:784
static char * buf
Definition: pg_test_fsync.c:67
Oid fn_lo_open
Definition: libpq-int.h:267
static Oid lo_import_internal(PGconn *conn, const char *filename, Oid oid)
Definition: fe-lobj.c:689
unsigned int uint32
Definition: c.h:258
Oid fn_lo_tell64
Definition: libpq-int.h:275
static pg_int64 lo_hton64(pg_int64 host64)
Definition: fe-lobj.c:1061
int lo_open(PGconn *conn, Oid lobjId, int mode)
Definition: fe-lobj.c:57
Oid fn_lo_truncate64
Definition: libpq-int.h:277
int lo_truncate64(PGconn *conn, int fd, pg_int64 len)
Definition: fe-lobj.c:205
PQExpBufferData errorMessage
Definition: libpq-int.h:491
#define InvalidOid
Definition: postgres_ext.h:36
Oid fn_lo_tell
Definition: libpq-int.h:274
void PQclear(PGresult *res)
Definition: fe-exec.c:671
#define free(a)
Definition: header.h:65
Oid lo_create(PGconn *conn, Oid lobjId)
Definition: fe-lobj.c:504
#define LO_BUFSIZE
Definition: fe-lobj.c:42
Oid lo_import_with_oid(PGconn *conn, const char *filename, Oid lobjId)
Definition: fe-lobj.c:683
Oid fn_lo_creat
Definition: libpq-int.h:269
Oid fn_lo_close
Definition: libpq-int.h:268
#define INV_WRITE
Definition: libpq-fs.h:21
Oid lo_creat(PGconn *conn, int mode)
Definition: fe-lobj.c:465
static char * filename
Definition: pg_dumpall.c:90
Oid fn_lo_lseek64
Definition: libpq-int.h:273
PGresult * PQexec(PGconn *conn, const char *query)
Definition: fe-exec.c:1897
int lo_read(PGconn *conn, int fd, char *buf, size_t len)
Definition: fe-lobj.c:258
Oid fn_lo_unlink
Definition: libpq-int.h:271
int isint
Definition: libpq-fe.h:223
int lo_truncate(PGconn *conn, int fd, size_t len)
Definition: fe-lobj.c:137
#define close(a)
Definition: win32.h:12
ExecStatusType resultStatus
Definition: libpq-int.h:177
PGlobjfuncs * lobjfuncs
Definition: libpq-int.h:426
Oid lo_import(PGconn *conn, const char *filename)
Definition: fe-lobj.c:668
#define read(a, b, c)
Definition: win32.h:13
int * ptr
Definition: libpq-fe.h:226
#define libpq_gettext(x)
Definition: libpq-int.h:682
int integer
Definition: libpq-fe.h:227
static pg_int64 lo_ntoh64(pg_int64 net64)
Definition: fe-lobj.c:1086
static int lo_initialize(PGconn *conn)
Definition: fe-lobj.c:876