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