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