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