2 * See the file LICENSE for redistribution information.
4 * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved.
12 #include "dbinc/db_page.h"
13 #include "dbinc/db_am.h"
16 static const char copyright[] =
17 "Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved.\n";
20 int db_init __P((DB_ENV *, char *, int, u_int32_t, int *));
21 int dump_sub __P((DB_ENV *, DB *, char *, int, int));
22 int main __P((int, char *[]));
23 int show_subs __P((DB *));
24 int usage __P((void));
25 int version_check __P((void));
38 db_pgno_t first, last;
41 int exitval, keyflag, lflag, mflag, nflag, pflag, sflag, private;
42 int ret, Rflag, rflag, resize;
43 char *data_len, *dbname, *dopt, *filename, *home, *passwd;
45 if ((progname = __db_rpath(argv[0])) == NULL)
50 if ((ret = version_check()) != 0)
55 exitval = lflag = mflag = nflag = pflag = rflag = Rflag = sflag = 0;
56 first = last = PGNO_INVALID;
60 data_len = dbname = dopt = filename = home = passwd = NULL;
61 while ((ch = getopt(argc, argv, "d:D:f:F:h:klL:m:NpP:rRs:V")) != EOF)
70 if (freopen(optarg, "w", stdout) == NULL) {
71 fprintf(stderr, DB_STR_A("5108",
72 "%s: %s: reopen: %s\n", "%s %s %s\n"),
73 progname, optarg, strerror(errno));
74 return (EXIT_FAILURE);
78 first = (db_pgno_t)strtoul(optarg, NULL, 10);
90 last = (db_pgno_t)strtoul(optarg, NULL, 10);
100 if (passwd != NULL) {
101 fprintf(stderr, DB_STR("5130",
102 "Password may not be specified twice"));
104 return (EXIT_FAILURE);
106 passwd = strdup(optarg);
107 memset(optarg, 0, strlen(optarg));
108 if (passwd == NULL) {
109 fprintf(stderr, DB_STR_A("5109",
110 "%s: strdup: %s\n", "%s %s\n"),
111 progname, strerror(errno));
112 return (EXIT_FAILURE);
124 /* DB_AGGRESSIVE requires DB_SALVAGE */
130 printf("%s\n", db_version(NULL, NULL, NULL));
131 return (EXIT_SUCCESS);
140 * A file name must be specified, unless we're looking for an in-memory
141 * db, in which case it must not.
143 if (argc == 0 && mflag)
145 else if (argc == 1 && !mflag)
150 if (dopt != NULL && pflag) {
151 fprintf(stderr, DB_STR_A("5110",
152 "%s: the -d and -p options may not both be specified\n",
154 return (EXIT_FAILURE);
156 if (lflag && sflag) {
157 fprintf(stderr, DB_STR_A("5111",
158 "%s: the -l and -s options may not both be specified\n",
160 return (EXIT_FAILURE);
162 if ((lflag || sflag) && mflag) {
163 fprintf(stderr, DB_STR_A("5112",
164 "%s: the -m option may not be specified with -l or -s\n",
166 return (EXIT_FAILURE);
169 if (keyflag && rflag) {
170 fprintf(stderr, DB_STR_A("5113",
171 "%s: the -k and -r or -R options may not both be specified\n",
173 return (EXIT_FAILURE);
176 if (sflag && rflag) {
177 fprintf(stderr, DB_STR_A("5114",
178 "%s: the -r or R options may not be specified with -s\n",
180 return (EXIT_FAILURE);
183 /* Handle possible interruptions. */
187 * Create an environment object and initialize it for error
190 retry: if ((ret = db_env_create(&dbenv, 0)) != 0) {
192 "%s: db_env_create: %s\n", progname, db_strerror(ret));
196 dbenv->set_errfile(dbenv, stderr);
197 dbenv->set_errpfx(dbenv, progname);
198 if (data_len != NULL)
199 (void)dbenv->set_data_len(dbenv, (u_int32_t)atol(data_len));
202 if ((ret = dbenv->set_flags(dbenv, DB_NOLOCKING, 1)) != 0) {
203 dbenv->err(dbenv, ret, "set_flags: DB_NOLOCKING");
206 if ((ret = dbenv->set_flags(dbenv, DB_NOPANIC, 1)) != 0) {
207 dbenv->err(dbenv, ret, "set_flags: DB_NOPANIC");
211 if (passwd != NULL && (ret = dbenv->set_encrypt(dbenv,
212 passwd, DB_ENCRYPT_AES)) != 0) {
213 dbenv->err(dbenv, ret, "set_passwd");
217 /* Initialize the environment. */
218 if (db_init(dbenv, home, rflag, cache, &private) != 0)
221 /* Create the DB object and open the file. */
222 if ((ret = db_create(&dbp, dbenv, 0)) != 0) {
223 dbenv->err(dbenv, ret, "db_create");
228 Set application-specific btree compression functions here. For example:
229 if ((ret = dbp->set_bt_compress(
230 dbp, local_compress_func, local_decompress_func)) != 0) {
231 dbp->err(dbp, ret, "DB->set_bt_compress");
237 * If we're salvaging, don't do an open; it might not be safe.
238 * Dispatch now into the salvager.
241 /* The verify method is a destructor. */
242 ret = dbp->verify(dbp, filename, dbname, stdout,
244 (Rflag ? DB_AGGRESSIVE : 0) |
245 (pflag ? DB_PRINTABLE : 0));
252 if ((ret = dbp->open(dbp, NULL,
253 filename, dbname, DB_UNKNOWN, DB_RDWRMASTER|DB_RDONLY, 0)) != 0) {
254 dbp->err(dbp, ret, DB_STR_A("5115", "open: %s", "%s"),
255 filename == NULL ? dbname : filename);
259 if ((ret = __db_util_cache(dbp, &cache, &resize)) != 0)
262 (void)dbp->close(dbp, 0);
265 (void)dbenv->close(dbenv, 0);
273 __db_dumptree(dbp, NULL, dopt, NULL, first, last)) != 0) {
274 dbp->err(dbp, ret, "__db_dumptree: %s", filename);
278 if (dbp->get_multiple(dbp)) {
282 dbp->errx(dbp, DB_STR_A("5116",
283 "%s: does not contain multiple databases", "%s"),
288 if (dbname == NULL && dbp->get_multiple(dbp)) {
289 if (dump_sub(dbenv, dbp, filename, pflag, keyflag))
292 if (dbp->dump(dbp, NULL,
293 __db_pr_callback, stdout, pflag, keyflag))
300 done: if (dbp != NULL && (ret = dbp->close(dbp, 0)) != 0) {
302 dbenv->err(dbenv, ret, DB_STR("5117", "close"));
304 if (dbenv != NULL && (ret = dbenv->close(dbenv, 0)) != 0) {
307 "%s: dbenv->close: %s\n", progname, db_strerror(ret));
313 /* Resend any caught signal. */
314 __db_util_sigresend();
316 return (exitval == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
321 * Initialize the environment.
324 db_init(dbenv, home, is_salvage, cache, is_privatep)
334 * Try and use the underlying environment when opening a database.
335 * We wish to use the buffer pool so our information is as up-to-date
336 * as possible, even if the mpool cache hasn't been flushed.
338 * If we are not doing a salvage, we want to join the environment;
339 * if a locking system is present, this will let us use it and be
340 * safe to run concurrently with other threads of control. (We never
341 * need to use transactions explicitly, as we're read-only.) Note
342 * that in CDB, too, this will configure our environment
343 * appropriately, and our cursors will (correctly) do locking as CDB
346 * If we are doing a salvage, the verification code will protest
347 * if we initialize transactions, logging, or locking; do an
348 * explicit DB_INIT_MPOOL to try to join any existing environment
349 * before we create our own.
352 if ((ret = dbenv->open(dbenv, home,
353 DB_USE_ENVIRON | (is_salvage ? DB_INIT_MPOOL : 0), 0)) == 0)
355 if (ret == DB_VERSION_MISMATCH)
359 * An environment is required because we may be trying to look at
360 * databases in directories other than the current one. We could
361 * avoid using an environment iff the -h option wasn't specified,
362 * but that seems like more work than it's worth.
364 * No environment exists (or, at least no environment that includes
365 * an mpool region exists). Create one, but make it private so that
366 * no files are actually created.
369 if ((ret = dbenv->set_cachesize(dbenv, 0, cache, 1)) == 0 &&
370 (ret = dbenv->open(dbenv, home,
371 DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE | DB_USE_ENVIRON, 0)) == 0)
374 /* An environment is required. */
375 err: dbenv->err(dbenv, ret, "DB_ENV->open");
381 * Dump out the records for a DB containing subdatabases.
384 dump_sub(dbenv, parent_dbp, parent_name, pflag, keyflag)
397 * Get a cursor and step through the database, dumping out each
400 if ((ret = parent_dbp->cursor(parent_dbp, NULL, &dbcp, 0)) != 0) {
401 dbenv->err(dbenv, ret, "DB->cursor");
405 memset(&key, 0, sizeof(key));
406 memset(&data, 0, sizeof(data));
407 while ((ret = dbcp->get(dbcp, &key, &data,
408 DB_IGNORE_LEASE | DB_NEXT)) == 0) {
409 /* Nul terminate the subdatabase name. */
410 if ((subdb = malloc(key.size + 1)) == NULL) {
411 dbenv->err(dbenv, ENOMEM, NULL);
414 memcpy(subdb, key.data, key.size);
415 subdb[key.size] = '\0';
417 /* Create the DB object and open the file. */
418 if ((ret = db_create(&dbp, dbenv, 0)) != 0) {
419 dbenv->err(dbenv, ret, "db_create");
425 Set application-specific btree compression functions here.
428 if ((ret = dbp->set_bt_compress(
429 dbp, local_compress_func, local_decompress_func)) != 0) {
430 dbp->err(dbp, ret, "DB->set_bt_compress");
435 if ((ret = dbp->open(dbp, NULL,
436 parent_name, subdb, DB_UNKNOWN, DB_RDONLY, 0)) != 0)
438 "DB->open: %s:%s", parent_name, subdb);
439 if (ret == 0 && dbp->dump(
440 dbp, subdb, __db_pr_callback, stdout, pflag, keyflag))
442 (void)dbp->close(dbp, 0);
447 if (ret != DB_NOTFOUND) {
448 parent_dbp->err(parent_dbp, ret, "DBcursor->get");
452 if ((ret = dbcp->close(dbcp)) != 0) {
453 parent_dbp->err(parent_dbp, ret, "DBcursor->close");
462 * Display the subdatabases for a database.
473 * Get a cursor and step through the database, printing out the key
474 * of each key/data pair.
476 if ((ret = dbp->cursor(dbp, NULL, &dbcp, 0)) != 0) {
477 dbp->err(dbp, ret, "DB->cursor");
481 memset(&key, 0, sizeof(key));
482 memset(&data, 0, sizeof(data));
483 while ((ret = dbcp->get(dbcp, &key, &data,
484 DB_IGNORE_LEASE | DB_NEXT)) == 0) {
485 if ((ret = dbp->dbenv->prdbt(
486 &key, 1, NULL, stdout, __db_pr_callback, 0, 0)) != 0) {
487 dbp->errx(dbp, NULL);
491 if (ret != DB_NOTFOUND) {
492 dbp->err(dbp, ret, "DBcursor->get");
496 if ((ret = dbcp->close(dbcp)) != 0) {
497 dbp->err(dbp, ret, "DBcursor->close");
505 * Display the usage message.
510 (void)fprintf(stderr, "usage: %s [-klNprRV]\n\t%s\n",
512 "[-d ahr] [-f output] [-h home] [-P password] [-s database] db_file");
513 (void)fprintf(stderr, "usage: %s [-kNpV] %s\n",
514 progname, "[-d ahr] [-f output] [-h home] -m database");
515 return (EXIT_FAILURE);
521 int v_major, v_minor, v_patch;
523 /* Make sure we're loaded with the right version of the DB library. */
524 (void)db_version(&v_major, &v_minor, &v_patch);
525 if (v_major != DB_VERSION_MAJOR || v_minor != DB_VERSION_MINOR) {
526 fprintf(stderr, DB_STR_A("5118",
527 "%s: version %d.%d doesn't match library version %d.%d\n",
528 "%s %d %d %d %d\n"), progname,
529 DB_VERSION_MAJOR, DB_VERSION_MINOR,
531 return (EXIT_FAILURE);