1 /* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 /* This file came from the SDBM package (written by oz@nexus.yorku.ca).
17 * That package was under public domain. This file has been ported to
18 * APR, updated to ANSI C and other, newer idioms, and added to the Apache
19 * codebase under the above copyright and license.
23 * testdbm: Simple APR dbm tester.
24 * Automatic test case: ./testdbm auto foo
25 * - Attempts to store and fetch values from the DBM.
27 * Run the program for more help.
31 #include "apr_general.h"
32 #include "apr_pools.h"
33 #include "apr_errno.h"
34 #include "apr_getopt.h"
36 #define APR_WANT_STRFUNC
45 #include <stdlib.h> /* for atexit(), malloc() */
50 static const char *progname;
73 static const cmd cmds[] = {
75 { "fetch", DLOOK, APR_DBM_READONLY },
76 { "get", DLOOK, APR_DBM_READONLY },
77 { "look", DLOOK, APR_DBM_READONLY },
78 { "add", DBUILD, APR_DBM_READWRITE },
79 { "insert", DBUILD, APR_DBM_READWRITE },
80 { "store", DBUILD, APR_DBM_READWRITE },
81 { "delete", DDELETE, APR_DBM_READWRITE },
82 { "remove", DDELETE, APR_DBM_READWRITE },
83 { "dump", DCAT, APR_DBM_READONLY },
84 { "list", DCAT, APR_DBM_READONLY },
85 { "cat", DCAT, APR_DBM_READONLY },
86 { "build", DBUILD, APR_DBM_RWCREATE }, /** this one creates the DB */
87 { "creat", DCREAT, APR_DBM_RWCREATE },
88 { "trunc", DTRUNC, APR_DBM_RWTRUNC },
89 { "new", DCREAT, APR_DBM_RWCREATE },
90 { "names", DNAME, APR_DBM_READONLY },
92 {"squash", DPRESS, APR_DBM_READWRITE, },
93 {"compact", DPRESS, APR_DBM_READWRITE, },
94 {"compress", DPRESS, APR_DBM_READWRITE, },
96 { "auto", DAUTO, APR_DBM_RWCREATE },
99 #define CMD_SIZE (sizeof(cmds)/sizeof(cmd))
101 static void doit(const cmd *act, const char*type, const char *file, apr_pool_t *pool);
102 static const cmd *parse_command(const char *str);
103 static void prdatum(FILE *stream, apr_datum_t d);
104 static void oops(apr_dbm_t *dbm, apr_status_t rv, const char *s1,
106 static void show_usage(void);
108 int main(int argc, const char * const * argv)
117 (void) apr_initialize();
118 apr_pool_create(&pool, NULL);
119 atexit(apr_terminate);
121 (void) apr_getopt_init(&os, pool, argc, argv);
126 while (apr_getopt(os, "Rt:", &optch, &optarg) == APR_SUCCESS) {
128 case 'R': /* raw processing */
136 fputs("unknown option.",stderr);
142 if (argc <= os->ind) {
144 fputs("Note: If you have no clue what this program is, start with:\n", stderr);
145 fputs(" ./testdbm auto foo\n", stderr);
146 fputs(" where foo is the DBM prefix.\n", stderr);
150 if ((act = parse_command(argv[os->ind])) == NULL) {
152 fprintf(stderr, "unrecognized command: %s\n", argv[os->ind]);
156 if (++os->ind >= argc) {
158 fputs("please supply a DB file to use (may be created)\n", stderr);
162 doit(act, dbtype, argv[os->ind], pool);
164 apr_pool_destroy(pool);
169 static void doit(const cmd *act, const char*type, const char *file,
186 rv = apr_dbm_open_ex(&db, type, file, act->flags, APR_OS_DEFAULT, pool);
187 if (rv != APR_SUCCESS)
188 oops(db, rv, "cannot open: %s", file);
190 line = (char *) apr_palloc(pool,LINEMAX);
192 switch (act->scode) {
195 while (fgets(line, LINEMAX, stdin) != NULL) {
196 n = strlen(line) - 1;
203 rv = apr_dbm_fetch(db, key, &val);
204 if (rv == APR_SUCCESS) {
205 prdatum(stdout, val);
209 prdatum(stderr, key);
210 fprintf(stderr, ": not found.\n");
215 while (fgets(line, LINEMAX, stdin) != NULL) {
216 n = strlen(line) - 1;
223 if (apr_dbm_delete(db, key) != APR_SUCCESS) {
224 prdatum(stderr, key);
225 fprintf(stderr, ": not found.\n");
230 rv = apr_dbm_firstkey(db, &key);
231 if (rv != APR_SUCCESS)
232 oops(db, rv, "could not fetch first key: %s", file);
234 while (key.dptr != NULL) {
235 prdatum(stdout, key);
237 rv = apr_dbm_fetch(db, key, &val);
238 if (rv != APR_SUCCESS)
239 oops(db, rv, "apr_dbm_fetch", "failure");
240 prdatum(stdout, val);
242 rv = apr_dbm_nextkey(db, &key);
243 if (rv != APR_SUCCESS)
244 oops(db, rv, "NextKey", "failure");
251 while (fgets(line, LINEMAX, stdin) != NULL) {
252 n = strlen(line) - 1;
258 if ((op = strchr(line, '\t')) != 0) {
259 key.dsize = op - line;
262 val.dsize = line + n - op;
265 oops(NULL, APR_EGENERAL, "bad input: %s", line);
267 rv = apr_dbm_store(db, key, val);
268 if (rv != APR_SUCCESS) {
269 prdatum(stderr, key);
270 fprintf(stderr, ": ");
271 oops(db, rv, "store: %s", "failed");
275 printf("done: %d seconds.\n", time(0) - start);
285 apr_dbm_get_usednames(pool, file, &use1, &use2);
286 fprintf(stderr, "%s %s\n", use1, use2);
291 char *valdata = "0123456789";
292 fprintf(stderr, "Generating data: ");
293 for (i = 0; i < 10; i++) {
296 for (j = 0, c = 'A' + (i % 16); j < 10; j++, c++) {
303 rv = apr_dbm_store(db, key, val);
304 if (rv != APR_SUCCESS) {
305 prdatum(stderr, key);
306 fprintf(stderr, ": ");
307 oops(db, rv, "store: %s", "failed");
310 fputs("OK\n", stderr);
311 fputs("Testing existence/retrieval: ", stderr);
312 for (i = 0; i < 10; i++) {
315 for (j = 0, c = 'A' + (i % 16); j < 10; j++, c++) {
320 if (!apr_dbm_exists(db, key)) {
321 prdatum(stderr, key);
322 oops(db, 0, "exists: %s", "failed");
324 rv = apr_dbm_fetch(db, key, &val);
325 if (rv != APR_SUCCESS || val.dsize != 10 ||
326 (strncmp(val.dptr, valdata, 10) != 0) ) {
327 prdatum(stderr, key);
328 fprintf(stderr, ": ");
329 oops(db, rv, "fetch: %s", "failed");
332 fputs("OK\n", stderr);
340 static const cmd *parse_command(const char *str)
344 for (i = 0; i < CMD_SIZE; i++)
345 if (strcasecmp(cmds[i].sname, str) == 0)
351 static void prdatum(FILE *stream, apr_datum_t d)
354 const char *p = d.dptr;
360 fprintf(stream, "M-");
363 if (c == 0177 || c < ' ')
364 fprintf(stream, "^%c", (c == 0177) ? '?' : c + '@');
370 static void oops(apr_dbm_t * dbm, apr_status_t rv, const char *s1,
376 fprintf(stderr, "%s: ", progname);
378 fprintf(stderr, s1, s2);
379 fprintf(stderr, "\n");
381 if (rv != APR_SUCCESS) {
382 apr_strerror(rv, errbuf, sizeof(errbuf));
383 fprintf(stderr, "APR Error %d - %s\n", rv, errbuf);
386 apr_dbm_geterror(dbm, &rv, errbuf, sizeof(errbuf));
387 fprintf(stderr, "APR_DB Error %d - %s\n", rv, errbuf);
393 static void show_usage(void)
398 progname = "testdbm";
401 fprintf(stderr, "%s [-t DBM-type] [-R] [commands] dbm-file-path\n",
404 fputs("Available DBM-types:", stderr);
406 fputs(" GDBM", stderr);
409 fputs(" NDBM", stderr);
412 fputs(" SDBM", stderr);
415 fputs(" DB", stderr);
417 fputs(" default\n", stderr);
419 fputs("Available commands:\n", stderr);
420 for (i = 0; i < CMD_SIZE; i++) {
421 fprintf(stderr, "%-8s%c", cmds[i].sname,
422 ((i + 1) % 6 == 0) ? '\n' : ' ');