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