Commit d1288523 authored by Bruce Momjian's avatar Bruce Momjian

In the Programmer's Guide, the sample code for accessing large objects

from libpq has two functions with memory leaks.

The functions pickout() and overwrite() malloc space for buf which is
never freed.

See
http://www.postgresql.org/users-lounge/docs/7.0/programmer/largeobjects3207.htm

This problem is also in the 6.5 docs at
http://www.postgresql.org/users-lounge/docs/6.5/programmer/x3184.htm

Nishad Prakash
parent a7ea9f46
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/lobj.sgml,v 1.14 2000/12/21 22:55:27 petere Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/lobj.sgml,v 1.15 2001/01/20 00:05:54 momjian Exp $
--> -->
<chapter id="largeObjects"> <chapter id="largeObjects">
...@@ -316,48 +316,52 @@ SELECT lo_export(image.raster, '/tmp/motd') from image ...@@ -316,48 +316,52 @@ SELECT lo_export(image.raster, '/tmp/motd') from image
*-------------------------------------------------------------- *--------------------------------------------------------------
*/ */
#include &lt;stdio.h&gt; #include &lt;stdio.h&gt;
#include "libpq-fe.h" #include &quot;libpq-fe.h&quot;
#include "libpq/libpq-fs.h" #include &quot;libpq/libpq-fs.h&quot;
#define BUFSIZE 1024 #define BUFSIZE 1024
/* /*
* importFile * import file "in_filename" into database as large object "lobjOid" * importFile * import file &quot;in_filename&quot; into database as large object &quot;lob
jOid&quot;
* *
*/ */
Oid importFile(PGconn *conn, char *filename) Oid
importFile(PGconn *conn, char *filename)
{ {
Oid lobjId; Oid lobjId;
int lobj_fd; int lobj_fd;
char buf[BUFSIZE]; char buf[BUFSIZE];
int nbytes, tmp; int nbytes,
int fd; tmp;
int fd;
/* /*
* open the file to be read in * open the file to be read in
*/ */
fd = open(filename, O_RDONLY, 0666); fd = open(filename, O_RDONLY, 0666);
if (fd &lt; 0) { /* error */ if (fd &lt; 0)
fprintf(stderr, "can't open unix file %s\n", filename); { /* error */
fprintf(stderr, &quot;can't open unix file %s\n&quot;, filename);
} }
/* /*
* create the large object * create the large object
*/ */
lobjId = lo_creat(conn, INV_READ|INV_WRITE); lobjId = lo_creat(conn, INV_READ | INV_WRITE);
if (lobjId == 0) { if (lobjId == 0)
fprintf(stderr, "can't create large object\n"); fprintf(stderr, &quot;can't create large object\n&quot;);
}
lobj_fd = lo_open(conn, lobjId, INV_WRITE); lobj_fd = lo_open(conn, lobjId, INV_WRITE);
/* /*
* read in from the Unix file and write to the inversion file * read in from the Unix file and write to the inversion file
*/ */
while ((nbytes = read(fd, buf, BUFSIZE)) &gt; 0) { while ((nbytes = read(fd, buf, BUFSIZE)) &gt; 0)
tmp = lo_write(conn, lobj_fd, buf, nbytes); {
if (tmp &lt; nbytes) { tmp = lo_write(conn, lobj_fd, buf, nbytes);
fprintf(stderr, "error while reading large object\n"); if (tmp &lt; nbytes)
} fprintf(stderr, &quot;error while reading large object\n&quot;);
} }
(void) close(fd); (void) close(fd);
...@@ -366,101 +370,115 @@ Oid importFile(PGconn *conn, char *filename) ...@@ -366,101 +370,115 @@ Oid importFile(PGconn *conn, char *filename)
return lobjId; return lobjId;
} }
void pickout(PGconn *conn, Oid lobjId, int start, int len) void
pickout(PGconn *conn, Oid lobjId, int start, int len)
{ {
int lobj_fd; int lobj_fd;
char* buf; char *buf;
int nbytes; int nbytes;
int nread; int nread;
lobj_fd = lo_open(conn, lobjId, INV_READ); lobj_fd = lo_open(conn, lobjId, INV_READ);
if (lobj_fd &lt; 0) { if (lobj_fd &lt; 0)
fprintf(stderr,"can't open large object %d\n", {
lobjId); fprintf(stderr, &quot;can't open large object %d\n&quot;,
lobjId);
} }
lo_lseek(conn, lobj_fd, start, SEEK_SET); lo_lseek(conn, lobj_fd, start, SEEK_SET);
buf = malloc(len+1); buf = malloc(len + 1);
nread = 0; nread = 0;
while (len - nread &gt; 0) { while (len - nread &gt; 0)
nbytes = lo_read(conn, lobj_fd, buf, len - nread); {
buf[nbytes] = ' '; nbytes = lo_read(conn, lobj_fd, buf, len - nread);
fprintf(stderr,"&gt;&gt;&gt; %s", buf); buf[nbytes] = ' ';
nread += nbytes; fprintf(stderr, &quot;&gt;&gt;&gt; %s&quot;, buf);
nread += nbytes;
} }
fprintf(stderr,"\n"); free(buf);
fprintf(stderr, &quot;\n&quot;);
lo_close(conn, lobj_fd); lo_close(conn, lobj_fd);
} }
void overwrite(PGconn *conn, Oid lobjId, int start, int len) void
overwrite(PGconn *conn, Oid lobjId, int start, int len)
{ {
int lobj_fd; int lobj_fd;
char* buf; char *buf;
int nbytes; int nbytes;
int nwritten; int nwritten;
int i; int i;
lobj_fd = lo_open(conn, lobjId, INV_READ); lobj_fd = lo_open(conn, lobjId, INV_READ);
if (lobj_fd &lt; 0) { if (lobj_fd &lt; 0)
fprintf(stderr,"can't open large object %d\n", {
lobjId); fprintf(stderr, &quot;can't open large object %d\n&quot;,
lobjId);
} }
lo_lseek(conn, lobj_fd, start, SEEK_SET); lo_lseek(conn, lobj_fd, start, SEEK_SET);
buf = malloc(len+1); buf = malloc(len + 1);
for (i=0;i&lt;len;i++) for (i = 0; i &lt; len; i++)
buf[i] = 'X'; buf[i] = 'X';
buf[i] = ' '; buf[i] = ' ';
nwritten = 0; nwritten = 0;
while (len - nwritten &gt; 0) { while (len - nwritten &gt; 0)
nbytes = lo_write(conn, lobj_fd, buf + nwritten, len - nwritten); {
nwritten += nbytes; nbytes = lo_write(conn, lobj_fd, buf + nwritten, len - nwritten);
nwritten += nbytes;
} }
fprintf(stderr,"\n"); free(buf);
fprintf(stderr, &quot;\n&quot;);
lo_close(conn, lobj_fd); lo_close(conn, lobj_fd);
} }
/* /*
* exportFile * export large object "lobjOid" to file "out_filename" * exportFile * export large object &quot;lobjOid&quot; to file &quot;out_filename&quot;
* *
*/ */
void exportFile(PGconn *conn, Oid lobjId, char *filename) void
exportFile(PGconn *conn, Oid lobjId, char *filename)
{ {
int lobj_fd; int lobj_fd;
char buf[BUFSIZE]; char buf[BUFSIZE];
int nbytes, tmp; int nbytes,
int fd; tmp;
int fd;
/* /*
* create an inversion "object" * create an inversion &quot;object&quot;
*/ */
lobj_fd = lo_open(conn, lobjId, INV_READ); lobj_fd = lo_open(conn, lobjId, INV_READ);
if (lobj_fd &lt; 0) { if (lobj_fd &lt; 0)
fprintf(stderr,"can't open large object %d\n", {
lobjId); fprintf(stderr, &quot;can't open large object %d\n&quot;,
lobjId);
} }
/* /*
* open the file to be written to * open the file to be written to
*/ */
fd = open(filename, O_CREAT|O_WRONLY, 0666); fd = open(filename, O_CREAT | O_WRONLY, 0666);
if (fd &lt; 0) { /* error */ if (fd &lt; 0)
fprintf(stderr, "can't open unix file %s\n", { /* error */
filename); fprintf(stderr, &quot;can't open unix file %s\n&quot;,
filename);
} }
/* /*
* read in from the Unix file and write to the inversion file * read in from the Unix file and write to the inversion file
*/ */
while ((nbytes = lo_read(conn, lobj_fd, buf, BUFSIZE)) &gt; 0) { while ((nbytes = lo_read(conn, lobj_fd, buf, BUFSIZE)) &gt; 0)
tmp = write(fd, buf, nbytes); {
if (tmp &lt; nbytes) { tmp = write(fd, buf, nbytes);
fprintf(stderr,"error while writing %s\n", if (tmp &lt; nbytes)
filename); {
} fprintf(stderr, &quot;error while writing %s\n&quot;,
filename);
}
} }
(void) lo_close(conn, lobj_fd); (void) lo_close(conn, lobj_fd);
...@@ -470,25 +488,27 @@ void exportFile(PGconn *conn, Oid lobjId, char *filename) ...@@ -470,25 +488,27 @@ void exportFile(PGconn *conn, Oid lobjId, char *filename)
} }
void void
exit_nicely(PGconn* conn) exit_nicely(PGconn *conn)
{ {
PQfinish(conn); PQfinish(conn);
exit(1); exit(1);
} }
int int
main(int argc, char **argv) main(int argc, char **argv)
{ {
char *in_filename, *out_filename; char *in_filename,
char *database; *out_filename;
Oid lobjOid; char *database;
PGconn *conn; Oid lobjOid;
PGresult *res; PGconn *conn;
PGresult *res;
if (argc != 4) {
fprintf(stderr, "Usage: %s database_name in_filename out_filename\n", if (argc != 4)
argv[0]); {
exit(1); fprintf(stderr, &quot;Usage: %s database_name in_filename out_filename\n&quot;,
argv[0]);
exit(1);
} }
database = argv[1]; database = argv[1];
...@@ -501,33 +521,34 @@ main(int argc, char **argv) ...@@ -501,33 +521,34 @@ main(int argc, char **argv)
conn = PQsetdb(NULL, NULL, NULL, NULL, database); conn = PQsetdb(NULL, NULL, NULL, NULL, database);
/* check to see that the backend connection was successfully made */ /* check to see that the backend connection was successfully made */
if (PQstatus(conn) == CONNECTION_BAD) { if (PQstatus(conn) == CONNECTION_BAD)
fprintf(stderr,"Connection to database '%s' failed.\n", database); {
fprintf(stderr,"%s",PQerrorMessage(conn)); fprintf(stderr, &quot;Connection to database '%s' failed.\n&quot;, database);
exit_nicely(conn); fprintf(stderr, &quot;%s&quot;, PQerrorMessage(conn));
exit_nicely(conn);
} }
res = PQexec(conn, "begin"); res = PQexec(conn, &quot;begin&quot;);
PQclear(res); PQclear(res);
printf("importing file %s\n", in_filename); printf(&quot;importing file %s\n&quot;, in_filename);
/* lobjOid = importFile(conn, in_filename); */ /* lobjOid = importFile(conn, in_filename); */
lobjOid = lo_import(conn, in_filename); lobjOid = lo_import(conn, in_filename);
/* /*
printf("as large object %d.\n", lobjOid); printf(&quot;as large object %d.\n&quot;, lobjOid);
printf("picking out bytes 1000-2000 of the large object\n"); printf(&quot;picking out bytes 1000-2000 of the large object\n&quot;);
pickout(conn, lobjOid, 1000, 1000); pickout(conn, lobjOid, 1000, 1000);
printf("overwriting bytes 1000-2000 of the large object with X's\n"); printf(&quot;overwriting bytes 1000-2000 of the large object with X's\n&quot;);
overwrite(conn, lobjOid, 1000, 1000); overwrite(conn, lobjOid, 1000, 1000);
*/ */
printf("exporting large object to file %s\n", out_filename); printf(&quot;exporting large object to file %s\n&quot;, out_filename);
/* exportFile(conn, lobjOid, out_filename); */ /* exportFile(conn, lobjOid, out_filename); */
lo_export(conn, lobjOid,out_filename); lo_export(conn, lobjOid, out_filename);
res = PQexec(conn, "end"); res = PQexec(conn, &quot;end&quot;);
PQclear(res); PQclear(res);
PQfinish(conn); PQfinish(conn);
exit(0); exit(0);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment