SPDX: Mass-update to GPL-2.0-or-later
[exim.git] / src / src / exim_dbutil.c
index 5f2e664172a1fcabbeb703ec5cd7f8d79a840e75..f16570d86a5ee57ef2c2cf6394806c0c3e526544 100644 (file)
@@ -2,9 +2,10 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
+/* Copyright (c) The Exim Maintainers 2020 - 2022 */
 /* Copyright (c) University of Cambridge 1995 - 2018 */
-/* Copyright (c) The Exim Maintainers 2020 - 2021 */
 /* See the file NOTICE for conditions of use and distribution. */
+/* SPDX-License-Identifier: GPL-2.0-or-later */
 
 
 /* This single source file is used to compile three utility programs for
@@ -47,6 +48,7 @@ whose inclusion is controlled by -D on the compilation command. */
 
 uschar *spool_directory;
 
+BOOL keyonly = FALSE;
 BOOL utc = FALSE;
 
 
@@ -84,31 +86,6 @@ BOOL    allow_insecure_tainted_data;
 /******************************************************************************/
 
 
-/*************************************************
-*         Berkeley DB error callback             *
-*************************************************/
-
-/* For Berkeley DB >= 2, we can define a function to be called in case of DB
-errors. This should help with debugging strange DB problems, e.g. getting "File
-exists" when you try to open a db file. The API changed at release 4.3. */
-
-#if defined(USE_DB) && defined(DB_VERSION_STRING)
-void
-#if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3)
-dbfn_bdb_error_callback(const DB_ENV *dbenv, const char *pfx, const char *msg)
-{
-dbenv = dbenv;
-#else
-dbfn_bdb_error_callback(const char *pfx, char *msg)
-{
-#endif
-pfx = pfx;
-printf("Berkeley DB error: %s\n", msg);
-}
-#endif
-
-
-
 /*************************************************
 *              SIGALRM handler                   *
 *************************************************/
@@ -150,30 +127,32 @@ check_args(int argc, uschar **argv, uschar *name, uschar *options)
 uschar * aname = argv[optind + 1];
 if (argc - optind == 2)
   {
-  if (Ustrcmp(aname, "retry") == 0)            return type_retry;
-  if (Ustrcmp(aname, "misc") == 0)             return type_misc;
+  if (Ustrcmp(aname, "retry") == 0)    return type_retry;
+  if (Ustrcmp(aname, "misc") == 0)     return type_misc;
   if (Ustrncmp(aname, "wait-", 5) == 0)        return type_wait;
-  if (Ustrcmp(aname, "callout") == 0)          return type_callout;
+  if (Ustrcmp(aname, "callout") == 0)  return type_callout;
   if (Ustrcmp(aname, "ratelimit") == 0)        return type_ratelimit;
-  if (Ustrcmp(aname, "tls") == 0)              return type_tls;
-  if (Ustrcmp(aname, "seen") == 0)             return type_seen;
+  if (Ustrcmp(aname, "tls") == 0)      return type_tls;
+  if (Ustrcmp(aname, "seen") == 0)     return type_seen;
   }
 usage(name, options);
 return -1;              /* Never obeyed */
 }
 
 
+FUNC_MAYBE_UNUSED
 static void
-options(int argc, uschar * argv[], uschar * name)
+options(int argc, uschar * argv[], uschar * name, const uschar * opts)
 {
 int opt;
 
 opterr = 0;
-while ((opt = getopt(argc, (char * const *)argv, "z")) != -1)
+while ((opt = getopt(argc, (char * const *)argv, CCS opts)) != -1)
   switch (opt)
   {
+  case 'k':    keyonly = TRUE; break;
   case 'z':    utc = TRUE; break;
-  default:     usage(name, US" [-z]");
+  default:     usage(name, US" [-z] [-k]");
   }
 }
 
@@ -364,7 +343,7 @@ if (asprintf(CSS &filename, "%s/%s", dirname, name) < 0) return NULL;
 #else
 filename = string_sprintf("%s/%s", dirname, name);
 #endif
