]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-3.10-20250109
authorWietse Z Venema <wietse@porcupine.org>
Thu, 9 Jan 2025 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <ietf-dane@dukhovni.org>
Fri, 24 Jan 2025 16:51:57 +0000 (03:51 +1100)
16 files changed:
postfix/HISTORY
postfix/README_FILES/CDB_README
postfix/WISHLIST
postfix/conf/post-install
postfix/conf/postfix-script
postfix/conf/postfix-wrapper
postfix/html/CDB_README.html
postfix/html/postfix-wrapper.5.html
postfix/man/man5/postfix-wrapper.5
postfix/proto/CDB_README.html
postfix/proto/postfix-wrapper
postfix/proto/stop
postfix/proto/stop.spell-cc
postfix/src/global/mail_version.h
postfix/src/postmap/Makefile.in
postfix/src/util/dict_cdb.c

index c57b542c8a26bb1f3563377fb87c7caf93ed6719..a9fea117b4acd32d8246a1ace0696aadd0314f50 100644 (file)
@@ -28780,3 +28780,18 @@ Apologies for any names omitted.
 
        Cleanup: the netstring client sets or clears errno to improve
        error messages from its callers. File: util/netstring.c.
+
+20250109
+
+       Bugfix (defect introduced: Postfix 2.6): fixed the parsing
+       of multiple commas in a multi_instance_directories parameter
+       value. Michael Tokarev. Files: conf/postfix-script,
+       conf/post-install, conf/postfix-wrapper, proto/postfix-wrapper.
+
+       Cleanup: replace static result buffer with per-instance buffer.
+       Michael Tokarev. File: util/dict_cdb.c.
+
+       Feature: first/next iterator support for cdb: tables, if
+       built with tinycdb. Michael Tokarev. Wietse added a test
+       and documentation. Files: util/dict_cdb.c proto/CDB_README.html,
+       postmap/Makefile.in.
index 0dbb5cbe2789cb09bdc7d3b47fc894c7415d65bb..6ccf26807c6bb48cbb5f3c7a9261703a7dc1621d 100644 (file)
@@ -17,8 +17,25 @@ temporarily while a CDB file is under construction). CDB databases are
 maintained with the postmap(1) or postalias(1) command. The DATABASE_README
 document has general information about Postfix databases.
 
-CDB support is available with Postfix 2.2 and later releases. This document
-describes how to build Postfix with CDB support.
+You can use "cdb:" tables wherever you can use read-only "hash", "btree" or
+"lmdb" tables with the following limitations:
+
+  * CDB databases cannot be larger than 4GB on LP64 and ILP32 systems, because
+    the CDB library API uses unsigned integers for file offsets.
+
+  * The "p\bpo\bos\bst\btm\bma\bap\bp -\b-i\bi" (incremental record insertion) and "p\bpo\bos\bst\btm\bma\bap\bp -\b-d\bd"
+    (incremental record deletion) command-line options are not available. For
+    the same reason the "cdb:" map type cannot be used to for persistent
+    caches, such as the address verification cache for the verify(8) service,
+    the TLS session cache for the tlsmgr(8) service, or the dynamic allowlist
+    for postscreen(8).
+
+  * The "sequence" operation ("p\bpo\bos\bst\btm\bma\bap\bp -\b-s\bs" or "p\bpo\bos\bst\bta\bal\bli\bia\bas\bs -\b-s\bs") is available only
+    wen Postfix is built with tinycdb by Michael Tokarev, not with the original
+    cdb library by Daniel Bernstein.
+
+CDB support is available with Postfix 2.2 and later releases. The remainder of
+this document describes how to build Postfix with CDB support.
 
 B\bBu\bui\bil\bld\bdi\bin\bng\bg P\bPo\bos\bst\btf\bfi\bix\bx w\bwi\bit\bth\bh C\bCD\bDB\bB s\bsu\bup\bpp\bpo\bor\brt\bt
 
@@ -64,11 +81,3 @@ building a dynamically-loaded or statically-loaded CDB database client.
     database library dependencies. And that was exactly what dynamic database
     client loading was meant to avoid.
 
