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