1*11be35a1SLionel Sambuc /* $NetBSD: h_db.c,v 1.1 2011/01/07 15:05:58 pgoyette Exp $ */
2*11be35a1SLionel Sambuc
3*11be35a1SLionel Sambuc /*-
4*11be35a1SLionel Sambuc * Copyright (c) 1992, 1993, 1994
5*11be35a1SLionel Sambuc * The Regents of the University of California. All rights reserved.
6*11be35a1SLionel Sambuc *
7*11be35a1SLionel Sambuc * Redistribution and use in source and binary forms, with or without
8*11be35a1SLionel Sambuc * modification, are permitted provided that the following conditions
9*11be35a1SLionel Sambuc * are met:
10*11be35a1SLionel Sambuc * 1. Redistributions of source code must retain the above copyright
11*11be35a1SLionel Sambuc * notice, this list of conditions and the following disclaimer.
12*11be35a1SLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright
13*11be35a1SLionel Sambuc * notice, this list of conditions and the following disclaimer in the
14*11be35a1SLionel Sambuc * documentation and/or other materials provided with the distribution.
15*11be35a1SLionel Sambuc * 3. Neither the name of the University nor the names of its contributors
16*11be35a1SLionel Sambuc * may be used to endorse or promote products derived from this software
17*11be35a1SLionel Sambuc * without specific prior written permission.
18*11be35a1SLionel Sambuc *
19*11be35a1SLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20*11be35a1SLionel Sambuc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21*11be35a1SLionel Sambuc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22*11be35a1SLionel Sambuc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23*11be35a1SLionel Sambuc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24*11be35a1SLionel Sambuc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25*11be35a1SLionel Sambuc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26*11be35a1SLionel Sambuc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27*11be35a1SLionel Sambuc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28*11be35a1SLionel Sambuc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29*11be35a1SLionel Sambuc * SUCH DAMAGE.
30*11be35a1SLionel Sambuc */
31*11be35a1SLionel Sambuc
32*11be35a1SLionel Sambuc #include <sys/cdefs.h>
33*11be35a1SLionel Sambuc #ifndef lint
34*11be35a1SLionel Sambuc __COPYRIGHT("@(#) Copyright (c) 1992, 1993, 1994\
35*11be35a1SLionel Sambuc The Regents of the University of California. All rights reserved.");
36*11be35a1SLionel Sambuc #endif /* not lint */
37*11be35a1SLionel Sambuc
38*11be35a1SLionel Sambuc #ifndef lint
39*11be35a1SLionel Sambuc #if 0
40*11be35a1SLionel Sambuc static char sccsid[] = "@(#)dbtest.c 8.17 (Berkeley) 9/1/94";
41*11be35a1SLionel Sambuc #else
42*11be35a1SLionel Sambuc __RCSID("$NetBSD: h_db.c,v 1.1 2011/01/07 15:05:58 pgoyette Exp $");
43*11be35a1SLionel Sambuc #endif
44*11be35a1SLionel Sambuc #endif /* not lint */
45*11be35a1SLionel Sambuc
46*11be35a1SLionel Sambuc #include <sys/param.h>
47*11be35a1SLionel Sambuc #include <sys/stat.h>
48*11be35a1SLionel Sambuc
49*11be35a1SLionel Sambuc #include <ctype.h>
50*11be35a1SLionel Sambuc #include <errno.h>
51*11be35a1SLionel Sambuc #include <fcntl.h>
52*11be35a1SLionel Sambuc #include <limits.h>
53*11be35a1SLionel Sambuc #include <stdio.h>
54*11be35a1SLionel Sambuc #include <stdlib.h>
55*11be35a1SLionel Sambuc #include <string.h>
56*11be35a1SLionel Sambuc #include <stdbool.h>
57*11be35a1SLionel Sambuc #include <unistd.h>
58*11be35a1SLionel Sambuc #include <err.h>
59*11be35a1SLionel Sambuc #include <db.h>
60*11be35a1SLionel Sambuc
61*11be35a1SLionel Sambuc enum S { COMMAND, COMPARE, GET, PUT, REMOVE, SEQ, SEQFLAG, KEY, DATA };
62*11be35a1SLionel Sambuc
63*11be35a1SLionel Sambuc static void compare(DBT *, DBT *);
64*11be35a1SLionel Sambuc static DBTYPE dbtype(const char *);
65*11be35a1SLionel Sambuc static void dump(DB *, int);
66*11be35a1SLionel Sambuc static void get(DB *, DBT *);
67*11be35a1SLionel Sambuc static void getdata(DB *, DBT *, DBT *);
68*11be35a1SLionel Sambuc static void put(DB *, DBT *, DBT *);
69*11be35a1SLionel Sambuc static void rem(DB *, DBT *);
70*11be35a1SLionel Sambuc static const char *sflags(int);
71*11be35a1SLionel Sambuc static void synk(DB *);
72*11be35a1SLionel Sambuc static void *rfile(char *, size_t *);
73*11be35a1SLionel Sambuc static void seq(DB *, DBT *);
74*11be35a1SLionel Sambuc static u_int setflags(char *);
75*11be35a1SLionel Sambuc static void *setinfo(DBTYPE, char *);
76*11be35a1SLionel Sambuc static void usage(void) __attribute__((__noreturn__));
77*11be35a1SLionel Sambuc static void *xcopy(void *, size_t);
78*11be35a1SLionel Sambuc static void chkcmd(enum S);
79*11be35a1SLionel Sambuc static void chkdata(enum S);
80*11be35a1SLionel Sambuc static void chkkey(enum S);
81*11be35a1SLionel Sambuc
82*11be35a1SLionel Sambuc #ifdef STATISTICS
83*11be35a1SLionel Sambuc extern void __bt_stat(DB *);
84*11be35a1SLionel Sambuc #endif
85*11be35a1SLionel Sambuc
86*11be35a1SLionel Sambuc static DBTYPE type; /* Database type. */
87*11be35a1SLionel Sambuc static void *infop; /* Iflags. */
88*11be35a1SLionel Sambuc static size_t lineno; /* Current line in test script. */
89*11be35a1SLionel Sambuc static u_int flags; /* Current DB flags. */
90*11be35a1SLionel Sambuc static int ofd = STDOUT_FILENO; /* Standard output fd. */
91*11be35a1SLionel Sambuc
92*11be35a1SLionel Sambuc static DB *XXdbp; /* Global for gdb. */
93*11be35a1SLionel Sambuc static size_t XXlineno; /* Fast breakpoint for gdb. */
94*11be35a1SLionel Sambuc
95*11be35a1SLionel Sambuc int
main(int argc,char * argv[])96*11be35a1SLionel Sambuc main(int argc, char *argv[])
97*11be35a1SLionel Sambuc {
98*11be35a1SLionel Sambuc extern int optind;
99*11be35a1SLionel Sambuc extern char *optarg;
100*11be35a1SLionel Sambuc enum S command = COMMAND, state;
101*11be35a1SLionel Sambuc DB *dbp;
102*11be35a1SLionel Sambuc DBT data, key, keydata;
103*11be35a1SLionel Sambuc size_t len;
104*11be35a1SLionel Sambuc int ch, oflags, sflag;
105*11be35a1SLionel Sambuc char *fname, *infoarg, *p, *t, buf[8 * 1024];
106*11be35a1SLionel Sambuc bool unlink_dbfile;
107*11be35a1SLionel Sambuc
108*11be35a1SLionel Sambuc infoarg = NULL;
109*11be35a1SLionel Sambuc fname = NULL;
110*11be35a1SLionel Sambuc unlink_dbfile = false;
111*11be35a1SLionel Sambuc oflags = O_CREAT | O_RDWR;
112*11be35a1SLionel Sambuc sflag = 0;
113*11be35a1SLionel Sambuc while ((ch = getopt(argc, argv, "f:i:lo:s")) != -1)
114*11be35a1SLionel Sambuc switch (ch) {
115*11be35a1SLionel Sambuc case 'f':
116*11be35a1SLionel Sambuc fname = optarg;
117*11be35a1SLionel Sambuc break;
118*11be35a1SLionel Sambuc case 'i':
119*11be35a1SLionel Sambuc infoarg = optarg;
120*11be35a1SLionel Sambuc break;
121*11be35a1SLionel Sambuc case 'l':
122*11be35a1SLionel Sambuc oflags |= DB_LOCK;
123*11be35a1SLionel Sambuc break;
124*11be35a1SLionel Sambuc case 'o':
125*11be35a1SLionel Sambuc if ((ofd = open(optarg,
126*11be35a1SLionel Sambuc O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
127*11be35a1SLionel Sambuc err(1, "Cannot create `%s'", optarg);
128*11be35a1SLionel Sambuc break;
129*11be35a1SLionel Sambuc case 's':
130*11be35a1SLionel Sambuc sflag = 1;
131*11be35a1SLionel Sambuc break;
132*11be35a1SLionel Sambuc case '?':
133*11be35a1SLionel Sambuc default:
134*11be35a1SLionel Sambuc usage();
135*11be35a1SLionel Sambuc }
136*11be35a1SLionel Sambuc argc -= optind;
137*11be35a1SLionel Sambuc argv += optind;
138*11be35a1SLionel Sambuc
139*11be35a1SLionel Sambuc if (argc != 2)
140*11be35a1SLionel Sambuc usage();
141*11be35a1SLionel Sambuc
142*11be35a1SLionel Sambuc /* Set the type. */
143*11be35a1SLionel Sambuc type = dbtype(*argv++);
144*11be35a1SLionel Sambuc
145*11be35a1SLionel Sambuc /* Open the descriptor file. */
146*11be35a1SLionel Sambuc if (strcmp(*argv, "-") && freopen(*argv, "r", stdin) == NULL)
147*11be35a1SLionel Sambuc err(1, "Cannot reopen `%s'", *argv);
148*11be35a1SLionel Sambuc
149*11be35a1SLionel Sambuc /* Set up the db structure as necessary. */
150*11be35a1SLionel Sambuc if (infoarg == NULL)
151*11be35a1SLionel Sambuc infop = NULL;
152*11be35a1SLionel Sambuc else
153*11be35a1SLionel Sambuc for (p = strtok(infoarg, ",\t "); p != NULL;
154*11be35a1SLionel Sambuc p = strtok(0, ",\t "))
155*11be35a1SLionel Sambuc if (*p != '\0')
156*11be35a1SLionel Sambuc infop = setinfo(type, p);
157*11be35a1SLionel Sambuc
158*11be35a1SLionel Sambuc /*
159*11be35a1SLionel Sambuc * Open the DB. Delete any preexisting copy, you almost never
160*11be35a1SLionel Sambuc * want it around, and it often screws up tests.
161*11be35a1SLionel Sambuc */
162*11be35a1SLionel Sambuc if (fname == NULL) {
163*11be35a1SLionel Sambuc const char *q = getenv("TMPDIR");
164*11be35a1SLionel Sambuc if (q == NULL)
165*11be35a1SLionel Sambuc q = "/var/tmp";
166*11be35a1SLionel Sambuc (void)snprintf(buf, sizeof(buf), "%s/__dbtest", q);
167*11be35a1SLionel Sambuc fname = buf;
168*11be35a1SLionel Sambuc (void)unlink(buf);
169*11be35a1SLionel Sambuc unlink_dbfile = true;
170*11be35a1SLionel Sambuc } else if (!sflag)
171*11be35a1SLionel Sambuc (void)unlink(fname);
172*11be35a1SLionel Sambuc
173*11be35a1SLionel Sambuc if ((dbp = dbopen(fname,
174*11be35a1SLionel Sambuc oflags, S_IRUSR | S_IWUSR, type, infop)) == NULL)
175*11be35a1SLionel Sambuc err(1, "Cannot dbopen `%s'", fname);
176*11be35a1SLionel Sambuc XXdbp = dbp;
177*11be35a1SLionel Sambuc if (unlink_dbfile)
178*11be35a1SLionel Sambuc (void)unlink(fname);
179*11be35a1SLionel Sambuc
180*11be35a1SLionel Sambuc state = COMMAND;
181*11be35a1SLionel Sambuc for (lineno = 1;
182*11be35a1SLionel Sambuc (p = fgets(buf, sizeof(buf), stdin)) != NULL; ++lineno) {
183*11be35a1SLionel Sambuc /* Delete the newline, displaying the key/data is easier. */
184*11be35a1SLionel Sambuc if (ofd == STDOUT_FILENO && (t = strchr(p, '\n')) != NULL)
185*11be35a1SLionel Sambuc *t = '\0';
186*11be35a1SLionel Sambuc if ((len = strlen(buf)) == 0 || isspace((unsigned char)*p) ||
187*11be35a1SLionel Sambuc *p == '#')
188*11be35a1SLionel Sambuc continue;
189*11be35a1SLionel Sambuc
190*11be35a1SLionel Sambuc /* Convenient gdb break point. */
191*11be35a1SLionel Sambuc if (XXlineno == lineno)
192*11be35a1SLionel Sambuc XXlineno = 1;
193*11be35a1SLionel Sambuc switch (*p) {
194*11be35a1SLionel Sambuc case 'c': /* compare */
195*11be35a1SLionel Sambuc chkcmd(state);
196*11be35a1SLionel Sambuc state = KEY;
197*11be35a1SLionel Sambuc command = COMPARE;
198*11be35a1SLionel Sambuc break;
199*11be35a1SLionel Sambuc case 'e': /* echo */
200*11be35a1SLionel Sambuc chkcmd(state);
201*11be35a1SLionel Sambuc /* Don't display the newline, if CR at EOL. */
202*11be35a1SLionel Sambuc if (p[len - 2] == '\r')
203*11be35a1SLionel Sambuc --len;
204*11be35a1SLionel Sambuc if (write(ofd, p + 1, len - 1) != (ssize_t)len - 1 ||
205*11be35a1SLionel Sambuc write(ofd, "\n", 1) != 1)
206*11be35a1SLionel Sambuc err(1, "write failed");
207*11be35a1SLionel Sambuc break;
208*11be35a1SLionel Sambuc case 'g': /* get */
209*11be35a1SLionel Sambuc chkcmd(state);
210*11be35a1SLionel Sambuc state = KEY;
211*11be35a1SLionel Sambuc command = GET;
212*11be35a1SLionel Sambuc break;
213*11be35a1SLionel Sambuc case 'p': /* put */
214*11be35a1SLionel Sambuc chkcmd(state);
215*11be35a1SLionel Sambuc state = KEY;
216*11be35a1SLionel Sambuc command = PUT;
217*11be35a1SLionel Sambuc break;
218*11be35a1SLionel Sambuc case 'r': /* remove */
219*11be35a1SLionel Sambuc chkcmd(state);
220*11be35a1SLionel Sambuc if (flags == R_CURSOR) {
221*11be35a1SLionel Sambuc rem(dbp, &key);
222*11be35a1SLionel Sambuc state = COMMAND;
223*11be35a1SLionel Sambuc } else {
224*11be35a1SLionel Sambuc state = KEY;
225*11be35a1SLionel Sambuc command = REMOVE;
226*11be35a1SLionel Sambuc }
227*11be35a1SLionel Sambuc break;
228*11be35a1SLionel Sambuc case 'S': /* sync */
229*11be35a1SLionel Sambuc chkcmd(state);
230*11be35a1SLionel Sambuc synk(dbp);
231*11be35a1SLionel Sambuc state = COMMAND;
232*11be35a1SLionel Sambuc break;
233*11be35a1SLionel Sambuc case 's': /* seq */
234*11be35a1SLionel Sambuc chkcmd(state);
235*11be35a1SLionel Sambuc if (flags == R_CURSOR) {
236*11be35a1SLionel Sambuc state = KEY;
237*11be35a1SLionel Sambuc command = SEQ;
238*11be35a1SLionel Sambuc } else
239*11be35a1SLionel Sambuc seq(dbp, &key);
240*11be35a1SLionel Sambuc break;
241*11be35a1SLionel Sambuc case 'f':
242*11be35a1SLionel Sambuc flags = setflags(p + 1);
243*11be35a1SLionel Sambuc break;
244*11be35a1SLionel Sambuc case 'D': /* data file */
245*11be35a1SLionel Sambuc chkdata(state);
246*11be35a1SLionel Sambuc data.data = rfile(p + 1, &data.size);
247*11be35a1SLionel Sambuc goto ldata;
248*11be35a1SLionel Sambuc case 'd': /* data */
249*11be35a1SLionel Sambuc chkdata(state);
250*11be35a1SLionel Sambuc data.data = xcopy(p + 1, len - 1);
251*11be35a1SLionel Sambuc data.size = len - 1;
252*11be35a1SLionel Sambuc ldata: switch (command) {
253*11be35a1SLionel Sambuc case COMPARE:
254*11be35a1SLionel Sambuc compare(&keydata, &data);
255*11be35a1SLionel Sambuc break;
256*11be35a1SLionel Sambuc case PUT:
257*11be35a1SLionel Sambuc put(dbp, &key, &data);
258*11be35a1SLionel Sambuc break;
259*11be35a1SLionel Sambuc default:
260*11be35a1SLionel Sambuc errx(1, "line %zu: command doesn't take data",
261*11be35a1SLionel Sambuc lineno);
262*11be35a1SLionel Sambuc }
263*11be35a1SLionel Sambuc if (type != DB_RECNO)
264*11be35a1SLionel Sambuc free(key.data);
265*11be35a1SLionel Sambuc free(data.data);
266*11be35a1SLionel Sambuc state = COMMAND;
267*11be35a1SLionel Sambuc break;
268*11be35a1SLionel Sambuc case 'K': /* key file */
269*11be35a1SLionel Sambuc chkkey(state);
270*11be35a1SLionel Sambuc if (type == DB_RECNO)
271*11be35a1SLionel Sambuc errx(1, "line %zu: 'K' not available for recno",
272*11be35a1SLionel Sambuc lineno);
273*11be35a1SLionel Sambuc key.data = rfile(p + 1, &key.size);
274*11be35a1SLionel Sambuc goto lkey;
275*11be35a1SLionel Sambuc case 'k': /* key */
276*11be35a1SLionel Sambuc chkkey(state);
277*11be35a1SLionel Sambuc if (type == DB_RECNO) {
278*11be35a1SLionel Sambuc static recno_t recno;
279*11be35a1SLionel Sambuc recno = atoi(p + 1);
280*11be35a1SLionel Sambuc key.data = &recno;
281*11be35a1SLionel Sambuc key.size = sizeof(recno);
282*11be35a1SLionel Sambuc } else {
283*11be35a1SLionel Sambuc key.data = xcopy(p + 1, len - 1);
284*11be35a1SLionel Sambuc key.size = len - 1;
285*11be35a1SLionel Sambuc }
286*11be35a1SLionel Sambuc lkey: switch (command) {
287*11be35a1SLionel Sambuc case COMPARE:
288*11be35a1SLionel Sambuc getdata(dbp, &key, &keydata);
289*11be35a1SLionel Sambuc state = DATA;
290*11be35a1SLionel Sambuc break;
291*11be35a1SLionel Sambuc case GET:
292*11be35a1SLionel Sambuc get(dbp, &key);
293*11be35a1SLionel Sambuc if (type != DB_RECNO)
294*11be35a1SLionel Sambuc free(key.data);
295*11be35a1SLionel Sambuc state = COMMAND;
296*11be35a1SLionel Sambuc break;
297*11be35a1SLionel Sambuc case PUT:
298*11be35a1SLionel Sambuc state = DATA;
299*11be35a1SLionel Sambuc break;
300*11be35a1SLionel Sambuc case REMOVE:
301*11be35a1SLionel Sambuc rem(dbp, &key);
302*11be35a1SLionel Sambuc if ((type != DB_RECNO) && (flags != R_CURSOR))
303*11be35a1SLionel Sambuc free(key.data);
304*11be35a1SLionel Sambuc state = COMMAND;
305*11be35a1SLionel Sambuc break;
306*11be35a1SLionel Sambuc case SEQ:
307*11be35a1SLionel Sambuc seq(dbp, &key);
308*11be35a1SLionel Sambuc if ((type != DB_RECNO) && (flags != R_CURSOR))
309*11be35a1SLionel Sambuc free(key.data);
310*11be35a1SLionel Sambuc state = COMMAND;
311*11be35a1SLionel Sambuc break;
312*11be35a1SLionel Sambuc default:
313*11be35a1SLionel Sambuc errx(1, "line %zu: command doesn't take a key",
314*11be35a1SLionel Sambuc lineno);
315*11be35a1SLionel Sambuc }
316*11be35a1SLionel Sambuc break;
317*11be35a1SLionel Sambuc case 'o':
318*11be35a1SLionel Sambuc dump(dbp, p[1] == 'r');
319*11be35a1SLionel Sambuc break;
320*11be35a1SLionel Sambuc default:
321*11be35a1SLionel Sambuc errx(1, "line %zu: %s: unknown command character",
322*11be35a1SLionel Sambuc lineno, p);
323*11be35a1SLionel Sambuc }
324*11be35a1SLionel Sambuc }
325*11be35a1SLionel Sambuc #ifdef STATISTICS
326*11be35a1SLionel Sambuc /*
327*11be35a1SLionel Sambuc * -l must be used (DB_LOCK must be set) for this to be
328*11be35a1SLionel Sambuc * used, otherwise a page will be locked and it will fail.
329*11be35a1SLionel Sambuc */
330*11be35a1SLionel Sambuc if (type == DB_BTREE && oflags & DB_LOCK)
331*11be35a1SLionel Sambuc __bt_stat(dbp);
332*11be35a1SLionel Sambuc #endif
333*11be35a1SLionel Sambuc if ((*dbp->close)(dbp))
334*11be35a1SLionel Sambuc err(1, "db->close failed");
335*11be35a1SLionel Sambuc (void)close(ofd);
336*11be35a1SLionel Sambuc return 0;
337*11be35a1SLionel Sambuc }
338*11be35a1SLionel Sambuc
339*11be35a1SLionel Sambuc #define NOOVERWRITE "put failed, would overwrite key\n"
340*11be35a1SLionel Sambuc
341*11be35a1SLionel Sambuc static void
compare(DBT * db1,DBT * db2)342*11be35a1SLionel Sambuc compare(DBT *db1, DBT *db2)
343*11be35a1SLionel Sambuc {
344*11be35a1SLionel Sambuc size_t len;
345*11be35a1SLionel Sambuc u_char *p1, *p2;
346*11be35a1SLionel Sambuc
347*11be35a1SLionel Sambuc if (db1->size != db2->size)
348*11be35a1SLionel Sambuc printf("compare failed: key->data len %zu != data len %zu\n",
349*11be35a1SLionel Sambuc db1->size, db2->size);
350*11be35a1SLionel Sambuc
351*11be35a1SLionel Sambuc len = MIN(db1->size, db2->size);
352*11be35a1SLionel Sambuc for (p1 = db1->data, p2 = db2->data; len--;)
353*11be35a1SLionel Sambuc if (*p1++ != *p2++) {
354*11be35a1SLionel Sambuc printf("compare failed at offset %lu\n",
355*11be35a1SLionel Sambuc (unsigned long)(p1 - (u_char *)db1->data));
356*11be35a1SLionel Sambuc break;
357*11be35a1SLionel Sambuc }
358*11be35a1SLionel Sambuc }
359*11be35a1SLionel Sambuc
360*11be35a1SLionel Sambuc static void
get(DB * dbp,DBT * kp)361*11be35a1SLionel Sambuc get(DB *dbp, DBT *kp)
362*11be35a1SLionel Sambuc {
363*11be35a1SLionel Sambuc DBT data;
364*11be35a1SLionel Sambuc
365*11be35a1SLionel Sambuc switch ((*dbp->get)(dbp, kp, &data, flags)) {
366*11be35a1SLionel Sambuc case 0:
367*11be35a1SLionel Sambuc (void)write(ofd, data.data, data.size);
368*11be35a1SLionel Sambuc if (ofd == STDOUT_FILENO)
369*11be35a1SLionel Sambuc (void)write(ofd, "\n", 1);
370*11be35a1SLionel Sambuc break;
371*11be35a1SLionel Sambuc case -1:
372*11be35a1SLionel Sambuc err(1, "line %zu: get failed", lineno);
373*11be35a1SLionel Sambuc /* NOTREACHED */
374*11be35a1SLionel Sambuc case 1:
375*11be35a1SLionel Sambuc #define NOSUCHKEY "get failed, no such key\n"
376*11be35a1SLionel Sambuc if (ofd != STDOUT_FILENO)
377*11be35a1SLionel Sambuc (void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1);
378*11be35a1SLionel Sambuc else
379*11be35a1SLionel Sambuc (void)fprintf(stderr, "%zu: %.*s: %s",
380*11be35a1SLionel Sambuc lineno, (int)MIN(kp->size, 20),
381*11be35a1SLionel Sambuc (const char *)kp->data,
382*11be35a1SLionel Sambuc NOSUCHKEY);
383*11be35a1SLionel Sambuc #undef NOSUCHKEY
384*11be35a1SLionel Sambuc break;
385*11be35a1SLionel Sambuc }
386*11be35a1SLionel Sambuc }
387*11be35a1SLionel Sambuc
388*11be35a1SLionel Sambuc static void
getdata(DB * dbp,DBT * kp,DBT * dp)389*11be35a1SLionel Sambuc getdata(DB *dbp, DBT *kp, DBT *dp)
390*11be35a1SLionel Sambuc {
391*11be35a1SLionel Sambuc switch ((*dbp->get)(dbp, kp, dp, flags)) {
392*11be35a1SLionel Sambuc case 0:
393*11be35a1SLionel Sambuc return;
394*11be35a1SLionel Sambuc case -1:
395*11be35a1SLionel Sambuc err(1, "line %zu: getdata failed", lineno);
396*11be35a1SLionel Sambuc /* NOTREACHED */
397*11be35a1SLionel Sambuc case 1:
398*11be35a1SLionel Sambuc errx(1, "line %zu: getdata failed, no such key", lineno);
399*11be35a1SLionel Sambuc /* NOTREACHED */
400*11be35a1SLionel Sambuc }
401*11be35a1SLionel Sambuc }
402*11be35a1SLionel Sambuc
403*11be35a1SLionel Sambuc static void
put(DB * dbp,DBT * kp,DBT * dp)404*11be35a1SLionel Sambuc put(DB *dbp, DBT *kp, DBT *dp)
405*11be35a1SLionel Sambuc {
406*11be35a1SLionel Sambuc switch ((*dbp->put)(dbp, kp, dp, flags)) {
407*11be35a1SLionel Sambuc case 0:
408*11be35a1SLionel Sambuc break;
409*11be35a1SLionel Sambuc case -1:
410*11be35a1SLionel Sambuc err(1, "line %zu: put failed", lineno);
411*11be35a1SLionel Sambuc /* NOTREACHED */
412*11be35a1SLionel Sambuc case 1:
413*11be35a1SLionel Sambuc (void)write(ofd, NOOVERWRITE, sizeof(NOOVERWRITE) - 1);
414*11be35a1SLionel Sambuc break;
415*11be35a1SLionel Sambuc }
416*11be35a1SLionel Sambuc }
417*11be35a1SLionel Sambuc
418*11be35a1SLionel Sambuc static void
rem(DB * dbp,DBT * kp)419*11be35a1SLionel Sambuc rem(DB *dbp, DBT *kp)
420*11be35a1SLionel Sambuc {
421*11be35a1SLionel Sambuc switch ((*dbp->del)(dbp, kp, flags)) {
422*11be35a1SLionel Sambuc case 0:
423*11be35a1SLionel Sambuc break;
424*11be35a1SLionel Sambuc case -1:
425*11be35a1SLionel Sambuc err(1, "line %zu: rem failed", lineno);
426*11be35a1SLionel Sambuc /* NOTREACHED */
427*11be35a1SLionel Sambuc case 1:
428*11be35a1SLionel Sambuc #define NOSUCHKEY "rem failed, no such key\n"
429*11be35a1SLionel Sambuc if (ofd != STDOUT_FILENO)
430*11be35a1SLionel Sambuc (void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1);
431*11be35a1SLionel Sambuc else if (flags != R_CURSOR)
432*11be35a1SLionel Sambuc (void)fprintf(stderr, "%zu: %.*s: %s",
433*11be35a1SLionel Sambuc lineno, (int)MIN(kp->size, 20),
434*11be35a1SLionel Sambuc (const char *)kp->data, NOSUCHKEY);
435*11be35a1SLionel Sambuc else
436*11be35a1SLionel Sambuc (void)fprintf(stderr,
437*11be35a1SLionel Sambuc "%zu: rem of cursor failed\n", lineno);
438*11be35a1SLionel Sambuc #undef NOSUCHKEY
439*11be35a1SLionel Sambuc break;
440*11be35a1SLionel Sambuc }
441*11be35a1SLionel Sambuc }
442*11be35a1SLionel Sambuc
443*11be35a1SLionel Sambuc static void
synk(DB * dbp)444*11be35a1SLionel Sambuc synk(DB *dbp)
445*11be35a1SLionel Sambuc {
446*11be35a1SLionel Sambuc switch ((*dbp->sync)(dbp, flags)) {
447*11be35a1SLionel Sambuc case 0:
448*11be35a1SLionel Sambuc break;
449*11be35a1SLionel Sambuc case -1:
450*11be35a1SLionel Sambuc err(1, "line %zu: synk failed", lineno);
451*11be35a1SLionel Sambuc /* NOTREACHED */
452*11be35a1SLionel Sambuc }
453*11be35a1SLionel Sambuc }
454*11be35a1SLionel Sambuc
455*11be35a1SLionel Sambuc static void
seq(DB * dbp,DBT * kp)456*11be35a1SLionel Sambuc seq(DB *dbp, DBT *kp)
457*11be35a1SLionel Sambuc {
458*11be35a1SLionel Sambuc DBT data;
459*11be35a1SLionel Sambuc
460*11be35a1SLionel Sambuc switch (dbp->seq(dbp, kp, &data, flags)) {
461*11be35a1SLionel Sambuc case 0:
462*11be35a1SLionel Sambuc (void)write(ofd, data.data, data.size);
463*11be35a1SLionel Sambuc if (ofd == STDOUT_FILENO)
464*11be35a1SLionel Sambuc (void)write(ofd, "\n", 1);
465*11be35a1SLionel Sambuc break;
466*11be35a1SLionel Sambuc case -1:
467*11be35a1SLionel Sambuc err(1, "line %zu: seq failed", lineno);
468*11be35a1SLionel Sambuc /* NOTREACHED */
469*11be35a1SLionel Sambuc case 1:
470*11be35a1SLionel Sambuc #define NOSUCHKEY "seq failed, no such key\n"
471*11be35a1SLionel Sambuc if (ofd != STDOUT_FILENO)
472*11be35a1SLionel Sambuc (void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1);
473*11be35a1SLionel Sambuc else if (flags == R_CURSOR)
474*11be35a1SLionel Sambuc (void)fprintf(stderr, "%zu: %.*s: %s",
475*11be35a1SLionel Sambuc lineno, (int)MIN(kp->size, 20),
476*11be35a1SLionel Sambuc (const char *)kp->data, NOSUCHKEY);
477*11be35a1SLionel Sambuc else
478*11be35a1SLionel Sambuc (void)fprintf(stderr,
479*11be35a1SLionel Sambuc "%zu: seq (%s) failed\n", lineno, sflags(flags));
480*11be35a1SLionel Sambuc #undef NOSUCHKEY
481*11be35a1SLionel Sambuc break;
482*11be35a1SLionel Sambuc }
483*11be35a1SLionel Sambuc }
484*11be35a1SLionel Sambuc
485*11be35a1SLionel Sambuc static void
dump(DB * dbp,int rev)486*11be35a1SLionel Sambuc dump(DB *dbp, int rev)
487*11be35a1SLionel Sambuc {
488*11be35a1SLionel Sambuc DBT key, data;
489*11be35a1SLionel Sambuc int xflags, nflags;
490*11be35a1SLionel Sambuc
491*11be35a1SLionel Sambuc if (rev) {
492*11be35a1SLionel Sambuc xflags = R_LAST;
493*11be35a1SLionel Sambuc nflags = R_PREV;
494*11be35a1SLionel Sambuc } else {
495*11be35a1SLionel Sambuc xflags = R_FIRST;
496*11be35a1SLionel Sambuc nflags = R_NEXT;
497*11be35a1SLionel Sambuc }
498*11be35a1SLionel Sambuc for (;; xflags = nflags)
499*11be35a1SLionel Sambuc switch (dbp->seq(dbp, &key, &data, xflags)) {
500*11be35a1SLionel Sambuc case 0:
501*11be35a1SLionel Sambuc (void)write(ofd, data.data, data.size);
502*11be35a1SLionel Sambuc if (ofd == STDOUT_FILENO)
503*11be35a1SLionel Sambuc (void)write(ofd, "\n", 1);
504*11be35a1SLionel Sambuc break;
505*11be35a1SLionel Sambuc case 1:
506*11be35a1SLionel Sambuc goto done;
507*11be35a1SLionel Sambuc case -1:
508*11be35a1SLionel Sambuc err(1, "line %zu: (dump) seq failed", lineno);
509*11be35a1SLionel Sambuc /* NOTREACHED */
510*11be35a1SLionel Sambuc }
511*11be35a1SLionel Sambuc done: return;
512*11be35a1SLionel Sambuc }
513*11be35a1SLionel Sambuc
514*11be35a1SLionel Sambuc static u_int
setflags(char * s)515*11be35a1SLionel Sambuc setflags(char *s)
516*11be35a1SLionel Sambuc {
517*11be35a1SLionel Sambuc char *p;
518*11be35a1SLionel Sambuc
519*11be35a1SLionel Sambuc for (; isspace((unsigned char)*s); ++s);
520*11be35a1SLionel Sambuc if (*s == '\n' || *s == '\0')
521*11be35a1SLionel Sambuc return 0;
522*11be35a1SLionel Sambuc if ((p = strchr(s, '\n')) != NULL)
523*11be35a1SLionel Sambuc *p = '\0';
524*11be35a1SLionel Sambuc if (!strcmp(s, "R_CURSOR")) return R_CURSOR;
525*11be35a1SLionel Sambuc if (!strcmp(s, "R_FIRST")) return R_FIRST;
526*11be35a1SLionel Sambuc if (!strcmp(s, "R_IAFTER")) return R_IAFTER;
527*11be35a1SLionel Sambuc if (!strcmp(s, "R_IBEFORE")) return R_IBEFORE;
528*11be35a1SLionel Sambuc if (!strcmp(s, "R_LAST")) return R_LAST;
529*11be35a1SLionel Sambuc if (!strcmp(s, "R_NEXT")) return R_NEXT;
530*11be35a1SLionel Sambuc if (!strcmp(s, "R_NOOVERWRITE")) return R_NOOVERWRITE;
531*11be35a1SLionel Sambuc if (!strcmp(s, "R_PREV")) return R_PREV;
532*11be35a1SLionel Sambuc if (!strcmp(s, "R_SETCURSOR")) return R_SETCURSOR;
533*11be35a1SLionel Sambuc
534*11be35a1SLionel Sambuc errx(1, "line %zu: %s: unknown flag", lineno, s);
535*11be35a1SLionel Sambuc /* NOTREACHED */
536*11be35a1SLionel Sambuc }
537*11be35a1SLionel Sambuc
538*11be35a1SLionel Sambuc static const char *
sflags(int xflags)539*11be35a1SLionel Sambuc sflags(int xflags)
540*11be35a1SLionel Sambuc {
541*11be35a1SLionel Sambuc switch (xflags) {
542*11be35a1SLionel Sambuc case R_CURSOR: return "R_CURSOR";
543*11be35a1SLionel Sambuc case R_FIRST: return "R_FIRST";
544*11be35a1SLionel Sambuc case R_IAFTER: return "R_IAFTER";
545*11be35a1SLionel Sambuc case R_IBEFORE: return "R_IBEFORE";
546*11be35a1SLionel Sambuc case R_LAST: return "R_LAST";
547*11be35a1SLionel Sambuc case R_NEXT: return "R_NEXT";
548*11be35a1SLionel Sambuc case R_NOOVERWRITE: return "R_NOOVERWRITE";
549*11be35a1SLionel Sambuc case R_PREV: return "R_PREV";
550*11be35a1SLionel Sambuc case R_SETCURSOR: return "R_SETCURSOR";
551*11be35a1SLionel Sambuc }
552*11be35a1SLionel Sambuc
553*11be35a1SLionel Sambuc return "UNKNOWN!";
554*11be35a1SLionel Sambuc }
555*11be35a1SLionel Sambuc
556*11be35a1SLionel Sambuc static DBTYPE
dbtype(const char * s)557*11be35a1SLionel Sambuc dbtype(const char *s)
558*11be35a1SLionel Sambuc {
559*11be35a1SLionel Sambuc if (!strcmp(s, "btree"))
560*11be35a1SLionel Sambuc return DB_BTREE;
561*11be35a1SLionel Sambuc if (!strcmp(s, "hash"))
562*11be35a1SLionel Sambuc return DB_HASH;
563*11be35a1SLionel Sambuc if (!strcmp(s, "recno"))
564*11be35a1SLionel Sambuc return DB_RECNO;
565*11be35a1SLionel Sambuc errx(1, "%s: unknown type (use btree, hash or recno)", s);
566*11be35a1SLionel Sambuc /* NOTREACHED */
567*11be35a1SLionel Sambuc }
568*11be35a1SLionel Sambuc
569*11be35a1SLionel Sambuc static void *
setinfo(DBTYPE dtype,char * s)570*11be35a1SLionel Sambuc setinfo(DBTYPE dtype, char *s)
571*11be35a1SLionel Sambuc {
572*11be35a1SLionel Sambuc static BTREEINFO ib;
573*11be35a1SLionel Sambuc static HASHINFO ih;
574*11be35a1SLionel Sambuc static RECNOINFO rh;
575*11be35a1SLionel Sambuc char *eq;
576*11be35a1SLionel Sambuc
577*11be35a1SLionel Sambuc if ((eq = strchr(s, '=')) == NULL)
578*11be35a1SLionel Sambuc errx(1, "%s: illegal structure set statement", s);
579*11be35a1SLionel Sambuc *eq++ = '\0';
580*11be35a1SLionel Sambuc if (!isdigit((unsigned char)*eq))
581*11be35a1SLionel Sambuc errx(1, "%s: structure set statement must be a number", s);
582*11be35a1SLionel Sambuc
583*11be35a1SLionel Sambuc switch (dtype) {
584*11be35a1SLionel Sambuc case DB_BTREE:
585*11be35a1SLionel Sambuc if (!strcmp("flags", s)) {
586*11be35a1SLionel Sambuc ib.flags = atoi(eq);
587*11be35a1SLionel Sambuc return &ib;
588*11be35a1SLionel Sambuc }
589*11be35a1SLionel Sambuc if (!strcmp("cachesize", s)) {
590*11be35a1SLionel Sambuc ib.cachesize = atoi(eq);
591*11be35a1SLionel Sambuc return &ib;
592*11be35a1SLionel Sambuc }
593*11be35a1SLionel Sambuc if (!strcmp("maxkeypage", s)) {
594*11be35a1SLionel Sambuc ib.maxkeypage = atoi(eq);
595*11be35a1SLionel Sambuc return &ib;
596*11be35a1SLionel Sambuc }
597*11be35a1SLionel Sambuc if (!strcmp("minkeypage", s)) {
598*11be35a1SLionel Sambuc ib.minkeypage = atoi(eq);
599*11be35a1SLionel Sambuc return &ib;
600*11be35a1SLionel Sambuc }
601*11be35a1SLionel Sambuc if (!strcmp("lorder", s)) {
602*11be35a1SLionel Sambuc ib.lorder = atoi(eq);
603*11be35a1SLionel Sambuc return &ib;
604*11be35a1SLionel Sambuc }
605*11be35a1SLionel Sambuc if (!strcmp("psize", s)) {
606*11be35a1SLionel Sambuc ib.psize = atoi(eq);
607*11be35a1SLionel Sambuc return &ib;
608*11be35a1SLionel Sambuc }
609*11be35a1SLionel Sambuc break;
610*11be35a1SLionel Sambuc case DB_HASH:
611*11be35a1SLionel Sambuc if (!strcmp("bsize", s)) {
612*11be35a1SLionel Sambuc ih.bsize = atoi(eq);
613*11be35a1SLionel Sambuc return &ih;
614*11be35a1SLionel Sambuc }
615*11be35a1SLionel Sambuc if (!strcmp("ffactor", s)) {
616*11be35a1SLionel Sambuc ih.ffactor = atoi(eq);
617*11be35a1SLionel Sambuc return &ih;
618*11be35a1SLionel Sambuc }
619*11be35a1SLionel Sambuc if (!strcmp("nelem", s)) {
620*11be35a1SLionel Sambuc ih.nelem = atoi(eq);
621*11be35a1SLionel Sambuc return &ih;
622*11be35a1SLionel Sambuc }
623*11be35a1SLionel Sambuc if (!strcmp("cachesize", s)) {
624*11be35a1SLionel Sambuc ih.cachesize = atoi(eq);
625*11be35a1SLionel Sambuc return &ih;
626*11be35a1SLionel Sambuc }
627*11be35a1SLionel Sambuc if (!strcmp("lorder", s)) {
628*11be35a1SLionel Sambuc ih.lorder = atoi(eq);
629*11be35a1SLionel Sambuc return &ih;
630*11be35a1SLionel Sambuc }
631*11be35a1SLionel Sambuc break;
632*11be35a1SLionel Sambuc case DB_RECNO:
633*11be35a1SLionel Sambuc if (!strcmp("flags", s)) {
634*11be35a1SLionel Sambuc rh.flags = atoi(eq);
635*11be35a1SLionel Sambuc return &rh;
636*11be35a1SLionel Sambuc }
637*11be35a1SLionel Sambuc if (!strcmp("cachesize", s)) {
638*11be35a1SLionel Sambuc rh.cachesize = atoi(eq);
639*11be35a1SLionel Sambuc return &rh;
640*11be35a1SLionel Sambuc }
641*11be35a1SLionel Sambuc if (!strcmp("lorder", s)) {
642*11be35a1SLionel Sambuc rh.lorder = atoi(eq);
643*11be35a1SLionel Sambuc return &rh;
644*11be35a1SLionel Sambuc }
645*11be35a1SLionel Sambuc if (!strcmp("reclen", s)) {
646*11be35a1SLionel Sambuc rh.reclen = atoi(eq);
647*11be35a1SLionel Sambuc return &rh;
648*11be35a1SLionel Sambuc }
649*11be35a1SLionel Sambuc if (!strcmp("bval", s)) {
650*11be35a1SLionel Sambuc rh.bval = atoi(eq);
651*11be35a1SLionel Sambuc return &rh;
652*11be35a1SLionel Sambuc }
653*11be35a1SLionel Sambuc if (!strcmp("psize", s)) {
654*11be35a1SLionel Sambuc rh.psize = atoi(eq);
655*11be35a1SLionel Sambuc return &rh;
656*11be35a1SLionel Sambuc }
657*11be35a1SLionel Sambuc break;
658*11be35a1SLionel Sambuc }
659*11be35a1SLionel Sambuc errx(1, "%s: unknown structure value", s);
660*11be35a1SLionel Sambuc /* NOTREACHED */
661*11be35a1SLionel Sambuc }
662*11be35a1SLionel Sambuc
663*11be35a1SLionel Sambuc static void *
rfile(char * name,size_t * lenp)664*11be35a1SLionel Sambuc rfile(char *name, size_t *lenp)
665*11be35a1SLionel Sambuc {
666*11be35a1SLionel Sambuc struct stat sb;
667*11be35a1SLionel Sambuc void *p;
668*11be35a1SLionel Sambuc int fd;
669*11be35a1SLionel Sambuc char *np;
670*11be35a1SLionel Sambuc
671*11be35a1SLionel Sambuc for (; isspace((unsigned char)*name); ++name)
672*11be35a1SLionel Sambuc continue;
673*11be35a1SLionel Sambuc if ((np = strchr(name, '\n')) != NULL)
674*11be35a1SLionel Sambuc *np = '\0';
675*11be35a1SLionel Sambuc if ((fd = open(name, O_RDONLY, 0)) == -1 || fstat(fd, &sb) == -1)
676*11be35a1SLionel Sambuc err(1, "Cannot open `%s'", name);
677*11be35a1SLionel Sambuc #ifdef NOT_PORTABLE
678*11be35a1SLionel Sambuc if (sb.st_size > (off_t)SIZE_T_MAX) {
679*11be35a1SLionel Sambuc errno = E2BIG;
680*11be35a1SLionel Sambuc err("Cannot process `%s'", name);
681*11be35a1SLionel Sambuc }
682*11be35a1SLionel Sambuc #endif
683*11be35a1SLionel Sambuc if ((p = malloc((size_t)sb.st_size)) == NULL)
684*11be35a1SLionel Sambuc err(1, "Cannot allocate %zu bytes", (size_t)sb.st_size);
685*11be35a1SLionel Sambuc if (read(fd, p, (ssize_t)sb.st_size) != (ssize_t)sb.st_size)
686*11be35a1SLionel Sambuc err(1, "read failed");
687*11be35a1SLionel Sambuc *lenp = (size_t)sb.st_size;
688*11be35a1SLionel Sambuc (void)close(fd);
689*11be35a1SLionel Sambuc return p;
690*11be35a1SLionel Sambuc }
691*11be35a1SLionel Sambuc
692*11be35a1SLionel Sambuc static void *
xcopy(void * text,size_t len)693*11be35a1SLionel Sambuc xcopy(void *text, size_t len)
694*11be35a1SLionel Sambuc {
695*11be35a1SLionel Sambuc void *p;
696*11be35a1SLionel Sambuc
697*11be35a1SLionel Sambuc if ((p = malloc(len)) == NULL)
698*11be35a1SLionel Sambuc err(1, "Cannot allocate %zu bytes", len);
699*11be35a1SLionel Sambuc (void)memmove(p, text, len);
700*11be35a1SLionel Sambuc return p;
701*11be35a1SLionel Sambuc }
702*11be35a1SLionel Sambuc
703*11be35a1SLionel Sambuc static void
chkcmd(enum S state)704*11be35a1SLionel Sambuc chkcmd(enum S state)
705*11be35a1SLionel Sambuc {
706*11be35a1SLionel Sambuc if (state != COMMAND)
707*11be35a1SLionel Sambuc errx(1, "line %zu: not expecting command", lineno);
708*11be35a1SLionel Sambuc }
709*11be35a1SLionel Sambuc
710*11be35a1SLionel Sambuc static void
chkdata(enum S state)711*11be35a1SLionel Sambuc chkdata(enum S state)
712*11be35a1SLionel Sambuc {
713*11be35a1SLionel Sambuc if (state != DATA)
714*11be35a1SLionel Sambuc errx(1, "line %zu: not expecting data", lineno);
715*11be35a1SLionel Sambuc }
716*11be35a1SLionel Sambuc
717*11be35a1SLionel Sambuc static void
chkkey(enum S state)718*11be35a1SLionel Sambuc chkkey(enum S state)
719*11be35a1SLionel Sambuc {
720*11be35a1SLionel Sambuc if (state != KEY)
721*11be35a1SLionel Sambuc errx(1, "line %zu: not expecting a key", lineno);
722*11be35a1SLionel Sambuc }
723*11be35a1SLionel Sambuc
724*11be35a1SLionel Sambuc static void
usage(void)725*11be35a1SLionel Sambuc usage(void)
726*11be35a1SLionel Sambuc {
727*11be35a1SLionel Sambuc (void)fprintf(stderr,
728*11be35a1SLionel Sambuc "Usage: %s [-l] [-f file] [-i info] [-o file] type script\n",
729*11be35a1SLionel Sambuc getprogname());
730*11be35a1SLionel Sambuc exit(1);
731*11be35a1SLionel Sambuc }
732