Header And Logo

PostgreSQL
| The world's most advanced open source database.

fe-lobj.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * fe-lobj.c
00004  *    Front-end large object interface
00005  *
00006  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00007  * Portions Copyright (c) 1994, Regents of the University of California
00008  *
00009  *
00010  * IDENTIFICATION
00011  *    src/interfaces/libpq/fe-lobj.c
00012  *
00013  *-------------------------------------------------------------------------
00014  */
00015 
00016 #ifdef WIN32
00017 /*
00018  *  As unlink/rename are #define'd in port.h (via postgres_fe.h), io.h
00019  *  must be included first on MS C.  Might as well do it for all WIN32's
00020  *  here.
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>         /* for ntohl/htonl */
00037 #include <arpa/inet.h>
00038 
00039 #include "libpq-fe.h"
00040 #include "libpq-int.h"
00041 #include "libpq/libpq-fs.h"     /* must come after sys/stat.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  * lo_open
00052  *    opens an existing large object
00053  *
00054  * returns the file descriptor for use in later lo_* calls
00055  * return -1 upon failure.
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  * lo_close
00094  *    closes an existing large object
00095  *
00096  * returns 0 upon success
00097  * returns -1 upon failure.
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  * lo_truncate
00132  *    truncates an existing large object to the given size
00133  *
00134  * returns 0 upon success
00135  * returns -1 upon failure
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     /* Must check this on-the-fly because it's not there pre-8.3 */
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      * Long ago, somebody thought it'd be a good idea to declare this function
00161      * as taking size_t ... but the underlying backend function only accepts a
00162      * signed int32 length.  So throw error if the given value overflows
00163      * int32.  (A possible alternative is to automatically redirect the call
00164      * to lo_truncate64; but if the caller wanted to rely on that backend
00165      * function being available, he could have called lo_truncate64 for
00166      * himself.)
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  * lo_truncate64
00200  *    truncates an existing large object to the given size
00201  *
00202  * returns 0 upon success
00203  * returns -1 upon failure
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  * lo_read
00252  *    read len bytes of the large object into buf
00253  *
00254  * returns the number of bytes read, or -1 on failure.
00255  * the CALLER must have allocated enough space to hold the result returned
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      * Long ago, somebody thought it'd be a good idea to declare this function
00273      * as taking size_t ... but the underlying backend function only accepts a
00274      * signed int32 length.  So throw error if the given value overflows
00275      * int32.
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  * lo_write
00308  *    write len bytes of buf into the large object fd
00309  *
00310  * returns the number of bytes written, or -1 on failure.
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      * Long ago, somebody thought it'd be a good idea to declare this function
00328      * as taking size_t ... but the underlying backend function only accepts a
00329      * signed int32 length.  So throw error if the given value overflows
00330      * int32.
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  * lo_lseek
00363  *    change the current read or write location on a large object
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  * lo_lseek64
00407  *    change the current read or write location on a large object
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  * lo_creat
00459  *    create a new large object
00460  * the mode is ignored (once upon a time it had a use)
00461  *
00462  * returns the oid of the large object created or
00463  * InvalidOid upon failure
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  * lo_create
00498  *    create a new large object
00499  * if lobjId isn't InvalidOid, it specifies the OID to (attempt to) create
00500  *
00501  * returns the oid of the large object created or
00502  * InvalidOid upon failure
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     /* Must check this on-the-fly because it's not there pre-8.1 */
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  * lo_tell
00546  *    returns the current seek location of the large object
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  * lo_tell64
00582  *    returns the current seek location of the large object
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  * lo_unlink
00625  *    delete a file
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  * lo_import -
00662  *    imports a file as an (inversion) large object.
00663  *
00664  * returns the oid of that object upon success,
00665  * returns InvalidOid upon failure
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  * lo_import_with_oid -
00676  *    imports a file as an (inversion) large object.
00677  *    large object id can be specified.
00678  *
00679  * returns the oid of that object upon success,
00680  * returns InvalidOid upon failure
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      * open the file to be read in
00702      */
00703     fd = open(filename, O_RDONLY | PG_BINARY, 0666);
00704     if (fd < 0)
00705     {                           /* error */
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      * create an inversion object
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         /* we assume lo_create() already set a suitable error message */
00723         (void) close(fd);
00724         return InvalidOid;
00725     }
00726 
00727     lobj = lo_open(conn, lobjOid, INV_WRITE);
00728     if (lobj == -1)
00729     {
00730         /* we assume lo_open() already set a suitable error message */
00731         (void) close(fd);
00732         return InvalidOid;
00733     }
00734 
00735     /*
00736      * read in from the file and write to the large object
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              * If lo_write() failed, we are now in an aborted transaction so
00745              * there's no need for lo_close(); furthermore, if we tried it
00746              * we'd overwrite the useful error result with a useless one. So
00747              * just nail the doors shut and get out of town.
00748              */
00749             (void) close(fd);
00750             return InvalidOid;
00751         }
00752     }
00753 
00754     if (nbytes < 0)
00755     {
00756         /* We must do lo_close before setting the errorMessage */
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         /* we assume lo_close() already set a suitable error message */
00773         return InvalidOid;
00774     }
00775 
00776     return lobjOid;
00777 }
00778 
00779 /*
00780  * lo_export -
00781  *    exports an (inversion) large object.
00782  * returns -1 upon failure, 1 if OK
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      * open the large object.
00797      */
00798     lobj = lo_open(conn, lobjId, INV_READ);
00799     if (lobj == -1)
00800     {
00801         /* we assume lo_open() already set a suitable error message */
00802         return -1;
00803     }
00804 
00805     /*
00806      * create the file to be written to
00807      */
00808     fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC | PG_BINARY, 0666);
00809     if (fd < 0)
00810     {
00811         /* We must do lo_close before setting the errorMessage */
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      * read in from the large object and write to the file
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             /* We must do lo_close before setting the errorMessage */
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      * If lo_read() failed, we are now in an aborted transaction so there's no
00845      * need for lo_close(); furthermore, if we tried it we'd overwrite the
00846      * useful error result with a useless one. So skip lo_close() if we got a
00847      * failure result.
00848      */
00849     if (nbytes < 0 ||
00850         lo_close(conn, lobj) != 0)
00851     {
00852         /* assume lo_read() or lo_close() left a suitable error message */
00853         result = -1;
00854     }
00855 
00856     /* if we already failed, don't overwrite that msg with a close error */
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  * lo_initialize
00871  *
00872  * Initialize the large object interface for an existing connection.
00873  * We ask the backend about the functions OID's in pg_proc for all
00874  * functions that are required for large object operations.
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      * Allocate the structure to hold the functions OID's
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      * Execute the query to get all the functions at once.  In 7.3 and later
00903      * we need to be schema-safe.  lo_create only exists in 8.1 and up.
00904      * lo_truncate only exists in 8.3 and up.
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      * Examine the result and put the OID's into the struct
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      * Finally check that we got all required large object interface functions
00990      * (ones that have been added later than the stone age are instead checked
00991      * only if used)
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      * Put the structure into the connection control
01052      */
01053     conn->lobjfuncs = lobjfuncs;
01054     return 0;
01055 }
01056 
01057 /*
01058  * lo_hton64
01059  *    converts a 64-bit integer from host byte order to network byte order
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     /* High order half first, since we're doing MSB-first */
01072     t = (uint32) (host64 >> 32);
01073     swap.i32[0] = htonl(t);
01074 
01075     /* Now the low order half */
01076     t = (uint32) host64;
01077     swap.i32[1] = htonl(t);
01078 
01079     return swap.i64;
01080 }
01081 
01082 /*
01083  * lo_ntoh64
01084  *    converts a 64-bit integer from network byte order to host byte order
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 }