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 <stdio.h>
00021 #include <stdlib.h>
00022 #include <string.h>
00023 #include <unistd.h>
00024 #endif
00025
00026 #include "db_int.h"
00027 #include "dbinc/db_page.h"
00028 #include "dbinc/db_am.h"
00029
00030 int db_init __P((DB_ENV *, char *, int, u_int32_t, int *));
00031 int dump_sub __P((DB_ENV *, DB *, char *, int, int));
00032 int is_sub __P((DB *, int *));
00033 int main __P((int, char *[]));
00034 int show_subs __P((DB *));
00035 int usage __P((void));
00036 int version_check __P((void));
00037
00038 const char *progname;
00039
00040 int
00041 main(argc, argv)
00042 int argc;
00043 char *argv[];
00044 {
00045 extern char *optarg;
00046 extern int optind;
00047 DB_ENV *dbenv;
00048 DB *dbp;
00049 u_int32_t cache;
00050 int ch;
00051 int exitval, keyflag, lflag, nflag, pflag, private;
00052 int ret, Rflag, rflag, resize, subs;
00053 char *dopt, *home, *passwd, *subname;
00054
00055 if ((progname = strrchr(argv[0], '/')) == NULL)
00056 progname = argv[0];
00057 else
00058 ++progname;
00059
00060 if ((ret = version_check()) != 0)
00061 return (ret);
00062
00063 dbenv = NULL;
00064 dbp = NULL;
00065 exitval = lflag = nflag = pflag = rflag = Rflag = 0;
00066 keyflag = 0;
00067 cache = MEGABYTE;
00068 private = 0;
00069 dopt = home = passwd = subname = NULL;
00070 while ((ch = getopt(argc, argv, "d:f:h:klNpP:rRs:V")) != EOF)
00071 switch (ch) {
00072 case 'd':
00073 dopt = optarg;
00074 break;
00075 case 'f':
00076 if (freopen(optarg, "w", stdout) == NULL) {
00077 fprintf(stderr, "%s: %s: reopen: %s\n",
00078 progname, optarg, strerror(errno));
00079 return (EXIT_FAILURE);
00080 }
00081 break;
00082 case 'h':
00083 home = optarg;
00084 break;
00085 case 'k':
00086 keyflag = 1;
00087 break;
00088 case 'l':
00089 lflag = 1;
00090 break;
00091 case 'N':
00092 nflag = 1;
00093 break;
00094 case 'P':
00095 passwd = strdup(optarg);
00096 memset(optarg, 0, strlen(optarg));
00097 if (passwd == NULL) {
00098 fprintf(stderr, "%s: strdup: %s\n",
00099 progname, strerror(errno));
00100 return (EXIT_FAILURE);
00101 }
00102 break;
00103 case 'p':
00104 pflag = 1;
00105 break;
00106 case 's':
00107 subname = optarg;
00108 break;
00109 case 'R':
00110 Rflag = 1;
00111
00112
00113 case 'r':
00114 rflag = 1;
00115 break;
00116 case 'V':
00117 printf("%s\n", db_version(NULL, NULL, NULL));
00118 return (EXIT_SUCCESS);
00119 case '?':
00120 default:
00121 return (usage());
00122 }
00123 argc -= optind;
00124 argv += optind;
00125
00126 if (argc != 1)
00127 return (usage());
00128
00129 if (dopt != NULL && pflag) {
00130 fprintf(stderr,
00131 "%s: the -d and -p options may not both be specified\n",
00132 progname);
00133 return (EXIT_FAILURE);
00134 }
00135 if (lflag && subname != NULL) {
00136 fprintf(stderr,
00137 "%s: the -l and -s options may not both be specified\n",
00138 progname);
00139 return (EXIT_FAILURE);
00140 }
00141
00142 if (keyflag && rflag) {
00143 fprintf(stderr, "%s: %s",
00144 "the -k and -r or -R options may not both be specified\n",
00145 progname);
00146 return (EXIT_FAILURE);
00147 }
00148
00149 if (subname != NULL && rflag) {
00150 fprintf(stderr, "%s: %s",
00151 "the -s and -r or R options may not both be specified\n",
00152 progname);
00153 return (EXIT_FAILURE);
00154 }
00155
00156
00157 __db_util_siginit();
00158
00159
00160
00161
00162
00163 retry: if ((ret = db_env_create(&dbenv, 0)) != 0) {
00164 fprintf(stderr,
00165 "%s: db_env_create: %s\n", progname, db_strerror(ret));
00166 goto err;
00167 }
00168
00169 dbenv->set_errfile(dbenv, stderr);
00170 dbenv->set_errpfx(dbenv, progname);
00171 if (nflag) {
00172 if ((ret = dbenv->set_flags(dbenv, DB_NOLOCKING, 1)) != 0) {
00173 dbenv->err(dbenv, ret, "set_flags: DB_NOLOCKING");
00174 goto err;
00175 }
00176 if ((ret = dbenv->set_flags(dbenv, DB_NOPANIC, 1)) != 0) {
00177 dbenv->err(dbenv, ret, "set_flags: DB_NOPANIC");
00178 goto err;
00179 }
00180 }
00181 if (passwd != NULL && (ret = dbenv->set_encrypt(dbenv,
00182 passwd, DB_ENCRYPT_AES)) != 0) {
00183 dbenv->err(dbenv, ret, "set_passwd");
00184 goto err;
00185 }
00186
00187
00188 if (db_init(dbenv, home, rflag, cache, &private) != 0)
00189 goto err;
00190
00191
00192 if ((ret = db_create(&dbp, dbenv, 0)) != 0) {
00193 dbenv->err(dbenv, ret, "db_create");
00194 goto err;
00195 }
00196
00197
00198
00199
00200
00201 if (rflag) {
00202
00203 ret = dbp->verify(dbp, argv[0], NULL, stdout,
00204 DB_SALVAGE |
00205 (Rflag ? DB_AGGRESSIVE : 0) |
00206 (pflag ? DB_PRINTABLE : 0));
00207 dbp = NULL;
00208 if (ret != 0)
00209 goto err;
00210 goto done;
00211 }
00212
00213 if ((ret = dbp->open(dbp, NULL,
00214 argv[0], subname, DB_UNKNOWN, DB_RDONLY, 0)) != 0) {
00215 dbp->err(dbp, ret, "open: %s", argv[0]);
00216 goto err;
00217 }
00218 if (private != 0) {
00219 if ((ret = __db_util_cache(dbp, &cache, &resize)) != 0)
00220 goto err;
00221 if (resize) {
00222 (void)dbp->close(dbp, 0);
00223 dbp = NULL;
00224
00225 (void)dbenv->close(dbenv, 0);
00226 dbenv = NULL;
00227 goto retry;
00228 }
00229 }
00230
00231 if (dopt != NULL) {
00232 if ((ret = __db_dumptree(dbp, dopt, NULL)) != 0) {
00233 dbp->err(dbp, ret, "__db_dumptree: %s", argv[0]);
00234 goto err;
00235 }
00236 } else if (lflag) {
00237 if (is_sub(dbp, &subs))
00238 goto err;
00239 if (subs == 0) {
00240 dbp->errx(dbp,
00241 "%s: does not contain multiple databases", argv[0]);
00242 goto err;
00243 }
00244 if (show_subs(dbp))
00245 goto err;
00246 } else {
00247 subs = 0;
00248 if (subname == NULL && is_sub(dbp, &subs))
00249 goto err;
00250 if (subs) {
00251 if (dump_sub(dbenv, dbp, argv[0], pflag, keyflag))
00252 goto err;
00253 } else
00254 if (dbp->dump(dbp, NULL,
00255 __db_pr_callback, stdout, pflag, keyflag))
00256 goto err;
00257 }
00258
00259 if (0) {
00260 err: exitval = 1;
00261 }
00262 done: if (dbp != NULL && (ret = dbp->close(dbp, 0)) != 0) {
00263 exitval = 1;
00264 dbenv->err(dbenv, ret, "close");
00265 }
00266 if (dbenv != NULL && (ret = dbenv->close(dbenv, 0)) != 0) {
00267 exitval = 1;
00268 fprintf(stderr,
00269 "%s: dbenv->close: %s\n", progname, db_strerror(ret));
00270 }
00271
00272 if (passwd != NULL)
00273 free(passwd);
00274
00275
00276 __db_util_sigresend();
00277
00278 return (exitval == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
00279 }
00280
00281
00282
00283
00284
00285 int
00286 db_init(dbenv, home, is_salvage, cache, is_privatep)
00287 DB_ENV *dbenv;
00288 char *home;
00289 int is_salvage;
00290 u_int32_t cache;
00291 int *is_privatep;
00292 {
00293 int ret;
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313 *is_privatep = 0;
00314 if ((ret = dbenv->open(dbenv, home,
00315 DB_USE_ENVIRON | (is_salvage ? DB_INIT_MPOOL : 0), 0)) == 0)
00316 return (0);
00317 if (ret == DB_VERSION_MISMATCH)
00318 goto err;
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330 *is_privatep = 1;
00331 if ((ret = dbenv->set_cachesize(dbenv, 0, cache, 1)) == 0 &&
00332 (ret = dbenv->open(dbenv, home,
00333 DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE | DB_USE_ENVIRON, 0)) == 0)
00334 return (0);
00335
00336
00337 err: dbenv->err(dbenv, ret, "DB_ENV->open");
00338 return (1);
00339 }
00340
00341
00342
00343
00344
00345 int
00346 is_sub(dbp, yesno)
00347 DB *dbp;
00348 int *yesno;
00349 {
00350 DB_BTREE_STAT *btsp;
00351 DB_HASH_STAT *hsp;
00352 int ret;
00353
00354 switch (dbp->type) {
00355 case DB_BTREE:
00356 case DB_RECNO:
00357 if ((ret = dbp->stat(dbp, NULL, &btsp, DB_FAST_STAT)) != 0) {
00358 dbp->err(dbp, ret, "DB->stat");
00359 return (ret);
00360 }
00361 *yesno = btsp->bt_metaflags & BTM_SUBDB ? 1 : 0;
00362 free(btsp);
00363 break;
00364 case DB_HASH:
00365 if ((ret = dbp->stat(dbp, NULL, &hsp, DB_FAST_STAT)) != 0) {
00366 dbp->err(dbp, ret, "DB->stat");
00367 return (ret);
00368 }
00369 *yesno = hsp->hash_metaflags & DB_HASH_SUBDB ? 1 : 0;
00370 free(hsp);
00371 break;
00372 case DB_QUEUE:
00373 break;
00374 case DB_UNKNOWN:
00375 default:
00376 dbp->errx(dbp, "unknown database type");
00377 return (1);
00378 }
00379 return (0);
00380 }
00381
00382
00383
00384
00385
00386 int
00387 dump_sub(dbenv, parent_dbp, parent_name, pflag, keyflag)
00388 DB_ENV *dbenv;
00389 DB *parent_dbp;
00390 char *parent_name;
00391 int pflag, keyflag;
00392 {
00393 DB *dbp;
00394 DBC *dbcp;
00395 DBT key, data;
00396 int ret;
00397 char *subdb;
00398
00399
00400
00401
00402
00403 if ((ret = parent_dbp->cursor(parent_dbp, NULL, &dbcp, 0)) != 0) {
00404 dbenv->err(dbenv, ret, "DB->cursor");
00405 return (1);
00406 }
00407
00408 memset(&key, 0, sizeof(key));
00409 memset(&data, 0, sizeof(data));
00410 while ((ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0) {
00411
00412 if ((subdb = malloc(key.size + 1)) == NULL) {
00413 dbenv->err(dbenv, ENOMEM, NULL);
00414 return (1);
00415 }
00416 memcpy(subdb, key.data, key.size);
00417 subdb[key.size] = '\0';
00418
00419
00420 if ((ret = db_create(&dbp, dbenv, 0)) != 0) {
00421 dbenv->err(dbenv, ret, "db_create");
00422 free(subdb);
00423 return (1);
00424 }
00425 if ((ret = dbp->open(dbp, NULL,
00426 parent_name, subdb, DB_UNKNOWN, DB_RDONLY, 0)) != 0)
00427 dbp->err(dbp, ret,
00428 "DB->open: %s:%s", parent_name, subdb);
00429 if (ret == 0 && dbp->dump(
00430 dbp, subdb, __db_pr_callback, stdout, pflag, keyflag))
00431 ret = 1;
00432 (void)dbp->close(dbp, 0);
00433 free(subdb);
00434 if (ret != 0)
00435 return (1);
00436 }
00437 if (ret != DB_NOTFOUND) {
00438 parent_dbp->err(parent_dbp, ret, "DBcursor->get");
00439 return (1);
00440 }
00441
00442 if ((ret = dbcp->c_close(dbcp)) != 0) {
00443 parent_dbp->err(parent_dbp, ret, "DBcursor->close");
00444 return (1);
00445 }
00446
00447 return (0);
00448 }
00449
00450
00451
00452
00453
00454 int
00455 show_subs(dbp)
00456 DB *dbp;
00457 {
00458 DBC *dbcp;
00459 DBT key, data;
00460 int ret;
00461
00462
00463
00464
00465
00466 if ((ret = dbp->cursor(dbp, NULL, &dbcp, 0)) != 0) {
00467 dbp->err(dbp, ret, "DB->cursor");
00468 return (1);
00469 }
00470
00471 memset(&key, 0, sizeof(key));
00472 memset(&data, 0, sizeof(data));
00473 while ((ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0) {
00474 if ((ret = dbp->dbenv->prdbt(
00475 &key, 1, NULL, stdout, __db_pr_callback, 0)) != 0) {
00476 dbp->errx(dbp, NULL);
00477 return (1);
00478 }
00479 }
00480 if (ret != DB_NOTFOUND) {
00481 dbp->err(dbp, ret, "DBcursor->get");
00482 return (1);
00483 }
00484
00485 if ((ret = dbcp->c_close(dbcp)) != 0) {
00486 dbp->err(dbp, ret, "DBcursor->close");
00487 return (1);
00488 }
00489 return (0);
00490 }
00491
00492
00493
00494
00495
00496 int
00497 usage()
00498 {
00499 (void)fprintf(stderr, "usage: %s [-klNprRV]\n\t%s\n",
00500 progname,
00501 "[-d ahr] [-f output] [-h home] [-P password] [-s database] db_file");
00502 return (EXIT_FAILURE);
00503 }
00504
00505 int
00506 version_check()
00507 {
00508 int v_major, v_minor, v_patch;
00509
00510
00511 (void)db_version(&v_major, &v_minor, &v_patch);
00512 if (v_major != DB_VERSION_MAJOR || v_minor != DB_VERSION_MINOR) {
00513 fprintf(stderr,
00514 "%s: version %d.%d doesn't match library version %d.%d\n",
00515 progname, DB_VERSION_MAJOR, DB_VERSION_MINOR,
00516 v_major, v_minor);
00517 return (EXIT_FAILURE);
00518 }
00519 return (0);
00520 }