-EXIM_DBOPEN(filename, dirname, flags, 0, &dbblock->dbptr);
+dbblock->dbptr = exim_dbopen(filename, dirname, flags, 0);
 
 if (!dbblock->dbptr)
   {
@@ -400,7 +379,7 @@ Returns:  nothing
 void
 dbfn_close(open_db *dbblock)
 {
-EXIM_DBCLOSE(dbblock->dbptr);
+exim_dbclose(dbblock->dbptr);
 (void)close(dbblock->lockfd);
 }
 
@@ -430,25 +409,25 @@ dbfn_read_with_length(open_db *dbblock, const uschar *key, int *length)
 void *yield;
 EXIM_DATUM key_datum, result_datum;
 int klen = Ustrlen(key) + 1;
-uschar * key_copy = store_get(klen, is_tainted(key));
+uschar * key_copy = store_get(klen, key);
 
 memcpy(key_copy, key, klen);
 
-EXIM_DATUM_INIT(key_datum);         /* Some DBM libraries require the datum */
-EXIM_DATUM_INIT(result_datum);      /* to be cleared before use. */
-EXIM_DATUM_DATA(key_datum) = CS key_copy;
-EXIM_DATUM_SIZE(key_datum) = klen;
+exim_datum_init(&key_datum);         /* Some DBM libraries require the datum */
+exim_datum_init(&result_datum);      /* to be cleared before use. */
+exim_datum_data_set(&key_datum, key_copy);
+exim_datum_size_set(&key_datum, klen);
 
-if (!EXIM_DBGET(dbblock->dbptr, key_datum, result_datum)) return NULL;
+if (!exim_dbget(dbblock->dbptr, &key_datum, &result_datum)) return NULL;
 
 /* Assume for now that anything stored could have been tainted. Properly
 we should store the taint status along with the data. */
 
-yield = store_get(EXIM_DATUM_SIZE(result_datum), TRUE);
-memcpy(yield, EXIM_DATUM_DATA(result_datum), EXIM_DATUM_SIZE(result_datum));
-if (length) *length = EXIM_DATUM_SIZE(result_datum);
+yield = store_get(exim_datum_size_get(&result_datum), GET_TAINTED);
+memcpy(yield, exim_datum_data_get(&result_datum), exim_datum_size_get(&result_datum));
+if (length) *length = exim_datum_size_get(&result_datum);
 
-EXIM_DATUM_FREE(result_datum);    /* Some DBM libs require freeing */
+exim_datum_free(&result_datum);    /* Some DBM libs require freeing */
 return yield;
 }
 
@@ -477,18 +456,18 @@ dbfn_write(open_db *dbblock, const uschar *key, void *ptr, int length)
 EXIM_DATUM key_datum, value_datum;
 dbdata_generic *gptr = (dbdata_generic *)ptr;
 int klen = Ustrlen(key) + 1;
-uschar * key_copy = store_get(klen, is_tainted(key));
+uschar * key_copy = store_get(klen, key);
 
 memcpy(key_copy, key, klen);
 gptr->time_stamp = time(NULL);
 
-EXIM_DATUM_INIT(key_datum);         /* Some DBM libraries require the datum */
-EXIM_DATUM_INIT(value_datum);       /* to be cleared before use. */
-EXIM_DATUM_DATA(key_datum) = CS key_copy;
-EXIM_DATUM_SIZE(key_datum) = klen;
-EXIM_DATUM_DATA(value_datum) = CS ptr;
-EXIM_DATUM_SIZE(value_datum) = length;
-return EXIM_DBPUT(dbblock->dbptr, key_datum, value_datum);
+exim_datum_init(&key_datum);         /* Some DBM libraries require the datum */
+exim_datum_init(&value_datum);       /* to be cleared before use. */
+exim_datum_data_set(&key_datum, key_copy);
+exim_datum_size_set(&key_datum, klen);
+exim_datum_data_set(&value_datum, ptr);
+exim_datum_size_set(&value_datum, length);
+return exim_dbput(dbblock->dbptr, &key_datum, &value_datum);
 }
 
 