-After Postfix has been built with cdb support, you can use "cdb" tables
-wherever you can use read-only "hash", "btree" or "dbm" tables. However, the
-"p\bpo\bos\bst\btm\bma\bap\bp -\b-i\bi" (incremental record insertion) and "p\bpo\bos\bst\btm\bma\bap\bp -\b-d\bd" (incremental
-record deletion) command-line options are not available. For the same reason
-the "cdb" map type cannot be used to store the persistent address verification
-cache for the verify(8) service, or to store TLS session information for the
-tlsmgr(8) service.
-
index 64e2ad51fc3802d32ada62c5570a4060a8fcfe62..50f56fd10f56f0b5fb7afec7e65f89c9df4a94ed 100644 (file)
@@ -19,6 +19,9 @@ Wish list:
        relay_recipient_maps empty should default to 'no valid
        recipients'. Subject to compatibility level.
 
+       Replace static result buffers with per-instance buffers in
+       dict_unix.c, dict_ni*c.
+
        The Milter 'quarantine' action should be reported with a
        call-back function, instead of setting the Milter default
        reply. However, we still need the existing 'reply' based
index cceef6770620f0b745fb26268d55bae75b7cfcc4..cd5f146785ec9d2093e309eb54aea63fedd7af4e 100644 (file)
@@ -296,7 +296,7 @@ test -d "$config_directory" || {
 
 instances=`test ! -f $def_config_directory/main.cf || 
     $POSTCONF -qc $def_config_directory -h multi_instance_directories | 
-       sed 's/,/ /'` || exit 1
+       sed 'y/,/ /'` || exit 1
 
 update_shared_files=1
 for name in $instances
index c43d764fb9d07c1ef7ef565970c079b7a7792683..de86d382b23eec9ffed77b94249013222e8daa92 100755 (executable)
@@ -97,7 +97,7 @@ def_config_directory=`$command_directory/postconf -dh config_directory` || {
 
 instances=`test ! -f $def_config_directory/main.cf ||
     $command_directory/postconf -qc $def_config_directory \
-    -h multi_instance_directories | sed 's/,/ /'` || {
+    -h multi_instance_directories | sed 'y/,/ /'` || {
        $FATAL cannot execute $command_directory/postconf!
        exit 1
 }
index dd0a517627fa24d1e260a81a3defd4a0d5909375..cb9dc10d8b44a58a95625e45a29f2f17484b8d6b 100644 (file)
@@ -188,7 +188,7 @@ POSTFIX=$command_directory/postfix
 # Canonicalize the instance directory list. The list is specified
 # in startup order.
 
-instance_dirs=`$POSTCONF -h multi_instance_directories | sed 's/,/ /'` ||
+instance_dirs=`$POSTCONF -h multi_instance_directories | sed 'y/,/ /'` ||
     exit 1
 
 case "$1" in
index e58ccc8188b47a9eaec8d65c459c1e71755133bf..e6952eed59a2bb0c74716b1931622ec82e58bc50 100644 (file)
@@ -35,8 +35,33 @@ under construction).  CDB databases are maintained with the <a href="postmap.1.h
 or <a href="postalias.1.html">postalias(1)</a> command. The <a href="DATABASE_README.html">DATABASE_README</a> document has general
 information about Postfix databases.  </p>
 
