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