LCOV - code coverage report
Current view: top level - lib/tdb/tools - tdbdump.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 38 99 38.4 %
Date: 2024-02-28 12:06:22 Functions: 4 7 57.1 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    simple tdb dump util
       4             :    Copyright (C) Andrew Tridgell              2001
       5             : 
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : #include "replace.h"
      21             : #include "system/locale.h"
      22             : #include "system/time.h"
      23             : #include "system/filesys.h"
      24             : #include "system/wait.h"
      25             : #include "tdb.h"
      26             : 
      27          34 : static void print_data(TDB_DATA d)
      28             : {
      29          34 :         unsigned char *p = (unsigned char *)d.dptr;
      30          34 :         int len = d.dsize;
      31        1734 :         while (len--) {
      32        1700 :                 if (isprint(*p) && !strchr("\"\\", *p)) {
      33        1078 :                         fputc(*p, stdout);
      34             :                 } else {
      35         622 :                         printf("\\%02X", *p);
      36             :                 }
      37        1700 :                 p++;
      38             :         }
      39          34 : }
      40             : 
      41          17 : static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
      42             : {
      43          17 :         printf("{\n");
      44          17 :         printf("key(%zu) = \"", key.dsize);
      45          17 :         print_data(key);
      46          17 :         printf("\"\n");
      47          17 :         printf("data(%zu) = \"", dbuf.dsize);
      48          17 :         print_data(dbuf);
      49          17 :         printf("\"\n");
      50          17 :         printf("}\n");
      51          17 :         return 0;
      52             : }
      53             : 
      54             : static void log_stderr(struct tdb_context *tdb, enum tdb_debug_level level,
      55             :                        const char *fmt, ...) PRINTF_ATTRIBUTE(3,4);
      56             : 
      57           0 : static void log_stderr(struct tdb_context *tdb, enum tdb_debug_level level,
      58             :                        const char *fmt, ...)
      59             : {
      60           0 :         va_list ap;
      61           0 :         const char *name = tdb_name(tdb);
      62           0 :         const char *prefix = "";
      63             : 
      64           0 :         if (!name)
      65           0 :                 name = "unnamed";
      66             : 
      67           0 :         switch (level) {
      68           0 :         case TDB_DEBUG_ERROR:
      69           0 :                 prefix = "ERROR: ";
      70           0 :                 break;
      71           0 :         case TDB_DEBUG_WARNING:
      72           0 :                 prefix = "WARNING: ";
      73           0 :                 break;
      74           0 :         case TDB_DEBUG_TRACE:
      75           0 :                 return;
      76             : 
      77           0 :         default:
      78             :         case TDB_DEBUG_FATAL:
      79           0 :                 prefix = "FATAL: ";
      80           0 :                 break;
      81             :         }
      82             : 
      83           0 :         va_start(ap, fmt);
      84           0 :         fprintf(stderr, "tdb(%s): %s", name, prefix);
      85           0 :         vfprintf(stderr, fmt, ap);
      86           0 :         va_end(ap);
      87             : }
      88             : 
      89           0 : static void emergency_walk(TDB_DATA key, TDB_DATA dbuf, void *keyname)
      90             : {
      91           0 :         if (keyname) {
      92           0 :                 if (key.dsize != strlen(keyname))
      93           0 :                         return;
      94           0 :                 if (memcmp(key.dptr, keyname, key.dsize) != 0)
      95           0 :                         return;
      96             :         }
      97           0 :         traverse_fn(NULL, key, dbuf, NULL);
      98             : }
      99             : 
     100           6 : static int dump_tdb(const char *fname, const char *keyname, bool emergency)
     101             : {
     102           1 :         TDB_CONTEXT *tdb;
     103           1 :         TDB_DATA key, value;
     104           6 :         struct tdb_logging_context logfn = {
     105             :                 .log_fn = log_stderr,
     106             :         };
     107           6 :         int tdb_flags = TDB_DEFAULT;
     108             : 
     109             :         /*
     110             :          * Note: that O_RDONLY implies TDB_NOLOCK, but we want to make it
     111             :          * explicit as it's important when working on databases which were
     112             :          * created with mutex locking.
     113             :          */
     114           6 :         tdb_flags |= TDB_NOLOCK;
     115             : 
     116           6 :         tdb = tdb_open_ex(fname, 0, tdb_flags, O_RDONLY, 0, &logfn, NULL);
     117           6 :         if (!tdb) {
     118           0 :                 printf("Failed to open %s\n", fname);
     119           0 :                 return 1;
     120             :         }
     121             : 
     122           6 :         if (emergency) {
     123           0 :                 return tdb_rescue(tdb, emergency_walk, discard_const(keyname)) == 0;
     124             :         }
     125           6 :         if (!keyname) {
     126           6 :                 return tdb_traverse(tdb, traverse_fn, NULL) == -1 ? 1 : 0;
     127             :         } else {
     128           0 :                 key.dptr = discard_const_p(uint8_t, keyname);
     129           0 :                 key.dsize = strlen(keyname);
     130           0 :                 value = tdb_fetch(tdb, key);
     131           0 :                 if (!value.dptr) {
     132           0 :                         return 1;
     133             :                 } else {
     134           0 :                         print_data(value);
     135           0 :                         free(value.dptr);
     136             :                 }
     137             :         }
     138             : 
     139           0 :         return 0;
     140             : }
     141             : 
     142           0 : static void usage( void)
     143             : {
     144           0 :         printf( "Usage: tdbdump [options] <filename>\n\n");
     145           0 :         printf( "   -h          this help message\n");
     146           0 :         printf( "   -k keyname  dumps value of keyname\n");
     147           0 :         printf( "   -e          emergency dump, for corrupt databases\n");
     148           0 : }
     149             : 
     150           6 :  int main(int argc, char *argv[])
     151             : {
     152           6 :         char *fname, *keyname=NULL;
     153           6 :         bool emergency = false;
     154           1 :         int c;
     155             : 
     156           6 :         if (argc < 2) {
     157           0 :                 printf("Usage: tdbdump <fname>\n");
     158           0 :                 exit(1);
     159             :         }
     160             : 
     161           6 :         while ((c = getopt( argc, argv, "hk:e")) != -1) {
     162           0 :                 switch (c) {
     163           0 :                 case 'h':
     164           0 :                         usage();
     165           0 :                         exit( 0);
     166           0 :                 case 'k':
     167           0 :                         keyname = optarg;
     168           0 :                         break;
     169           0 :                 case 'e':
     170           0 :                         emergency = true;
     171           0 :                         break;
     172           0 :                 default:
     173           0 :                         usage();
     174           0 :                         exit( 1);
     175             :                 }
     176             :         }
     177             : 
     178           6 :         fname = argv[optind];
     179             : 
     180           6 :         return dump_tdb(fname, keyname, emergency);
     181             : }

Generated by: LCOV version 1.14