1 /*-------------------------------------------------------------------------
2  *
3  * fe-lobj.c
4  *	  Front-end large object interface
5  *
6  * Portions Copyright (c) 1996-2020, 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
lo_open(PGconn * conn,Oid lobjId,int mode)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
lo_close(PGconn * conn,int fd)99 lo_close(PGconn *conn, int fd)
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
lo_truncate(PGconn * conn,int fd,size_t len)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 	{
153 		printfPQExpBuffer(&conn->errorMessage,
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 	{
169 		printfPQExpBuffer(&conn->errorMessage,
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
lo_truncate64(PGconn * conn,int fd,pg_int64 len)205 lo_truncate64(PGconn *conn, int fd, pg_int64 len)
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 	{
220 		printfPQExpBuffer(&conn->errorMessage,
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
lo_read(PGconn * conn,int fd,char * buf,size_t len)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 	{
278 		printfPQExpBuffer(&conn->errorMessage,
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
lo_write(PGconn * conn,int fd,const char * buf,size_t len)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 	{
333 		printfPQExpBuffer(&conn->errorMessage,
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 *) unconstify(char *, 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
lo_lseek(PGconn * conn,int fd,int offset,int whence)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
lo_lseek64(PGconn * conn,int fd,pg_int64 offset,int whence)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 	{
424 		printfPQExpBuffer(&conn->errorMessage,
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
lo_creat(PGconn * conn,int mode)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
lo_create(PGconn * conn,Oid lobjId)504 lo_create(PGconn *conn, Oid lobjId)
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 	{
520 		printfPQExpBuffer(&conn->errorMessage,
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
lo_tell(PGconn * conn,int fd)548 lo_tell(PGconn *conn, int fd)
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
lo_tell64(PGconn * conn,int fd)584 lo_tell64(PGconn *conn, int fd)
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 	{
599 		printfPQExpBuffer(&conn->errorMessage,
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
lo_unlink(PGconn * conn,Oid lobjId)628 lo_unlink(PGconn *conn, Oid lobjId)
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
lo_import(PGconn * conn,const char * filename)668 lo_import(PGconn *conn, const char *filename)
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
lo_import_with_oid(PGconn * conn,const char * filename,Oid lobjId)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
lo_import_internal(PGconn * conn,const char * filename,Oid oid)689 lo_import_internal(PGconn *conn, const char *filename, Oid oid)
690 {
691 	int			fd;
692 	int			nbytes,
693 				tmp;
694 	char		buf[LO_BUFSIZE];
695 	Oid			lobjOid;
696 	int			lobj;
697 	char		sebuf[PG_STRERROR_R_BUFLEN];
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 */
705 		printfPQExpBuffer(&conn->errorMessage,
706 						  libpq_gettext("could not open file \"%s\": %s\n"),
707 						  filename, strerror_r(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);
760 		printfPQExpBuffer(&conn->errorMessage,
761 						  libpq_gettext("could not read from file \"%s\": %s\n"),
762 						  filename,
763 						  strerror_r(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
lo_export(PGconn * conn,Oid lobjId,const char * filename)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[PG_STRERROR_R_BUFLEN];
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);
814 		printfPQExpBuffer(&conn->errorMessage,
815 						  libpq_gettext("could not open file \"%s\": %s\n"),
816 						  filename,
817 						  strerror_r(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);
834 			printfPQExpBuffer(&conn->errorMessage,
835 							  libpq_gettext("could not write to file \"%s\": %s\n"),
836 							  filename,
837 							  strerror_r(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) != 0 && result >= 0)
857 	{
858 		printfPQExpBuffer(&conn->errorMessage,
859 						  libpq_gettext("could not write to file \"%s\": %s\n"),
860 						  filename, strerror_r(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
lo_initialize(PGconn * conn)876 lo_initialize(PGconn *conn)
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 	{
894 		printfPQExpBuffer(&conn->errorMessage,
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);
945 		printfPQExpBuffer(&conn->errorMessage,
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 	{
994 		printfPQExpBuffer(&conn->errorMessage,
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 	{
1001 		printfPQExpBuffer(&conn->errorMessage,
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 	{
1008 		printfPQExpBuffer(&conn->errorMessage,
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 	{
1015 		printfPQExpBuffer(&conn->errorMessage,
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 	{
1022 		printfPQExpBuffer(&conn->errorMessage,
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 	{
1029 		printfPQExpBuffer(&conn->errorMessage,
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 	{
1036 		printfPQExpBuffer(&conn->errorMessage,
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 	{
1043 		printfPQExpBuffer(&conn->errorMessage,
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
lo_hton64(pg_int64 host64)1061 lo_hton64(pg_int64 host64)
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
lo_ntoh64(pg_int64 net64)1086 lo_ntoh64(pg_int64 net64)
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 }
1103