158f0484fSRodney W. Grimes /*- 2*8a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 3*8a16b7a1SPedro F. Giffuni * 4f1e396bcSPaul Traina * Copyright (c) 1992, 1993, 1994 558f0484fSRodney W. Grimes * The Regents of the University of California. All rights reserved. 658f0484fSRodney W. Grimes * 758f0484fSRodney W. Grimes * Redistribution and use in source and binary forms, with or without 858f0484fSRodney W. Grimes * modification, are permitted provided that the following conditions 958f0484fSRodney W. Grimes * are met: 1058f0484fSRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 1158f0484fSRodney W. Grimes * notice, this list of conditions and the following disclaimer. 1258f0484fSRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 1358f0484fSRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 1458f0484fSRodney W. Grimes * documentation and/or other materials provided with the distribution. 15fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors 1658f0484fSRodney W. Grimes * may be used to endorse or promote products derived from this software 1758f0484fSRodney W. Grimes * without specific prior written permission. 1858f0484fSRodney W. Grimes * 1958f0484fSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2058f0484fSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2158f0484fSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2258f0484fSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2358f0484fSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2458f0484fSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2558f0484fSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2658f0484fSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2758f0484fSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2858f0484fSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2958f0484fSRodney W. Grimes * SUCH DAMAGE. 3058f0484fSRodney W. Grimes */ 3158f0484fSRodney W. Grimes 3258f0484fSRodney W. Grimes #ifndef lint 3358f0484fSRodney W. Grimes static char copyright[] = 34f1e396bcSPaul Traina "@(#) Copyright (c) 1992, 1993, 1994\n\ 3558f0484fSRodney W. Grimes The Regents of the University of California. All rights reserved.\n"; 3658f0484fSRodney W. Grimes #endif /* not lint */ 3758f0484fSRodney W. Grimes 38333fc21eSDavid E. O'Brien #if defined(LIBC_SCCS) && !defined(lint) 39f1e396bcSPaul Traina static char sccsid[] = "@(#)dbtest.c 8.17 (Berkeley) 9/1/94"; 40333fc21eSDavid E. O'Brien #endif /* LIBC_SCCS and not lint */ 41333fc21eSDavid E. O'Brien #include <sys/cdefs.h> 42333fc21eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 4358f0484fSRodney W. Grimes 4458f0484fSRodney W. Grimes #include <sys/param.h> 4558f0484fSRodney W. Grimes #include <sys/stat.h> 4658f0484fSRodney W. Grimes 4758f0484fSRodney W. Grimes #include <ctype.h> 4858f0484fSRodney W. Grimes #include <errno.h> 4958f0484fSRodney W. Grimes #include <fcntl.h> 5058f0484fSRodney W. Grimes #include <limits.h> 5158f0484fSRodney W. Grimes #include <stdio.h> 5258f0484fSRodney W. Grimes #include <stdlib.h> 5358f0484fSRodney W. Grimes #include <string.h> 5458f0484fSRodney W. Grimes #include <unistd.h> 5558f0484fSRodney W. Grimes 5658f0484fSRodney W. Grimes #include <db.h> 5758f0484fSRodney W. Grimes 5858f0484fSRodney W. Grimes enum S { COMMAND, COMPARE, GET, PUT, REMOVE, SEQ, SEQFLAG, KEY, DATA }; 5958f0484fSRodney W. Grimes 60c05ac53bSDavid E. O'Brien void compare(DBT *, DBT *); 61c05ac53bSDavid E. O'Brien DBTYPE dbtype(char *); 62c05ac53bSDavid E. O'Brien void dump(DB *, int); 631372519bSDavid E. O'Brien void err(const char *, ...) __printflike(1, 2); 64c05ac53bSDavid E. O'Brien void get(DB *, DBT *); 65c05ac53bSDavid E. O'Brien void getdata(DB *, DBT *, DBT *); 66c05ac53bSDavid E. O'Brien void put(DB *, DBT *, DBT *); 67c05ac53bSDavid E. O'Brien void rem(DB *, DBT *); 68c05ac53bSDavid E. O'Brien char *sflags(int); 69c05ac53bSDavid E. O'Brien void synk(DB *); 70c05ac53bSDavid E. O'Brien void *rfile(char *, size_t *); 71c05ac53bSDavid E. O'Brien void seq(DB *, DBT *); 72c05ac53bSDavid E. O'Brien u_int setflags(char *); 73c05ac53bSDavid E. O'Brien void *setinfo(DBTYPE, char *); 74c05ac53bSDavid E. O'Brien void usage(void); 75c05ac53bSDavid E. O'Brien void *xmalloc(char *, size_t); 7658f0484fSRodney W. Grimes 77f1e396bcSPaul Traina DBTYPE type; /* Database type. */ 78f1e396bcSPaul Traina void *infop; /* Iflags. */ 79f1e396bcSPaul Traina u_long lineno; /* Current line in test script. */ 80f1e396bcSPaul Traina u_int flags; /* Current DB flags. */ 81f1e396bcSPaul Traina int ofd = STDOUT_FILENO; /* Standard output fd. */ 8258f0484fSRodney W. Grimes 8358f0484fSRodney W. Grimes DB *XXdbp; /* Global for gdb. */ 84f1e396bcSPaul Traina int XXlineno; /* Fast breakpoint for gdb. */ 8558f0484fSRodney W. Grimes 8658f0484fSRodney W. Grimes int 8758f0484fSRodney W. Grimes main(argc, argv) 8858f0484fSRodney W. Grimes int argc; 8958f0484fSRodney W. Grimes char *argv[]; 9058f0484fSRodney W. Grimes { 9158f0484fSRodney W. Grimes extern int optind; 9258f0484fSRodney W. Grimes extern char *optarg; 9358f0484fSRodney W. Grimes enum S command, state; 9458f0484fSRodney W. Grimes DB *dbp; 9558f0484fSRodney W. Grimes DBT data, key, keydata; 9658f0484fSRodney W. Grimes size_t len; 97f1e396bcSPaul Traina int ch, oflags, sflag; 98f1e396bcSPaul Traina char *fname, *infoarg, *p, *t, buf[8 * 1024]; 9958f0484fSRodney W. Grimes 10058f0484fSRodney W. Grimes infoarg = NULL; 10158f0484fSRodney W. Grimes fname = NULL; 10258f0484fSRodney W. Grimes oflags = O_CREAT | O_RDWR; 103f1e396bcSPaul Traina sflag = 0; 1048f9872ccSKevin Lo while ((ch = getopt(argc, argv, "f:i:lo:s")) != -1) 10558f0484fSRodney W. Grimes switch (ch) { 10658f0484fSRodney W. Grimes case 'f': 10758f0484fSRodney W. Grimes fname = optarg; 10858f0484fSRodney W. Grimes break; 10958f0484fSRodney W. Grimes case 'i': 11058f0484fSRodney W. Grimes infoarg = optarg; 11158f0484fSRodney W. Grimes break; 11258f0484fSRodney W. Grimes case 'l': 11358f0484fSRodney W. Grimes oflags |= DB_LOCK; 11458f0484fSRodney W. Grimes break; 11558f0484fSRodney W. Grimes case 'o': 11658f0484fSRodney W. Grimes if ((ofd = open(optarg, 11758f0484fSRodney W. Grimes O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0) 11858f0484fSRodney W. Grimes err("%s: %s", optarg, strerror(errno)); 11958f0484fSRodney W. Grimes break; 120f1e396bcSPaul Traina case 's': 121f1e396bcSPaul Traina sflag = 1; 122f1e396bcSPaul Traina break; 12358f0484fSRodney W. Grimes case '?': 12458f0484fSRodney W. Grimes default: 12558f0484fSRodney W. Grimes usage(); 12658f0484fSRodney W. Grimes } 12758f0484fSRodney W. Grimes argc -= optind; 12858f0484fSRodney W. Grimes argv += optind; 12958f0484fSRodney W. Grimes 13058f0484fSRodney W. Grimes if (argc != 2) 13158f0484fSRodney W. Grimes usage(); 13258f0484fSRodney W. Grimes 13358f0484fSRodney W. Grimes /* Set the type. */ 13458f0484fSRodney W. Grimes type = dbtype(*argv++); 13558f0484fSRodney W. Grimes 13658f0484fSRodney W. Grimes /* Open the descriptor file. */ 137f1e396bcSPaul Traina if (strcmp(*argv, "-") && freopen(*argv, "r", stdin) == NULL) 13858f0484fSRodney W. Grimes err("%s: %s", *argv, strerror(errno)); 13958f0484fSRodney W. Grimes 14058f0484fSRodney W. Grimes /* Set up the db structure as necessary. */ 14158f0484fSRodney W. Grimes if (infoarg == NULL) 14258f0484fSRodney W. Grimes infop = NULL; 14358f0484fSRodney W. Grimes else 14458f0484fSRodney W. Grimes for (p = strtok(infoarg, ",\t "); p != NULL; 14558f0484fSRodney W. Grimes p = strtok(0, ",\t ")) 14658f0484fSRodney W. Grimes if (*p != '\0') 14758f0484fSRodney W. Grimes infop = setinfo(type, p); 14858f0484fSRodney W. Grimes 149f1e396bcSPaul Traina /* 150f1e396bcSPaul Traina * Open the DB. Delete any preexisting copy, you almost never 151f1e396bcSPaul Traina * want it around, and it often screws up tests. 152f1e396bcSPaul Traina */ 15358f0484fSRodney W. Grimes if (fname == NULL) { 15458f0484fSRodney W. Grimes p = getenv("TMPDIR"); 15558f0484fSRodney W. Grimes if (p == NULL) 15658f0484fSRodney W. Grimes p = "/var/tmp"; 157099d8832SKris Kennaway (void)snprintf(buf, sizeof(buf), "%s/__dbtest", p); 15858f0484fSRodney W. Grimes fname = buf; 15958f0484fSRodney W. Grimes (void)unlink(buf); 160f1e396bcSPaul Traina } else if (!sflag) 161f1e396bcSPaul Traina (void)unlink(fname); 162f1e396bcSPaul Traina 16358f0484fSRodney W. Grimes if ((dbp = dbopen(fname, 16458f0484fSRodney W. Grimes oflags, S_IRUSR | S_IWUSR, type, infop)) == NULL) 16558f0484fSRodney W. Grimes err("dbopen: %s", strerror(errno)); 16658f0484fSRodney W. Grimes XXdbp = dbp; 16758f0484fSRodney W. Grimes 16858f0484fSRodney W. Grimes state = COMMAND; 16958f0484fSRodney W. Grimes for (lineno = 1; 17058f0484fSRodney W. Grimes (p = fgets(buf, sizeof(buf), stdin)) != NULL; ++lineno) { 171f1e396bcSPaul Traina /* Delete the newline, displaying the key/data is easier. */ 172f1e396bcSPaul Traina if (ofd == STDOUT_FILENO && (t = strchr(p, '\n')) != NULL) 173f1e396bcSPaul Traina *t = '\0'; 174f1e396bcSPaul Traina if ((len = strlen(buf)) == 0 || isspace(*p) || *p == '#') 175f1e396bcSPaul Traina continue; 176f1e396bcSPaul Traina 177f1e396bcSPaul Traina /* Convenient gdb break point. */ 178f1e396bcSPaul Traina if (XXlineno == lineno) 179f1e396bcSPaul Traina XXlineno = 1; 18058f0484fSRodney W. Grimes switch (*p) { 18158f0484fSRodney W. Grimes case 'c': /* compare */ 18258f0484fSRodney W. Grimes if (state != COMMAND) 18358f0484fSRodney W. Grimes err("line %lu: not expecting command", lineno); 18458f0484fSRodney W. Grimes state = KEY; 18558f0484fSRodney W. Grimes command = COMPARE; 18658f0484fSRodney W. Grimes break; 18758f0484fSRodney W. Grimes case 'e': /* echo */ 18858f0484fSRodney W. Grimes if (state != COMMAND) 18958f0484fSRodney W. Grimes err("line %lu: not expecting command", lineno); 19058f0484fSRodney W. Grimes /* Don't display the newline, if CR at EOL. */ 19158f0484fSRodney W. Grimes if (p[len - 2] == '\r') 19258f0484fSRodney W. Grimes --len; 193f1e396bcSPaul Traina if (write(ofd, p + 1, len - 1) != len - 1 || 194f1e396bcSPaul Traina write(ofd, "\n", 1) != 1) 19558f0484fSRodney W. Grimes err("write: %s", strerror(errno)); 19658f0484fSRodney W. Grimes break; 19758f0484fSRodney W. Grimes case 'g': /* get */ 19858f0484fSRodney W. Grimes if (state != COMMAND) 19958f0484fSRodney W. Grimes err("line %lu: not expecting command", lineno); 20058f0484fSRodney W. Grimes state = KEY; 20158f0484fSRodney W. Grimes command = GET; 20258f0484fSRodney W. Grimes break; 20358f0484fSRodney W. Grimes case 'p': /* put */ 20458f0484fSRodney W. Grimes if (state != COMMAND) 20558f0484fSRodney W. Grimes err("line %lu: not expecting command", lineno); 20658f0484fSRodney W. Grimes state = KEY; 20758f0484fSRodney W. Grimes command = PUT; 20858f0484fSRodney W. Grimes break; 20958f0484fSRodney W. Grimes case 'r': /* remove */ 21058f0484fSRodney W. Grimes if (state != COMMAND) 21158f0484fSRodney W. Grimes err("line %lu: not expecting command", lineno); 212f1e396bcSPaul Traina if (flags == R_CURSOR) { 213f1e396bcSPaul Traina rem(dbp, &key); 214f1e396bcSPaul Traina state = COMMAND; 215f1e396bcSPaul Traina } else { 21658f0484fSRodney W. Grimes state = KEY; 21758f0484fSRodney W. Grimes command = REMOVE; 218f1e396bcSPaul Traina } 219f1e396bcSPaul Traina break; 220f1e396bcSPaul Traina case 'S': /* sync */ 221f1e396bcSPaul Traina if (state != COMMAND) 222f1e396bcSPaul Traina err("line %lu: not expecting command", lineno); 223f1e396bcSPaul Traina synk(dbp); 224f1e396bcSPaul Traina state = COMMAND; 22558f0484fSRodney W. Grimes break; 22658f0484fSRodney W. Grimes case 's': /* seq */ 22758f0484fSRodney W. Grimes if (state != COMMAND) 22858f0484fSRodney W. Grimes err("line %lu: not expecting command", lineno); 22958f0484fSRodney W. Grimes if (flags == R_CURSOR) { 23058f0484fSRodney W. Grimes state = KEY; 23158f0484fSRodney W. Grimes command = SEQ; 23258f0484fSRodney W. Grimes } else 23358f0484fSRodney W. Grimes seq(dbp, &key); 23458f0484fSRodney W. Grimes break; 23558f0484fSRodney W. Grimes case 'f': 23658f0484fSRodney W. Grimes flags = setflags(p + 1); 23758f0484fSRodney W. Grimes break; 23858f0484fSRodney W. Grimes case 'D': /* data file */ 23958f0484fSRodney W. Grimes if (state != DATA) 24058f0484fSRodney W. Grimes err("line %lu: not expecting data", lineno); 24158f0484fSRodney W. Grimes data.data = rfile(p + 1, &data.size); 24258f0484fSRodney W. Grimes goto ldata; 24358f0484fSRodney W. Grimes case 'd': /* data */ 24458f0484fSRodney W. Grimes if (state != DATA) 24558f0484fSRodney W. Grimes err("line %lu: not expecting data", lineno); 24658f0484fSRodney W. Grimes data.data = xmalloc(p + 1, len - 1); 24758f0484fSRodney W. Grimes data.size = len - 1; 24858f0484fSRodney W. Grimes ldata: switch (command) { 24958f0484fSRodney W. Grimes case COMPARE: 25058f0484fSRodney W. Grimes compare(&keydata, &data); 25158f0484fSRodney W. Grimes break; 25258f0484fSRodney W. Grimes case PUT: 25358f0484fSRodney W. Grimes put(dbp, &key, &data); 25458f0484fSRodney W. Grimes break; 25558f0484fSRodney W. Grimes default: 25658f0484fSRodney W. Grimes err("line %lu: command doesn't take data", 25758f0484fSRodney W. Grimes lineno); 25858f0484fSRodney W. Grimes } 25958f0484fSRodney W. Grimes if (type != DB_RECNO) 26058f0484fSRodney W. Grimes free(key.data); 26158f0484fSRodney W. Grimes free(data.data); 26258f0484fSRodney W. Grimes state = COMMAND; 26358f0484fSRodney W. Grimes break; 26458f0484fSRodney W. Grimes case 'K': /* key file */ 26558f0484fSRodney W. Grimes if (state != KEY) 26658f0484fSRodney W. Grimes err("line %lu: not expecting a key", lineno); 26758f0484fSRodney W. Grimes if (type == DB_RECNO) 26858f0484fSRodney W. Grimes err("line %lu: 'K' not available for recno", 26958f0484fSRodney W. Grimes lineno); 27058f0484fSRodney W. Grimes key.data = rfile(p + 1, &key.size); 27158f0484fSRodney W. Grimes goto lkey; 27258f0484fSRodney W. Grimes case 'k': /* key */ 27358f0484fSRodney W. Grimes if (state != KEY) 27458f0484fSRodney W. Grimes err("line %lu: not expecting a key", lineno); 27558f0484fSRodney W. Grimes if (type == DB_RECNO) { 27658f0484fSRodney W. Grimes static recno_t recno; 27758f0484fSRodney W. Grimes recno = atoi(p + 1); 27858f0484fSRodney W. Grimes key.data = &recno; 27958f0484fSRodney W. Grimes key.size = sizeof(recno); 28058f0484fSRodney W. Grimes } else { 28158f0484fSRodney W. Grimes key.data = xmalloc(p + 1, len - 1); 28258f0484fSRodney W. Grimes key.size = len - 1; 28358f0484fSRodney W. Grimes } 28458f0484fSRodney W. Grimes lkey: switch (command) { 28558f0484fSRodney W. Grimes case COMPARE: 28658f0484fSRodney W. Grimes getdata(dbp, &key, &keydata); 28758f0484fSRodney W. Grimes state = DATA; 28858f0484fSRodney W. Grimes break; 28958f0484fSRodney W. Grimes case GET: 29058f0484fSRodney W. Grimes get(dbp, &key); 29158f0484fSRodney W. Grimes if (type != DB_RECNO) 29258f0484fSRodney W. Grimes free(key.data); 29358f0484fSRodney W. Grimes state = COMMAND; 29458f0484fSRodney W. Grimes break; 29558f0484fSRodney W. Grimes case PUT: 29658f0484fSRodney W. Grimes state = DATA; 29758f0484fSRodney W. Grimes break; 29858f0484fSRodney W. Grimes case REMOVE: 29958f0484fSRodney W. Grimes rem(dbp, &key); 300f1e396bcSPaul Traina if ((type != DB_RECNO) && (flags != R_CURSOR)) 30158f0484fSRodney W. Grimes free(key.data); 30258f0484fSRodney W. Grimes state = COMMAND; 30358f0484fSRodney W. Grimes break; 30458f0484fSRodney W. Grimes case SEQ: 30558f0484fSRodney W. Grimes seq(dbp, &key); 306f1e396bcSPaul Traina if ((type != DB_RECNO) && (flags != R_CURSOR)) 30758f0484fSRodney W. Grimes free(key.data); 30858f0484fSRodney W. Grimes state = COMMAND; 30958f0484fSRodney W. Grimes break; 31058f0484fSRodney W. Grimes default: 31158f0484fSRodney W. Grimes err("line %lu: command doesn't take a key", 31258f0484fSRodney W. Grimes lineno); 31358f0484fSRodney W. Grimes } 31458f0484fSRodney W. Grimes break; 31558f0484fSRodney W. Grimes case 'o': 31658f0484fSRodney W. Grimes dump(dbp, p[1] == 'r'); 31758f0484fSRodney W. Grimes break; 31858f0484fSRodney W. Grimes default: 31958f0484fSRodney W. Grimes err("line %lu: %s: unknown command character", 320f1e396bcSPaul Traina lineno, p); 32158f0484fSRodney W. Grimes } 32258f0484fSRodney W. Grimes } 32358f0484fSRodney W. Grimes #ifdef STATISTICS 324f1e396bcSPaul Traina /* 325f1e396bcSPaul Traina * -l must be used (DB_LOCK must be set) for this to be 326f1e396bcSPaul Traina * used, otherwise a page will be locked and it will fail. 327f1e396bcSPaul Traina */ 328f1e396bcSPaul Traina if (type == DB_BTREE && oflags & DB_LOCK) 32958f0484fSRodney W. Grimes __bt_stat(dbp); 33058f0484fSRodney W. Grimes #endif 33158f0484fSRodney W. Grimes if (dbp->close(dbp)) 33258f0484fSRodney W. Grimes err("db->close: %s", strerror(errno)); 33358f0484fSRodney W. Grimes (void)close(ofd); 33458f0484fSRodney W. Grimes exit(0); 33558f0484fSRodney W. Grimes } 33658f0484fSRodney W. Grimes 33758f0484fSRodney W. Grimes #define NOOVERWRITE "put failed, would overwrite key\n" 33858f0484fSRodney W. Grimes 33958f0484fSRodney W. Grimes void 34058f0484fSRodney W. Grimes compare(db1, db2) 34158f0484fSRodney W. Grimes DBT *db1, *db2; 34258f0484fSRodney W. Grimes { 3438fb3f3f6SDavid E. O'Brien size_t len; 3448fb3f3f6SDavid E. O'Brien u_char *p1, *p2; 34558f0484fSRodney W. Grimes 34658f0484fSRodney W. Grimes if (db1->size != db2->size) 34758f0484fSRodney W. Grimes printf("compare failed: key->data len %lu != data len %lu\n", 34858f0484fSRodney W. Grimes db1->size, db2->size); 34958f0484fSRodney W. Grimes 35058f0484fSRodney W. Grimes len = MIN(db1->size, db2->size); 35158f0484fSRodney W. Grimes for (p1 = db1->data, p2 = db2->data; len--;) 35258f0484fSRodney W. Grimes if (*p1++ != *p2++) { 35358f0484fSRodney W. Grimes printf("compare failed at offset %d\n", 35458f0484fSRodney W. Grimes p1 - (u_char *)db1->data); 35558f0484fSRodney W. Grimes break; 35658f0484fSRodney W. Grimes } 35758f0484fSRodney W. Grimes } 35858f0484fSRodney W. Grimes 35958f0484fSRodney W. Grimes void 36058f0484fSRodney W. Grimes get(dbp, kp) 36158f0484fSRodney W. Grimes DB *dbp; 36258f0484fSRodney W. Grimes DBT *kp; 36358f0484fSRodney W. Grimes { 36458f0484fSRodney W. Grimes DBT data; 36558f0484fSRodney W. Grimes 36658f0484fSRodney W. Grimes switch (dbp->get(dbp, kp, &data, flags)) { 36758f0484fSRodney W. Grimes case 0: 36858f0484fSRodney W. Grimes (void)write(ofd, data.data, data.size); 369f1e396bcSPaul Traina if (ofd == STDOUT_FILENO) 370f1e396bcSPaul Traina (void)write(ofd, "\n", 1); 37158f0484fSRodney W. Grimes break; 37258f0484fSRodney W. Grimes case -1: 37358f0484fSRodney W. Grimes err("line %lu: get: %s", lineno, strerror(errno)); 37458f0484fSRodney W. Grimes /* NOTREACHED */ 37558f0484fSRodney W. Grimes case 1: 376f1e396bcSPaul Traina #define NOSUCHKEY "get failed, no such key\n" 377f1e396bcSPaul Traina if (ofd != STDOUT_FILENO) 37858f0484fSRodney W. Grimes (void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1); 379f1e396bcSPaul Traina else 380f1e396bcSPaul Traina (void)fprintf(stderr, "%d: %.*s: %s", 381f1e396bcSPaul Traina lineno, MIN(kp->size, 20), kp->data, NOSUCHKEY); 382f1e396bcSPaul Traina #undef NOSUCHKEY 38358f0484fSRodney W. Grimes break; 38458f0484fSRodney W. Grimes } 38558f0484fSRodney W. Grimes } 38658f0484fSRodney W. Grimes 38758f0484fSRodney W. Grimes void 38858f0484fSRodney W. Grimes getdata(dbp, kp, dp) 38958f0484fSRodney W. Grimes DB *dbp; 39058f0484fSRodney W. Grimes DBT *kp, *dp; 39158f0484fSRodney W. Grimes { 39258f0484fSRodney W. Grimes switch (dbp->get(dbp, kp, dp, flags)) { 39358f0484fSRodney W. Grimes case 0: 39458f0484fSRodney W. Grimes return; 39558f0484fSRodney W. Grimes case -1: 39658f0484fSRodney W. Grimes err("line %lu: getdata: %s", lineno, strerror(errno)); 39758f0484fSRodney W. Grimes /* NOTREACHED */ 39858f0484fSRodney W. Grimes case 1: 399f1e396bcSPaul Traina err("line %lu: getdata failed, no such key", lineno); 40058f0484fSRodney W. Grimes /* NOTREACHED */ 40158f0484fSRodney W. Grimes } 40258f0484fSRodney W. Grimes } 40358f0484fSRodney W. Grimes 40458f0484fSRodney W. Grimes void 40558f0484fSRodney W. Grimes put(dbp, kp, dp) 40658f0484fSRodney W. Grimes DB *dbp; 40758f0484fSRodney W. Grimes DBT *kp, *dp; 40858f0484fSRodney W. Grimes { 40958f0484fSRodney W. Grimes switch (dbp->put(dbp, kp, dp, flags)) { 41058f0484fSRodney W. Grimes case 0: 41158f0484fSRodney W. Grimes break; 41258f0484fSRodney W. Grimes case -1: 41358f0484fSRodney W. Grimes err("line %lu: put: %s", lineno, strerror(errno)); 41458f0484fSRodney W. Grimes /* NOTREACHED */ 41558f0484fSRodney W. Grimes case 1: 41658f0484fSRodney W. Grimes (void)write(ofd, NOOVERWRITE, sizeof(NOOVERWRITE) - 1); 41758f0484fSRodney W. Grimes break; 41858f0484fSRodney W. Grimes } 41958f0484fSRodney W. Grimes } 42058f0484fSRodney W. Grimes 42158f0484fSRodney W. Grimes void 42258f0484fSRodney W. Grimes rem(dbp, kp) 42358f0484fSRodney W. Grimes DB *dbp; 42458f0484fSRodney W. Grimes DBT *kp; 42558f0484fSRodney W. Grimes { 42658f0484fSRodney W. Grimes switch (dbp->del(dbp, kp, flags)) { 42758f0484fSRodney W. Grimes case 0: 42858f0484fSRodney W. Grimes break; 42958f0484fSRodney W. Grimes case -1: 430f1e396bcSPaul Traina err("line %lu: rem: %s", lineno, strerror(errno)); 43158f0484fSRodney W. Grimes /* NOTREACHED */ 43258f0484fSRodney W. Grimes case 1: 433f1e396bcSPaul Traina #define NOSUCHKEY "rem failed, no such key\n" 434f1e396bcSPaul Traina if (ofd != STDOUT_FILENO) 43558f0484fSRodney W. Grimes (void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1); 436f1e396bcSPaul Traina else if (flags != R_CURSOR) 437f1e396bcSPaul Traina (void)fprintf(stderr, "%d: %.*s: %s", 438f1e396bcSPaul Traina lineno, MIN(kp->size, 20), kp->data, NOSUCHKEY); 439f1e396bcSPaul Traina else 440f1e396bcSPaul Traina (void)fprintf(stderr, 441f1e396bcSPaul Traina "%d: rem of cursor failed\n", lineno); 442f1e396bcSPaul Traina #undef NOSUCHKEY 44358f0484fSRodney W. Grimes break; 44458f0484fSRodney W. Grimes } 44558f0484fSRodney W. Grimes } 44658f0484fSRodney W. Grimes 44758f0484fSRodney W. Grimes void 448f1e396bcSPaul Traina synk(dbp) 449f1e396bcSPaul Traina DB *dbp; 450f1e396bcSPaul Traina { 451f1e396bcSPaul Traina switch (dbp->sync(dbp, flags)) { 452f1e396bcSPaul Traina case 0: 453f1e396bcSPaul Traina break; 454f1e396bcSPaul Traina case -1: 455f1e396bcSPaul Traina err("line %lu: synk: %s", lineno, strerror(errno)); 456f1e396bcSPaul Traina /* NOTREACHED */ 457f1e396bcSPaul Traina } 458f1e396bcSPaul Traina } 459f1e396bcSPaul Traina 460f1e396bcSPaul Traina void 46158f0484fSRodney W. Grimes seq(dbp, kp) 46258f0484fSRodney W. Grimes DB *dbp; 46358f0484fSRodney W. Grimes DBT *kp; 46458f0484fSRodney W. Grimes { 46558f0484fSRodney W. Grimes DBT data; 46658f0484fSRodney W. Grimes 46758f0484fSRodney W. Grimes switch (dbp->seq(dbp, kp, &data, flags)) { 46858f0484fSRodney W. Grimes case 0: 46958f0484fSRodney W. Grimes (void)write(ofd, data.data, data.size); 470f1e396bcSPaul Traina if (ofd == STDOUT_FILENO) 471f1e396bcSPaul Traina (void)write(ofd, "\n", 1); 47258f0484fSRodney W. Grimes break; 47358f0484fSRodney W. Grimes case -1: 47458f0484fSRodney W. Grimes err("line %lu: seq: %s", lineno, strerror(errno)); 47558f0484fSRodney W. Grimes /* NOTREACHED */ 47658f0484fSRodney W. Grimes case 1: 477f1e396bcSPaul Traina #define NOSUCHKEY "seq failed, no such key\n" 478f1e396bcSPaul Traina if (ofd != STDOUT_FILENO) 47958f0484fSRodney W. Grimes (void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1); 480f1e396bcSPaul Traina else if (flags == R_CURSOR) 481f1e396bcSPaul Traina (void)fprintf(stderr, "%d: %.*s: %s", 482f1e396bcSPaul Traina lineno, MIN(kp->size, 20), kp->data, NOSUCHKEY); 483f1e396bcSPaul Traina else 484f1e396bcSPaul Traina (void)fprintf(stderr, 485f1e396bcSPaul Traina "%d: seq (%s) failed\n", lineno, sflags(flags)); 486f1e396bcSPaul Traina #undef NOSUCHKEY 48758f0484fSRodney W. Grimes break; 48858f0484fSRodney W. Grimes } 48958f0484fSRodney W. Grimes } 49058f0484fSRodney W. Grimes 49158f0484fSRodney W. Grimes void 49258f0484fSRodney W. Grimes dump(dbp, rev) 49358f0484fSRodney W. Grimes DB *dbp; 49458f0484fSRodney W. Grimes int rev; 49558f0484fSRodney W. Grimes { 49658f0484fSRodney W. Grimes DBT key, data; 49758f0484fSRodney W. Grimes int flags, nflags; 49858f0484fSRodney W. Grimes 49958f0484fSRodney W. Grimes if (rev) { 50058f0484fSRodney W. Grimes flags = R_LAST; 50158f0484fSRodney W. Grimes nflags = R_PREV; 50258f0484fSRodney W. Grimes } else { 50358f0484fSRodney W. Grimes flags = R_FIRST; 50458f0484fSRodney W. Grimes nflags = R_NEXT; 50558f0484fSRodney W. Grimes } 50658f0484fSRodney W. Grimes for (;; flags = nflags) 50758f0484fSRodney W. Grimes switch (dbp->seq(dbp, &key, &data, flags)) { 50858f0484fSRodney W. Grimes case 0: 50958f0484fSRodney W. Grimes (void)write(ofd, data.data, data.size); 510f1e396bcSPaul Traina if (ofd == STDOUT_FILENO) 511f1e396bcSPaul Traina (void)write(ofd, "\n", 1); 51258f0484fSRodney W. Grimes break; 51358f0484fSRodney W. Grimes case 1: 51458f0484fSRodney W. Grimes goto done; 51558f0484fSRodney W. Grimes case -1: 51658f0484fSRodney W. Grimes err("line %lu: (dump) seq: %s", 51758f0484fSRodney W. Grimes lineno, strerror(errno)); 51858f0484fSRodney W. Grimes /* NOTREACHED */ 51958f0484fSRodney W. Grimes } 52058f0484fSRodney W. Grimes done: return; 52158f0484fSRodney W. Grimes } 52258f0484fSRodney W. Grimes 52358f0484fSRodney W. Grimes u_int 52458f0484fSRodney W. Grimes setflags(s) 52558f0484fSRodney W. Grimes char *s; 52658f0484fSRodney W. Grimes { 52758f0484fSRodney W. Grimes char *p, *index(); 52858f0484fSRodney W. Grimes 52958f0484fSRodney W. Grimes for (; isspace(*s); ++s); 530f1e396bcSPaul Traina if (*s == '\n' || *s == '\0') 53158f0484fSRodney W. Grimes return (0); 53258f0484fSRodney W. Grimes if ((p = index(s, '\n')) != NULL) 53358f0484fSRodney W. Grimes *p = '\0'; 534f1e396bcSPaul Traina if (!strcmp(s, "R_CURSOR")) return (R_CURSOR); 535f1e396bcSPaul Traina if (!strcmp(s, "R_FIRST")) return (R_FIRST); 536f1e396bcSPaul Traina if (!strcmp(s, "R_IAFTER")) return (R_IAFTER); 537f1e396bcSPaul Traina if (!strcmp(s, "R_IBEFORE")) return (R_IBEFORE); 538f1e396bcSPaul Traina if (!strcmp(s, "R_LAST")) return (R_LAST); 539f1e396bcSPaul Traina if (!strcmp(s, "R_NEXT")) return (R_NEXT); 540f1e396bcSPaul Traina if (!strcmp(s, "R_NOOVERWRITE")) return (R_NOOVERWRITE); 541f1e396bcSPaul Traina if (!strcmp(s, "R_PREV")) return (R_PREV); 542f1e396bcSPaul Traina if (!strcmp(s, "R_SETCURSOR")) return (R_SETCURSOR); 543f1e396bcSPaul Traina 54458f0484fSRodney W. Grimes err("line %lu: %s: unknown flag", lineno, s); 54558f0484fSRodney W. Grimes /* NOTREACHED */ 54658f0484fSRodney W. Grimes } 54758f0484fSRodney W. Grimes 548f1e396bcSPaul Traina char * 549f1e396bcSPaul Traina sflags(flags) 550f1e396bcSPaul Traina int flags; 551f1e396bcSPaul Traina { 552f1e396bcSPaul Traina switch (flags) { 553f1e396bcSPaul Traina case R_CURSOR: return ("R_CURSOR"); 554f1e396bcSPaul Traina case R_FIRST: return ("R_FIRST"); 555f1e396bcSPaul Traina case R_IAFTER: return ("R_IAFTER"); 556f1e396bcSPaul Traina case R_IBEFORE: return ("R_IBEFORE"); 557f1e396bcSPaul Traina case R_LAST: return ("R_LAST"); 558f1e396bcSPaul Traina case R_NEXT: return ("R_NEXT"); 559f1e396bcSPaul Traina case R_NOOVERWRITE: return ("R_NOOVERWRITE"); 560f1e396bcSPaul Traina case R_PREV: return ("R_PREV"); 561f1e396bcSPaul Traina case R_SETCURSOR: return ("R_SETCURSOR"); 562f1e396bcSPaul Traina } 563f1e396bcSPaul Traina 564f1e396bcSPaul Traina return ("UNKNOWN!"); 565f1e396bcSPaul Traina } 566f1e396bcSPaul Traina 56758f0484fSRodney W. Grimes DBTYPE 56858f0484fSRodney W. Grimes dbtype(s) 56958f0484fSRodney W. Grimes char *s; 57058f0484fSRodney W. Grimes { 57158f0484fSRodney W. Grimes if (!strcmp(s, "btree")) 57258f0484fSRodney W. Grimes return (DB_BTREE); 57358f0484fSRodney W. Grimes if (!strcmp(s, "hash")) 57458f0484fSRodney W. Grimes return (DB_HASH); 57558f0484fSRodney W. Grimes if (!strcmp(s, "recno")) 57658f0484fSRodney W. Grimes return (DB_RECNO); 57758f0484fSRodney W. Grimes err("%s: unknown type (use btree, hash or recno)", s); 57858f0484fSRodney W. Grimes /* NOTREACHED */ 57958f0484fSRodney W. Grimes } 58058f0484fSRodney W. Grimes 58158f0484fSRodney W. Grimes void * 58258f0484fSRodney W. Grimes setinfo(type, s) 58358f0484fSRodney W. Grimes DBTYPE type; 58458f0484fSRodney W. Grimes char *s; 58558f0484fSRodney W. Grimes { 58658f0484fSRodney W. Grimes static BTREEINFO ib; 58758f0484fSRodney W. Grimes static HASHINFO ih; 58858f0484fSRodney W. Grimes static RECNOINFO rh; 58958f0484fSRodney W. Grimes char *eq, *index(); 59058f0484fSRodney W. Grimes 59158f0484fSRodney W. Grimes if ((eq = index(s, '=')) == NULL) 59258f0484fSRodney W. Grimes err("%s: illegal structure set statement", s); 59358f0484fSRodney W. Grimes *eq++ = '\0'; 59458f0484fSRodney W. Grimes if (!isdigit(*eq)) 59558f0484fSRodney W. Grimes err("%s: structure set statement must be a number", s); 59658f0484fSRodney W. Grimes 59758f0484fSRodney W. Grimes switch (type) { 59858f0484fSRodney W. Grimes case DB_BTREE: 59958f0484fSRodney W. Grimes if (!strcmp("flags", s)) { 60058f0484fSRodney W. Grimes ib.flags = atoi(eq); 60158f0484fSRodney W. Grimes return (&ib); 60258f0484fSRodney W. Grimes } 60358f0484fSRodney W. Grimes if (!strcmp("cachesize", s)) { 60458f0484fSRodney W. Grimes ib.cachesize = atoi(eq); 60558f0484fSRodney W. Grimes return (&ib); 60658f0484fSRodney W. Grimes } 60758f0484fSRodney W. Grimes if (!strcmp("maxkeypage", s)) { 60858f0484fSRodney W. Grimes ib.maxkeypage = atoi(eq); 60958f0484fSRodney W. Grimes return (&ib); 61058f0484fSRodney W. Grimes } 61158f0484fSRodney W. Grimes if (!strcmp("minkeypage", s)) { 61258f0484fSRodney W. Grimes ib.minkeypage = atoi(eq); 61358f0484fSRodney W. Grimes return (&ib); 61458f0484fSRodney W. Grimes } 61558f0484fSRodney W. Grimes if (!strcmp("lorder", s)) { 61658f0484fSRodney W. Grimes ib.lorder = atoi(eq); 61758f0484fSRodney W. Grimes return (&ib); 61858f0484fSRodney W. Grimes } 61958f0484fSRodney W. Grimes if (!strcmp("psize", s)) { 62058f0484fSRodney W. Grimes ib.psize = atoi(eq); 62158f0484fSRodney W. Grimes return (&ib); 62258f0484fSRodney W. Grimes } 62358f0484fSRodney W. Grimes break; 62458f0484fSRodney W. Grimes case DB_HASH: 62558f0484fSRodney W. Grimes if (!strcmp("bsize", s)) { 62658f0484fSRodney W. Grimes ih.bsize = atoi(eq); 62758f0484fSRodney W. Grimes return (&ih); 62858f0484fSRodney W. Grimes } 62958f0484fSRodney W. Grimes if (!strcmp("ffactor", s)) { 63058f0484fSRodney W. Grimes ih.ffactor = atoi(eq); 63158f0484fSRodney W. Grimes return (&ih); 63258f0484fSRodney W. Grimes } 63358f0484fSRodney W. Grimes if (!strcmp("nelem", s)) { 63458f0484fSRodney W. Grimes ih.nelem = atoi(eq); 63558f0484fSRodney W. Grimes return (&ih); 63658f0484fSRodney W. Grimes } 63758f0484fSRodney W. Grimes if (!strcmp("cachesize", s)) { 63858f0484fSRodney W. Grimes ih.cachesize = atoi(eq); 63958f0484fSRodney W. Grimes return (&ih); 64058f0484fSRodney W. Grimes } 64158f0484fSRodney W. Grimes if (!strcmp("lorder", s)) { 64258f0484fSRodney W. Grimes ih.lorder = atoi(eq); 64358f0484fSRodney W. Grimes return (&ih); 64458f0484fSRodney W. Grimes } 64558f0484fSRodney W. Grimes break; 64658f0484fSRodney W. Grimes case DB_RECNO: 64758f0484fSRodney W. Grimes if (!strcmp("flags", s)) { 64858f0484fSRodney W. Grimes rh.flags = atoi(eq); 64958f0484fSRodney W. Grimes return (&rh); 65058f0484fSRodney W. Grimes } 65158f0484fSRodney W. Grimes if (!strcmp("cachesize", s)) { 65258f0484fSRodney W. Grimes rh.cachesize = atoi(eq); 65358f0484fSRodney W. Grimes return (&rh); 65458f0484fSRodney W. Grimes } 65558f0484fSRodney W. Grimes if (!strcmp("lorder", s)) { 65658f0484fSRodney W. Grimes rh.lorder = atoi(eq); 65758f0484fSRodney W. Grimes return (&rh); 65858f0484fSRodney W. Grimes } 65958f0484fSRodney W. Grimes if (!strcmp("reclen", s)) { 66058f0484fSRodney W. Grimes rh.reclen = atoi(eq); 66158f0484fSRodney W. Grimes return (&rh); 66258f0484fSRodney W. Grimes } 66358f0484fSRodney W. Grimes if (!strcmp("bval", s)) { 66458f0484fSRodney W. Grimes rh.bval = atoi(eq); 66558f0484fSRodney W. Grimes return (&rh); 66658f0484fSRodney W. Grimes } 66758f0484fSRodney W. Grimes if (!strcmp("psize", s)) { 66858f0484fSRodney W. Grimes rh.psize = atoi(eq); 66958f0484fSRodney W. Grimes return (&rh); 67058f0484fSRodney W. Grimes } 67158f0484fSRodney W. Grimes break; 67258f0484fSRodney W. Grimes } 67358f0484fSRodney W. Grimes err("%s: unknown structure value", s); 67458f0484fSRodney W. Grimes /* NOTREACHED */ 67558f0484fSRodney W. Grimes } 67658f0484fSRodney W. Grimes 67758f0484fSRodney W. Grimes void * 67858f0484fSRodney W. Grimes rfile(name, lenp) 67958f0484fSRodney W. Grimes char *name; 68058f0484fSRodney W. Grimes size_t *lenp; 68158f0484fSRodney W. Grimes { 68258f0484fSRodney W. Grimes struct stat sb; 68358f0484fSRodney W. Grimes void *p; 68458f0484fSRodney W. Grimes int fd; 68558f0484fSRodney W. Grimes char *np, *index(); 68658f0484fSRodney W. Grimes 68758f0484fSRodney W. Grimes for (; isspace(*name); ++name); 68858f0484fSRodney W. Grimes if ((np = index(name, '\n')) != NULL) 68958f0484fSRodney W. Grimes *np = '\0'; 69058f0484fSRodney W. Grimes if ((fd = open(name, O_RDONLY, 0)) < 0 || 69158f0484fSRodney W. Grimes fstat(fd, &sb)) 69258f0484fSRodney W. Grimes err("%s: %s\n", name, strerror(errno)); 69358f0484fSRodney W. Grimes #ifdef NOT_PORTABLE 69458f0484fSRodney W. Grimes if (sb.st_size > (off_t)SIZE_T_MAX) 69558f0484fSRodney W. Grimes err("%s: %s\n", name, strerror(E2BIG)); 69658f0484fSRodney W. Grimes #endif 69758f0484fSRodney W. Grimes if ((p = (void *)malloc((u_int)sb.st_size)) == NULL) 69858f0484fSRodney W. Grimes err("%s", strerror(errno)); 69958f0484fSRodney W. Grimes (void)read(fd, p, (int)sb.st_size); 70058f0484fSRodney W. Grimes *lenp = sb.st_size; 70158f0484fSRodney W. Grimes (void)close(fd); 70258f0484fSRodney W. Grimes return (p); 70358f0484fSRodney W. Grimes } 70458f0484fSRodney W. Grimes 70558f0484fSRodney W. Grimes void * 70658f0484fSRodney W. Grimes xmalloc(text, len) 70758f0484fSRodney W. Grimes char *text; 70858f0484fSRodney W. Grimes size_t len; 70958f0484fSRodney W. Grimes { 71058f0484fSRodney W. Grimes void *p; 71158f0484fSRodney W. Grimes 71258f0484fSRodney W. Grimes if ((p = (void *)malloc(len)) == NULL) 71358f0484fSRodney W. Grimes err("%s", strerror(errno)); 71458f0484fSRodney W. Grimes memmove(p, text, len); 71558f0484fSRodney W. Grimes return (p); 71658f0484fSRodney W. Grimes } 71758f0484fSRodney W. Grimes 71858f0484fSRodney W. Grimes void 71958f0484fSRodney W. Grimes usage() 72058f0484fSRodney W. Grimes { 72158f0484fSRodney W. Grimes (void)fprintf(stderr, 72258f0484fSRodney W. Grimes "usage: dbtest [-l] [-f file] [-i info] [-o file] type script\n"); 72358f0484fSRodney W. Grimes exit(1); 72458f0484fSRodney W. Grimes } 72558f0484fSRodney W. Grimes 72658f0484fSRodney W. Grimes #include <stdarg.h> 72758f0484fSRodney W. Grimes 72858f0484fSRodney W. Grimes void 72958f0484fSRodney W. Grimes err(const char *fmt, ...) 73058f0484fSRodney W. Grimes { 73158f0484fSRodney W. Grimes va_list ap; 732a82bbc73SAlfred Perlstein 73358f0484fSRodney W. Grimes va_start(ap, fmt); 73458f0484fSRodney W. Grimes (void)fprintf(stderr, "dbtest: "); 73558f0484fSRodney W. Grimes (void)vfprintf(stderr, fmt, ap); 73658f0484fSRodney W. Grimes va_end(ap); 73758f0484fSRodney W. Grimes (void)fprintf(stderr, "\n"); 73858f0484fSRodney W. Grimes exit(1); 73958f0484fSRodney W. Grimes /* NOTREACHED */ 74058f0484fSRodney W. Grimes } 741