@@ -509,14 +488,14 @@ int
 dbfn_delete(open_db *dbblock, const uschar *key)
 {
 int klen = Ustrlen(key) + 1;
-uschar * key_copy = store_get(klen, is_tainted(key));
+uschar * key_copy = store_get(klen, key);
+EXIM_DATUM key_datum;
 
 memcpy(key_copy, key, klen);
-EXIM_DATUM key_datum;
-EXIM_DATUM_INIT(key_datum);         /* Some DBM libraries require clearing */
-EXIM_DATUM_DATA(key_datum) = CS key_copy;
-EXIM_DATUM_SIZE(key_datum) = klen;
-return EXIM_DBDEL(dbblock->dbptr, key_datum);
+exim_datum_init(&key_datum);         /* Some DBM libraries require clearing */
+exim_datum_data_set(&key_datum, key_copy);
+exim_datum_size_set(&key_datum, klen);
+return exim_dbdel(dbblock->dbptr, &key_datum);
 }
 
 #endif  /* EXIM_TIDYDB || EXIM_FIXDB */
@@ -548,17 +527,17 @@ uschar *yield;
 
 /* Some dbm require an initialization */
 
-if (start) EXIM_DBCREATE_CURSOR(dbblock->dbptr, cursor);
+if (start) *cursor = exim_dbcreate_cursor(dbblock->dbptr);
 
-EXIM_DATUM_INIT(key_datum);         /* Some DBM libraries require the datum */
-EXIM_DATUM_INIT(value_datum);       /* to be cleared before use. */
+exim_datum_init(&key_datum);         /* Some DBM libraries require the datum */
+exim_datum_init(&value_datum);       /* to be cleared before use. */
 
-yield = (EXIM_DBSCAN(dbblock->dbptr, key_datum, value_datum, start, *cursor))?
-  US EXIM_DATUM_DATA(key_datum) : NULL;
+yield = exim_dbscan(dbblock->dbptr, &key_datum, &value_datum, start, *cursor)
+  ? US exim_datum_data_get(&key_datum) : NULL;
 
 /* Some dbm require a termination */
 
-if (!yield) EXIM_DBDELETE_CURSOR(*cursor);
+if (!yield) exim_dbdelete_cursor(*cursor);
 return yield;
 }
 #endif  /* EXIM_DUMPDB || EXIM_TIDYDB */
@@ -582,11 +561,11 @@ uschar **argv = USS cargv;
 uschar keybuffer[1024];
 
 store_init();
-options(argc, argv, US"dumpdb");
+options(argc, argv, US"dumpdb", US"kz");
 
 /* Check the arguments, and open the database */
 
-dbdata_type = check_args(argc, argv, US"dumpdb", US" [-z]");
+dbdata_type = check_args(argc, argv, US"dumpdb", US" [-z] [-k]");
 argc -= optind; argv += optind;
 spool_directory = argv[0];
 
@@ -625,12 +604,13 @@ for (uschar * key = dbfn_scan(dbm, TRUE, &cursor);
     }
   Ustrcpy(keybuffer, key);
 
-  if (!(value = dbfn_read_with_length(dbm, keybuffer, &length)))
+  if (keyonly)
+    printf("  %s\n", keybuffer);
+  else if (!(value = dbfn_read_with_length(dbm, keybuffer, &length)))
     fprintf(stderr, "**** Entry \"%s\" was in the key scan, but the record "
                     "was not found in the file - something is wrong!\n",
       CS keybuffer);
   else
-    {
     /* Note: don't use print_time more than once in one statement, since
     it uses a single buffer. */
 
@@ -753,7 +733,6 @@ for (uschar * key = dbfn_scan(dbm, TRUE, &cursor);
        printf("%s\t%s\n", keybuffer, print_time(seen->time_stamp));
        break;
       }
-    }
   store_reset(reset_point);
   }
 
@@ -809,7 +788,7 @@ rmark reset_point;
 uschar * aname;
 
 store_init();
-options(argc, argv, US"fixdb");
+options(argc, argv, US"fixdb", US"z");
 name[0] = 0;  /* No name set */
 
 /* Sort out the database type, verify what we are working on and then process
@@ -1249,7 +1228,7 @@ for (key = dbfn_scan(dbm, TRUE, &cursor);
      key;
      key = dbfn_scan(dbm, FALSE, &cursor))
   {
-  key_item *k = store_get(sizeof(key_item) + Ustrlen(key), is_tainted(key));
+  key_item * k = store_get(sizeof(key_item) + Ustrlen(key), key);
   k->next = keychain;
   keychain = k;
   Ustrcpy(k->key, key);