LCOV - code coverage report
Current view: top level - lib/tdb/tools - tdbdump.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 16 95 16.8 %
Date: 2024-06-13 04:01:37 Functions: 2 7 28.6 %

          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           0 : static void print_data(TDB_DATA d)
      28             : {
      29           0 :         unsigned char *p = (unsigned char *)d.dptr;
      30           0 :         int len = d.dsize;
      31           0 :         while (len--) {
      32           0 :                 if (isprint(*p) && !strchr("\"\\", *p)) {
      33           0 :                         fputc(*p, stdout);
      34             :                 } else {
      35           0 :                         printf("\\%02X", *p);
      36             :                 }
      37           0 :                 p++;
      38             :         }
      39           0 : }
      40             : 
      41           0 : static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
      42             : {
      43           0 :         printf("{\n");
      44           0 :         printf("key(%zu) = \"", key.dsize);
      45           0 :         print_data(key);
      46           0 :         printf("\"\n");
      47           0 :         printf("data(%zu) = \"", dbuf.dsize);
      48           0 :         print_data(dbuf);
      49           0 :         printf("\"\n");
      50           0 :         printf("}\n");
      51           0 :         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             :         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           3 : static int dump_tdb(const char *fname, const char *keyname, bool emergency)
     101             : {
     102             :         TDB_CONTEXT *tdb;
     103             :         TDB_DATA key, value;
     104           3 :         struct tdb_logging_context logfn = {
     105             :                 .log_fn = log_stderr,
     106             :         };
     107           3 :         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           3 :         tdb_flags |= TDB_NOLOCK;
     115             : 
     116           3 :         tdb = tdb_open_ex(fname, 0, tdb_flags, O_RDONLY, 0, &logfn, NULL);
     117           3 :         if (!tdb) {
     118           0 :                 printf("Failed to open %s\n", fname);
     119           0 :                 return 1;
     120             :         }
     121             : 
     122           3 :         if (emergency) {
     123           0 :                 return tdb_rescue(tdb, emergency_walk, discard_const(keyname)) == 0;
     124             :         }
     125           3 :         if (!keyname) {
     126           3 :                 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           3 :  int main(int argc, char *argv[])
     151             : {
     152           3 :         char *fname, *keyname=NULL;
     153           3 :         bool emergency = false;
     154             :         int c;
     155             : 
     156           3 :         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           3 :         fname = argv[optind];
     179             : 
     180           3 :         return dump_tdb(fname, keyname, emergency);
     181             : }

Generated by: LCOV version 1.13