static void emergency_walk(TDB_DATA key, TDB_DATA dbuf, void *keyname) { if (keyname) { if (key.dsize != strlen(keyname)) return; if (memcmp(key.dptr, keyname, key.dsize) != 0) return; } traverse_fn(NULL, key, dbuf, NULL); }
static void emergency_walk(TDB_DATA key, TDB_DATA dbuf, void *keyname) { traverse_fn(NULL, key, dbuf, keyname); }
static int dump_lmdb(const char *fname, struct ldb_dn *dn, bool emergency) { int ret; struct MDB_env *env = NULL; struct MDB_txn *txn = NULL; MDB_dbi dbi; struct MDB_cursor *cursor = NULL; struct MDB_val key; struct MDB_val data; ret = mdb_env_create(&env); if (ret != 0) { fprintf(stderr, "Could not create MDB environment: (%d) %s\n", ret, mdb_strerror(ret)); goto close_env; } ret = mdb_env_open(env, fname, MDB_NOSUBDIR|MDB_NOTLS|MDB_RDONLY, 0600); if (ret != 0) { fprintf(stderr, "Could not open environment for %s: (%d) %s\n", fname, ret, mdb_strerror(ret)); goto close_env; } ret = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn); if (ret != 0) { fprintf(stderr, "Could not start transaction: (%d) %s\n", ret, mdb_strerror(ret)); goto close_env; } ret = mdb_dbi_open(txn, NULL, 0, &dbi); if (ret != 0) { fprintf(stderr, "Could not open database: (%d) %s\n", ret, mdb_strerror(ret)); goto close_txn; } ret = mdb_cursor_open(txn, dbi, &cursor); if (ret != 0) { fprintf(stderr, "Could not open cursor: (%d) %s\n", ret, mdb_strerror(ret)); goto close_txn; } ret = mdb_cursor_get(cursor, &key, &data, MDB_FIRST); if (ret != 0 && ret != MDB_NOTFOUND) { fprintf(stderr, "Could not find first record: (%d) %s\n", ret, mdb_strerror(ret)); goto close_cursor; } while (ret != MDB_NOTFOUND) { struct TDB_DATA tkey = { .dptr = key.mv_data, .dsize = key.mv_size }; struct TDB_DATA tdata = { .dptr = data.mv_data, .dsize = data.mv_size }; traverse_fn(NULL, tkey, tdata, dn); ret = mdb_cursor_get(cursor, &key, &data, MDB_NEXT); if (ret != 0 && ret != MDB_NOTFOUND) { fprintf(stderr, "Could not read next record: (%d) %s\n", ret, mdb_strerror(ret)); goto close_cursor; } } ret = 0; close_cursor: mdb_cursor_close(cursor); close_txn: mdb_txn_commit(txn); close_env: mdb_env_close(env); if (ret != 0) { return 1; } return 0; } #else static int dump_lmdb(const char *fname, struct ldb_dn *dn, bool emergency) { /* not built with lmdb support */ return 1; } #endif /* #ifdef HAVE_LMDB */ static void usage( void) { printf( "Usage: ldbdump [options] <filename>\n\n"); printf( " -h this help message\n"); printf( " -d DN dumps DN only\n"); printf( " -e emergency dump, for corrupt databases\n"); printf( " -i include index and @BASEINFO records in dump\n"); printf( " -c validate contents of the records\n"); } int main(int argc, char *argv[]) { bool emergency = false; int c, rc; char *fname; struct ldb_dn *dn = NULL; ldb = ldb_init(NULL, NULL); if (ldb == NULL) { fprintf(stderr, "ldb: ldb_init failed()"); exit(1); } rc = ldb_modules_hook(ldb, LDB_MODULE_HOOK_CMDLINE_PRECONNECT); if (rc != LDB_SUCCESS) { fprintf(stderr, "ldb: failed to run preconnect hooks (needed to get Samba LDIF handlers): %s\n", ldb_strerror(rc)); exit(1); } if (argc < 2) { printf("Usage: ldbdump <fname>\n"); exit(1); } while ((c = getopt( argc, argv, "hd:eic")) != -1) { switch (c) { case 'h': usage(); exit( 0); case 'd': dn = ldb_dn_new(ldb, ldb, optarg); if (!dn) { fprintf(stderr, "ldb failed to parse %s as a DN\n", optarg); exit(1); } break; case 'e': emergency = true; break; case 'i': show_index = true; break; case 'c': validate_contents = true; break; default: usage(); exit( 1); } } fname = argv[optind]; rc = dump_lmdb(fname, dn, emergency); if (rc != 0) { rc = dump_tdb(fname, dn, emergency); if (rc != 0) { fprintf(stderr, "Failed to open %s\n", fname); return 1; } } return 0; }