LCOV - code coverage report
Current view: top level - lib/tdb/tools - tdbdump.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 46 108 42.6 %
Date: 2024-05-31 13:13:24 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             : struct traverse_state {
      28             :         bool hex_output;
      29             :         const char *keyname;
      30             : };
      31             : 
      32          46 : static void print_data(TDB_DATA d, bool hex_output)
      33             : {
      34          46 :         unsigned char *p = (unsigned char *)d.dptr;
      35          46 :         int len = d.dsize;
      36        2004 :         while (len--) {
      37        1958 :                 if (hex_output) {
      38         124 :                         printf("%02X", *p);
      39        1834 :                 } else if(isprint(*p) && !strchr("\"\\", *p)) {
      40        1234 :                         fputc(*p, stdout);
      41             :                 } else {
      42         600 :                         printf("\\%02X", *p);
      43             :                 }
      44        1958 :                 p++;
      45             :         }
      46          46 : }
      47             : 
      48          23 : static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
      49             : {
      50          23 :         struct traverse_state *traverse = state;
      51             : 
      52          23 :         printf("{\n");
      53          23 :         printf("key(%zu) = \"", key.dsize);
      54          23 :         print_data(key, traverse->hex_output);
      55          23 :         printf("\"\n");
      56          23 :         printf("data(%zu) = \"", dbuf.dsize);
      57          23 :         print_data(dbuf, traverse->hex_output);
      58          23 :         printf("\"\n");
      59          23 :         printf("}\n");
      60          23 :         return 0;
      61             : }
      62             : 
      63             : static void log_stderr(struct tdb_context *tdb, enum tdb_debug_level level,
      64             :                        const char *fmt, ...) PRINTF_ATTRIBUTE(3,4);
      65             : 
      66           0 : static void log_stderr(struct tdb_context *tdb, enum tdb_debug_level level,
      67             :                        const char *fmt, ...)
      68             : {
      69           0 :         va_list ap;
      70           0 :         const char *name = tdb_name(tdb);
      71           0 :         const char *prefix = "";
      72             : 
      73           0 :         if (!name)
      74           0 :                 name = "unnamed";
      75             : 
      76           0 :         switch (level) {
      77           0 :         case TDB_DEBUG_ERROR:
      78           0 :                 prefix = "ERROR: ";
      79           0 :                 break;
      80           0 :         case TDB_DEBUG_WARNING:
      81           0 :                 prefix = "WARNING: ";
      82           0 :                 break;
      83           0 :         case TDB_DEBUG_TRACE:
      84           0 :                 return;
      85             : 
      86           0 :         default:
      87             :         case TDB_DEBUG_FATAL:
      88           0 :                 prefix = "FATAL: ";
      89           0 :                 break;
      90             :         }
      91             : 
      92           0 :         va_start(ap, fmt);
      93           0 :         fprintf(stderr, "tdb(%s): %s", name, prefix);
      94           0 :         vfprintf(stderr, fmt, ap);
      95           0 :         va_end(ap);
      96             : }
      97             : 
      98           0 : static void emergency_walk(TDB_DATA key, TDB_DATA dbuf, void *state)
      99             : {
     100           0 :         struct traverse_state *traverse = state;
     101             : 
     102           0 :         if (traverse->keyname) {
     103           0 :                 if (key.dsize != strlen(traverse->keyname))
     104           0 :                         return;
     105           0 :                 if (memcmp(key.dptr, traverse->keyname, key.dsize) != 0)
     106           0 :                         return;
     107             :         }
     108           0 :         traverse_fn(NULL, key, dbuf, traverse);
     109             : }
     110             : 
     111           8 : static int dump_tdb(const char *fname, const char *keyname,
     112             :                     bool emergency, bool hex_output)
     113             : {
     114           1 :         TDB_CONTEXT *tdb;
     115           1 :         TDB_DATA key, value;
     116           8 :         struct tdb_logging_context logfn = {
     117             :                 .log_fn = log_stderr,
     118             :         };
     119           8 :         int tdb_flags = TDB_DEFAULT;
     120             : 
     121             :         /*
     122             :          * Note: that O_RDONLY implies TDB_NOLOCK, but we want to make it
     123             :          * explicit as it's important when working on databases which were
     124             :          * created with mutex locking.
     125             :          */
     126           8 :         tdb_flags |= TDB_NOLOCK;
     127             : 
     128           8 :         tdb = tdb_open_ex(fname, 0, tdb_flags, O_RDONLY, 0, &logfn, NULL);
     129           8 :         if (!tdb) {
     130           0 :                 printf("Failed to open %s\n", fname);
     131           0 :                 return 1;
     132             :         }
     133             : 
     134           8 :         if (emergency) {
     135           0 :                 struct traverse_state traverse =
     136             :                         { .hex_output = hex_output,
     137             :                           .keyname = keyname };
     138           0 :                 return tdb_rescue(tdb, emergency_walk, &traverse) == 0;
     139             :         }
     140           8 :         if (!keyname) {
     141           8 :                 struct traverse_state traverse = { .hex_output = hex_output };
     142           8 :                 return tdb_traverse(tdb, traverse_fn, &traverse) == -1 ? 1 : 0;
     143             :         } else {
     144           0 :                 key.dptr = discard_const_p(uint8_t, keyname);
     145           0 :                 key.dsize = strlen(keyname);
     146           0 :                 value = tdb_fetch(tdb, key);
     147           0 :                 if (!value.dptr) {
     148           0 :                         return 1;
     149             :                 } else {
     150           0 :                         print_data(value, hex_output);
     151           0 :                         free(value.dptr);
     152             :                 }
     153             :         }
     154             : 
     155           0 :         return 0;
     156             : }
     157             : 
     158           0 : static void usage( void)
     159             : {
     160           0 :         printf( "Usage: tdbdump [options] <filename>\n\n");
     161           0 :         printf( "   -h          this help message\n");
     162           0 :         printf( "   -k keyname  dumps value of keyname\n");
     163           0 :         printf( "   -e          emergency dump, for corrupt databases\n");
     164           0 : }
     165             : 
     166           8 :  int main(int argc, char *argv[])
     167             : {
     168           8 :         char *fname, *keyname=NULL;
     169           8 :         bool emergency = false, hex_output = false;
     170           1 :         int c;
     171             : 
     172           8 :         if (argc < 2) {
     173           0 :                 printf("Usage: tdbdump <fname>\n");
     174           0 :                 exit(1);
     175             :         }
     176             : 
     177           9 :         while ((c = getopt( argc, argv, "hk:ex")) != -1) {
     178           1 :                 switch (c) {
     179           0 :                 case 'h':
     180           0 :                         usage();
     181           0 :                         exit( 0);
     182           0 :                 case 'k':
     183           0 :                         keyname = optarg;
     184           0 :                         break;
     185           0 :                 case 'e':
     186           0 :                         emergency = true;
     187           0 :                         break;
     188           1 :                 case 'x':
     189           1 :                         hex_output = true;
     190           1 :                         break;
     191           0 :                 default:
     192           0 :                         usage();
     193           0 :                         exit( 1);
     194             :                 }
     195             :         }
     196             : 
     197           8 :         fname = argv[optind];
     198             : 
     199           8 :         return dump_tdb(fname, keyname, emergency, hex_output);
     200             : }

Generated by: LCOV version 1.14