00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "db_config.h"
00011
00012 #ifndef lint
00013 static const char copyright[] =
00014 "Copyright (c) 1996-2005\nSleepycat Software Inc. All rights reserved.\n";
00015 #endif
00016
00017 #ifndef NO_SYSTEM_INCLUDES
00018 #include <sys/types.h>
00019
00020 #include <limits.h>
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #include <string.h>
00024 #include <unistd.h>
00025 #endif
00026
00027 #include "db_int.h"
00028 #include "dbinc/db_page.h"
00029 #include "dbinc/db_am.h"
00030
00031 typedef struct {
00032 const char *progname;
00033 char *hdrbuf;
00034 u_long lineno;
00035 u_long origline;
00036 int endodata;
00037 int endofile;
00038 int version;
00039 char *home;
00040 char *passwd;
00041 int private;
00042 u_int32_t cache;
00043 } LDG;
00044
00045 void badend __P((DB_ENV *));
00046 void badnum __P((DB_ENV *));
00047 int configure __P((DB_ENV *, DB *, char **, char **, int *));
00048 int convprintable __P((DB_ENV *, char *, char **));
00049 int db_init __P((DB_ENV *, char *, u_int32_t, int *));
00050 int dbt_rdump __P((DB_ENV *, DBT *));
00051 int dbt_rprint __P((DB_ENV *, DBT *));
00052 int dbt_rrecno __P((DB_ENV *, DBT *, int));
00053 int dbt_to_recno __P((DB_ENV *, DBT *, db_recno_t *));
00054 int digitize __P((DB_ENV *, int, int *));
00055 int env_create __P((DB_ENV **, LDG *));
00056 int load __P((DB_ENV *, char *, DBTYPE, char **, u_int, LDG *, int *));
00057 int main __P((int, char *[]));
00058 int rheader __P((DB_ENV *, DB *, DBTYPE *, char **, int *, int *));
00059 int usage __P((void));
00060 int version_check __P((void));
00061
00062 const char *progname;
00063
00064 #define G(f) ((LDG *)dbenv->app_private)->f
00065
00066
00067 #define LDF_NOHEADER 0x01
00068 #define LDF_NOOVERWRITE 0x02
00069 #define LDF_PASSWORD 0x04
00070
00071 int
00072 main(argc, argv)
00073 int argc;
00074 char *argv[];
00075 {
00076 enum { NOTSET, FILEID_RESET, LSN_RESET, STANDARD_LOAD } mode;
00077 extern char *optarg;
00078 extern int optind;
00079 DBTYPE dbtype;
00080 DB_ENV *dbenv;
00081 LDG ldg;
00082 u_int ldf;
00083 int ch, existed, exitval, ret;
00084 char **clist, **clp;
00085
00086 if ((progname = strrchr(argv[0], '/')) == NULL)
00087 progname = argv[0];
00088 else
00089 ++progname;
00090
00091 if ((ret = version_check()) != 0)
00092 return (ret);
00093
00094 ldg.progname = progname;
00095 ldg.lineno = 0;
00096 ldg.endodata = ldg.endofile = 0;
00097 ldg.version = 1;
00098 ldg.cache = MEGABYTE;
00099 ldg.hdrbuf = NULL;
00100 ldg.home = NULL;
00101 ldg.passwd = NULL;
00102
00103 mode = NOTSET;
00104 ldf = 0;
00105 exitval = existed = 0;
00106 dbtype = DB_UNKNOWN;
00107
00108
00109 if ((clp = clist =
00110 (char **)calloc((size_t)argc + 1, sizeof(char *))) == NULL) {
00111 fprintf(stderr, "%s: %s\n", ldg.progname, strerror(ENOMEM));
00112 return (EXIT_FAILURE);
00113 }
00114
00115
00116
00117
00118
00119
00120
00121
00122 while ((ch = getopt(argc, argv, "c:f:h:nP:r:Tt:V")) != EOF)
00123 switch (ch) {
00124 case 'c':
00125 if (mode != NOTSET && mode != STANDARD_LOAD)
00126 return (usage());
00127 mode = STANDARD_LOAD;
00128
00129 *clp++ = optarg;
00130 break;
00131 case 'f':
00132 if (mode != NOTSET && mode != STANDARD_LOAD)
00133 return (usage());
00134 mode = STANDARD_LOAD;
00135
00136 if (freopen(optarg, "r", stdin) == NULL) {
00137 fprintf(stderr, "%s: %s: reopen: %s\n",
00138 ldg.progname, optarg, strerror(errno));
00139 return (EXIT_FAILURE);
00140 }
00141 break;
00142 case 'h':
00143 ldg.home = optarg;
00144 break;
00145 case 'n':
00146 if (mode != NOTSET && mode != STANDARD_LOAD)
00147 return (usage());
00148 mode = STANDARD_LOAD;
00149
00150 ldf |= LDF_NOOVERWRITE;
00151 break;
00152 case 'P':
00153 ldg.passwd = strdup(optarg);
00154 memset(optarg, 0, strlen(optarg));
00155 if (ldg.passwd == NULL) {
00156 fprintf(stderr, "%s: strdup: %s\n",
00157 ldg.progname, strerror(errno));
00158 return (EXIT_FAILURE);
00159 }
00160 ldf |= LDF_PASSWORD;
00161 break;
00162 case 'r':
00163 if (mode == STANDARD_LOAD)
00164 return (usage());
00165 if (strcmp(optarg, "lsn") == 0)
00166 mode = LSN_RESET;
00167 else if (strcmp(optarg, "fileid") == 0)
00168 mode = FILEID_RESET;
00169 else
00170 return (usage());
00171 break;
00172 case 'T':
00173 if (mode != NOTSET && mode != STANDARD_LOAD)
00174 return (usage());
00175 mode = STANDARD_LOAD;
00176
00177 ldf |= LDF_NOHEADER;
00178 break;
00179 case 't':
00180 if (mode != NOTSET && mode != STANDARD_LOAD)
00181 return (usage());
00182 mode = STANDARD_LOAD;
00183
00184 if (strcmp(optarg, "btree") == 0) {
00185 dbtype = DB_BTREE;
00186 break;
00187 }
00188 if (strcmp(optarg, "hash") == 0) {
00189 dbtype = DB_HASH;
00190 break;
00191 }
00192 if (strcmp(optarg, "recno") == 0) {
00193 dbtype = DB_RECNO;
00194 break;
00195 }
00196 if (strcmp(optarg, "queue") == 0) {
00197 dbtype = DB_QUEUE;
00198 break;
00199 }
00200 return (usage());
00201 case 'V':
00202 printf("%s\n", db_version(NULL, NULL, NULL));
00203 return (EXIT_SUCCESS);
00204 case '?':
00205 default:
00206 return (usage());
00207 }
00208 argc -= optind;
00209 argv += optind;
00210
00211 if (argc != 1)
00212 return (usage());
00213
00214
00215 __db_util_siginit();
00216
00217
00218
00219
00220
00221 if (env_create(&dbenv, &ldg) != 0)
00222 goto shutdown;
00223
00224
00225 switch (mode) {
00226 case FILEID_RESET:
00227 exitval = dbenv->fileid_reset(
00228 dbenv, argv[0], ldf & LDF_PASSWORD ? DB_ENCRYPT : 0);
00229 break;
00230 case LSN_RESET:
00231 exitval = dbenv->lsn_reset(
00232 dbenv, argv[0], ldf & LDF_PASSWORD ? DB_ENCRYPT : 0);
00233 break;
00234 case NOTSET:
00235 case STANDARD_LOAD:
00236 while (!ldg.endofile)
00237 if (load(dbenv, argv[0], dbtype, clist, ldf,
00238 &ldg, &existed) != 0)
00239 goto shutdown;
00240 break;
00241 }
00242
00243 if (0) {
00244 shutdown: exitval = 1;
00245 }
00246 if ((ret = dbenv->close(dbenv, 0)) != 0) {
00247 exitval = 1;
00248 fprintf(stderr,
00249 "%s: dbenv->close: %s\n", ldg.progname, db_strerror(ret));
00250 }
00251
00252
00253 __db_util_sigresend();
00254 free(clist);
00255 if (ldg.passwd != NULL)
00256 free(ldg.passwd);
00257
00258
00259
00260
00261
00262
00263
00264
00265 return (exitval == 0 ? (existed == 0 ? 0 : 1) : 2);
00266 }
00267
00268
00269
00270
00271
00272 int
00273 load(dbenv, name, argtype, clist, flags, ldg, existedp)
00274 DB_ENV *dbenv;
00275 char *name, **clist;
00276 DBTYPE argtype;
00277 u_int flags;
00278 LDG *ldg;
00279 int *existedp;
00280 {
00281 DB *dbp;
00282 DBT key, rkey, data, *readp, *writep;
00283 DBTYPE dbtype;
00284 DB_TXN *ctxn, *txn;
00285 db_recno_t recno, datarecno;
00286 u_int32_t put_flags;
00287 int ascii_recno, checkprint, hexkeys, keyflag, keys, resize, ret, rval;
00288 char *subdb;
00289
00290 put_flags = LF_ISSET(LDF_NOOVERWRITE) ? DB_NOOVERWRITE : 0;
00291 G(endodata) = 0;
00292
00293 subdb = NULL;
00294 ctxn = txn = NULL;
00295 memset(&key, 0, sizeof(DBT));
00296 memset(&data, 0, sizeof(DBT));
00297 memset(&rkey, 0, sizeof(DBT));
00298
00299 retry_db:
00300 dbtype = DB_UNKNOWN;
00301 keys = -1;
00302 hexkeys = -1;
00303 keyflag = -1;
00304
00305
00306 if ((ret = db_create(&dbp, dbenv, 0)) != 0) {
00307 dbenv->err(dbenv, ret, "db_create");
00308 goto err;
00309 }
00310
00311
00312 if (LF_ISSET(LDF_NOHEADER)) {
00313 checkprint = 1;
00314 dbtype = argtype;
00315 } else {
00316 if (rheader(dbenv,
00317 dbp, &dbtype, &subdb, &checkprint, &keys) != 0)
00318 goto err;
00319 if (G(endofile))
00320 goto done;
00321 }
00322
00323
00324
00325
00326
00327
00328 if (configure(dbenv, dbp, clist, &subdb, &keyflag))
00329 goto err;
00330
00331 if (keys != 1) {
00332 if (keyflag == 1) {
00333 dbp->err(dbp, EINVAL, "No keys specified in file");
00334 goto err;
00335 }
00336 }
00337 else if (keyflag == 0) {
00338 dbp->err(dbp, EINVAL, "Keys specified in file");
00339 goto err;
00340 }
00341 else
00342 keyflag = 1;
00343
00344 if (dbtype == DB_BTREE || dbtype == DB_HASH) {
00345 if (keyflag == 0)
00346 dbp->err(dbp,
00347 EINVAL, "Btree and Hash must specify keys");
00348 else
00349 keyflag = 1;
00350 }
00351
00352 if (argtype != DB_UNKNOWN) {
00353
00354 if (dbtype == DB_RECNO || dbtype == DB_QUEUE)
00355 if (keyflag != 1 && argtype != DB_RECNO &&
00356 argtype != DB_QUEUE) {
00357 dbenv->errx(dbenv,
00358 "improper database type conversion specified");
00359 goto err;
00360 }
00361 dbtype = argtype;
00362 }
00363
00364 if (dbtype == DB_UNKNOWN) {
00365 dbenv->errx(dbenv, "no database type specified");
00366 goto err;
00367 }
00368
00369 if (keyflag == -1)
00370 keyflag = 0;
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380 hexkeys = (G(version) >= 3 && keyflag == 1 && checkprint == 0);
00381
00382 if (keyflag == 1 && (dbtype == DB_RECNO || dbtype == DB_QUEUE))
00383 ascii_recno = 1;
00384 else
00385 ascii_recno = 0;
00386
00387
00388 if (LF_ISSET(LDF_PASSWORD) &&
00389 (ret = dbp->set_flags(dbp, DB_ENCRYPT)) != 0) {
00390 dbp->err(dbp, ret, "DB->set_flags: DB_ENCRYPT");
00391 goto err;
00392 }
00393
00394 #if 0
00395 Set application-specific btree comparison or hash functions here.
00396 For example:
00397
00398 if ((ret = dbp->set_bt_compare(dbp, local_comparison_func)) != 0) {
00399 dbp->err(dbp, ret, "DB->set_bt_compare");
00400 goto err;
00401 }
00402 if ((ret = dbp->set_h_hash(dbp, local_hash_func)) != 0) {
00403 dbp->err(dbp, ret, "DB->set_h_hash");
00404 goto err;
00405 }
00406 #endif
00407
00408
00409 if ((ret = dbp->open(dbp, NULL, name, subdb, dbtype,
00410 DB_CREATE | (TXN_ON(dbenv) ? DB_AUTO_COMMIT : 0),
00411 __db_omode("rw-rw-rw-"))) != 0) {
00412 dbp->err(dbp, ret, "DB->open: %s", name);
00413 goto err;
00414 }
00415 if (ldg->private != 0) {
00416 if ((ret = __db_util_cache(dbp, &ldg->cache, &resize)) != 0)
00417 goto err;
00418 if (resize) {
00419 if ((ret = dbp->close(dbp, 0)) != 0)
00420 goto err;
00421 dbp = NULL;
00422 if ((ret = dbenv->close(dbenv, 0)) != 0)
00423 goto err;
00424 if ((ret = env_create(&dbenv, ldg)) != 0)
00425 goto err;
00426 goto retry_db;
00427 }
00428 }
00429
00430
00431 readp = writep = &key;
00432 if (dbtype == DB_RECNO || dbtype == DB_QUEUE) {
00433 key.size = sizeof(recno);
00434 if (keyflag) {
00435 key.data = &datarecno;
00436 if (checkprint) {
00437 readp = &rkey;
00438 goto key_data;
00439 }
00440 } else
00441 key.data = &recno;
00442 } else
00443 key_data: if ((readp->data = malloc(readp->ulen = 1024)) == NULL) {
00444 dbenv->err(dbenv, ENOMEM, NULL);
00445 goto err;
00446 }
00447 if ((data.data = malloc(data.ulen = 1024)) == NULL) {
00448 dbenv->err(dbenv, ENOMEM, NULL);
00449 goto err;
00450 }
00451
00452 if (TXN_ON(dbenv) &&
00453 (ret = dbenv->txn_begin(dbenv, NULL, &txn, 0)) != 0)
00454 goto err;
00455
00456
00457 for (recno = 1; !__db_util_interrupted(); ++recno) {
00458 if (!keyflag) {
00459 if (checkprint) {
00460 if (dbt_rprint(dbenv, &data))
00461 goto err;
00462 } else {
00463 if (dbt_rdump(dbenv, &data))
00464 goto err;
00465 }
00466 } else {
00467 if (checkprint) {
00468 if (dbt_rprint(dbenv, readp))
00469 goto err;
00470 if (ascii_recno &&
00471 dbt_to_recno(dbenv, readp, &datarecno) != 0)
00472 goto err;
00473
00474 if (!G(endodata) && dbt_rprint(dbenv, &data))
00475 goto odd_count;
00476 } else {
00477 if (ascii_recno) {
00478 if (dbt_rrecno(dbenv, readp, hexkeys))
00479 goto err;
00480 } else
00481 if (dbt_rdump(dbenv, readp))
00482 goto err;
00483
00484 if (!G(endodata) && dbt_rdump(dbenv, &data)) {
00485 odd_count: dbenv->errx(dbenv,
00486 "odd number of key/data pairs");
00487 goto err;
00488 }
00489 }
00490 }
00491 if (G(endodata))
00492 break;
00493 retry: if (txn != NULL)
00494 if ((ret = dbenv->txn_begin(dbenv, txn, &ctxn, 0)) != 0)
00495 goto err;
00496 switch (ret = dbp->put(dbp, ctxn, writep, &data, put_flags)) {
00497 case 0:
00498 if (ctxn != NULL) {
00499 if ((ret =
00500 ctxn->commit(ctxn, DB_TXN_NOSYNC)) != 0)
00501 goto err;
00502 ctxn = NULL;
00503 }
00504 break;
00505 case DB_KEYEXIST:
00506 *existedp = 1;
00507 dbenv->errx(dbenv,
00508 "%s: line %d: key already exists, not loaded:",
00509 name,
00510 !keyflag ? recno : recno * 2 - 1);
00511
00512 (void)dbenv->prdbt(&key,
00513 checkprint, 0, stderr, __db_pr_callback, 0);
00514 break;
00515 case DB_LOCK_DEADLOCK:
00516
00517 if (ctxn != NULL) {
00518 if ((ret = ctxn->abort(ctxn)) != 0)
00519 goto err;
00520 ctxn = NULL;
00521 goto retry;
00522 }
00523
00524 default:
00525 dbenv->err(dbenv, ret, NULL);
00526 if (ctxn != NULL) {
00527 (void)ctxn->abort(ctxn);
00528 ctxn = NULL;
00529 }
00530 goto err;
00531 }
00532 if (ctxn != NULL) {
00533 if ((ret = ctxn->abort(ctxn)) != 0)
00534 goto err;
00535 ctxn = NULL;
00536 }
00537 }
00538 done: rval = 0;
00539 DB_ASSERT(ctxn == NULL);
00540 if (txn != NULL && (ret = txn->commit(txn, 0)) != 0) {
00541 txn = NULL;
00542 goto err;
00543 }
00544
00545 if (0) {
00546 err: rval = 1;
00547 DB_ASSERT(ctxn == NULL);
00548 if (txn != NULL)
00549 (void)txn->abort(txn);
00550 }
00551
00552
00553 if (dbp != NULL && (ret = dbp->close(dbp, 0)) != 0) {
00554 dbenv->err(dbenv, ret, "DB->close");
00555 rval = 1;
00556 }
00557
00558 if (G(hdrbuf) != NULL)
00559 free(G(hdrbuf));
00560 G(hdrbuf) = NULL;
00561
00562 if (subdb != NULL)
00563 free(subdb);
00564 if (dbtype != DB_RECNO && dbtype != DB_QUEUE && key.data != NULL)
00565 free(key.data);
00566 if (rkey.data != NULL)
00567 free(rkey.data);
00568 free(data.data);
00569
00570 return (rval);
00571 }
00572
00573
00574
00575
00576
00577 int
00578 env_create(dbenvp, ldg)
00579 DB_ENV **dbenvp;
00580 LDG *ldg;
00581 {
00582 DB_ENV *dbenv;
00583 int ret;
00584
00585 if ((ret = db_env_create(dbenvp, 0)) != 0) {
00586 fprintf(stderr,
00587 "%s: db_env_create: %s\n", ldg->progname, db_strerror(ret));
00588 return (ret);
00589 }
00590 dbenv = *dbenvp;
00591 dbenv->set_errfile(dbenv, stderr);
00592 dbenv->set_errpfx(dbenv, ldg->progname);
00593 if (ldg->passwd != NULL && (ret = dbenv->set_encrypt(dbenv,
00594 ldg->passwd, DB_ENCRYPT_AES)) != 0) {
00595 dbenv->err(dbenv, ret, "set_passwd");
00596 return (ret);
00597 }
00598 if ((ret = db_init(dbenv, ldg->home, ldg->cache, &ldg->private)) != 0)
00599 return (ret);
00600 dbenv->app_private = ldg;
00601
00602 return (0);
00603 }
00604
00605
00606
00607
00608
00609 int
00610 db_init(dbenv, home, cache, is_private)
00611 DB_ENV *dbenv;
00612 char *home;
00613 u_int32_t cache;
00614 int *is_private;
00615 {
00616 u_int32_t flags;
00617 int ret;
00618
00619 *is_private = 0;
00620
00621 flags = DB_USE_ENVIRON |
00622 DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN;
00623 if ((ret = dbenv->open(dbenv, home, flags, 0)) == 0)
00624 return (0);
00625 if (ret == DB_VERSION_MISMATCH)
00626 goto err;
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640 LF_CLR(DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_TXN);
00641 LF_SET(DB_CREATE | DB_PRIVATE);
00642 *is_private = 1;
00643 if ((ret = dbenv->set_cachesize(dbenv, 0, cache, 1)) != 0) {
00644 dbenv->err(dbenv, ret, "set_cachesize");
00645 return (1);
00646 }
00647 if ((ret = dbenv->open(dbenv, home, flags, 0)) == 0)
00648 return (0);
00649
00650
00651 err: dbenv->err(dbenv, ret, "DB_ENV->open");
00652 return (1);
00653 }
00654
00655 #define FLAG(name, value, keyword, flag) \
00656 if (strcmp(name, keyword) == 0) { \
00657 switch (*value) { \
00658 case '1': \
00659 if ((ret = dbp->set_flags(dbp, flag)) != 0) { \
00660 dbp->err(dbp, ret, "%s: set_flags: %s", \
00661 G(progname), name); \
00662 goto err; \
00663 } \
00664 break; \
00665 case '0': \
00666 break; \
00667 default: \
00668 badnum(dbenv); \
00669 goto err; \
00670 } \
00671 continue; \
00672 }
00673 #define NUMBER(name, value, keyword, func, t) \
00674 if (strcmp(name, keyword) == 0) { \
00675 if ((ret = __db_getlong(dbenv, \
00676 NULL, value, 0, LONG_MAX, &val)) != 0 || \
00677 (ret = dbp->func(dbp, (t)val)) != 0) \
00678 goto nameerr; \
00679 continue; \
00680 }
00681 #define STRING(name, value, keyword, func) \
00682 if (strcmp(name, keyword) == 0) { \
00683 if ((ret = dbp->func(dbp, value[0])) != 0) \
00684 goto nameerr; \
00685 continue; \
00686 }
00687
00688
00689
00690
00691
00692 int
00693 configure(dbenv, dbp, clp, subdbp, keysp)
00694 DB_ENV *dbenv;
00695 DB *dbp;
00696 char **clp, **subdbp;
00697 int *keysp;
00698 {
00699 long val;
00700 int ret, savech;
00701 char *name, *value;
00702
00703 for (; (name = *clp) != NULL; *--value = savech, ++clp) {
00704 if ((value = strchr(name, '=')) == NULL) {
00705 dbp->errx(dbp,
00706 "command-line configuration uses name=value format");
00707 return (1);
00708 }
00709 savech = *value;
00710 *value++ = '\0';
00711
00712 if (strcmp(name, "database") == 0 ||
00713 strcmp(name, "subdatabase") == 0) {
00714 if (*subdbp != NULL)
00715 free(*subdbp);
00716 if ((*subdbp = strdup(value)) == NULL) {
00717 dbp->err(dbp, ENOMEM, NULL);
00718 return (1);
00719 }
00720 continue;
00721 }
00722 if (strcmp(name, "keys") == 0) {
00723 if (strcmp(value, "1") == 0)
00724 *keysp = 1;
00725 else if (strcmp(value, "0") == 0)
00726 *keysp = 0;
00727 else {
00728 badnum(dbenv);
00729 return (1);
00730 }
00731 continue;
00732 }
00733
00734 NUMBER(name, value, "bt_minkey", set_bt_minkey, u_int32_t);
00735 NUMBER(name, value, "db_lorder", set_lorder, int);
00736 NUMBER(name, value, "db_pagesize", set_pagesize, u_int32_t);
00737 FLAG(name, value, "chksum", DB_CHKSUM);
00738 FLAG(name, value, "duplicates", DB_DUP);
00739 FLAG(name, value, "dupsort", DB_DUPSORT);
00740 NUMBER(name, value, "h_ffactor", set_h_ffactor, u_int32_t);
00741 NUMBER(name, value, "h_nelem", set_h_nelem, u_int32_t);
00742 NUMBER(name, value, "re_len", set_re_len, u_int32_t);
00743 STRING(name, value, "re_pad", set_re_pad);
00744 FLAG(name, value, "recnum", DB_RECNUM);
00745 FLAG(name, value, "renumber", DB_RENUMBER);
00746
00747 dbp->errx(dbp,
00748 "unknown command-line configuration keyword \"%s\"", name);
00749 return (1);
00750 }
00751 return (0);
00752
00753 nameerr:
00754 dbp->err(dbp, ret, "%s: %s=%s", G(progname), name, value);
00755 err: return (1);
00756 }
00757
00758
00759
00760
00761
00762 int
00763 rheader(dbenv, dbp, dbtypep, subdbp, checkprintp, keysp)
00764 DB_ENV *dbenv;
00765 DB *dbp;
00766 DBTYPE *dbtypep;
00767 char **subdbp;
00768 int *checkprintp, *keysp;
00769 {
00770 size_t buflen, linelen, start;
00771 long val;
00772 int ch, first, hdr, ret;
00773 char *buf, *name, *p, *value;
00774
00775 *dbtypep = DB_UNKNOWN;
00776 *checkprintp = 0;
00777 name = NULL;
00778
00779
00780
00781
00782
00783 buflen = 4096;
00784 if (G(hdrbuf) == NULL) {
00785 hdr = 0;
00786 if ((buf = malloc(buflen)) == NULL)
00787 goto memerr;
00788 G(hdrbuf) = buf;
00789 G(origline) = G(lineno);
00790 } else {
00791 hdr = 1;
00792 buf = G(hdrbuf);
00793 G(lineno) = G(origline);
00794 }
00795
00796 start = 0;
00797 for (first = 1;; first = 0) {
00798 ++G(lineno);
00799
00800
00801 linelen = 0;
00802 buf = &G(hdrbuf)[start];
00803 if (hdr == 0) {
00804 for (;;) {
00805 if ((ch = getchar()) == EOF) {
00806 if (!first || ferror(stdin))
00807 goto badfmt;
00808 G(endofile) = 1;
00809 break;
00810 }
00811
00812
00813
00814
00815 if (linelen + start == buflen) {
00816 G(hdrbuf) =
00817 realloc(G(hdrbuf), buflen *= 2);
00818 if (G(hdrbuf) == NULL)
00819 goto memerr;
00820 buf = &G(hdrbuf)[start];
00821 }
00822
00823 if (ch == '\n')
00824 break;
00825
00826 buf[linelen++] = ch;
00827 }
00828 if (G(endofile) == 1)
00829 break;
00830 buf[linelen++] = '\0';
00831 } else
00832 linelen = strlen(buf) + 1;
00833 start += linelen;
00834
00835 if (name != NULL) {
00836 free(name);
00837 name = NULL;
00838 }
00839
00840 if ((name = strdup(buf)) == NULL)
00841 goto memerr;
00842 if ((p = strchr(name, '=')) == NULL)
00843 goto badfmt;
00844 *p++ = '\0';
00845
00846 value = p--;
00847
00848 if (name[0] == '\0' || value[0] == '\0')
00849 goto badfmt;
00850
00851 if (strcmp(name, "HEADER") == 0)
00852 break;
00853 if (strcmp(name, "VERSION") == 0) {
00854
00855
00856
00857
00858 G(version) = atoi(value);
00859
00860 if (G(version) > 3) {
00861 dbp->errx(dbp,
00862 "line %lu: VERSION %d is unsupported",
00863 G(lineno), G(version));
00864 goto err;
00865 }
00866 continue;
00867 }
00868 if (strcmp(name, "format") == 0) {
00869 if (strcmp(value, "bytevalue") == 0) {
00870 *checkprintp = 0;
00871 continue;
00872 }
00873 if (strcmp(value, "print") == 0) {
00874 *checkprintp = 1;
00875 continue;
00876 }
00877 goto badfmt;
00878 }
00879 if (strcmp(name, "type") == 0) {
00880 if (strcmp(value, "btree") == 0) {
00881 *dbtypep = DB_BTREE;
00882 continue;
00883 }
00884 if (strcmp(value, "hash") == 0) {
00885 *dbtypep = DB_HASH;
00886 continue;
00887 }
00888 if (strcmp(value, "recno") == 0) {
00889 *dbtypep = DB_RECNO;
00890 continue;
00891 }
00892 if (strcmp(value, "queue") == 0) {
00893 *dbtypep = DB_QUEUE;
00894 continue;
00895 }
00896 dbp->errx(dbp, "line %lu: unknown type", G(lineno));
00897 goto err;
00898 }
00899 if (strcmp(name, "database") == 0 ||
00900 strcmp(name, "subdatabase") == 0) {
00901 if ((ret = convprintable(dbenv, value, subdbp)) != 0) {
00902 dbp->err(dbp, ret, "error reading db name");
00903 goto err;
00904 }
00905 continue;
00906 }
00907 if (strcmp(name, "keys") == 0) {
00908 if (strcmp(value, "1") == 0)
00909 *keysp = 1;
00910 else if (strcmp(value, "0") == 0)
00911 *keysp = 0;
00912 else {
00913 badnum(dbenv);
00914 goto err;
00915 }
00916 continue;
00917 }
00918
00919 #ifdef notyet
00920 NUMBER(name, value, "bt_maxkey", set_bt_maxkey, u_int32_t);
00921 #endif
00922 NUMBER(name, value, "bt_minkey", set_bt_minkey, u_int32_t);
00923 NUMBER(name, value, "db_lorder", set_lorder, int);
00924 NUMBER(name, value, "db_pagesize", set_pagesize, u_int32_t);
00925 NUMBER(name, value, "extentsize", set_q_extentsize, u_int32_t);
00926 FLAG(name, value, "chksum", DB_CHKSUM);
00927 FLAG(name, value, "duplicates", DB_DUP);
00928 FLAG(name, value, "dupsort", DB_DUPSORT);
00929 NUMBER(name, value, "h_ffactor", set_h_ffactor, u_int32_t);
00930 NUMBER(name, value, "h_nelem", set_h_nelem, u_int32_t);
00931 NUMBER(name, value, "re_len", set_re_len, u_int32_t);
00932 STRING(name, value, "re_pad", set_re_pad);
00933 FLAG(name, value, "recnum", DB_RECNUM);
00934 FLAG(name, value, "renumber", DB_RENUMBER);
00935
00936 dbp->errx(dbp,
00937 "unknown input-file header configuration keyword \"%s\"",
00938 name);
00939 goto err;
00940 }
00941 ret = 0;
00942
00943 if (0) {
00944 nameerr: dbp->err(dbp, ret, "%s: %s=%s", G(progname), name, value);
00945 ret = 1;
00946 }
00947 if (0) {
00948 badfmt: dbp->errx(dbp, "line %lu: unexpected format", G(lineno));
00949 ret = 1;
00950 }
00951 if (0) {
00952 memerr: dbp->errx(dbp, "unable to allocate memory");
00953 err: ret = 1;
00954 }
00955 if (name != NULL)
00956 free(name);
00957 return (ret);
00958 }
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973 int
00974 convprintable(dbenv, instr, outstrp)
00975 DB_ENV *dbenv;
00976 char *instr, **outstrp;
00977 {
00978 char c, *outstr;
00979 int e1, e2;
00980
00981
00982
00983
00984
00985 if ((outstr = malloc(strlen(instr) + 1)) == NULL)
00986 return (ENOMEM);
00987
00988 *outstrp = outstr;
00989
00990 e1 = e2 = 0;
00991 for ( ; *instr != '\0'; instr++)
00992 if (*instr == '\\') {
00993 if (*++instr == '\\') {
00994 *outstr++ = '\\';
00995 continue;
00996 }
00997 c = digitize(dbenv, *instr, &e1) << 4;
00998 c |= digitize(dbenv, *++instr, &e2);
00999 if (e1 || e2) {
01000 badend(dbenv);
01001 return (EINVAL);
01002 }
01003
01004 *outstr++ = c;
01005 } else
01006 *outstr++ = *instr;
01007
01008 *outstr = '\0';
01009
01010 return (0);
01011 }
01012
01013
01014
01015
01016
01017 int
01018 dbt_rprint(dbenv, dbtp)
01019 DB_ENV *dbenv;
01020 DBT *dbtp;
01021 {
01022 u_int32_t len;
01023 u_int8_t *p;
01024 int c1, c2, e, escape, first;
01025 char buf[32];
01026
01027 ++G(lineno);
01028
01029 first = 1;
01030 e = escape = 0;
01031 for (p = dbtp->data, len = 0; (c1 = getchar()) != '\n';) {
01032 if (c1 == EOF) {
01033 if (len == 0) {
01034 G(endofile) = G(endodata) = 1;
01035 return (0);
01036 }
01037 badend(dbenv);
01038 return (1);
01039 }
01040 if (first) {
01041 first = 0;
01042 if (G(version) > 1) {
01043 if (c1 != ' ') {
01044 buf[0] = c1;
01045 if (fgets(buf + 1,
01046 sizeof(buf) - 1, stdin) == NULL ||
01047 strcmp(buf, "DATA=END\n") != 0) {
01048 badend(dbenv);
01049 return (1);
01050 }
01051 G(endodata) = 1;
01052 return (0);
01053 }
01054 continue;
01055 }
01056 }
01057 if (escape) {
01058 if (c1 != '\\') {
01059 if ((c2 = getchar()) == EOF) {
01060 badend(dbenv);
01061 return (1);
01062 }
01063 c1 = digitize(dbenv,
01064 c1, &e) << 4 | digitize(dbenv, c2, &e);
01065 if (e)
01066 return (1);
01067 }
01068 escape = 0;
01069 } else
01070 if (c1 == '\\') {
01071 escape = 1;
01072 continue;
01073 }
01074 if (len >= dbtp->ulen - 10) {
01075 dbtp->ulen *= 2;
01076 if ((dbtp->data =
01077 realloc(dbtp->data, dbtp->ulen)) == NULL) {
01078 dbenv->err(dbenv, ENOMEM, NULL);
01079 return (1);
01080 }
01081 p = (u_int8_t *)dbtp->data + len;
01082 }
01083 ++len;
01084 *p++ = c1;
01085 }
01086 dbtp->size = len;
01087
01088 return (0);
01089 }
01090
01091
01092
01093
01094
01095 int
01096 dbt_rdump(dbenv, dbtp)
01097 DB_ENV *dbenv;
01098 DBT *dbtp;
01099 {
01100 u_int32_t len;
01101 u_int8_t *p;
01102 int c1, c2, e, first;
01103 char buf[32];
01104
01105 ++G(lineno);
01106
01107 first = 1;
01108 e = 0;
01109 for (p = dbtp->data, len = 0; (c1 = getchar()) != '\n';) {
01110 if (c1 == EOF) {
01111 if (len == 0) {
01112 G(endofile) = G(endodata) = 1;
01113 return (0);
01114 }
01115 badend(dbenv);
01116 return (1);
01117 }
01118 if (first) {
01119 first = 0;
01120 if (G(version) > 1) {
01121 if (c1 != ' ') {
01122 buf[0] = c1;
01123 if (fgets(buf + 1,
01124 sizeof(buf) - 1, stdin) == NULL ||
01125 strcmp(buf, "DATA=END\n") != 0) {
01126 badend(dbenv);
01127 return (1);
01128 }
01129 G(endodata) = 1;
01130 return (0);
01131 }
01132 continue;
01133 }
01134 }
01135 if ((c2 = getchar()) == EOF) {
01136 badend(dbenv);
01137 return (1);
01138 }
01139 if (len >= dbtp->ulen - 10) {
01140 dbtp->ulen *= 2;
01141 if ((dbtp->data =
01142 realloc(dbtp->data, dbtp->ulen)) == NULL) {
01143 dbenv->err(dbenv, ENOMEM, NULL);
01144 return (1);
01145 }
01146 p = (u_int8_t *)dbtp->data + len;
01147 }
01148 ++len;
01149 *p++ = digitize(dbenv, c1, &e) << 4 | digitize(dbenv, c2, &e);
01150 if (e)
01151 return (1);
01152 }
01153 dbtp->size = len;
01154
01155 return (0);
01156 }
01157
01158
01159
01160
01161
01162 int
01163 dbt_rrecno(dbenv, dbtp, ishex)
01164 DB_ENV *dbenv;
01165 DBT *dbtp;
01166 int ishex;
01167 {
01168 char buf[32], *p, *q;
01169 u_long recno;
01170
01171 ++G(lineno);
01172
01173 if (fgets(buf, sizeof(buf), stdin) == NULL) {
01174 G(endofile) = G(endodata) = 1;
01175 return (0);
01176 }
01177
01178 if (strcmp(buf, "DATA=END\n") == 0) {
01179 G(endodata) = 1;
01180 return (0);
01181 }
01182
01183 if (buf[0] != ' ')
01184 goto bad;
01185
01186
01187
01188
01189
01190 if (ishex) {
01191 for (p = q = buf + 1; *q != '\0' && *q != '\n';) {
01192
01193
01194
01195
01196
01197
01198
01199 if (*q++ != '3')
01200 goto bad;
01201 if (*q == '\n' || *q == '\0')
01202 goto bad;
01203 *p++ = *q++;
01204 }
01205 *p = '\0';
01206 }
01207
01208 if (__db_getulong(dbenv, G(progname), buf + 1, 0, 0, &recno)) {
01209 bad: badend(dbenv);
01210 return (1);
01211 }
01212
01213 *((db_recno_t *)dbtp->data) = recno;
01214 dbtp->size = sizeof(db_recno_t);
01215 return (0);
01216 }
01217
01218 int
01219 dbt_to_recno(dbenv, dbt, recnop)
01220 DB_ENV *dbenv;
01221 DBT *dbt;
01222 db_recno_t *recnop;
01223 {
01224 char buf[32];
01225
01226 memcpy(buf, dbt->data, dbt->size);
01227 buf[dbt->size] = '\0';
01228
01229 return (__db_getulong(dbenv, G(progname), buf, 0, 0, (u_long *)recnop));
01230 }
01231
01232
01233
01234
01235
01236 int
01237 digitize(dbenv, c, errorp)
01238 DB_ENV *dbenv;
01239 int c, *errorp;
01240 {
01241 switch (c) {
01242 case '0': return (0);
01243 case '1': return (1);
01244 case '2': return (2);
01245 case '3': return (3);
01246 case '4': return (4);
01247 case '5': return (5);
01248 case '6': return (6);
01249 case '7': return (7);
01250 case '8': return (8);
01251 case '9': return (9);
01252 case 'a': return (10);
01253 case 'b': return (11);
01254 case 'c': return (12);
01255 case 'd': return (13);
01256 case 'e': return (14);
01257 case 'f': return (15);
01258 default:
01259 break;
01260 }
01261
01262 dbenv->errx(dbenv, "unexpected hexadecimal value");
01263 *errorp = 1;
01264
01265 return (0);
01266 }
01267
01268
01269
01270
01271
01272 void
01273 badnum(dbenv)
01274 DB_ENV *dbenv;
01275 {
01276 dbenv->errx(dbenv,
01277 "boolean name=value pairs require a value of 0 or 1");
01278 }
01279
01280
01281
01282
01283
01284 void
01285 badend(dbenv)
01286 DB_ENV *dbenv;
01287 {
01288 dbenv->errx(dbenv, "unexpected end of input data or key/data pair");
01289 }
01290
01291
01292
01293
01294
01295 int
01296 usage()
01297 {
01298 (void)fprintf(stderr, "usage: %s %s\n\t%s\n", progname,
01299 "[-nTV] [-c name=value] [-f file]",
01300 "[-h home] [-P password] [-t btree | hash | recno | queue] db_file");
01301 (void)fprintf(stderr, "usage: %s %s\n",
01302 progname, "-r lsn | fileid [-h home] [-P password] db_file");
01303 return (EXIT_FAILURE);
01304 }
01305
01306 int
01307 version_check()
01308 {
01309 int v_major, v_minor, v_patch;
01310
01311
01312 (void)db_version(&v_major, &v_minor, &v_patch);
01313 if (v_major != DB_VERSION_MAJOR || v_minor != DB_VERSION_MINOR) {
01314 fprintf(stderr,
01315 "%s: version %d.%d doesn't match library version %d.%d\n",
01316 progname, DB_VERSION_MAJOR, DB_VERSION_MINOR,
01317 v_major, v_minor);
01318 return (EXIT_FAILURE);
01319 }
01320 return (0);
01321 }