00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #ifdef WIN32
00017
00018
00019
00020
00021
00022 #include <io.h>
00023 #endif
00024
00025 #include "postgres_fe.h"
00026
00027 #ifdef WIN32
00028 #include "win32.h"
00029 #else
00030 #include <unistd.h>
00031 #endif
00032
00033 #include <fcntl.h>
00034 #include <limits.h>
00035 #include <sys/stat.h>
00036 #include <netinet/in.h>
00037 #include <arpa/inet.h>
00038
00039 #include "libpq-fe.h"
00040 #include "libpq-int.h"
00041 #include "libpq/libpq-fs.h"
00042
00043 #define LO_BUFSIZE 8192
00044
00045 static int lo_initialize(PGconn *conn);
00046 static Oid lo_import_internal(PGconn *conn, const char *filename, Oid oid);
00047 static pg_int64 lo_hton64(pg_int64 host64);
00048 static pg_int64 lo_ntoh64(pg_int64 net64);
00049
00050
00051
00052
00053
00054
00055
00056
00057 int
00058 lo_open(PGconn *conn, Oid lobjId, int mode)
00059 {
00060 int fd;
00061 int result_len;
00062 PQArgBlock argv[2];
00063 PGresult *res;
00064
00065 if (conn == NULL || conn->lobjfuncs == NULL)
00066 {
00067 if (lo_initialize(conn) < 0)
00068 return -1;
00069 }
00070
00071 argv[0].isint = 1;
00072 argv[0].len = 4;
00073 argv[0].u.integer = lobjId;
00074
00075 argv[1].isint = 1;
00076 argv[1].len = 4;
00077 argv[1].u.integer = mode;
00078
00079 res = PQfn(conn, conn->lobjfuncs->fn_lo_open, &fd, &result_len, 1, argv, 2);
00080 if (PQresultStatus(res) == PGRES_COMMAND_OK)
00081 {
00082 PQclear(res);
00083 return fd;
00084 }
00085 else
00086 {
00087 PQclear(res);
00088 return -1;
00089 }
00090 }
00091
00092
00093
00094
00095
00096
00097
00098
00099 int
00100 lo_close(PGconn *conn, int fd)
00101 {
00102 PQArgBlock argv[1];
00103 PGresult *res;
00104 int retval;
00105 int result_len;
00106
00107 if (conn == NULL || conn->lobjfuncs == NULL)
00108 {
00109 if (lo_initialize(conn) < 0)
00110 return -1;
00111 }
00112
00113 argv[0].isint = 1;
00114 argv[0].len = 4;
00115 argv[0].u.integer = fd;
00116 res = PQfn(conn, conn->lobjfuncs->fn_lo_close,
00117 &retval, &result_len, 1, argv, 1);
00118 if (PQresultStatus(res) == PGRES_COMMAND_OK)
00119 {
00120 PQclear(res);
00121 return retval;
00122 }
00123 else
00124 {
00125 PQclear(res);
00126 return -1;
00127 }
00128 }
00129
00130
00131
00132
00133
00134
00135
00136
00137 int
00138 lo_truncate(PGconn *conn, int fd, size_t len)
00139 {
00140 PQArgBlock argv[2];
00141 PGresult *res;
00142 int retval;
00143 int result_len;
00144
00145 if (conn == NULL || conn->lobjfuncs == NULL)
00146 {
00147 if (lo_initialize(conn) < 0)
00148 return -1;
00149 }
00150
00151
00152 if (conn->lobjfuncs->fn_lo_truncate == 0)
00153 {
00154 printfPQExpBuffer(&conn->errorMessage,
00155 libpq_gettext("cannot determine OID of function lo_truncate\n"));
00156 return -1;
00157 }
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168 if (len > (size_t) INT_MAX)
00169 {
00170 printfPQExpBuffer(&conn->errorMessage,
00171 libpq_gettext("argument of lo_truncate exceeds integer range\n"));
00172 return -1;
00173 }
00174
00175 argv[0].isint = 1;
00176 argv[0].len = 4;
00177 argv[0].u.integer = fd;
00178
00179 argv[1].isint = 1;
00180 argv[1].len = 4;
00181 argv[1].u.integer = (int) len;
00182
00183 res = PQfn(conn, conn->lobjfuncs->fn_lo_truncate,
00184 &retval, &result_len, 1, argv, 2);
00185
00186 if (PQresultStatus(res) == PGRES_COMMAND_OK)
00187 {
00188 PQclear(res);
00189 return retval;
00190 }
00191 else
00192 {
00193 PQclear(res);
00194 return -1;
00195 }
00196 }
00197
00198
00199
00200
00201
00202
00203
00204
00205 int
00206 lo_truncate64(PGconn *conn, int fd, pg_int64 len)
00207 {
00208 PQArgBlock argv[2];
00209 PGresult *res;
00210 int retval;
00211 int result_len;
00212
00213 if (conn == NULL || conn->lobjfuncs == NULL)
00214 {
00215 if (lo_initialize(conn) < 0)
00216 return -1;
00217 }
00218
00219 if (conn->lobjfuncs->fn_lo_truncate64 == 0)
00220 {
00221 printfPQExpBuffer(&conn->errorMessage,
00222 libpq_gettext("cannot determine OID of function lo_truncate64\n"));
00223 return -1;
00224 }
00225
00226 argv[0].isint = 1;
00227 argv[0].len = 4;
00228 argv[0].u.integer = fd;
00229
00230 len = lo_hton64(len);
00231 argv[1].isint = 0;
00232 argv[1].len = 8;
00233 argv[1].u.ptr = (int *) &len;
00234
00235 res = PQfn(conn, conn->lobjfuncs->fn_lo_truncate64,
00236 &retval, &result_len, 1, argv, 2);
00237
00238 if (PQresultStatus(res) == PGRES_COMMAND_OK)
00239 {
00240 PQclear(res);
00241 return retval;
00242 }
00243 else
00244 {
00245 PQclear(res);
00246 return -1;
00247 }
00248 }
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258 int
00259 lo_read(PGconn *conn, int fd, char *buf, size_t len)
00260 {
00261 PQArgBlock argv[2];
00262 PGresult *res;
00263 int result_len;
00264
00265 if (conn == NULL || conn->lobjfuncs == NULL)
00266 {
00267 if (lo_initialize(conn) < 0)
00268 return -1;
00269 }
00270
00271
00272
00273
00274
00275
00276
00277 if (len > (size_t) INT_MAX)
00278 {
00279 printfPQExpBuffer(&conn->errorMessage,
00280 libpq_gettext("argument of lo_read exceeds integer range\n"));
00281 return -1;
00282 }
00283
00284 argv[0].isint = 1;
00285 argv[0].len = 4;
00286 argv[0].u.integer = fd;
00287
00288 argv[1].isint = 1;
00289 argv[1].len = 4;
00290 argv[1].u.integer = (int) len;
00291
00292 res = PQfn(conn, conn->lobjfuncs->fn_lo_read,
00293 (int *) buf, &result_len, 0, argv, 2);
00294 if (PQresultStatus(res) == PGRES_COMMAND_OK)
00295 {
00296 PQclear(res);
00297 return result_len;
00298 }
00299 else
00300 {
00301 PQclear(res);
00302 return -1;
00303 }
00304 }
00305
00306
00307
00308
00309
00310
00311
00312 int
00313 lo_write(PGconn *conn, int fd, const char *buf, size_t len)
00314 {
00315 PQArgBlock argv[2];
00316 PGresult *res;
00317 int result_len;
00318 int retval;
00319
00320 if (conn == NULL || conn->lobjfuncs == NULL)
00321 {
00322 if (lo_initialize(conn) < 0)
00323 return -1;
00324 }
00325
00326
00327
00328
00329
00330
00331
00332 if (len > (size_t) INT_MAX)
00333 {
00334 printfPQExpBuffer(&conn->errorMessage,
00335 libpq_gettext("argument of lo_write exceeds integer range\n"));
00336 return -1;
00337 }
00338
00339 argv[0].isint = 1;
00340 argv[0].len = 4;
00341 argv[0].u.integer = fd;
00342
00343 argv[1].isint = 0;
00344 argv[1].len = (int) len;
00345 argv[1].u.ptr = (int *) buf;
00346
00347 res = PQfn(conn, conn->lobjfuncs->fn_lo_write,
00348 &retval, &result_len, 1, argv, 2);
00349 if (PQresultStatus(res) == PGRES_COMMAND_OK)
00350 {
00351 PQclear(res);
00352 return retval;
00353 }
00354 else
00355 {
00356 PQclear(res);
00357 return -1;
00358 }
00359 }
00360
00361
00362
00363
00364
00365 int
00366 lo_lseek(PGconn *conn, int fd, int offset, int whence)
00367 {
00368 PQArgBlock argv[3];
00369 PGresult *res;
00370 int retval;
00371 int result_len;
00372
00373 if (conn == NULL || conn->lobjfuncs == NULL)
00374 {
00375 if (lo_initialize(conn) < 0)
00376 return -1;
00377 }
00378
00379 argv[0].isint = 1;
00380 argv[0].len = 4;
00381 argv[0].u.integer = fd;
00382
00383 argv[1].isint = 1;
00384 argv[1].len = 4;
00385 argv[1].u.integer = offset;
00386
00387 argv[2].isint = 1;
00388 argv[2].len = 4;
00389 argv[2].u.integer = whence;
00390
00391 res = PQfn(conn, conn->lobjfuncs->fn_lo_lseek,
00392 &retval, &result_len, 1, argv, 3);
00393 if (PQresultStatus(res) == PGRES_COMMAND_OK)
00394 {
00395 PQclear(res);
00396 return retval;
00397 }
00398 else
00399 {
00400 PQclear(res);
00401 return -1;
00402 }
00403 }
00404
00405
00406
00407
00408
00409 pg_int64
00410 lo_lseek64(PGconn *conn, int fd, pg_int64 offset, int whence)
00411 {
00412 PQArgBlock argv[3];
00413 PGresult *res;
00414 pg_int64 retval;
00415 int result_len;
00416
00417 if (conn == NULL || conn->lobjfuncs == NULL)
00418 {
00419 if (lo_initialize(conn) < 0)
00420 return -1;
00421 }
00422
00423 if (conn->lobjfuncs->fn_lo_lseek64 == 0)
00424 {
00425 printfPQExpBuffer(&conn->errorMessage,
00426 libpq_gettext("cannot determine OID of function lo_lseek64\n"));
00427 return -1;
00428 }
00429
00430 argv[0].isint = 1;
00431 argv[0].len = 4;
00432 argv[0].u.integer = fd;
00433
00434 offset = lo_hton64(offset);
00435 argv[1].isint = 0;
00436 argv[1].len = 8;
00437 argv[1].u.ptr = (int *) &offset;
00438
00439 argv[2].isint = 1;
00440 argv[2].len = 4;
00441 argv[2].u.integer = whence;
00442
00443 res = PQfn(conn, conn->lobjfuncs->fn_lo_lseek64,
00444 (int *) &retval, &result_len, 0, argv, 3);
00445 if (PQresultStatus(res) == PGRES_COMMAND_OK)
00446 {
00447 PQclear(res);
00448 return lo_ntoh64(retval);
00449 }
00450 else
00451 {
00452 PQclear(res);
00453 return -1;
00454 }
00455 }
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465 Oid
00466 lo_creat(PGconn *conn, int mode)
00467 {
00468 PQArgBlock argv[1];
00469 PGresult *res;
00470 int retval;
00471 int result_len;
00472
00473 if (conn == NULL || conn->lobjfuncs == NULL)
00474 {
00475 if (lo_initialize(conn) < 0)
00476 return InvalidOid;
00477 }
00478
00479 argv[0].isint = 1;
00480 argv[0].len = 4;
00481 argv[0].u.integer = mode;
00482 res = PQfn(conn, conn->lobjfuncs->fn_lo_creat,
00483 &retval, &result_len, 1, argv, 1);
00484 if (PQresultStatus(res) == PGRES_COMMAND_OK)
00485 {
00486 PQclear(res);
00487 return (Oid) retval;
00488 }
00489 else
00490 {
00491 PQclear(res);
00492 return InvalidOid;
00493 }
00494 }
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504 Oid
00505 lo_create(PGconn *conn, Oid lobjId)
00506 {
00507 PQArgBlock argv[1];
00508 PGresult *res;
00509 int retval;
00510 int result_len;
00511
00512 if (conn == NULL || conn->lobjfuncs == NULL)
00513 {
00514 if (lo_initialize(conn) < 0)
00515 return InvalidOid;
00516 }
00517
00518
00519 if (conn->lobjfuncs->fn_lo_create == 0)
00520 {
00521 printfPQExpBuffer(&conn->errorMessage,
00522 libpq_gettext("cannot determine OID of function lo_create\n"));
00523 return InvalidOid;
00524 }
00525
00526 argv[0].isint = 1;
00527 argv[0].len = 4;
00528 argv[0].u.integer = lobjId;
00529 res = PQfn(conn, conn->lobjfuncs->fn_lo_create,
00530 &retval, &result_len, 1, argv, 1);
00531 if (PQresultStatus(res) == PGRES_COMMAND_OK)
00532 {
00533 PQclear(res);
00534 return (Oid) retval;
00535 }
00536 else
00537 {
00538 PQclear(res);
00539 return InvalidOid;
00540 }
00541 }
00542
00543
00544
00545
00546
00547
00548 int
00549 lo_tell(PGconn *conn, int fd)
00550 {
00551 int retval;
00552 PQArgBlock argv[1];
00553 PGresult *res;
00554 int result_len;
00555
00556 if (conn == NULL || conn->lobjfuncs == NULL)
00557 {
00558 if (lo_initialize(conn) < 0)
00559 return -1;
00560 }
00561
00562 argv[0].isint = 1;
00563 argv[0].len = 4;
00564 argv[0].u.integer = fd;
00565
00566 res = PQfn(conn, conn->lobjfuncs->fn_lo_tell,
00567 &retval, &result_len, 1, argv, 1);
00568 if (PQresultStatus(res) == PGRES_COMMAND_OK)
00569 {
00570 PQclear(res);
00571 return retval;
00572 }
00573 else
00574 {
00575 PQclear(res);
00576 return -1;
00577 }
00578 }
00579
00580
00581
00582
00583
00584 pg_int64
00585 lo_tell64(PGconn *conn, int fd)
00586 {
00587 pg_int64 retval;
00588 PQArgBlock argv[1];
00589 PGresult *res;
00590 int result_len;
00591
00592 if (conn == NULL || conn->lobjfuncs == NULL)
00593 {
00594 if (lo_initialize(conn) < 0)
00595 return -1;
00596 }
00597
00598 if (conn->lobjfuncs->fn_lo_tell64 == 0)
00599 {
00600 printfPQExpBuffer(&conn->errorMessage,
00601 libpq_gettext("cannot determine OID of function lo_tell64\n"));
00602 return -1;
00603 }
00604
00605 argv[0].isint = 1;
00606 argv[0].len = 4;
00607 argv[0].u.integer = fd;
00608
00609 res = PQfn(conn, conn->lobjfuncs->fn_lo_tell64,
00610 (int *) &retval, &result_len, 0, argv, 1);
00611 if (PQresultStatus(res) == PGRES_COMMAND_OK)
00612 {
00613 PQclear(res);
00614 return lo_ntoh64(retval);
00615 }
00616 else
00617 {
00618 PQclear(res);
00619 return -1;
00620 }
00621 }
00622
00623
00624
00625
00626
00627
00628 int
00629 lo_unlink(PGconn *conn, Oid lobjId)
00630 {
00631 PQArgBlock argv[1];
00632 PGresult *res;
00633 int result_len;
00634 int retval;
00635
00636 if (conn == NULL || conn->lobjfuncs == NULL)
00637 {
00638 if (lo_initialize(conn) < 0)
00639 return -1;
00640 }
00641
00642 argv[0].isint = 1;
00643 argv[0].len = 4;
00644 argv[0].u.integer = lobjId;
00645
00646 res = PQfn(conn, conn->lobjfuncs->fn_lo_unlink,
00647 &retval, &result_len, 1, argv, 1);
00648 if (PQresultStatus(res) == PGRES_COMMAND_OK)
00649 {
00650 PQclear(res);
00651 return retval;
00652 }
00653 else
00654 {
00655 PQclear(res);
00656 return -1;
00657 }
00658 }
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668 Oid
00669 lo_import(PGconn *conn, const char *filename)
00670 {
00671 return lo_import_internal(conn, filename, InvalidOid);
00672 }
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683 Oid
00684 lo_import_with_oid(PGconn *conn, const char *filename, Oid lobjId)
00685 {
00686 return lo_import_internal(conn, filename, lobjId);
00687 }
00688
00689 static Oid
00690 lo_import_internal(PGconn *conn, const char *filename, Oid oid)
00691 {
00692 int fd;
00693 int nbytes,
00694 tmp;
00695 char buf[LO_BUFSIZE];
00696 Oid lobjOid;
00697 int lobj;
00698 char sebuf[256];
00699
00700
00701
00702
00703 fd = open(filename, O_RDONLY | PG_BINARY, 0666);
00704 if (fd < 0)
00705 {
00706 printfPQExpBuffer(&conn->errorMessage,
00707 libpq_gettext("could not open file \"%s\": %s\n"),
00708 filename, pqStrerror(errno, sebuf, sizeof(sebuf)));
00709 return InvalidOid;
00710 }
00711
00712
00713
00714
00715 if (oid == InvalidOid)
00716 lobjOid = lo_creat(conn, INV_READ | INV_WRITE);
00717 else
00718 lobjOid = lo_create(conn, oid);
00719
00720 if (lobjOid == InvalidOid)
00721 {
00722
00723 (void) close(fd);
00724 return InvalidOid;
00725 }
00726
00727 lobj = lo_open(conn, lobjOid, INV_WRITE);
00728 if (lobj == -1)
00729 {
00730
00731 (void) close(fd);
00732 return InvalidOid;
00733 }
00734
00735
00736
00737
00738 while ((nbytes = read(fd, buf, LO_BUFSIZE)) > 0)
00739 {
00740 tmp = lo_write(conn, lobj, buf, nbytes);
00741 if (tmp != nbytes)
00742 {
00743
00744
00745
00746
00747
00748
00749 (void) close(fd);
00750 return InvalidOid;
00751 }
00752 }
00753
00754 if (nbytes < 0)
00755 {
00756
00757 int save_errno = errno;
00758
00759 (void) lo_close(conn, lobj);
00760 (void) close(fd);
00761 printfPQExpBuffer(&conn->errorMessage,
00762 libpq_gettext("could not read from file \"%s\": %s\n"),
00763 filename,
00764 pqStrerror(save_errno, sebuf, sizeof(sebuf)));
00765 return InvalidOid;
00766 }
00767
00768 (void) close(fd);
00769
00770 if (lo_close(conn, lobj) != 0)
00771 {
00772
00773 return InvalidOid;
00774 }
00775
00776 return lobjOid;
00777 }
00778
00779
00780
00781
00782
00783
00784 int
00785 lo_export(PGconn *conn, Oid lobjId, const char *filename)
00786 {
00787 int result = 1;
00788 int fd;
00789 int nbytes,
00790 tmp;
00791 char buf[LO_BUFSIZE];
00792 int lobj;
00793 char sebuf[256];
00794
00795
00796
00797
00798 lobj = lo_open(conn, lobjId, INV_READ);
00799 if (lobj == -1)
00800 {
00801
00802 return -1;
00803 }
00804
00805
00806
00807
00808 fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC | PG_BINARY, 0666);
00809 if (fd < 0)
00810 {
00811
00812 int save_errno = errno;
00813
00814 (void) lo_close(conn, lobj);
00815 printfPQExpBuffer(&conn->errorMessage,
00816 libpq_gettext("could not open file \"%s\": %s\n"),
00817 filename,
00818 pqStrerror(save_errno, sebuf, sizeof(sebuf)));
00819 return -1;
00820 }
00821
00822
00823
00824
00825 while ((nbytes = lo_read(conn, lobj, buf, LO_BUFSIZE)) > 0)
00826 {
00827 tmp = write(fd, buf, nbytes);
00828 if (tmp != nbytes)
00829 {
00830
00831 int save_errno = errno;
00832
00833 (void) lo_close(conn, lobj);
00834 (void) close(fd);
00835 printfPQExpBuffer(&conn->errorMessage,
00836 libpq_gettext("could not write to file \"%s\": %s\n"),
00837 filename,
00838 pqStrerror(save_errno, sebuf, sizeof(sebuf)));
00839 return -1;
00840 }
00841 }
00842
00843
00844
00845
00846
00847
00848
00849 if (nbytes < 0 ||
00850 lo_close(conn, lobj) != 0)
00851 {
00852
00853 result = -1;
00854 }
00855
00856
00857 if (close(fd) && result >= 0)
00858 {
00859 printfPQExpBuffer(&conn->errorMessage,
00860 libpq_gettext("could not write to file \"%s\": %s\n"),
00861 filename, pqStrerror(errno, sebuf, sizeof(sebuf)));
00862 result = -1;
00863 }
00864
00865 return result;
00866 }
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876 static int
00877 lo_initialize(PGconn *conn)
00878 {
00879 PGresult *res;
00880 PGlobjfuncs *lobjfuncs;
00881 int n;
00882 const char *query;
00883 const char *fname;
00884 Oid foid;
00885
00886 if (!conn)
00887 return -1;
00888
00889
00890
00891
00892 lobjfuncs = (PGlobjfuncs *) malloc(sizeof(PGlobjfuncs));
00893 if (lobjfuncs == NULL)
00894 {
00895 printfPQExpBuffer(&conn->errorMessage,
00896 libpq_gettext("out of memory\n"));
00897 return -1;
00898 }
00899 MemSet((char *) lobjfuncs, 0, sizeof(PGlobjfuncs));
00900
00901
00902
00903
00904
00905
00906 if (conn->sversion >= 70300)
00907 query = "select proname, oid from pg_catalog.pg_proc "
00908 "where proname in ("
00909 "'lo_open', "
00910 "'lo_close', "
00911 "'lo_creat', "
00912 "'lo_create', "
00913 "'lo_unlink', "
00914 "'lo_lseek', "
00915 "'lo_lseek64', "
00916 "'lo_tell', "
00917 "'lo_tell64', "
00918 "'lo_truncate', "
00919 "'lo_truncate64', "
00920 "'loread', "
00921 "'lowrite') "
00922 "and pronamespace = (select oid from pg_catalog.pg_namespace "
00923 "where nspname = 'pg_catalog')";
00924 else
00925 query = "select proname, oid from pg_proc "
00926 "where proname = 'lo_open' "
00927 "or proname = 'lo_close' "
00928 "or proname = 'lo_creat' "
00929 "or proname = 'lo_unlink' "
00930 "or proname = 'lo_lseek' "
00931 "or proname = 'lo_tell' "
00932 "or proname = 'loread' "
00933 "or proname = 'lowrite'";
00934
00935 res = PQexec(conn, query);
00936 if (res == NULL)
00937 {
00938 free(lobjfuncs);
00939 return -1;
00940 }
00941
00942 if (res->resultStatus != PGRES_TUPLES_OK)
00943 {
00944 free(lobjfuncs);
00945 PQclear(res);
00946 printfPQExpBuffer(&conn->errorMessage,
00947 libpq_gettext("query to initialize large object functions did not return data\n"));
00948 return -1;
00949 }
00950
00951
00952
00953
00954 for (n = 0; n < PQntuples(res); n++)
00955 {
00956 fname = PQgetvalue(res, n, 0);
00957 foid = (Oid) atoi(PQgetvalue(res, n, 1));
00958 if (strcmp(fname, "lo_open") == 0)
00959 lobjfuncs->fn_lo_open = foid;
00960 else if (strcmp(fname, "lo_close") == 0)
00961 lobjfuncs->fn_lo_close = foid;
00962 else if (strcmp(fname, "lo_creat") == 0)
00963 lobjfuncs->fn_lo_creat = foid;
00964 else if (strcmp(fname, "lo_create") == 0)
00965 lobjfuncs->fn_lo_create = foid;
00966 else if (strcmp(fname, "lo_unlink") == 0)
00967 lobjfuncs->fn_lo_unlink = foid;
00968 else if (strcmp(fname, "lo_lseek") == 0)
00969 lobjfuncs->fn_lo_lseek = foid;
00970 else if (strcmp(fname, "lo_lseek64") == 0)
00971 lobjfuncs->fn_lo_lseek64 = foid;
00972 else if (strcmp(fname, "lo_tell") == 0)
00973 lobjfuncs->fn_lo_tell = foid;
00974 else if (strcmp(fname, "lo_tell64") == 0)
00975 lobjfuncs->fn_lo_tell64 = foid;
00976 else if (strcmp(fname, "lo_truncate") == 0)
00977 lobjfuncs->fn_lo_truncate = foid;
00978 else if (strcmp(fname, "lo_truncate64") == 0)
00979 lobjfuncs->fn_lo_truncate64 = foid;
00980 else if (strcmp(fname, "loread") == 0)
00981 lobjfuncs->fn_lo_read = foid;
00982 else if (strcmp(fname, "lowrite") == 0)
00983 lobjfuncs->fn_lo_write = foid;
00984 }
00985
00986 PQclear(res);
00987
00988
00989
00990
00991
00992
00993 if (lobjfuncs->fn_lo_open == 0)
00994 {
00995 printfPQExpBuffer(&conn->errorMessage,
00996 libpq_gettext("cannot determine OID of function lo_open\n"));
00997 free(lobjfuncs);
00998 return -1;
00999 }
01000 if (lobjfuncs->fn_lo_close == 0)
01001 {
01002 printfPQExpBuffer(&conn->errorMessage,
01003 libpq_gettext("cannot determine OID of function lo_close\n"));
01004 free(lobjfuncs);
01005 return -1;
01006 }
01007 if (lobjfuncs->fn_lo_creat == 0)
01008 {
01009 printfPQExpBuffer(&conn->errorMessage,
01010 libpq_gettext("cannot determine OID of function lo_creat\n"));
01011 free(lobjfuncs);
01012 return -1;
01013 }
01014 if (lobjfuncs->fn_lo_unlink == 0)
01015 {
01016 printfPQExpBuffer(&conn->errorMessage,
01017 libpq_gettext("cannot determine OID of function lo_unlink\n"));
01018 free(lobjfuncs);
01019 return -1;
01020 }
01021 if (lobjfuncs->fn_lo_lseek == 0)
01022 {
01023 printfPQExpBuffer(&conn->errorMessage,
01024 libpq_gettext("cannot determine OID of function lo_lseek\n"));
01025 free(lobjfuncs);
01026 return -1;
01027 }
01028 if (lobjfuncs->fn_lo_tell == 0)
01029 {
01030 printfPQExpBuffer(&conn->errorMessage,
01031 libpq_gettext("cannot determine OID of function lo_tell\n"));
01032 free(lobjfuncs);
01033 return -1;
01034 }
01035 if (lobjfuncs->fn_lo_read == 0)
01036 {
01037 printfPQExpBuffer(&conn->errorMessage,
01038 libpq_gettext("cannot determine OID of function loread\n"));
01039 free(lobjfuncs);
01040 return -1;
01041 }
01042 if (lobjfuncs->fn_lo_write == 0)
01043 {
01044 printfPQExpBuffer(&conn->errorMessage,
01045 libpq_gettext("cannot determine OID of function lowrite\n"));
01046 free(lobjfuncs);
01047 return -1;
01048 }
01049
01050
01051
01052
01053 conn->lobjfuncs = lobjfuncs;
01054 return 0;
01055 }
01056
01057
01058
01059
01060
01061 static pg_int64
01062 lo_hton64(pg_int64 host64)
01063 {
01064 union
01065 {
01066 pg_int64 i64;
01067 uint32 i32[2];
01068 } swap;
01069 uint32 t;
01070
01071
01072 t = (uint32) (host64 >> 32);
01073 swap.i32[0] = htonl(t);
01074
01075
01076 t = (uint32) host64;
01077 swap.i32[1] = htonl(t);
01078
01079 return swap.i64;
01080 }
01081
01082
01083
01084
01085
01086 static pg_int64
01087 lo_ntoh64(pg_int64 net64)
01088 {
01089 union
01090 {
01091 pg_int64 i64;
01092 uint32 i32[2];
01093 } swap;
01094 pg_int64 result;
01095
01096 swap.i64 = net64;
01097
01098 result = (uint32) ntohl(swap.i32[0]);
01099 result <<= 32;
01100 result |= (uint32) ntohl(swap.i32[1]);
01101
01102 return result;
01103 }