PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
testlo64.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * testlo64.c
4 * test using large objects with libpq using 64-bit APIs
5 *
6 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 *
10 * IDENTIFICATION
11 * src/test/examples/testlo64.c
12 *
13 *-------------------------------------------------------------------------
14 */
15#include <stdint.h>
16#include <stdio.h>
17#include <stdlib.h>
18
19#include <sys/types.h>
20#include <sys/stat.h>
21#include <fcntl.h>
22#include <unistd.h>
23
24#include "libpq-fe.h"
25#include "libpq/libpq-fs.h"
26
27#define BUFSIZE 1024
28
29/*
30 * importFile -
31 * import file "in_filename" into database as large object "lobjOid"
32 *
33 */
34static Oid
36{
37 Oid lobjId;
38 int lobj_fd;
39 char buf[BUFSIZE];
40 int nbytes,
41 tmp;
42 int fd;
43
44 /*
45 * open the file to be read in
46 */
47 fd = open(filename, O_RDONLY, 0666);
48 if (fd < 0)
49 { /* error */
50 fprintf(stderr, "cannot open unix file\"%s\"\n", filename);
51 }
52
53 /*
54 * create the large object
55 */
56 lobjId = lo_creat(conn, INV_READ | INV_WRITE);
57 if (lobjId == 0)
58 fprintf(stderr, "cannot create large object");
59
60 lobj_fd = lo_open(conn, lobjId, INV_WRITE);
61
62 /*
63 * read in from the Unix file and write to the inversion file
64 */
65 while ((nbytes = read(fd, buf, BUFSIZE)) > 0)
66 {
67 tmp = lo_write(conn, lobj_fd, buf, nbytes);
68 if (tmp < nbytes)
69 fprintf(stderr, "error while reading \"%s\"", filename);
70 }
71
72 close(fd);
73 lo_close(conn, lobj_fd);
74
75 return lobjId;
76}
77
78static void
79pickout(PGconn *conn, Oid lobjId, int64_t start, int len)
80{
81 int lobj_fd;
82 char *buf;
83 int nbytes;
84 int nread;
85
86 lobj_fd = lo_open(conn, lobjId, INV_READ);
87 if (lobj_fd < 0)
88 fprintf(stderr, "cannot open large object %u", lobjId);
89
90 if (lo_lseek64(conn, lobj_fd, start, SEEK_SET) < 0)
91 fprintf(stderr, "error in lo_lseek64: %s", PQerrorMessage(conn));
92
93 if (lo_tell64(conn, lobj_fd) != start)
94 fprintf(stderr, "error in lo_tell64: %s", PQerrorMessage(conn));
95
96 buf = malloc(len + 1);
97
98 nread = 0;
99 while (len - nread > 0)
100 {
101 nbytes = lo_read(conn, lobj_fd, buf, len - nread);
102 buf[nbytes] = '\0';
103 fprintf(stderr, ">>> %s", buf);
104 nread += nbytes;
105 if (nbytes <= 0)
106 break; /* no more data? */
107 }
108 free(buf);
109 fprintf(stderr, "\n");
110 lo_close(conn, lobj_fd);
111}
112
113static void
114overwrite(PGconn *conn, Oid lobjId, int64_t start, int len)
115{
116 int lobj_fd;
117 char *buf;
118 int nbytes;
119 int nwritten;
120 int i;
121
122 lobj_fd = lo_open(conn, lobjId, INV_WRITE);
123 if (lobj_fd < 0)
124 fprintf(stderr, "cannot open large object %u", lobjId);
125
126 if (lo_lseek64(conn, lobj_fd, start, SEEK_SET) < 0)
127 fprintf(stderr, "error in lo_lseek64: %s", PQerrorMessage(conn));
128
129 buf = malloc(len + 1);
130
131 for (i = 0; i < len; i++)
132 buf[i] = 'X';
133 buf[i] = '\0';
134
135 nwritten = 0;
136 while (len - nwritten > 0)
137 {
138 nbytes = lo_write(conn, lobj_fd, buf + nwritten, len - nwritten);
139 nwritten += nbytes;
140 if (nbytes <= 0)
141 {
142 fprintf(stderr, "\nWRITE FAILED!\n");
143 break;
144 }
145 }
146 free(buf);
147 fprintf(stderr, "\n");
148 lo_close(conn, lobj_fd);
149}
150
151static void
152my_truncate(PGconn *conn, Oid lobjId, int64_t len)
153{
154 int lobj_fd;
155
156 lobj_fd = lo_open(conn, lobjId, INV_READ | INV_WRITE);
157 if (lobj_fd < 0)
158 fprintf(stderr, "cannot open large object %u", lobjId);
159
160 if (lo_truncate64(conn, lobj_fd, len) < 0)
161 fprintf(stderr, "error in lo_truncate64: %s", PQerrorMessage(conn));
162
163 lo_close(conn, lobj_fd);
164}
165
166
167/*
168 * exportFile -
169 * export large object "lobjOid" to file "out_filename"
170 *
171 */
172static void
174{
175 int lobj_fd;
176 char buf[BUFSIZE];
177 int nbytes,
178 tmp;
179 int fd;
180
181 /*
182 * open the large object
183 */
184 lobj_fd = lo_open(conn, lobjId, INV_READ);
185 if (lobj_fd < 0)
186 fprintf(stderr, "cannot open large object %u", lobjId);
187
188 /*
189 * open the file to be written to
190 */
191 fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666);
192 if (fd < 0)
193 { /* error */
194 fprintf(stderr, "cannot open unix file\"%s\"",
195 filename);
196 }
197
198 /*
199 * read in from the inversion file and write to the Unix file
200 */
201 while ((nbytes = lo_read(conn, lobj_fd, buf, BUFSIZE)) > 0)
202 {
203 tmp = write(fd, buf, nbytes);
204 if (tmp < nbytes)
205 {
206 fprintf(stderr, "error while writing \"%s\"",
207 filename);
208 }
209 }
210
211 lo_close(conn, lobj_fd);
212 close(fd);
213}
214
215static void
217{
218 PQfinish(conn);
219 exit(1);
220}
221
222int
223main(int argc, char **argv)
224{
225 char *in_filename,
226 *out_filename,
227 *out_filename2;
228 char *database;
229 Oid lobjOid;
230 PGconn *conn;
231 PGresult *res;
232
233 if (argc != 5)
234 {
235 fprintf(stderr, "Usage: %s database_name in_filename out_filename out_filename2\n",
236 argv[0]);
237 exit(1);
238 }
239
240 database = argv[1];
241 in_filename = argv[2];
242 out_filename = argv[3];
243 out_filename2 = argv[4];
244
245 /*
246 * set up the connection
247 */
248 conn = PQsetdb(NULL, NULL, NULL, NULL, database);
249
250 /* check to see that the backend connection was successfully made */
252 {
253 fprintf(stderr, "%s", PQerrorMessage(conn));
255 }
256
257 /* Set always-secure search path, so malicious users can't take control. */
258 res = PQexec(conn,
259 "SELECT pg_catalog.set_config('search_path', '', false)");
261 {
262 fprintf(stderr, "SET failed: %s", PQerrorMessage(conn));
263 PQclear(res);
265 }
266 PQclear(res);
267
268 res = PQexec(conn, "begin");
269 PQclear(res);
270 printf("importing file \"%s\" ...\n", in_filename);
271/* lobjOid = importFile(conn, in_filename); */
272 lobjOid = lo_import(conn, in_filename);
273 if (lobjOid == 0)
274 fprintf(stderr, "%s\n", PQerrorMessage(conn));
275 else
276 {
277 printf("\tas large object %u.\n", lobjOid);
278
279 printf("picking out bytes 4294967000-4294968000 of the large object\n");
280 pickout(conn, lobjOid, 4294967000U, 1000);
281
282 printf("overwriting bytes 4294967000-4294968000 of the large object with X's\n");
283 overwrite(conn, lobjOid, 4294967000U, 1000);
284
285 printf("exporting large object to file \"%s\" ...\n", out_filename);
286/* exportFile(conn, lobjOid, out_filename); */
287 if (lo_export(conn, lobjOid, out_filename) < 0)
288 fprintf(stderr, "%s\n", PQerrorMessage(conn));
289
290 printf("truncating to 3294968000 bytes\n");
291 my_truncate(conn, lobjOid, 3294968000U);
292
293 printf("exporting truncated large object to file \"%s\" ...\n", out_filename2);
294 if (lo_export(conn, lobjOid, out_filename2) < 0)
295 fprintf(stderr, "%s\n", PQerrorMessage(conn));
296 }
297
298 res = PQexec(conn, "end");
299 PQclear(res);
300 PQfinish(conn);
301 return 0;
302}
int lo_write(int fd, const char *buf, int len)
Definition: be-fsstubs.c:182
int lo_read(int fd, char *buf, int len)
Definition: be-fsstubs.c:154
#define fprintf(file, fmt, msg)
Definition: cubescan.l:21
ConnStatusType PQstatus(const PGconn *conn)
Definition: fe-connect.c:7556
void PQfinish(PGconn *conn)
Definition: fe-connect.c:5290
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:7619
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:3411
void PQclear(PGresult *res)
Definition: fe-exec.c:721
PGresult * PQexec(PGconn *conn, const char *query)
Definition: fe-exec.c:2262
int lo_close(PGconn *conn, int fd)
Definition: fe-lobj.c:96
int lo_truncate64(PGconn *conn, int fd, int64_t len)
Definition: fe-lobj.c:195
Oid lo_creat(PGconn *conn, int mode)
Definition: fe-lobj.c:438
int lo_open(PGconn *conn, Oid lobjId, int mode)
Definition: fe-lobj.c:57
int64_t lo_lseek64(PGconn *conn, int fd, int64_t offset, int whence)
Definition: fe-lobj.c:385
int64_t lo_tell64(PGconn *conn, int fd)
Definition: fe-lobj.c:548
Oid lo_import(PGconn *conn, const char *filename)
Definition: fe-lobj.c:626
int lo_export(PGconn *conn, Oid lobjId, const char *filename)
Definition: fe-lobj.c:748
return str start
#define free(a)
Definition: header.h:65
#define malloc(a)
Definition: header.h:50
#define close(a)
Definition: win32.h:12
#define write(a, b, c)
Definition: win32.h:14
#define read(a, b, c)
Definition: win32.h:13
int i
Definition: isn.c:77
@ CONNECTION_OK
Definition: libpq-fe.h:84
@ PGRES_TUPLES_OK
Definition: libpq-fe.h:128
#define PQsetdb(M_PGHOST, M_PGPORT, M_PGOPT, M_PGTTY, M_DBNAME)
Definition: libpq-fe.h:342
#define INV_READ
Definition: libpq-fs.h:22
#define INV_WRITE
Definition: libpq-fs.h:21
const void size_t len
static char * filename
Definition: pg_dumpall.c:123
static char * buf
Definition: pg_test_fsync.c:72
#define printf(...)
Definition: port.h:245
unsigned int Oid
Definition: postgres_ext.h:30
static int fd(const char *x, int i)
Definition: preproc-init.c:105
PGconn * conn
Definition: streamutil.c:52
static void exit_nicely(PGconn *conn)
Definition: testlo64.c:216
int main(int argc, char **argv)
Definition: testlo64.c:223
static void overwrite(PGconn *conn, Oid lobjId, int64_t start, int len)
Definition: testlo64.c:114
static void my_truncate(PGconn *conn, Oid lobjId, int64_t len)
Definition: testlo64.c:152
static void exportFile(PGconn *conn, Oid lobjId, char *filename)
Definition: testlo64.c:173
static void pickout(PGconn *conn, Oid lobjId, int64_t start, int len)
Definition: testlo64.c:79
#define BUFSIZE
Definition: testlo64.c:27
static Oid importFile(PGconn *conn, char *filename)
Definition: testlo64.c:35