+<p> You can use "<a href="CDB_README.html">cdb</a>:" tables wherever you can use read-only "hash",
+"btree" or "lmdb" tables with the following limitations: </p>
+
+<ul>
+
+<li> <p> CDB databases cannot be larger than 4GB on LP64 and ILP32
+systems, because the CDB library API uses unsigned integers for
+file offsets.  </p>
+
+<li> <p> The "<b>postmap -i</b>" (incremental record insertion) and
+"<b>postmap -d</b>" (incremental record deletion) command-line
+options are not available. For the same reason the "<a href="CDB_README.html">cdb</a>:" map type
+cannot be used to for persistent caches, such as the address
+verification cache for the <a href="verify.8.html">verify(8)</a> service, the TLS session cache
+for the <a href="tlsmgr.8.html">tlsmgr(8)</a> service, or the dynamic allowlist for <a href="postscreen.8.html">postscreen(8)</a>.
+</p>
+
+<li> <p> The "sequence" operation ("<b>postmap -s</b>" or "<b>postalias
+-s</b>") is available only wen Postfix is built with tinycdb by
+Michael Tokarev, not with the original cdb library by Daniel Bernstein.
+</p>
+
+</ul>
+
 <p> CDB support is available with Postfix 2.2 and later releases.
-This document describes how to build Postfix with CDB support. </p>
+The remainder of this document describes how to build Postfix with
+CDB support. </p>
 
 <h2>Building Postfix with CDB support</h2>
 
@@ -99,12 +124,3 @@ will have CDB database library dependencies. And that was exactly
 what dynamic database client loading was meant to avoid. </p>
 
 </blockquote>
-
-<p> After Postfix has been built with cdb support, you can use
-"cdb" tables wherever you can use read-only "hash", "btree" or
-"dbm" tables. However, the "<b>postmap -i</b>" (incremental record
-insertion) and "<b>postmap -d</b>" (incremental record deletion)
-command-line options are not available. For the same reason the
-"cdb" map type cannot be used to store the persistent address
-verification cache for the <a href="verify.8.html">verify(8)</a> service, or to store
-TLS session information for the <a href="tlsmgr.8.html">tlsmgr(8)</a> service. </p>
index 88884eece7974ae021e3a39c644cd37c58e6171f..845e23126183e1d4b6f98aa4890e0e6b19bec484 100644 (file)
@@ -106,7 +106,7 @@ POSTFIX-WRAPPER(5)                                          POSTFIX-WRAPPER(5)
               POSTCONF=$<a href="postconf.5.html#command_directory">command_directory</a>/postconf
               POSTFIX=$<a href="postconf.5.html#command_directory">command_directory</a>/postfix
               instance_dirs=`$POSTCONF -h <a href="postconf.5.html#multi_instance_directories">multi_instance_directories</a> |
-                              sed 's/,/ /'` || exit 1
+                              sed 'y/,/ /'` || exit 1
 
               err=0
               for dir in $<a href="postconf.5.html#config_directory">config_directory</a> $instance_dirs
index 3f4ee9cd09e38b71a2b652f11f73c00145e97b11..d6e66910c45f7999f9f17591378701b4157a4a59 100644 (file)
@@ -123,7 +123,7 @@ manager implementation:
 POSTCONF=$command_directory/postconf
 POSTFIX=$command_directory/postfix
 instance_dirs=\`$POSTCONF \-h multi_instance_directories |
-                sed 's/,/ /'\` || exit 1
+                sed 'y/,/ /'\` || exit 1
 
 err=0
 for dir in $config_directory $instance_dirs
index 0654551d38e7d69d26ae96e18160884aa07428c7..cb25a8a7486b7438a0c4ed7b205c5bb331531cea 100644 (file)
@@ -35,8 +35,33 @@ under construction).  CDB databases are maintained with the postmap(1)
 or postalias(1) command. The DATABASE_README document has general
 information about Postfix databases.  </p>
 
+<p> You can use "cdb:" tables wherever you can use read-only "hash",
+"btree" or "lmdb" tables with the following limitations: </p>
+
+<ul>
+
+<li> <p> CDB databases cannot be larger than 4GB on LP64 and ILP32
+systems, because the CDB library API uses unsigned integers for
+file offsets.  </p>
+
+<li> <p> The "<b>postmap -i</b>" (incremental record insertion) and
+"<b>postmap -d</b>" (incremental record deletion) command-line
+options are not available. For the same reason the "cdb:" map type
+cannot be used to for persistent caches, such as the address
+verification cache for the verify(8) service, the TLS session cache
+for the tlsmgr(8) service, or the dynamic allowlist for postscreen(8).
+</p>
+
+<li> <p> The "sequence" operation ("<b>postmap -s</b>" or "<b>postalias
+-s</b>") is available only wen Postfix is built with tinycdb by
+Michael Tokarev, not with the original cdb library by Daniel Bernstein.
+</p>
+
+</ul>
+
 <p> CDB support is available with Postfix 2.2 and later releases.
-This document describes how to build Postfix with CDB support. </p>
+The remainder of this document describes how to build Postfix with
+CDB support. </p>
 
 <h2>Building Postfix with CDB support</h2>
 
@@ -99,12 +124,3 @@ will have CDB database library dependencies. And that was exactly
 what dynamic database client loading was meant to avoid. </p>
 
 </blockquote>
-
-<p> After Postfix has been built with cdb support, you can use
-"cdb" tables wherever you can use read-only "hash", "btree" or
-"dbm" tables. However, the "<b>postmap -i</b>" (incremental record
-insertion) and "<b>postmap -d</b>" (incremental record deletion)
-command-line options are not available. For the same reason the
-"cdb" map type cannot be used to store the persistent address
-verification cache for the verify(8) service, or to store
-TLS session information for the tlsmgr(8) service. </p>
index 177282ef7676f20f4d4b3e1a5e6ca4dbd3f9c047..aaf6a53c62981d18abb69656c60c3e634a6a3424 100644 (file)
 #      POSTCONF=$command_directory/postconf
 #      POSTFIX=$command_directory/postfix
 #      instance_dirs=\`$POSTCONF -h multi_instance_directories |
-#                      sed 's/,/ /'\` || exit 1
+#                      sed 'y/,/ /'\` || exit 1
 #
 #      err=0
 #      for dir in $config_directory $instance_dirs
index 22af8cf39ac042dd8ab78a639d56952af8817466..99dfe31991fac11c62ba217ab9cfcc18199dbd77 100644 (file)
@@ -1659,3 +1659,4 @@ GECOS
 iso
 ORCPT
 RET
+ILP
index 97b6705467d474f1bd01e6606bb4b02ce538bac8..4295afb1e6a6e94fe9312fc20b701208e19a0a3e 100644 (file)
@@ -1854,3 +1854,5 @@ Charset
 atext
 qp
 cntrl
+TINYCDB
+getdata
index dbd0f0afd86523f99e6f8bf777218002188ad502..08d6ed2647bec8bfde45a784ae1dac4d8e45ba19 100644 (file)
@@ -20,7 +20,7 @@
   * Patches change both the patchlevel and the release date. Snapshots have no
   * patchlevel; they change the release date only.
   */
-#define MAIL_RELEASE_DATE      "20250107"
+#define MAIL_RELEASE_DATE      "20250109"
 #define MAIL_VERSION_NUMBER    "3.10"
 
 #ifdef SNAPSHOT
index 9175767e7f2f81629c4cbb976ae7c01224011cf1..4f114f50417116a9ced9f0dd3e77e9ab2d4bc4a2 100644 (file)
@@ -27,7 +27,7 @@ update: ../../bin/$(PROG)
        cp $(PROG) ../../bin
 
 tests: test1 test2 fail_test quote_test file_test lmdb_abb_test \
-       lmdb_bulk_test lmdb_incr_test
+       lmdb_bulk_test lmdb_incr_test cdb_bulk_test
 
 root_tests:
 
@@ -74,6 +74,17 @@ file_test: $(PROG) file_test.in file_test.ref
        diff file_test.ref file_test.tmp
        rm -f file_test.tmp file_test_map.* postmap-file-1 postmap-file-2
 
+cdb_bulk_test: $(PROG)
+       rm -f cdb_bulk.cdb main.cf
+       tr A-Z a-z < /usr/share/dict/words| \
+           sed -e 's/.*/&      &/' -e 10000q| LANG=C sort -u >cdb_bulk
+       touch -t 197101010000 main.cf
+       ($(SHLIB_ENV) $(VALGRIND) ./postmap -c . cdb:cdb_bulk; \
+       $(SHLIB_ENV) $(VALGRIND) ./postmap -s cdb:cdb_bulk | \
+           LANG=C sort > cdb_bulk.tmp)
+       cmp cdb_bulk cdb_bulk.tmp
+       rm -f cdb_bulk cdb_bulk.tmp cdb_bulk.cdb main.cf
+
 lmdb_abb_test: $(PROG) lmdb_abb lmdb_abb.ref
        rm -f lmdb_abb.lmdb
        ($(SHLIB_ENV) $(VALGRIND) ./postmap lmdb:lmdb_abb; \
@@ -86,6 +97,7 @@ lmdb_bulk_test: $(PROG)
        tr A-Z a-z < /usr/share/dict/words| \
            sed -e 's/.*/&      &/' -e 10000q| LANG=C sort -u >lmdb_retry
        echo lmdb_map_size=10240 >main.cf
+       touch -t 197101010000 main.cf
        ($(SHLIB_ENV) $(VALGRIND) ./postmap -c . lmdb:lmdb_retry; \
        $(SHLIB_ENV) $(VALGRIND) ./postmap -s lmdb:lmdb_retry | \
            LANG=C sort > lmdb_retry.tmp)
@@ -97,6 +109,7 @@ lmdb_incr_test: $(PROG)
        tr A-Z a-z < /usr/share/dict/words| \
            sed -e 's/.*/&      &/' -e 1000q| LANG=C sort -u >lmdb_retry
        echo lmdb_map_size=10240 >main.cf
+       touch -t 197101010000 main.cf
        ($(SHLIB_ENV) $(VALGRIND) ./postmap -ic . lmdb:lmdb_retry <lmdb_retry; \
        $(SHLIB_ENV) $(VALGRIND) ./postmap -s lmdb:lmdb_retry | \
            LANG=C sort > lmdb_retry.tmp)
index a9133cc3555f9361cbfa224d082fb19ffb2c91eb..ea98363ff100a0393f1acef2c6bacd9ead616430 100644 (file)
 typedef struct {
     DICT    dict;                      /* generic members */
     struct cdb cdb;                    /* cdb structure */
+    VSTRING *val_buf;                  /* value result */
+#ifdef TINYCDB_VERSION
+    VSTRING *key_buf;                  /* key result */
+    unsigned seq_cptr;                 /* current sequence pointer */
+#endif
 } DICT_CDBQ;                           /* query interface */
 
 typedef struct {
@@ -93,15 +98,31 @@ typedef struct {
     char   *tmp_path;                  /* temporary pathname (.tmp) */
 } DICT_CDBM;                           /* rebuild interface */
 
+/* dict_cdbq_getdata - get data out of the cdb using given buffer */
+
+static const char *dict_cdbq_get_data(DICT_CDBQ *dict_cdbq,
+                                VSTRING **bufp, unsigned len, unsigned pos)
+{
+    VSTRING *buf = *bufp;
+
+    if (!buf)
+       buf = *bufp = vstring_alloc(len < 20 ? 20 : len);
+    VSTRING_RESET(buf);
+    VSTRING_SPACE(buf, len);
+
+    if (cdb_read(&dict_cdbq->cdb, vstring_str(buf), len, pos) < 0)
+       msg_fatal("error reading %s: %m", dict_cdbq->dict.name);
+    vstring_set_payload_size(buf, len);
+    VSTRING_TERMINATE(buf);
+    return vstring_str(buf);
+}
+
 /* dict_cdbq_lookup - find database entry, query mode */
 
 static const char *dict_cdbq_lookup(DICT *dict, const char *name)
 {
     DICT_CDBQ *dict_cdbq = (DICT_CDBQ *) dict;
-    unsigned vlen;
     int     status = 0;
-    static char *buf;
-    static unsigned len;
     const char *result = 0;
 
     dict->error = 0;
@@ -141,25 +162,56 @@ static const char *dict_cdbq_lookup(DICT *dict, const char *name)
        msg_fatal("error reading %s: %m", dict->name);
 
     if (status) {
-       vlen = cdb_datalen(&dict_cdbq->cdb);
-       if (len < vlen) {
-           if (buf == 0)
-               buf = mymalloc(vlen + 1);
-           else
-               buf = myrealloc(buf, vlen + 1);
-           len = vlen;
-       }
-       if (cdb_read(&dict_cdbq->cdb, buf, vlen,
-                    cdb_datapos(&dict_cdbq->cdb)) < 0)
-           msg_fatal("error reading %s: %m", dict->name);
-       buf[vlen] = '\0';
-       result = buf;
+       result = dict_cdbq_get_data(dict_cdbq, &dict_cdbq->val_buf,
+               cdb_datalen(&dict_cdbq->cdb), cdb_datapos(&dict_cdbq->cdb));
     }
     /* No locking so not release the lock.  */
 
     return (result);
 }
 
+#ifdef TINYCDB_VERSION
+
+/* dict_cdbq_sequence - traverse the dictionary */
+
+static int dict_cdbq_sequence(DICT *dict, int function,
+                                     const char **key, const char **value)
+{
+    const char *myname = "dict_cdbq_sequence";
+    DICT_CDBQ *dict_cdbq = (DICT_CDBQ *) dict;
+    int     status;
+
+    switch (function) {
+    case DICT_SEQ_FUN_FIRST:
+       cdb_seqinit(&dict_cdbq->seq_cptr, &dict_cdbq->cdb);
+       break;
+    case DICT_SEQ_FUN_NEXT:
+       if (!dict_cdbq->seq_cptr)
+           msg_panic("%s: %s: no cursor", myname, dict_cdbq->dict.name);
+       break;
+    default:
+       msg_panic("%s: invalid function %d", myname, function);
+    }
+
+    status = cdb_seqnext(&dict_cdbq->seq_cptr, &dict_cdbq->cdb);
+
+    if (status < 0)
+       msg_fatal("error seeking %s: %m", dict_cdbq->dict.name);
+
+    if (!status) {
+       dict_cdbq->seq_cptr = 0;
+       return -1;                              /* not found */
+    }
+    *key = dict_cdbq_get_data(dict_cdbq, &dict_cdbq->key_buf,
+                 cdb_keylen(&dict_cdbq->cdb), cdb_keypos(&dict_cdbq->cdb));
+    *value = dict_cdbq_get_data(dict_cdbq, &dict_cdbq->val_buf,
+               cdb_datalen(&dict_cdbq->cdb), cdb_datapos(&dict_cdbq->cdb));
+
+    return 0;
+}
+
+#endif                                 /* TINYCDB_VERSION */
+
 /* dict_cdbq_close - close data base, query mode */
 
 static void dict_cdbq_close(DICT *dict)
@@ -170,6 +222,12 @@ static void dict_cdbq_close(DICT *dict)
     close(dict->stat_fd);
     if (dict->fold_buf)
        vstring_free(dict->fold_buf);
+    if (dict_cdbq->val_buf)
+       vstring_free(dict_cdbq->val_buf);
+#ifdef TINYCDB_VERSION
+    if (dict_cdbq->key_buf)
+       vstring_free(dict_cdbq->key_buf);
+#endif
     dict_free(dict);
 }
 
@@ -200,9 +258,13 @@ static DICT *dict_cdbq_open(const char *path, int dict_flags)
 
     dict_cdbq = (DICT_CDBQ *) dict_alloc(DICT_TYPE_CDB,
                                         cdb_path, sizeof(*dict_cdbq));
+    dict_cdbq->val_buf = 0;
 #if defined(TINYCDB_VERSION)
+    dict_cdbq->key_buf = 0;
+    dict_cdbq->seq_cptr = 0;
     if (cdb_init(&(dict_cdbq->cdb), fd) != 0)
        msg_fatal("dict_cdbq_open: unable to init %s: %m", cdb_path);
+    dict_cdbq->dict.sequence = dict_cdbq_sequence;
 #else
     cdb_init(&(dict_cdbq->cdb), fd);
 #endif