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