xref: /csrg-svn/lib/libc/db/test/dbtest.c (revision 56039)
1*56039Sbostic /*-
2*56039Sbostic  * Copyright (c) 1992 The Regents of the University of California.
3*56039Sbostic  * All rights reserved.
4*56039Sbostic  *
5*56039Sbostic  * %sccs.include.redist.c%
6*56039Sbostic  */
7*56039Sbostic 
8*56039Sbostic #ifndef lint
9*56039Sbostic char copyright[] =
10*56039Sbostic "@(#) Copyright (c) 1992 The Regents of the University of California.\n\
11*56039Sbostic  All rights reserved.\n";
12*56039Sbostic #endif /* not lint */
13*56039Sbostic 
14*56039Sbostic #ifndef lint
15*56039Sbostic static char sccsid[] = "@(#)dbtest.c	5.1 (Berkeley) 08/26/92";
16*56039Sbostic #endif /* not lint */
17*56039Sbostic 
18*56039Sbostic #include <sys/param.h>
19*56039Sbostic #include <sys/stat.h>
20*56039Sbostic 
21*56039Sbostic #include <ctype.h>
22*56039Sbostic #include <db.h>
23*56039Sbostic #include <errno.h>
24*56039Sbostic #include <fcntl.h>
25*56039Sbostic #include <limits.h>
26*56039Sbostic #include <stdio.h>
27*56039Sbostic #include <stdlib.h>
28*56039Sbostic #include <string.h>
29*56039Sbostic #include <unistd.h>
30*56039Sbostic 
31*56039Sbostic enum S { COMMAND, GET, PUT, REMOVE, SEQ, SEQFLAG, KEY, DATA };
32*56039Sbostic 
33*56039Sbostic DBTYPE	 dbtype __P((char *));
34*56039Sbostic void	 err __P((const char *, ...));
35*56039Sbostic void	 get __P((DB *, DBT *));
36*56039Sbostic void	 put __P((DB *, DBT *, DBT *));
37*56039Sbostic void	 rem __P((DB *, DBT *));
38*56039Sbostic void	*rfile __P((char *, size_t *));
39*56039Sbostic void	 seq __P((DB *));
40*56039Sbostic u_int	 setflags __P((char *));
41*56039Sbostic void	*setinfo __P((DBTYPE, char *));
42*56039Sbostic void	 usage __P((void));
43*56039Sbostic void	*xmalloc __P((char *, size_t));
44*56039Sbostic 
45*56039Sbostic DBTYPE type;
46*56039Sbostic void *infop;
47*56039Sbostic u_long lineno;
48*56039Sbostic u_int flags;
49*56039Sbostic int ofd = STDOUT_FILENO;
50*56039Sbostic 
51*56039Sbostic int
52*56039Sbostic main(argc, argv)
53*56039Sbostic 	int argc;
54*56039Sbostic 	char *argv[];
55*56039Sbostic {
56*56039Sbostic 	enum S command, state;
57*56039Sbostic 	DB *dbp;
58*56039Sbostic 	DBT data, key;
59*56039Sbostic 	size_t len;
60*56039Sbostic 	int ch;
61*56039Sbostic 	char *infoarg, *p, buf[8 * 1024];
62*56039Sbostic 
63*56039Sbostic 	infoarg = NULL;
64*56039Sbostic 	while ((ch = getopt(argc, argv, "i:o:")) != EOF)
65*56039Sbostic 		switch(ch) {
66*56039Sbostic 		case 'i':
67*56039Sbostic 			infoarg = optarg;
68*56039Sbostic 			break;
69*56039Sbostic 		case 'o':
70*56039Sbostic 			if ((ofd = open(optarg,
71*56039Sbostic 			    O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
72*56039Sbostic 				err("%s: %s", optarg, strerror(errno));
73*56039Sbostic 			break;
74*56039Sbostic 		case '?':
75*56039Sbostic 		default:
76*56039Sbostic 			usage();
77*56039Sbostic 		}
78*56039Sbostic 	argc -= optind;
79*56039Sbostic 	argv += optind;
80*56039Sbostic 
81*56039Sbostic 	if (argc != 2)
82*56039Sbostic 		usage();
83*56039Sbostic 
84*56039Sbostic 	/* Set the type. */
85*56039Sbostic 	type = dbtype(*argv++);
86*56039Sbostic 
87*56039Sbostic 	/* Open the descriptor file. */
88*56039Sbostic 	if (freopen(*argv, "r", stdin) == NULL)
89*56039Sbostic 		err("%s: %s", *argv, strerror(errno));
90*56039Sbostic 
91*56039Sbostic 	/* Set up the db structure as necessary. */
92*56039Sbostic 	if (infoarg == NULL)
93*56039Sbostic 		infop = NULL;
94*56039Sbostic 	else
95*56039Sbostic 		while ((p = strsep(&infoarg, ",\t ")) != NULL)
96*56039Sbostic 			if (*p != '\0')
97*56039Sbostic 				infop = setinfo(type, p);
98*56039Sbostic 
99*56039Sbostic #define	BACKINGFILE	"/tmp/__dbtest"
100*56039Sbostic 	/* Open the DB. */
101*56039Sbostic 	(void)unlink(BACKINGFILE);
102*56039Sbostic 	if ((dbp = dbopen(BACKINGFILE,
103*56039Sbostic 	    O_CREAT | O_RDWR, S_IRUSR | S_IWUSR, type, infop)) == NULL)
104*56039Sbostic 		err("dbopen: %s", strerror(errno));
105*56039Sbostic 
106*56039Sbostic 	state = COMMAND;
107*56039Sbostic 	for (lineno = 1;
108*56039Sbostic 	    (p = fgets(buf, sizeof(buf), stdin)) != NULL; ++lineno) {
109*56039Sbostic 		len = strlen(buf);
110*56039Sbostic 		switch(*p) {
111*56039Sbostic 		case 'g':			/* get */
112*56039Sbostic 			if (state != COMMAND)
113*56039Sbostic 				err("line %lu: not expecting command", lineno);
114*56039Sbostic 			state = KEY;
115*56039Sbostic 			command = GET;
116*56039Sbostic 			break;
117*56039Sbostic 		case 'p':			/* put */
118*56039Sbostic 			if (state != COMMAND)
119*56039Sbostic 				err("line %lu: not expecting command", lineno);
120*56039Sbostic 			state = KEY;
121*56039Sbostic 			command = PUT;
122*56039Sbostic 			break;
123*56039Sbostic 		case 'r':			/* remove */
124*56039Sbostic 			if (state != COMMAND)
125*56039Sbostic 				err("line %lu: not expecting command", lineno);
126*56039Sbostic 			state = KEY;
127*56039Sbostic 			command = REMOVE;
128*56039Sbostic 			break;
129*56039Sbostic 		case 's':			/* seq */
130*56039Sbostic 			if (state != COMMAND)
131*56039Sbostic 				err("line %lu: not expecting command", lineno);
132*56039Sbostic 			seq(dbp);
133*56039Sbostic 			break;
134*56039Sbostic 		case 'f':
135*56039Sbostic 			flags |= setflags(p + 1);
136*56039Sbostic 			break;
137*56039Sbostic 		case 'D':			/* data file */
138*56039Sbostic 			if (state != DATA)
139*56039Sbostic 				err("line %lu: not expecting data", lineno);
140*56039Sbostic 			if (command != PUT)
141*56039Sbostic 				err("line %lu: command doesn't take data",
142*56039Sbostic 				    lineno);
143*56039Sbostic 			data.data = rfile(p + 1, &data.size);
144*56039Sbostic 			put(dbp, &key, &data);
145*56039Sbostic 			free(key.data);
146*56039Sbostic 			free(data.data);
147*56039Sbostic 			state = COMMAND;
148*56039Sbostic 			break;
149*56039Sbostic 		case 'd':			/* data */
150*56039Sbostic 			if (state != DATA)
151*56039Sbostic 				err("line %lu: not expecting data", lineno);
152*56039Sbostic 			if (command != PUT)
153*56039Sbostic 				err("line %lu: command doesn't take data",
154*56039Sbostic 				    lineno);
155*56039Sbostic 			data.data = xmalloc(p + 1, len - 1);
156*56039Sbostic 			data.size = len - 1;
157*56039Sbostic 			put(dbp, &key, &data);
158*56039Sbostic 			free(key.data);
159*56039Sbostic 			free(data.data);
160*56039Sbostic 			state = COMMAND;
161*56039Sbostic 			break;
162*56039Sbostic 		case 'K':			/* key file */
163*56039Sbostic 			if (state != KEY)
164*56039Sbostic 				err("line %lu: not expecting a key", lineno);
165*56039Sbostic 			if (type == DB_RECNO)
166*56039Sbostic 				err("line %lu: 'K' not available for recno",
167*56039Sbostic 				    lineno);
168*56039Sbostic 			key.data = rfile(p + 1, &key.size);
169*56039Sbostic 			switch(command) {
170*56039Sbostic 			case GET:
171*56039Sbostic 				get(dbp, &key);
172*56039Sbostic 				free(key.data);
173*56039Sbostic 				state = COMMAND;
174*56039Sbostic 				break;
175*56039Sbostic 			case PUT:
176*56039Sbostic 				state = DATA;
177*56039Sbostic 				break;
178*56039Sbostic 			case REMOVE:
179*56039Sbostic 				rem(dbp, &key);
180*56039Sbostic 				free(key.data);
181*56039Sbostic 				state = COMMAND;
182*56039Sbostic 				break;
183*56039Sbostic 			default:
184*56039Sbostic 				err("line %lu: command doesn't take a key",
185*56039Sbostic 				    lineno);
186*56039Sbostic 			}
187*56039Sbostic 			break;
188*56039Sbostic 		case 'k':			/* key */
189*56039Sbostic 			if (state != KEY)
190*56039Sbostic 				err("line %lu: not expecting a key", lineno);
191*56039Sbostic 			if (type == DB_RECNO) {
192*56039Sbostic 				static recno_t recno;
193*56039Sbostic 				recno = strtol(p + 1, NULL, 0);
194*56039Sbostic 				key.data = &recno;
195*56039Sbostic 				key.size = sizeof(recno);
196*56039Sbostic 			} else {
197*56039Sbostic 				key.data = xmalloc(p + 1, len - 1);
198*56039Sbostic 				key.size = len - 1;
199*56039Sbostic 			}
200*56039Sbostic 			switch(command) {
201*56039Sbostic 			case GET:
202*56039Sbostic 				get(dbp, &key);
203*56039Sbostic 				if (type != DB_RECNO)
204*56039Sbostic 					free(key.data);
205*56039Sbostic 				state = COMMAND;
206*56039Sbostic 				break;
207*56039Sbostic 			case PUT:
208*56039Sbostic 				state = DATA;
209*56039Sbostic 				break;
210*56039Sbostic 			case REMOVE:
211*56039Sbostic 				rem(dbp, &key);
212*56039Sbostic 				if (type != DB_RECNO)
213*56039Sbostic 					free(key.data);
214*56039Sbostic 				state = COMMAND;
215*56039Sbostic 				break;
216*56039Sbostic 			default:
217*56039Sbostic 				err("line %lu: command doesn't take a key",
218*56039Sbostic 				    lineno);
219*56039Sbostic 			}
220*56039Sbostic 			break;
221*56039Sbostic 		default:
222*56039Sbostic 			err("line %lu: %s: unknown command character",
223*56039Sbostic 			    *p, lineno);
224*56039Sbostic 		}
225*56039Sbostic 	}
226*56039Sbostic 	(void)close(ofd);
227*56039Sbostic 	exit(0);
228*56039Sbostic }
229*56039Sbostic 
230*56039Sbostic void
231*56039Sbostic get(dbp, kp)
232*56039Sbostic 	DB *dbp;
233*56039Sbostic 	DBT *kp;
234*56039Sbostic {
235*56039Sbostic 	DBT data;
236*56039Sbostic 
237*56039Sbostic 	if (dbp->get(dbp, kp, &data, flags) == -1)
238*56039Sbostic 		err("line %lu: get: %s", lineno, strerror(errno));
239*56039Sbostic 	(void)write(ofd, data.data, data.size);
240*56039Sbostic }
241*56039Sbostic 
242*56039Sbostic void
243*56039Sbostic put(dbp, kp, dp)
244*56039Sbostic 	DB *dbp;
245*56039Sbostic 	DBT *kp, *dp;
246*56039Sbostic {
247*56039Sbostic 	if (dbp->put(dbp, kp, dp, flags) == -1)
248*56039Sbostic 		err("line %lu: put: %s", lineno, strerror(errno));
249*56039Sbostic }
250*56039Sbostic 
251*56039Sbostic void
252*56039Sbostic rem(dbp, kp)
253*56039Sbostic 	DB *dbp;
254*56039Sbostic 	DBT *kp;
255*56039Sbostic {
256*56039Sbostic 	if (dbp->del(dbp, kp, flags) == -1)
257*56039Sbostic 		err("line %lu: get: %s", lineno, strerror(errno));
258*56039Sbostic }
259*56039Sbostic 
260*56039Sbostic void
261*56039Sbostic seq(dbp)
262*56039Sbostic 	DB *dbp;
263*56039Sbostic {
264*56039Sbostic 	DBT key, data;
265*56039Sbostic 	size_t len;
266*56039Sbostic 	char nbuf[20];
267*56039Sbostic 
268*56039Sbostic 	if (dbp->seq(dbp, &key, &data, flags) == -1)
269*56039Sbostic 		err("line %lu: seq: %s", lineno, strerror(errno));
270*56039Sbostic 	if (type == DB_RECNO) {
271*56039Sbostic 		len = sprintf(nbuf, "%lu\n", *(u_long *)key.data);
272*56039Sbostic 		(void)write(ofd, nbuf, len);
273*56039Sbostic 	} else
274*56039Sbostic 		(void)write(ofd, key.data, key.size);
275*56039Sbostic 	(void)write(ofd, data.data, data.size);
276*56039Sbostic }
277*56039Sbostic 
278*56039Sbostic u_int
279*56039Sbostic setflags(s)
280*56039Sbostic 	char *s;
281*56039Sbostic {
282*56039Sbostic 	char *p;
283*56039Sbostic 
284*56039Sbostic 	for (; isspace(*s); ++s);
285*56039Sbostic 	if (*s == '\n')
286*56039Sbostic 		return (0);
287*56039Sbostic 	if ((p = index(s, '\n')) != NULL)
288*56039Sbostic 		*p = '\0';
289*56039Sbostic 	if (!strcmp(s, "R_APPEND"))
290*56039Sbostic 		return (R_APPEND);
291*56039Sbostic 	if (!strcmp(s, "R_CURSOR"))
292*56039Sbostic 		return (R_CURSOR);
293*56039Sbostic 	if (!strcmp(s, "R_IAFTER"))
294*56039Sbostic 		return (R_IAFTER);
295*56039Sbostic 	if (!strcmp(s, "R_IBEFORE"))
296*56039Sbostic 		return (R_IBEFORE);
297*56039Sbostic 	if (!strcmp(s, "R_NOOVERWRITE"))
298*56039Sbostic 		return (R_NOOVERWRITE);
299*56039Sbostic 	if (!strcmp(s, "R_FIRST"))
300*56039Sbostic 		return (R_FIRST);
301*56039Sbostic 	if (!strcmp(s, "R_LAST"))
302*56039Sbostic 		return (R_LAST);
303*56039Sbostic 	if (!strcmp(s, "R_NEXT"))
304*56039Sbostic 		return (R_NEXT);
305*56039Sbostic 	if (!strcmp(s, "R_PREV"))
306*56039Sbostic 		return (R_PREV);
307*56039Sbostic 	err("line %lu: %s: unknown flag", lineno, s);
308*56039Sbostic 	/* NOTREACHED */
309*56039Sbostic }
310*56039Sbostic 
311*56039Sbostic DBTYPE
312*56039Sbostic dbtype(s)
313*56039Sbostic 	char *s;
314*56039Sbostic {
315*56039Sbostic 	if (!strcmp(s, "btree"))
316*56039Sbostic 		return (DB_BTREE);
317*56039Sbostic 	if (!strcmp(s, "hash"))
318*56039Sbostic 		return (DB_HASH);
319*56039Sbostic 	if (!strcmp(s, "recno"))
320*56039Sbostic 		return (DB_RECNO);
321*56039Sbostic 	err("%s: unknown type (use btree, hash or recno)", s);
322*56039Sbostic 	/* NOTREACHED */
323*56039Sbostic }
324*56039Sbostic 
325*56039Sbostic void *
326*56039Sbostic setinfo(type, s)
327*56039Sbostic 	DBTYPE type;
328*56039Sbostic 	char *s;
329*56039Sbostic {
330*56039Sbostic 	static BTREEINFO ib;
331*56039Sbostic 	static HASHINFO ih;
332*56039Sbostic 	static RECNOINFO rh;
333*56039Sbostic 	char *eq;
334*56039Sbostic 
335*56039Sbostic 	if ((eq = index(s, '=')) == NULL)
336*56039Sbostic 		err("%s: illegal structure set statement", s);
337*56039Sbostic 	*eq++ = '\0';
338*56039Sbostic 	if (!isdigit(*eq))
339*56039Sbostic 		err("%s: structure set statement must be a number", s);
340*56039Sbostic 
341*56039Sbostic 	switch(type) {
342*56039Sbostic 	case DB_BTREE:
343*56039Sbostic 		if (!strcmp("flags", s)) {
344*56039Sbostic 			ib.flags = strtoul(eq, NULL, 0);
345*56039Sbostic 			return (&ib);
346*56039Sbostic 		}
347*56039Sbostic 		if (!strcmp("cachesize", s)) {
348*56039Sbostic 			ib.cachesize = strtoul(eq, NULL, 0);
349*56039Sbostic 			return (&ib);
350*56039Sbostic 		}
351*56039Sbostic 		if (!strcmp("maxkeypage", s)) {
352*56039Sbostic 			ib.maxkeypage = strtoul(eq, NULL, 0);
353*56039Sbostic 			return (&ib);
354*56039Sbostic 		}
355*56039Sbostic 		if (!strcmp("minkeypage", s)) {
356*56039Sbostic 			ib.minkeypage = strtoul(eq, NULL, 0);
357*56039Sbostic 			return (&ib);
358*56039Sbostic 		}
359*56039Sbostic 		if (!strcmp("lorder", s)) {
360*56039Sbostic 			ib.lorder = strtoul(eq, NULL, 0);
361*56039Sbostic 			return (&ib);
362*56039Sbostic 		}
363*56039Sbostic 		break;
364*56039Sbostic 	case DB_HASH:
365*56039Sbostic 		if (!strcmp("bsize", s)) {
366*56039Sbostic 			ih.bsize = strtoul(eq, NULL, 0);
367*56039Sbostic 			return (&ib);
368*56039Sbostic 		}
369*56039Sbostic 		if (!strcmp("ffactor", s)) {
370*56039Sbostic 			ih.ffactor = strtoul(eq, NULL, 0);
371*56039Sbostic 			return (&ib);
372*56039Sbostic 		}
373*56039Sbostic 		if (!strcmp("nelem", s)) {
374*56039Sbostic 			ih.nelem = strtoul(eq, NULL, 0);
375*56039Sbostic 			return (&ib);
376*56039Sbostic 		}
377*56039Sbostic 		if (!strcmp("cachesize", s)) {
378*56039Sbostic 			ih.cachesize = strtoul(eq, NULL, 0);
379*56039Sbostic 			return (&ib);
380*56039Sbostic 		}
381*56039Sbostic 		if (!strcmp("lorder", s)) {
382*56039Sbostic 			ih.lorder = strtoul(eq, NULL, 0);
383*56039Sbostic 			return (&ib);
384*56039Sbostic 		}
385*56039Sbostic 		break;
386*56039Sbostic 	case DB_RECNO:
387*56039Sbostic 		if (!strcmp("flags", s)) {
388*56039Sbostic 			rh.flags = strtoul(eq, NULL, 0);
389*56039Sbostic 			return (&ib);
390*56039Sbostic 		}
391*56039Sbostic 		if (!strcmp("cachesize", s)) {
392*56039Sbostic 			rh.cachesize = strtoul(eq, NULL, 0);
393*56039Sbostic 			return (&ib);
394*56039Sbostic 		}
395*56039Sbostic 		if (!strcmp("lorder", s)) {
396*56039Sbostic 			rh.lorder = strtoul(eq, NULL, 0);
397*56039Sbostic 			return (&ib);
398*56039Sbostic 		}
399*56039Sbostic 		if (!strcmp("reclen", s)) {
400*56039Sbostic 			rh.reclen = strtoul(eq, NULL, 0);
401*56039Sbostic 			return (&ib);
402*56039Sbostic 		}
403*56039Sbostic 		if (!strcmp("bval", s)) {
404*56039Sbostic 			rh.bval = strtoul(eq, NULL, 0);
405*56039Sbostic 			return (&ib);
406*56039Sbostic 		}
407*56039Sbostic 		break;
408*56039Sbostic 	}
409*56039Sbostic 	err("%s: unknown structure value", s);
410*56039Sbostic 	/* NOTREACHED */
411*56039Sbostic }
412*56039Sbostic 
413*56039Sbostic void *
414*56039Sbostic rfile(name, lenp)
415*56039Sbostic 	char *name;
416*56039Sbostic 	size_t *lenp;
417*56039Sbostic {
418*56039Sbostic 	struct stat sb;
419*56039Sbostic 	void *p;
420*56039Sbostic 	int fd;
421*56039Sbostic 	char *np;
422*56039Sbostic 
423*56039Sbostic 	for (; isspace(*name); ++name);
424*56039Sbostic 	if ((np = index(name, '\n')) != NULL)
425*56039Sbostic 		*np = '\0';
426*56039Sbostic 	if ((fd = open(name, O_RDONLY, 0)) < 0 ||
427*56039Sbostic 	    fstat(fd, &sb))
428*56039Sbostic 		err("%s: %s\n", name, strerror(errno));
429*56039Sbostic 	if (sb.st_size > SIZE_T_MAX)
430*56039Sbostic 		err("%s: %s\n", name, strerror(E2BIG));
431*56039Sbostic 	if ((p = malloc((u_int)sb.st_size)) == NULL)
432*56039Sbostic 		err("%s", strerror(errno));
433*56039Sbostic 	(void)read(fd, p, (int)sb.st_size);
434*56039Sbostic 	*lenp = sb.st_size;
435*56039Sbostic 	return (p);
436*56039Sbostic }
437*56039Sbostic 
438*56039Sbostic void *
439*56039Sbostic xmalloc(text, len)
440*56039Sbostic 	char *text;
441*56039Sbostic 	size_t len;
442*56039Sbostic {
443*56039Sbostic 	void *p;
444*56039Sbostic 
445*56039Sbostic 	if ((p = malloc(len)) == NULL)
446*56039Sbostic 		err("%s", strerror(errno));
447*56039Sbostic 	bcopy(text, p, len);
448*56039Sbostic 	return (p);
449*56039Sbostic }
450*56039Sbostic 
451*56039Sbostic void
452*56039Sbostic usage()
453*56039Sbostic {
454*56039Sbostic 	(void)fprintf(stderr,
455*56039Sbostic 	    "usage: dbtest [-i info] [-o file] type script\n");
456*56039Sbostic 	exit(1);
457*56039Sbostic }
458*56039Sbostic 
459*56039Sbostic #if __STDC__
460*56039Sbostic #include <stdarg.h>
461*56039Sbostic #else
462*56039Sbostic #include <varargs.h>
463*56039Sbostic #endif
464*56039Sbostic 
465*56039Sbostic void
466*56039Sbostic #if __STDC__
467*56039Sbostic err(const char *fmt, ...)
468*56039Sbostic #else
469*56039Sbostic err(fmt, va_alist)
470*56039Sbostic 	char *fmt;
471*56039Sbostic         va_dcl
472*56039Sbostic #endif
473*56039Sbostic {
474*56039Sbostic 	va_list ap;
475*56039Sbostic #if __STDC__
476*56039Sbostic 	va_start(ap, fmt);
477*56039Sbostic #else
478*56039Sbostic 	va_start(ap);
479*56039Sbostic #endif
480*56039Sbostic 	(void)fprintf(stderr, "dbtest: ");
481*56039Sbostic 	(void)vfprintf(stderr, fmt, ap);
482*56039Sbostic 	va_end(ap);
483*56039Sbostic 	(void)fprintf(stderr, "\n");
484*56039Sbostic 	exit(1);
485*56039Sbostic 	/* NOTREACHED */
486*56039Sbostic }
487