103 switch (ch) { 104 case 'f': 105 fname = optarg; 106 break; 107 case 'i': 108 infoarg = optarg; 109 break; 110 case 'l': 111 oflags |= DB_LOCK; 112 break; 113 case 'o': 114 if ((ofd = open(optarg, 115 O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0) 116 err("%s: %s", optarg, strerror(errno)); 117 break; 118 case 's': 119 sflag = 1; 120 break; 121 case '?': 122 default: 123 usage(); 124 } 125 argc -= optind; 126 argv += optind; 127 128 if (argc != 2) 129 usage(); 130 131 /* Set the type. */ 132 type = dbtype(*argv++); 133 134 /* Open the descriptor file. */ 135 if (strcmp(*argv, "-") && freopen(*argv, "r", stdin) == NULL) 136 err("%s: %s", *argv, strerror(errno)); 137 138 /* Set up the db structure as necessary. */ 139 if (infoarg == NULL) 140 infop = NULL; 141 else 142 for (p = strtok(infoarg, ",\t "); p != NULL; 143 p = strtok(0, ",\t ")) 144 if (*p != '\0') 145 infop = setinfo(type, p); 146 147 /* 148 * Open the DB. Delete any preexisting copy, you almost never 149 * want it around, and it often screws up tests. 150 */ 151 if (fname == NULL) { 152 p = getenv("TMPDIR"); 153 if (p == NULL) 154 p = "/var/tmp"; 155 (void)snprintf(buf, sizeof(buf), "%s/__dbtest", p); 156 fname = buf; 157 (void)unlink(buf); 158 } else if (!sflag) 159 (void)unlink(fname); 160 161 if ((dbp = dbopen(fname, 162 oflags, S_IRUSR | S_IWUSR, type, infop)) == NULL) 163 err("dbopen: %s", strerror(errno)); 164 XXdbp = dbp; 165 166 state = COMMAND; 167 for (lineno = 1; 168 (p = fgets(buf, sizeof(buf), stdin)) != NULL; ++lineno) { 169 /* Delete the newline, displaying the key/data is easier. */ 170 if (ofd == STDOUT_FILENO && (t = strchr(p, '\n')) != NULL) 171 *t = '\0'; 172 if ((len = strlen(buf)) == 0 || isspace(*p) || *p == '#') 173 continue; 174 175 /* Convenient gdb break point. */ 176 if (XXlineno == lineno) 177 XXlineno = 1; 178 switch (*p) { 179 case 'c': /* compare */ 180 if (state != COMMAND) 181 err("line %lu: not expecting command", lineno); 182 state = KEY; 183 command = COMPARE; 184 break; 185 case 'e': /* echo */ 186 if (state != COMMAND) 187 err("line %lu: not expecting command", lineno); 188 /* Don't display the newline, if CR at EOL. */ 189 if (p[len - 2] == '\r') 190 --len; 191 if (write(ofd, p + 1, len - 1) != len - 1 || 192 write(ofd, "\n", 1) != 1) 193 err("write: %s", strerror(errno)); 194 break; 195 case 'g': /* get */ 196 if (state != COMMAND) 197 err("line %lu: not expecting command", lineno); 198 state = KEY; 199 command = GET; 200 break; 201 case 'p': /* put */ 202 if (state != COMMAND) 203 err("line %lu: not expecting command", lineno); 204 state = KEY; 205 command = PUT; 206 break; 207 case 'r': /* remove */ 208 if (state != COMMAND) 209 err("line %lu: not expecting command", lineno); 210 if (flags == R_CURSOR) { 211 rem(dbp, &key); 212 state = COMMAND; 213 } else { 214 state = KEY; 215 command = REMOVE; 216 } 217 break; 218 case 'S': /* sync */ 219 if (state != COMMAND) 220 err("line %lu: not expecting command", lineno); 221 synk(dbp); 222 state = COMMAND; 223 break; 224 case 's': /* seq */ 225 if (state != COMMAND) 226 err("line %lu: not expecting command", lineno); 227 if (flags == R_CURSOR) { 228 state = KEY; 229 command = SEQ; 230 } else 231 seq(dbp, &key); 232 break; 233 case 'f': 234 flags = setflags(p + 1); 235 break; 236 case 'D': /* data file */ 237 if (state != DATA) 238 err("line %lu: not expecting data", lineno); 239 data.data = rfile(p + 1, &data.size); 240 goto ldata; 241 case 'd': /* data */ 242 if (state != DATA) 243 err("line %lu: not expecting data", lineno); 244 data.data = xmalloc(p + 1, len - 1); 245 data.size = len - 1; 246ldata: switch (command) { 247 case COMPARE: 248 compare(&keydata, &data); 249 break; 250 case PUT: 251 put(dbp, &key, &data); 252 break; 253 default: 254 err("line %lu: command doesn't take data", 255 lineno); 256 } 257 if (type != DB_RECNO) 258 free(key.data); 259 free(data.data); 260 state = COMMAND; 261 break; 262 case 'K': /* key file */ 263 if (state != KEY) 264 err("line %lu: not expecting a key", lineno); 265 if (type == DB_RECNO) 266 err("line %lu: 'K' not available for recno", 267 lineno); 268 key.data = rfile(p + 1, &key.size); 269 goto lkey; 270 case 'k': /* key */ 271 if (state != KEY) 272 err("line %lu: not expecting a key", lineno); 273 if (type == DB_RECNO) { 274 static recno_t recno; 275 recno = atoi(p + 1); 276 key.data = &recno; 277 key.size = sizeof(recno); 278 } else { 279 key.data = xmalloc(p + 1, len - 1); 280 key.size = len - 1; 281 } 282lkey: switch (command) { 283 case COMPARE: 284 getdata(dbp, &key, &keydata); 285 state = DATA; 286 break; 287 case GET: 288 get(dbp, &key); 289 if (type != DB_RECNO) 290 free(key.data); 291 state = COMMAND; 292 break; 293 case PUT: 294 state = DATA; 295 break; 296 case REMOVE: 297 rem(dbp, &key); 298 if ((type != DB_RECNO) && (flags != R_CURSOR)) 299 free(key.data); 300 state = COMMAND; 301 break; 302 case SEQ: 303 seq(dbp, &key); 304 if ((type != DB_RECNO) && (flags != R_CURSOR)) 305 free(key.data); 306 state = COMMAND; 307 break; 308 default: 309 err("line %lu: command doesn't take a key", 310 lineno); 311 } 312 break; 313 case 'o': 314 dump(dbp, p[1] == 'r'); 315 break; 316 default: 317 err("line %lu: %s: unknown command character", 318 lineno, p); 319 } 320 } 321#ifdef STATISTICS 322 /* 323 * -l must be used (DB_LOCK must be set) for this to be 324 * used, otherwise a page will be locked and it will fail. 325 */ 326 if (type == DB_BTREE && oflags & DB_LOCK) 327 __bt_stat(dbp); 328#endif 329 if (dbp->close(dbp)) 330 err("db->close: %s", strerror(errno)); 331 (void)close(ofd); 332 exit(0); 333} 334 335#define NOOVERWRITE "put failed, would overwrite key\n" 336 337void 338compare(db1, db2) 339 DBT *db1, *db2; 340{ 341 size_t len; 342 u_char *p1, *p2; 343 344 if (db1->size != db2->size) 345 printf("compare failed: key->data len %lu != data len %lu\n", 346 db1->size, db2->size); 347 348 len = MIN(db1->size, db2->size); 349 for (p1 = db1->data, p2 = db2->data; len--;) 350 if (*p1++ != *p2++) { 351 printf("compare failed at offset %d\n", 352 p1 - (u_char *)db1->data); 353 break; 354 } 355} 356 357void 358get(dbp, kp) 359 DB *dbp; 360 DBT *kp; 361{ 362 DBT data; 363 364 switch (dbp->get(dbp, kp, &data, flags)) { 365 case 0: 366 (void)write(ofd, data.data, data.size); 367 if (ofd == STDOUT_FILENO) 368 (void)write(ofd, "\n", 1); 369 break; 370 case -1: 371 err("line %lu: get: %s", lineno, strerror(errno)); 372 /* NOTREACHED */ 373 case 1: 374#define NOSUCHKEY "get failed, no such key\n" 375 if (ofd != STDOUT_FILENO) 376 (void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1); 377 else 378 (void)fprintf(stderr, "%d: %.*s: %s", 379 lineno, MIN(kp->size, 20), kp->data, NOSUCHKEY); 380#undef NOSUCHKEY 381 break; 382 } 383} 384 385void 386getdata(dbp, kp, dp) 387 DB *dbp; 388 DBT *kp, *dp; 389{ 390 switch (dbp->get(dbp, kp, dp, flags)) { 391 case 0: 392 return; 393 case -1: 394 err("line %lu: getdata: %s", lineno, strerror(errno)); 395 /* NOTREACHED */ 396 case 1: 397 err("line %lu: getdata failed, no such key", lineno); 398 /* NOTREACHED */ 399 } 400} 401 402void 403put(dbp, kp, dp) 404 DB *dbp; 405 DBT *kp, *dp; 406{ 407 switch (dbp->put(dbp, kp, dp, flags)) { 408 case 0: 409 break; 410 case -1: 411 err("line %lu: put: %s", lineno, strerror(errno)); 412 /* NOTREACHED */ 413 case 1: 414 (void)write(ofd, NOOVERWRITE, sizeof(NOOVERWRITE) - 1); 415 break; 416 } 417} 418 419void 420rem(dbp, kp) 421 DB *dbp; 422 DBT *kp; 423{ 424 switch (dbp->del(dbp, kp, flags)) { 425 case 0: 426 break; 427 case -1: 428 err("line %lu: rem: %s", lineno, strerror(errno)); 429 /* NOTREACHED */ 430 case 1: 431#define NOSUCHKEY "rem failed, no such key\n" 432 if (ofd != STDOUT_FILENO) 433 (void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1); 434 else if (flags != R_CURSOR) 435 (void)fprintf(stderr, "%d: %.*s: %s", 436 lineno, MIN(kp->size, 20), kp->data, NOSUCHKEY); 437 else 438 (void)fprintf(stderr, 439 "%d: rem of cursor failed\n", lineno); 440#undef NOSUCHKEY 441 break; 442 } 443} 444 445void 446synk(dbp) 447 DB *dbp; 448{ 449 switch (dbp->sync(dbp, flags)) { 450 case 0: 451 break; 452 case -1: 453 err("line %lu: synk: %s", lineno, strerror(errno)); 454 /* NOTREACHED */ 455 } 456} 457 458void 459seq(dbp, kp) 460 DB *dbp; 461 DBT *kp; 462{ 463 DBT data; 464 465 switch (dbp->seq(dbp, kp, &data, flags)) { 466 case 0: 467 (void)write(ofd, data.data, data.size); 468 if (ofd == STDOUT_FILENO) 469 (void)write(ofd, "\n", 1); 470 break; 471 case -1: 472 err("line %lu: seq: %s", lineno, strerror(errno)); 473 /* NOTREACHED */ 474 case 1: 475#define NOSUCHKEY "seq failed, no such key\n" 476 if (ofd != STDOUT_FILENO) 477 (void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1); 478 else if (flags == R_CURSOR) 479 (void)fprintf(stderr, "%d: %.*s: %s", 480 lineno, MIN(kp->size, 20), kp->data, NOSUCHKEY); 481 else 482 (void)fprintf(stderr, 483 "%d: seq (%s) failed\n", lineno, sflags(flags)); 484#undef NOSUCHKEY 485 break; 486 } 487} 488 489void 490dump(dbp, rev) 491 DB *dbp; 492 int rev; 493{ 494 DBT key, data; 495 int flags, nflags; 496 497 if (rev) { 498 flags = R_LAST; 499 nflags = R_PREV; 500 } else { 501 flags = R_FIRST; 502 nflags = R_NEXT; 503 } 504 for (;; flags = nflags) 505 switch (dbp->seq(dbp, &key, &data, flags)) { 506 case 0: 507 (void)write(ofd, data.data, data.size); 508 if (ofd == STDOUT_FILENO) 509 (void)write(ofd, "\n", 1); 510 break; 511 case 1: 512 goto done; 513 case -1: 514 err("line %lu: (dump) seq: %s", 515 lineno, strerror(errno)); 516 /* NOTREACHED */ 517 } 518done: return; 519} 520 521u_int 522setflags(s) 523 char *s; 524{ 525 char *p, *index(); 526 527 for (; isspace(*s); ++s); 528 if (*s == '\n' || *s == '\0') 529 return (0); 530 if ((p = index(s, '\n')) != NULL) 531 *p = '\0'; 532 if (!strcmp(s, "R_CURSOR")) return (R_CURSOR); 533 if (!strcmp(s, "R_FIRST")) return (R_FIRST); 534 if (!strcmp(s, "R_IAFTER")) return (R_IAFTER); 535 if (!strcmp(s, "R_IBEFORE")) return (R_IBEFORE); 536 if (!strcmp(s, "R_LAST")) return (R_LAST); 537 if (!strcmp(s, "R_NEXT")) return (R_NEXT); 538 if (!strcmp(s, "R_NOOVERWRITE")) return (R_NOOVERWRITE); 539 if (!strcmp(s, "R_PREV")) return (R_PREV); 540 if (!strcmp(s, "R_SETCURSOR")) return (R_SETCURSOR); 541 542 err("line %lu: %s: unknown flag", lineno, s); 543 /* NOTREACHED */ 544} 545 546char * 547sflags(flags) 548 int flags; 549{ 550 switch (flags) { 551 case R_CURSOR: return ("R_CURSOR"); 552 case R_FIRST: return ("R_FIRST"); 553 case R_IAFTER: return ("R_IAFTER"); 554 case R_IBEFORE: return ("R_IBEFORE"); 555 case R_LAST: return ("R_LAST"); 556 case R_NEXT: return ("R_NEXT"); 557 case R_NOOVERWRITE: return ("R_NOOVERWRITE"); 558 case R_PREV: return ("R_PREV"); 559 case R_SETCURSOR: return ("R_SETCURSOR"); 560 } 561 562 return ("UNKNOWN!"); 563} 564 565DBTYPE 566dbtype(s) 567 char *s; 568{ 569 if (!strcmp(s, "btree")) 570 return (DB_BTREE); 571 if (!strcmp(s, "hash")) 572 return (DB_HASH); 573 if (!strcmp(s, "recno")) 574 return (DB_RECNO); 575 err("%s: unknown type (use btree, hash or recno)", s); 576 /* NOTREACHED */ 577} 578 579void * 580setinfo(type, s) 581 DBTYPE type; 582 char *s; 583{ 584 static BTREEINFO ib; 585 static HASHINFO ih; 586 static RECNOINFO rh; 587 char *eq, *index(); 588 589 if ((eq = index(s, '=')) == NULL) 590 err("%s: illegal structure set statement", s); 591 *eq++ = '\0'; 592 if (!isdigit(*eq)) 593 err("%s: structure set statement must be a number", s); 594 595 switch (type) { 596 case DB_BTREE: 597 if (!strcmp("flags", s)) { 598 ib.flags = atoi(eq); 599 return (&ib); 600 } 601 if (!strcmp("cachesize", s)) { 602 ib.cachesize = atoi(eq); 603 return (&ib); 604 } 605 if (!strcmp("maxkeypage", s)) { 606 ib.maxkeypage = atoi(eq); 607 return (&ib); 608 } 609 if (!strcmp("minkeypage", s)) { 610 ib.minkeypage = atoi(eq); 611 return (&ib); 612 } 613 if (!strcmp("lorder", s)) { 614 ib.lorder = atoi(eq); 615 return (&ib); 616 } 617 if (!strcmp("psize", s)) { 618 ib.psize = atoi(eq); 619 return (&ib); 620 } 621 break; 622 case DB_HASH: 623 if (!strcmp("bsize", s)) { 624 ih.bsize = atoi(eq); 625 return (&ih); 626 } 627 if (!strcmp("ffactor", s)) { 628 ih.ffactor = atoi(eq); 629 return (&ih); 630 } 631 if (!strcmp("nelem", s)) { 632 ih.nelem = atoi(eq); 633 return (&ih); 634 } 635 if (!strcmp("cachesize", s)) { 636 ih.cachesize = atoi(eq); 637 return (&ih); 638 } 639 if (!strcmp("lorder", s)) { 640 ih.lorder = atoi(eq); 641 return (&ih); 642 } 643 break; 644 case DB_RECNO: 645 if (!strcmp("flags", s)) { 646 rh.flags = atoi(eq); 647 return (&rh); 648 } 649 if (!strcmp("cachesize", s)) { 650 rh.cachesize = atoi(eq); 651 return (&rh); 652 } 653 if (!strcmp("lorder", s)) { 654 rh.lorder = atoi(eq); 655 return (&rh); 656 } 657 if (!strcmp("reclen", s)) { 658 rh.reclen = atoi(eq); 659 return (&rh); 660 } 661 if (!strcmp("bval", s)) { 662 rh.bval = atoi(eq); 663 return (&rh); 664 } 665 if (!strcmp("psize", s)) { 666 rh.psize = atoi(eq); 667 return (&rh); 668 } 669 break; 670 } 671 err("%s: unknown structure value", s); 672 /* NOTREACHED */ 673} 674 675void * 676rfile(name, lenp) 677 char *name; 678 size_t *lenp; 679{ 680 struct stat sb; 681 void *p; 682 int fd; 683 char *np, *index(); 684 685 for (; isspace(*name); ++name); 686 if ((np = index(name, '\n')) != NULL) 687 *np = '\0'; 688 if ((fd = open(name, O_RDONLY, 0)) < 0 || 689 fstat(fd, &sb)) 690 err("%s: %s\n", name, strerror(errno)); 691#ifdef NOT_PORTABLE 692 if (sb.st_size > (off_t)SIZE_T_MAX) 693 err("%s: %s\n", name, strerror(E2BIG)); 694#endif 695 if ((p = (void *)malloc((u_int)sb.st_size)) == NULL) 696 err("%s", strerror(errno)); 697 (void)read(fd, p, (int)sb.st_size); 698 *lenp = sb.st_size; 699 (void)close(fd); 700 return (p); 701} 702 703void * 704xmalloc(text, len) 705 char *text; 706 size_t len; 707{ 708 void *p; 709 710 if ((p = (void *)malloc(len)) == NULL) 711 err("%s", strerror(errno)); 712 memmove(p, text, len); 713 return (p); 714} 715 716void 717usage() 718{ 719 (void)fprintf(stderr, 720 "usage: dbtest [-l] [-f file] [-i info] [-o file] type script\n"); 721 exit(1); 722} 723 724#include <stdarg.h> 725 726void 727err(const char *fmt, ...) 728{ 729 va_list ap; 730 731 va_start(ap, fmt); 732 (void)fprintf(stderr, "dbtest: "); 733 (void)vfprintf(stderr, fmt, ap); 734 va_end(ap); 735 (void)fprintf(stderr, "\n"); 736 exit(1); 737 /* NOTREACHED */ 738}
| 103 switch (ch) { 104 case 'f': 105 fname = optarg; 106 break; 107 case 'i': 108 infoarg = optarg; 109 break; 110 case 'l': 111 oflags |= DB_LOCK; 112 break; 113 case 'o': 114 if ((ofd = open(optarg, 115 O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0) 116 err("%s: %s", optarg, strerror(errno)); 117 break; 118 case 's': 119 sflag = 1; 120 break; 121 case '?': 122 default: 123 usage(); 124 } 125 argc -= optind; 126 argv += optind; 127 128 if (argc != 2) 129 usage(); 130 131 /* Set the type. */ 132 type = dbtype(*argv++); 133 134 /* Open the descriptor file. */ 135 if (strcmp(*argv, "-") && freopen(*argv, "r", stdin) == NULL) 136 err("%s: %s", *argv, strerror(errno)); 137 138 /* Set up the db structure as necessary. */ 139 if (infoarg == NULL) 140 infop = NULL; 141 else 142 for (p = strtok(infoarg, ",\t "); p != NULL; 143 p = strtok(0, ",\t ")) 144 if (*p != '\0') 145 infop = setinfo(type, p); 146 147 /* 148 * Open the DB. Delete any preexisting copy, you almost never 149 * want it around, and it often screws up tests. 150 */ 151 if (fname == NULL) { 152 p = getenv("TMPDIR"); 153 if (p == NULL) 154 p = "/var/tmp"; 155 (void)snprintf(buf, sizeof(buf), "%s/__dbtest", p); 156 fname = buf; 157 (void)unlink(buf); 158 } else if (!sflag) 159 (void)unlink(fname); 160 161 if ((dbp = dbopen(fname, 162 oflags, S_IRUSR | S_IWUSR, type, infop)) == NULL) 163 err("dbopen: %s", strerror(errno)); 164 XXdbp = dbp; 165 166 state = COMMAND; 167 for (lineno = 1; 168 (p = fgets(buf, sizeof(buf), stdin)) != NULL; ++lineno) { 169 /* Delete the newline, displaying the key/data is easier. */ 170 if (ofd == STDOUT_FILENO && (t = strchr(p, '\n')) != NULL) 171 *t = '\0'; 172 if ((len = strlen(buf)) == 0 || isspace(*p) || *p == '#') 173 continue; 174 175 /* Convenient gdb break point. */ 176 if (XXlineno == lineno) 177 XXlineno = 1; 178 switch (*p) { 179 case 'c': /* compare */ 180 if (state != COMMAND) 181 err("line %lu: not expecting command", lineno); 182 state = KEY; 183 command = COMPARE; 184 break; 185 case 'e': /* echo */ 186 if (state != COMMAND) 187 err("line %lu: not expecting command", lineno); 188 /* Don't display the newline, if CR at EOL. */ 189 if (p[len - 2] == '\r') 190 --len; 191 if (write(ofd, p + 1, len - 1) != len - 1 || 192 write(ofd, "\n", 1) != 1) 193 err("write: %s", strerror(errno)); 194 break; 195 case 'g': /* get */ 196 if (state != COMMAND) 197 err("line %lu: not expecting command", lineno); 198 state = KEY; 199 command = GET; 200 break; 201 case 'p': /* put */ 202 if (state != COMMAND) 203 err("line %lu: not expecting command", lineno); 204 state = KEY; 205 command = PUT; 206 break; 207 case 'r': /* remove */ 208 if (state != COMMAND) 209 err("line %lu: not expecting command", lineno); 210 if (flags == R_CURSOR) { 211 rem(dbp, &key); 212 state = COMMAND; 213 } else { 214 state = KEY; 215 command = REMOVE; 216 } 217 break; 218 case 'S': /* sync */ 219 if (state != COMMAND) 220 err("line %lu: not expecting command", lineno); 221 synk(dbp); 222 state = COMMAND; 223 break; 224 case 's': /* seq */ 225 if (state != COMMAND) 226 err("line %lu: not expecting command", lineno); 227 if (flags == R_CURSOR) { 228 state = KEY; 229 command = SEQ; 230 } else 231 seq(dbp, &key); 232 break; 233 case 'f': 234 flags = setflags(p + 1); 235 break; 236 case 'D': /* data file */ 237 if (state != DATA) 238 err("line %lu: not expecting data", lineno); 239 data.data = rfile(p + 1, &data.size); 240 goto ldata; 241 case 'd': /* data */ 242 if (state != DATA) 243 err("line %lu: not expecting data", lineno); 244 data.data = xmalloc(p + 1, len - 1); 245 data.size = len - 1; 246ldata: switch (command) { 247 case COMPARE: 248 compare(&keydata, &data); 249 break; 250 case PUT: 251 put(dbp, &key, &data); 252 break; 253 default: 254 err("line %lu: command doesn't take data", 255 lineno); 256 } 257 if (type != DB_RECNO) 258 free(key.data); 259 free(data.data); 260 state = COMMAND; 261 break; 262 case 'K': /* key file */ 263 if (state != KEY) 264 err("line %lu: not expecting a key", lineno); 265 if (type == DB_RECNO) 266 err("line %lu: 'K' not available for recno", 267 lineno); 268 key.data = rfile(p + 1, &key.size); 269 goto lkey; 270 case 'k': /* key */ 271 if (state != KEY) 272 err("line %lu: not expecting a key", lineno); 273 if (type == DB_RECNO) { 274 static recno_t recno; 275 recno = atoi(p + 1); 276 key.data = &recno; 277 key.size = sizeof(recno); 278 } else { 279 key.data = xmalloc(p + 1, len - 1); 280 key.size = len - 1; 281 } 282lkey: switch (command) { 283 case COMPARE: 284 getdata(dbp, &key, &keydata); 285 state = DATA; 286 break; 287 case GET: 288 get(dbp, &key); 289 if (type != DB_RECNO) 290 free(key.data); 291 state = COMMAND; 292 break; 293 case PUT: 294 state = DATA; 295 break; 296 case REMOVE: 297 rem(dbp, &key); 298 if ((type != DB_RECNO) && (flags != R_CURSOR)) 299 free(key.data); 300 state = COMMAND; 301 break; 302 case SEQ: 303 seq(dbp, &key); 304 if ((type != DB_RECNO) && (flags != R_CURSOR)) 305 free(key.data); 306 state = COMMAND; 307 break; 308 default: 309 err("line %lu: command doesn't take a key", 310 lineno); 311 } 312 break; 313 case 'o': 314 dump(dbp, p[1] == 'r'); 315 break; 316 default: 317 err("line %lu: %s: unknown command character", 318 lineno, p); 319 } 320 } 321#ifdef STATISTICS 322 /* 323 * -l must be used (DB_LOCK must be set) for this to be 324 * used, otherwise a page will be locked and it will fail. 325 */ 326 if (type == DB_BTREE && oflags & DB_LOCK) 327 __bt_stat(dbp); 328#endif 329 if (dbp->close(dbp)) 330 err("db->close: %s", strerror(errno)); 331 (void)close(ofd); 332 exit(0); 333} 334 335#define NOOVERWRITE "put failed, would overwrite key\n" 336 337void 338compare(db1, db2) 339 DBT *db1, *db2; 340{ 341 size_t len; 342 u_char *p1, *p2; 343 344 if (db1->size != db2->size) 345 printf("compare failed: key->data len %lu != data len %lu\n", 346 db1->size, db2->size); 347 348 len = MIN(db1->size, db2->size); 349 for (p1 = db1->data, p2 = db2->data; len--;) 350 if (*p1++ != *p2++) { 351 printf("compare failed at offset %d\n", 352 p1 - (u_char *)db1->data); 353 break; 354 } 355} 356 357void 358get(dbp, kp) 359 DB *dbp; 360 DBT *kp; 361{ 362 DBT data; 363 364 switch (dbp->get(dbp, kp, &data, flags)) { 365 case 0: 366 (void)write(ofd, data.data, data.size); 367 if (ofd == STDOUT_FILENO) 368 (void)write(ofd, "\n", 1); 369 break; 370 case -1: 371 err("line %lu: get: %s", lineno, strerror(errno)); 372 /* NOTREACHED */ 373 case 1: 374#define NOSUCHKEY "get failed, no such key\n" 375 if (ofd != STDOUT_FILENO) 376 (void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1); 377 else 378 (void)fprintf(stderr, "%d: %.*s: %s", 379 lineno, MIN(kp->size, 20), kp->data, NOSUCHKEY); 380#undef NOSUCHKEY 381 break; 382 } 383} 384 385void 386getdata(dbp, kp, dp) 387 DB *dbp; 388 DBT *kp, *dp; 389{ 390 switch (dbp->get(dbp, kp, dp, flags)) { 391 case 0: 392 return; 393 case -1: 394 err("line %lu: getdata: %s", lineno, strerror(errno)); 395 /* NOTREACHED */ 396 case 1: 397 err("line %lu: getdata failed, no such key", lineno); 398 /* NOTREACHED */ 399 } 400} 401 402void 403put(dbp, kp, dp) 404 DB *dbp; 405 DBT *kp, *dp; 406{ 407 switch (dbp->put(dbp, kp, dp, flags)) { 408 case 0: 409 break; 410 case -1: 411 err("line %lu: put: %s", lineno, strerror(errno)); 412 /* NOTREACHED */ 413 case 1: 414 (void)write(ofd, NOOVERWRITE, sizeof(NOOVERWRITE) - 1); 415 break; 416 } 417} 418 419void 420rem(dbp, kp) 421 DB *dbp; 422 DBT *kp; 423{ 424 switch (dbp->del(dbp, kp, flags)) { 425 case 0: 426 break; 427 case -1: 428 err("line %lu: rem: %s", lineno, strerror(errno)); 429 /* NOTREACHED */ 430 case 1: 431#define NOSUCHKEY "rem failed, no such key\n" 432 if (ofd != STDOUT_FILENO) 433 (void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1); 434 else if (flags != R_CURSOR) 435 (void)fprintf(stderr, "%d: %.*s: %s", 436 lineno, MIN(kp->size, 20), kp->data, NOSUCHKEY); 437 else 438 (void)fprintf(stderr, 439 "%d: rem of cursor failed\n", lineno); 440#undef NOSUCHKEY 441 break; 442 } 443} 444 445void 446synk(dbp) 447 DB *dbp; 448{ 449 switch (dbp->sync(dbp, flags)) { 450 case 0: 451 break; 452 case -1: 453 err("line %lu: synk: %s", lineno, strerror(errno)); 454 /* NOTREACHED */ 455 } 456} 457 458void 459seq(dbp, kp) 460 DB *dbp; 461 DBT *kp; 462{ 463 DBT data; 464 465 switch (dbp->seq(dbp, kp, &data, flags)) { 466 case 0: 467 (void)write(ofd, data.data, data.size); 468 if (ofd == STDOUT_FILENO) 469 (void)write(ofd, "\n", 1); 470 break; 471 case -1: 472 err("line %lu: seq: %s", lineno, strerror(errno)); 473 /* NOTREACHED */ 474 case 1: 475#define NOSUCHKEY "seq failed, no such key\n" 476 if (ofd != STDOUT_FILENO) 477 (void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1); 478 else if (flags == R_CURSOR) 479 (void)fprintf(stderr, "%d: %.*s: %s", 480 lineno, MIN(kp->size, 20), kp->data, NOSUCHKEY); 481 else 482 (void)fprintf(stderr, 483 "%d: seq (%s) failed\n", lineno, sflags(flags)); 484#undef NOSUCHKEY 485 break; 486 } 487} 488 489void 490dump(dbp, rev) 491 DB *dbp; 492 int rev; 493{ 494 DBT key, data; 495 int flags, nflags; 496 497 if (rev) { 498 flags = R_LAST; 499 nflags = R_PREV; 500 } else { 501 flags = R_FIRST; 502 nflags = R_NEXT; 503 } 504 for (;; flags = nflags) 505 switch (dbp->seq(dbp, &key, &data, flags)) { 506 case 0: 507 (void)write(ofd, data.data, data.size); 508 if (ofd == STDOUT_FILENO) 509 (void)write(ofd, "\n", 1); 510 break; 511 case 1: 512 goto done; 513 case -1: 514 err("line %lu: (dump) seq: %s", 515 lineno, strerror(errno)); 516 /* NOTREACHED */ 517 } 518done: return; 519} 520 521u_int 522setflags(s) 523 char *s; 524{ 525 char *p, *index(); 526 527 for (; isspace(*s); ++s); 528 if (*s == '\n' || *s == '\0') 529 return (0); 530 if ((p = index(s, '\n')) != NULL) 531 *p = '\0'; 532 if (!strcmp(s, "R_CURSOR")) return (R_CURSOR); 533 if (!strcmp(s, "R_FIRST")) return (R_FIRST); 534 if (!strcmp(s, "R_IAFTER")) return (R_IAFTER); 535 if (!strcmp(s, "R_IBEFORE")) return (R_IBEFORE); 536 if (!strcmp(s, "R_LAST")) return (R_LAST); 537 if (!strcmp(s, "R_NEXT")) return (R_NEXT); 538 if (!strcmp(s, "R_NOOVERWRITE")) return (R_NOOVERWRITE); 539 if (!strcmp(s, "R_PREV")) return (R_PREV); 540 if (!strcmp(s, "R_SETCURSOR")) return (R_SETCURSOR); 541 542 err("line %lu: %s: unknown flag", lineno, s); 543 /* NOTREACHED */ 544} 545 546char * 547sflags(flags) 548 int flags; 549{ 550 switch (flags) { 551 case R_CURSOR: return ("R_CURSOR"); 552 case R_FIRST: return ("R_FIRST"); 553 case R_IAFTER: return ("R_IAFTER"); 554 case R_IBEFORE: return ("R_IBEFORE"); 555 case R_LAST: return ("R_LAST"); 556 case R_NEXT: return ("R_NEXT"); 557 case R_NOOVERWRITE: return ("R_NOOVERWRITE"); 558 case R_PREV: return ("R_PREV"); 559 case R_SETCURSOR: return ("R_SETCURSOR"); 560 } 561 562 return ("UNKNOWN!"); 563} 564 565DBTYPE 566dbtype(s) 567 char *s; 568{ 569 if (!strcmp(s, "btree")) 570 return (DB_BTREE); 571 if (!strcmp(s, "hash")) 572 return (DB_HASH); 573 if (!strcmp(s, "recno")) 574 return (DB_RECNO); 575 err("%s: unknown type (use btree, hash or recno)", s); 576 /* NOTREACHED */ 577} 578 579void * 580setinfo(type, s) 581 DBTYPE type; 582 char *s; 583{ 584 static BTREEINFO ib; 585 static HASHINFO ih; 586 static RECNOINFO rh; 587 char *eq, *index(); 588 589 if ((eq = index(s, '=')) == NULL) 590 err("%s: illegal structure set statement", s); 591 *eq++ = '\0'; 592 if (!isdigit(*eq)) 593 err("%s: structure set statement must be a number", s); 594 595 switch (type) { 596 case DB_BTREE: 597 if (!strcmp("flags", s)) { 598 ib.flags = atoi(eq); 599 return (&ib); 600 } 601 if (!strcmp("cachesize", s)) { 602 ib.cachesize = atoi(eq); 603 return (&ib); 604 } 605 if (!strcmp("maxkeypage", s)) { 606 ib.maxkeypage = atoi(eq); 607 return (&ib); 608 } 609 if (!strcmp("minkeypage", s)) { 610 ib.minkeypage = atoi(eq); 611 return (&ib); 612 } 613 if (!strcmp("lorder", s)) { 614 ib.lorder = atoi(eq); 615 return (&ib); 616 } 617 if (!strcmp("psize", s)) { 618 ib.psize = atoi(eq); 619 return (&ib); 620 } 621 break; 622 case DB_HASH: 623 if (!strcmp("bsize", s)) { 624 ih.bsize = atoi(eq); 625 return (&ih); 626 } 627 if (!strcmp("ffactor", s)) { 628 ih.ffactor = atoi(eq); 629 return (&ih); 630 } 631 if (!strcmp("nelem", s)) { 632 ih.nelem = atoi(eq); 633 return (&ih); 634 } 635 if (!strcmp("cachesize", s)) { 636 ih.cachesize = atoi(eq); 637 return (&ih); 638 } 639 if (!strcmp("lorder", s)) { 640 ih.lorder = atoi(eq); 641 return (&ih); 642 } 643 break; 644 case DB_RECNO: 645 if (!strcmp("flags", s)) { 646 rh.flags = atoi(eq); 647 return (&rh); 648 } 649 if (!strcmp("cachesize", s)) { 650 rh.cachesize = atoi(eq); 651 return (&rh); 652 } 653 if (!strcmp("lorder", s)) { 654 rh.lorder = atoi(eq); 655 return (&rh); 656 } 657 if (!strcmp("reclen", s)) { 658 rh.reclen = atoi(eq); 659 return (&rh); 660 } 661 if (!strcmp("bval", s)) { 662 rh.bval = atoi(eq); 663 return (&rh); 664 } 665 if (!strcmp("psize", s)) { 666 rh.psize = atoi(eq); 667 return (&rh); 668 } 669 break; 670 } 671 err("%s: unknown structure value", s); 672 /* NOTREACHED */ 673} 674 675void * 676rfile(name, lenp) 677 char *name; 678 size_t *lenp; 679{ 680 struct stat sb; 681 void *p; 682 int fd; 683 char *np, *index(); 684 685 for (; isspace(*name); ++name); 686 if ((np = index(name, '\n')) != NULL) 687 *np = '\0'; 688 if ((fd = open(name, O_RDONLY, 0)) < 0 || 689 fstat(fd, &sb)) 690 err("%s: %s\n", name, strerror(errno)); 691#ifdef NOT_PORTABLE 692 if (sb.st_size > (off_t)SIZE_T_MAX) 693 err("%s: %s\n", name, strerror(E2BIG)); 694#endif 695 if ((p = (void *)malloc((u_int)sb.st_size)) == NULL) 696 err("%s", strerror(errno)); 697 (void)read(fd, p, (int)sb.st_size); 698 *lenp = sb.st_size; 699 (void)close(fd); 700 return (p); 701} 702 703void * 704xmalloc(text, len) 705 char *text; 706 size_t len; 707{ 708 void *p; 709 710 if ((p = (void *)malloc(len)) == NULL) 711 err("%s", strerror(errno)); 712 memmove(p, text, len); 713 return (p); 714} 715 716void 717usage() 718{ 719 (void)fprintf(stderr, 720 "usage: dbtest [-l] [-f file] [-i info] [-o file] type script\n"); 721 exit(1); 722} 723 724#include <stdarg.h> 725 726void 727err(const char *fmt, ...) 728{ 729 va_list ap; 730 731 va_start(ap, fmt); 732 (void)fprintf(stderr, "dbtest: "); 733 (void)vfprintf(stderr, fmt, ap); 734 va_end(ap); 735 (void)fprintf(stderr, "\n"); 736 exit(1); 737 /* NOTREACHED */ 738}
|