]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-3.11-20250717
authorWietse Z Venema <wietse@porcupine.org>
Thu, 17 Jul 2025 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <ietf-dane@dukhovni.org>
Fri, 18 Jul 2025 06:34:39 +0000 (16:34 +1000)
16 files changed:
postfix/HISTORY
postfix/html/postscreen.8.html
postfix/html/proxymap.8.html
postfix/man/man8/postscreen.8
postfix/man/man8/proxymap.8
postfix/proto/stop.double-history
postfix/src/global/mail_version.h
postfix/src/postscreen/postscreen.c
postfix/src/posttls-finger/posttls-finger.c
postfix/src/proxymap/proxymap.c
postfix/src/util/dict.c
postfix/src/util/dict_db.c
postfix/src/util/dict_dbm.c
postfix/src/util/dict_lmdb.c
postfix/src/util/dict_sdbm.c
postfix/src/util/htable.c

index 15344f8b58a021a55bc4da179c7730c74d22b396..78a961cc7fef1785e6eb7a1d0e3aaa19eb47f2f8 100644 (file)
@@ -29400,3 +29400,44 @@ Apologies for any names omitted.
 
        Uploaded the wrong postfix-3.11-20250713 tarball. Files:
        master/event_server.c, master/multi_server.c.
+
+       Deleted an <openssl/engine.h> dependency, because the feature is
+       being removed from OpenSSL, and Postfix no longer needs it. File:
+       posttls-finger/posttls-finger.c.
+
+       Updated the proxymap(8) manpage and some internal documentation.
+       File: proxymap/proxymap.c.
+
+20250715
+
+       Cleanup: the proxymap 'open' service always returns the
+       dict->flags from a newly-initialized instance. This avoids
+       cross-talk between different clients. File: proxymap/proxymap.c.
+
+20250716
+
+       Bugfix (defect introduced: Postfix 2.7, date 20121223):
+       segfault in the internal: table iterator when the table
+       contained exactly one element. File: util/htable.c.
+
+       Technical debt: allow an element to be deleted before the
+       internal: table's first/next iterator has visited it. File:
+       util/htable.c.
+
+20250716
+
+       Bugfix (defect introduced: Postfix 2.8, date 20101230):
+       after detecting a cache table change and before starting a
+       new postscreen process, the old postscreen process did not
+       close the postscreen_cache_map, and therefore kept an
+       exclusive lock that could prevent a new postscreen process
+       from starting. Problem reported by Florian Piekert. File:
+       postscreen/postscreen.c.
+
+20250717
+
+       Workaround: Postfix daemons no longer automatically restart
+       after a btree:, dbm:, hash:, lmdb:, or sdbm: table file
+       modification time change, when they opened that table for
+       writing. Files: util/dict.c, util/dict_db.c, util/dict_dbm.c,
+       util/dict_lmdb.c, util/dict_sdbm.c.
index e2183ba6f93e7cff8007f858a0843d2f4c59f43c..52a4e206ceec4692ae2cf486413e021d86e68aa7 100644 (file)
@@ -222,7 +222,7 @@ POSTSCREEN(8)                                                    POSTSCREEN(8)
               text..." response, in an attempt to confuse bad SMTP clients  so
               that they speak before their turn (pre-greet).
 
-       <b><a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> (normal: 6s, overload: 2s)</b>
+       <b><a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> (normal: 6s, <a href="STRESS_README.html">overload</a>: 2s)</b>
               The  amount  of  time  that  <a href="postscreen.8.html"><b>postscreen</b>(8)</a> will wait for an SMTP
               client to send a command before its turn, and for DNS  blocklist
               lookup results to arrive (default: up to 2 seconds under stress,
@@ -359,7 +359,7 @@ POSTSCREEN(8)                                                    POSTSCREEN(8)
               The  limit  on the total number of commands per SMTP session for
               <a href="postscreen.8.html"><b>postscreen</b>(8)</a>'s built-in SMTP protocol engine.
 
-       <b><a href="postconf.5.html#postscreen_command_time_limit">postscreen_command_time_limit</a> (normal: 300s, overload: 10s)</b>
+       <b><a href="postconf.5.html#postscreen_command_time_limit">postscreen_command_time_limit</a> (normal: 300s, <a href="STRESS_README.html">overload</a>: 10s)</b>
               The  time  limit  to  read   an   entire   command   line   with
               <a href="postscreen.8.html"><b>postscreen</b>(8)</a>'s built-in SMTP protocol engine.
 
@@ -405,7 +405,7 @@ POSTSCREEN(8)                                                    POSTSCREEN(8)
 
        <b><a href="postconf.5.html#delay_logging_resolution_limit">delay_logging_resolution_limit</a> (2)</b>
               The maximal number of digits after the decimal point  when  log-
-              ging sub-second delay values.
+              ging delay values.
 
        <b><a href="postconf.5.html#command_directory">command_directory</a> (see 'postconf -d' output)</b>
               The location of all postfix administrative commands.
@@ -468,5 +468,8 @@ POSTSCREEN(8)                                                    POSTSCREEN(8)
        111 8th Avenue
        New York, NY 10011, USA
 
+       Wietse Venema
+       porcupine.org
+
                                                                  POSTSCREEN(8)
 </pre> </body> </html>
index b1967216ee90281147c441fa267fae9b89b624a1..e105425022ef348b726a014ac144f957ae1ff221 100644 (file)
@@ -45,51 +45,60 @@ PROXYMAP(8)                                                        PROXYMAP(8)
 
        The <a href="proxymap.8.html"><b>proxymap</b>(8)</a> server implements the following requests:
 
-       <b>open</b> <i>maptype:mapname flags</i>
-              Open the table with type <i>maptype</i> and name <i>mapname</i>, as controlled
-              by  <i>flags</i>.  The  reply  includes the <i>maptype</i> dependent flags (to
-              distinguish a fixed string table from a regular  expression  ta-
-              ble).
-
-       <b>lookup</b> <i>maptype:mapname flags key</i>
-              Look  up  the data stored under the requested key.  The reply is
-              the request completion status code and the lookup result  value.
-              The  <i>maptype:mapname</i>  and  <i>flags</i>  are  the same as with the <b>open</b>
+       <b>open</b> <i>maptype:mapname instance-flags</i>
+              Open the table with type <i>maptype</i> and name <i>mapname</i>, with  initial
+              dictionary  flags  <i>instance-flags</i>. The reply contains the actual
+              dictionary flags (for example, to distinguish a fixed-string ta-
+              ble from a regular-expression table).
+
+       <b>lookup</b> <i>maptype:mapname instance-flags request-flags key</i>
+              Look  up  the data stored under the requested key using the dic-
+              tionary flags in <i>request-flags</i>.  The reply contains the  request
+              completion  status code, the resulting dictionary flags, and the
+              lookup result value.  The <i>maptype:mapname</i> and <i>instance-flags</i> are
+              the same as with the <b>open</b> request.
+
+       <b>update</b> <i>maptype:mapname instance-flags request-flags key value</i>
+              Update the data stored under the requested key using the dictio-
+              nary flags in <i>request-flags</i>.  The  reply  contains  the  request
+              completion  status code and the resulting dictionary flags.  The
+              <i>maptype:mapname</i> and <i>instance-flags</i> are the same as with the <b>open</b>
               request.
 
-       <b>update</b> <i>maptype:mapname flags key value</i>
-              Update the data stored under the requested key.   The  reply  is
-              the  request  completion  status  code.  The <i>maptype:mapname</i> and
-              <i>flags</i> are the same as with the <b>open</b> request.
-
-              To implement single-updater maps, specify a process limit  of  1
+              To  implement  single-updater maps, specify a process limit of 1
               in the <a href="master.5.html">master.cf</a> file entry for the <b>proxywrite</b> service.
 
               This request is supported in Postfix 2.5 and later.
 
-       <b>delete</b> <i>maptype:mapname flags key</i>
-              Delete  the  data  stored under the requested key.  The reply is
-              the request completion status  code.   The  <i>maptype:mapname</i>  and
-              <i>flags</i> are the same as with the <b>open</b> request.
+       <b>delete</b> <i>maptype:mapname instance-flags request-flags key</i>
+              Delete the data stored under the requested key, using  the  dic-
+              tionary  flags in <i>request-flags</i>.  The reply contains the request
+              completion status code and the resulting dictionary flags.   The
+              <i>maptype:mapname</i> and <i>instance-flags</i> are the same as with the <b>open</b>
+              request.
 
               This request is supported in Postfix 2.5 and later.
 
-       <b>sequence</b> <i>maptype:mapname flags function</i>
-              Iterate  over  the  specified  database.  The <i>function</i> is one of
-              DICT_SEQ_FUN_FIRST  or  DICT_SEQ_FUN_NEXT.   The  reply  is  the
-              request  completion  status  code  and  a  lookup key and result
-              value, if found.
+       <b>sequence</b> <i>maptype:mapname instance-flags request-flags function</i>
+              Iterate over the specified database, using the dictionary  flags
+              in  <i>request-flags</i>.  The <i>function</i> is either DICT_SEQ_FUN_FIRST or
+              DICT_SEQ_FUN_NEXT.  The reply contains  the  request  completion
+              status  code,  the  resulting dictionary flags, and a lookup key
+              and  result   value   if   found.    The   <i>maptype:mapname</i>   and
+              <i>instance-flags</i> are the same as with the <b>open</b> request.
 
               This request is supported in Postfix 2.9 and later.
 
+       Not implemented: close
+              There is no <b>close</b> request, nor are tables implicitly closed when
+              a client disconnects. The purpose is to share tables among  mul-
+              tiple  client  processes.  Due  to the absence of an explicit or
+              implicit <b>close</b>, updates are forced to be synchronous.
+
        The request completion status is one of OK, RETRY, NOKEY (lookup failed
        because  the  key  was not found), BAD (malformed request) or DENY (the
        table is not approved for proxy read or update access).
 
-       There is no <b>close</b> command, nor are  tables  implicitly  closed  when  a
-       client  disconnects.  The  purpose  is  to  share tables among multiple
-       client processes.
-
 <b><a name="server_process_management">SERVER PROCESS MANAGEMENT</a></b>
        <a href="proxymap.8.html"><b>proxymap</b>(8)</a> servers run under control by the Postfix <a href="master.8.html"><b>master</b>(8)</a>  server.
        Each  server  can  handle  multiple simultaneous connections.  When all
@@ -219,5 +228,8 @@ PROXYMAP(8)                                                        PROXYMAP(8)
        111 8th Avenue
        New York, NY 10011, USA
 
+       Wietse Venema
+       porcupine.org
+
                                                                    PROXYMAP(8)
 </pre> </body> </html>
index 0231b0a24b345bb7494e382f954159763ac76552..07013ea98f65f8e329ee2a168527cc85e9245b4c 100644 (file)
@@ -410,7 +410,7 @@ The default location of the Postfix main.cf and master.cf
 configuration files.
 .IP "\fBdelay_logging_resolution_limit (2)\fR"
 The maximal number of digits after the decimal point when logging
-sub\-second delay values.
+delay values.
 .IP "\fBcommand_directory (see 'postconf -d' output)\fR"
 The location of all postfix administrative commands.
 .IP "\fBmax_idle (100s)\fR"
@@ -480,3 +480,6 @@ Wietse Venema
 Google, Inc.
 111 8th Avenue
 New York, NY 10011, USA
+
+Wietse Venema
+porcupine.org
index ff0d7592c4dae59ad389c7b9db736d305fc2f45c..beb841e23444c5fdb776d6dcce13ceb5ed71e63f 100644 (file)
@@ -46,21 +46,24 @@ that do not reliably support multiple writers (i.e. all
 file\-based tables that are not based on \fBlmdb\fR).
 .PP
 The \fBproxymap\fR(8) server implements the following requests:
-.IP "\fBopen\fR \fImaptype:mapname flags\fR"
+.IP "\fBopen\fR \fImaptype:mapname instance\-flags\fR"
 Open the table with type \fImaptype\fR and name \fImapname\fR,
-as controlled by \fIflags\fR. The reply includes the \fImaptype\fR
-dependent flags (to distinguish a fixed string table from a regular
-expression table).
-.IP "\fBlookup\fR \fImaptype:mapname flags key\fR"
-Look up the data stored under the requested key.
-The reply is the request completion status code and
-the lookup result value.
-The \fImaptype:mapname\fR and \fIflags\fR are the same
+with initial dictionary flags \fIinstance\-flags\fR. The reply
+contains the actual dictionary flags (for example, to distinguish
+a fixed\-string table from a regular\-expression table).
+.IP "\fBlookup\fR \fImaptype:mapname instance\-flags request\-flags key\fR"
+Look up the data stored under the requested key using the
+dictionary flags in \fIrequest\-flags\fR.
+The reply contains the request completion status code, the
+resulting dictionary flags, and the lookup result value.
+The \fImaptype:mapname\fR and \fIinstance\-flags\fR are the same
 as with the \fBopen\fR request.
-.IP "\fBupdate\fR \fImaptype:mapname flags key value\fR"
-Update the data stored under the requested key.
-The reply is the request completion status code.
-The \fImaptype:mapname\fR and \fIflags\fR are the same
+.IP "\fBupdate\fR \fImaptype:mapname instance\-flags request\-flags key value\fR"
+Update the data stored under the requested key using the
+dictionary flags in \fIrequest\-flags\fR.
+The reply contains the request completion status code and the
+resulting dictionary flags.
+The \fImaptype:mapname\fR and \fIinstance\-flags\fR are the same
 as with the \fBopen\fR request.
 .sp
 To implement single\-updater maps, specify a process limit
@@ -68,29 +71,36 @@ of 1 in the master.cf file entry for the \fBproxywrite\fR
 service.
 .sp
 This request is supported in Postfix 2.5 and later.
-.IP "\fBdelete\fR \fImaptype:mapname flags key\fR"
-Delete the data stored under the requested key.
-The reply is the request completion status code.
-The \fImaptype:mapname\fR and \fIflags\fR are the same
+.IP "\fBdelete\fR \fImaptype:mapname instance\-flags request\-flags key\fR"
+Delete the data stored under the requested key, using the
+dictionary flags in \fIrequest\-flags\fR.
+The reply contains the request completion status code and the
+resulting dictionary flags.
+The \fImaptype:mapname\fR and \fIinstance\-flags\fR are the same
 as with the \fBopen\fR request.
 .sp
 This request is supported in Postfix 2.5 and later.
-.IP "\fBsequence\fR \fImaptype:mapname flags function\fR"
-Iterate over the specified database. The \fIfunction\fR
-is one of DICT_SEQ_FUN_FIRST or DICT_SEQ_FUN_NEXT.
-The reply is the request completion status code and
-a lookup key and result value, if found.
+.IP "\fBsequence\fR \fImaptype:mapname instance\-flags request\-flags function\fR"
+Iterate over the specified database, using the dictionary flags
+in \fIrequest\-flags\fR. The \fIfunction\fR is either
+DICT_SEQ_FUN_FIRST or DICT_SEQ_FUN_NEXT.
+The reply contains the request completion status code, the
+resulting dictionary flags, and a lookup key and result value
+if found.
+The \fImaptype:mapname\fR and \fIinstance\-flags\fR are the same
+as with the \fBopen\fR request.
 .sp
 This request is supported in Postfix 2.9 and later.
+.IP "Not implemented: close"
+There is no \fBclose\fR request, nor are tables implicitly closed
+when a client disconnects. The purpose is to share tables among
+multiple client processes. Due to the absence of an explicit or
+implicit \fBclose\fR, updates are forced to be synchronous.
 .PP
 The request completion status is one of OK, RETRY, NOKEY
 (lookup failed because the key was not found), BAD (malformed
 request) or DENY (the table is not approved for proxy read
 or update access).
-
-There is no \fBclose\fR command, nor are tables implicitly closed
-when a client disconnects. The purpose is to share tables among
-multiple client processes.
 .SH "SERVER PROCESS MANAGEMENT"
 .na
 .nf
@@ -241,3 +251,6 @@ Wietse Venema
 Google, Inc.
 111 8th Avenue
 New York, NY 10011, USA
+
+Wietse Venema
+porcupine.org
index 6fb0842b727b9b9328bea5dfdd133a98b033da7a..96639d3845a30bb1ecf5740f085e60a3d1e3ffa8 100644 (file)
@@ -181,3 +181,5 @@ proto  proto COMPATIBILITY_README html
  proxymap proxymap c 
  postmap postmap c postalias postalias c 
  client Files dict h dict_proxy c proxymap proxymap c 
+ cross talk between different clients File proxymap proxymap c 
+ postscreen postscreen c 
index 8c6f9137adbd96b6faad3bdb508890163d29b130..67e8164b50bcf1e733e3458cdf3cc68c84c4674d 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      "20250714"
+#define MAIL_RELEASE_DATE      "20250717"
 #define MAIL_VERSION_NUMBER    "3.11"
 
 #ifdef SNAPSHOT
index ebb680c06805588f38c248eb9c8aa0840d178613..5f16459ae11e40b182f3bf58863ae78ac1dc6eba 100644 (file)
 /*     configuration files.
 /* .IP "\fBdelay_logging_resolution_limit (2)\fR"
 /*     The maximal number of digits after the decimal point when logging
-/*     sub-second delay values.
+/*     delay values.
 /* .IP "\fBcommand_directory (see 'postconf -d' output)\fR"
 /*     The location of all postfix administrative commands.
 /* .IP "\fBmax_idle (100s)\fR"
 /*     Google, Inc.
 /*     111 8th Avenue
 /*     New York, NY 10011, USA
+/*
+/*     Wietse Venema
+/*     porcupine.org
 /*--*/
 
 /* System library. */
@@ -996,7 +999,7 @@ static void pre_accept(char *unused_name, char **unused_argv)
     if (new_event_time >= last_event_time + 1
        && (name = dict_changed_name()) != 0) {
        msg_info("table %s has changed - finishing in the background", name);
-       event_server_drain();
+       psc_drain(unused_name, unused_argv);
     } else {
        last_event_time = new_event_time;
     }
index dc25a3e095230629b02bdd28abc71322e3f82509..baa5ca81b357fae62d8ab5c368214e8efd75ede4 100644 (file)
 
 #ifdef USE_TLS
 #include <tls_proxy.h>
-#include <openssl/engine.h>
 #endif
 
  /*
index 270e491a0ead1838323043c4224fd5c8bd3f83ce..4a2c6755a9d2a73b7ef04d3c1fda6c649e884743 100644 (file)
 /*     file-based tables that are not based on \fBlmdb\fR).
 /* .PP
 /*     The \fBproxymap\fR(8) server implements the following requests:
-/* .IP "\fBopen\fR \fImaptype:mapname flags\fR"
+/* .IP "\fBopen\fR \fImaptype:mapname instance-flags\fR"
 /*     Open the table with type \fImaptype\fR and name \fImapname\fR,
-/*     as controlled by \fIflags\fR. The reply includes the \fImaptype\fR
-/*     dependent flags (to distinguish a fixed string table from a regular
-/*     expression table).
-/* .IP "\fBlookup\fR \fImaptype:mapname flags key\fR"
-/*     Look up the data stored under the requested key.
-/*     The reply is the request completion status code and
-/*     the lookup result value.
-/*     The \fImaptype:mapname\fR and \fIflags\fR are the same
+/*     with initial dictionary flags \fIinstance-flags\fR. The reply
+/*     contains the actual dictionary flags (for example, to distinguish
+/*     a fixed-string table from a regular-expression table).
+/* .IP "\fBlookup\fR \fImaptype:mapname instance-flags request-flags key\fR"
+/*     Look up the data stored under the requested key using the
+/*     dictionary flags in \fIrequest-flags\fR.
+/*     The reply contains the request completion status code, the
+/*     resulting dictionary flags, and the lookup result value.
+/*     The \fImaptype:mapname\fR and \fIinstance-flags\fR are the same
 /*     as with the \fBopen\fR request.
-/* .IP "\fBupdate\fR \fImaptype:mapname flags key value\fR"
-/*     Update the data stored under the requested key.
-/*     The reply is the request completion status code.
-/*     The \fImaptype:mapname\fR and \fIflags\fR are the same
+/* .IP "\fBupdate\fR \fImaptype:mapname instance-flags request-flags key value\fR"
+/*     Update the data stored under the requested key using the
+/*     dictionary flags in \fIrequest-flags\fR.
+/*     The reply contains the request completion status code and the
+/*     resulting dictionary flags.
+/*     The \fImaptype:mapname\fR and \fIinstance-flags\fR are the same
 /*     as with the \fBopen\fR request.
 /* .sp
 /*     To implement single-updater maps, specify a process limit
 /*     service.
 /* .sp
 /*     This request is supported in Postfix 2.5 and later.
-/* .IP "\fBdelete\fR \fImaptype:mapname flags key\fR"
-/*     Delete the data stored under the requested key.
-/*     The reply is the request completion status code.
-/*     The \fImaptype:mapname\fR and \fIflags\fR are the same
+/* .IP "\fBdelete\fR \fImaptype:mapname instance-flags request-flags key\fR"
+/*     Delete the data stored under the requested key, using the
+/*     dictionary flags in \fIrequest-flags\fR.
+/*     The reply contains the request completion status code and the
+/*     resulting dictionary flags.
+/*     The \fImaptype:mapname\fR and \fIinstance-flags\fR are the same
 /*     as with the \fBopen\fR request.
 /* .sp
 /*     This request is supported in Postfix 2.5 and later.
-/* .IP "\fBsequence\fR \fImaptype:mapname flags function\fR"
-/*     Iterate over the specified database. The \fIfunction\fR
-/*     is one of DICT_SEQ_FUN_FIRST or DICT_SEQ_FUN_NEXT.
-/*     The reply is the request completion status code and
-/*     a lookup key and result value, if found.
+/* .IP "\fBsequence\fR \fImaptype:mapname instance-flags request-flags function\fR"
+/*     Iterate over the specified database, using the dictionary flags
+/*     in \fIrequest-flags\fR. The \fIfunction\fR is either
+/*     DICT_SEQ_FUN_FIRST or DICT_SEQ_FUN_NEXT.
+/*     The reply contains the request completion status code, the
+/*     resulting dictionary flags, and a lookup key and result value
+/*     if found.
+/*     The \fImaptype:mapname\fR and \fIinstance-flags\fR are the same
+/*     as with the \fBopen\fR request.
 /* .sp
 /*     This request is supported in Postfix 2.9 and later.
+/* .IP "Not implemented: close"
+/*     There is no \fBclose\fR request, nor are tables implicitly closed
+/*     when a client disconnects. The purpose is to share tables among
+/*     multiple client processes. Due to the absence of an explicit or
+/*     implicit \fBclose\fR, updates are forced to be synchronous.
 /* .PP
 /*     The request completion status is one of OK, RETRY, NOKEY
 /*     (lookup failed because the key was not found), BAD (malformed
 /*     request) or DENY (the table is not approved for proxy read
 /*     or update access).
-/*
-/*     There is no \fBclose\fR command, nor are tables implicitly closed
-/*     when a client disconnects. The purpose is to share tables among
-/*     multiple client processes.
 /* SERVER PROCESS MANAGEMENT
 /* .ad
 /* .fi
 /*     Google, Inc.
 /*     111 8th Avenue
 /*     New York, NY 10011, USA
+/*
+/*     Wietse Venema
+/*     porcupine.org
 /*--*/
 
 /* System library. */
@@ -323,6 +336,8 @@ static char *get_nested_dict_name(char *type_name)
 static DICT *proxy_map_find(const char *map_type_name, int inst_flags,
                                    int *statp)
 {
+    static HTABLE *new_flags;
+    HTABLE_INFO *ht;
     DICT   *dict;
 
 #define PROXY_COLON    DICT_TYPE_PROXY ":"
@@ -360,6 +375,20 @@ static DICT *proxy_map_find(const char *map_type_name, int inst_flags,
                     inst_flags);
     if (dict == 0)
        msg_panic("proxy_map_find: dict_open null result");
+
+    /*
+     * Remember the mapping from dict->reg_name to the dict->flags of a
+     * newly-initialized instance. Always return an instance with those new
+     * dict->flags, to avoid crosstalk between different clients.
+     */
+    if (new_flags == 0)
+       new_flags = htable_create(100);
+    if ((ht = htable_locate(new_flags, dict->reg_name)) == 0) {
+       (void) htable_enter(new_flags, dict->reg_name,
+                           CAST_INT_TO_VOID_PTR(dict->flags));
+    } else {
+       dict->flags = CAST_ANY_PTR_TO_INT(ht->value);
+    }
     dict->error = 0;
     return (dict);
 }
index 943772325656dd9ed3264e65bcfa4797272e6d8a..8189b5e898f038098362d62e0517ff44a922c11a 100644 (file)
 /* .IP "char *context"
 /*     Application context from the caller.
 /* .PP
-/*     dict_changed_name() returns non-zero when any dictionary needs to
-/*     be re-opened because it has changed or because it was unlinked.
+/*     dict_changed_name() returns non-zero when any dictionary is
+/*     opened read-only and has changed, or because it was unlinked.
 /*     A non-zero result is the name of a changed dictionary.
 /*
 /*     dict_load_file_xt() reads name-value entries from the named file.
@@ -641,11 +641,12 @@ const char *dict_changed_name(void)
        dict = ((DICT_NODE *) h->value)->dict;
        if (dict->stat_fd < 0)                  /* not file-based */
            continue;
-       if (dict->mtime == 0)                   /* not bloody likely */
-           msg_warn("%s: table %s: null time stamp", myname, h->key);
+       if (dict->mtime < 0)                    /* not bloody likely */
+           msg_warn("%s: table %s: negative time stamp", myname, h->key);
        if (fstat(dict->stat_fd, &st) < 0)
            msg_fatal("%s: fstat: %m", myname);
        if (((dict->flags & DICT_FLAG_MULTI_WRITER) == 0
+            && dict->mtime > 0
             && st.st_mtime != dict->mtime)
            || st.st_nlink == 0)
            status = h->key;
index 7ac03464108ead692cf29d1efb4df11e6cdd4af0..b1ce8327fa1fe097a8c6c13aad15471e6e1753c2 100644 (file)
@@ -789,7 +789,8 @@ static DICT *dict_db_open(const char *class, const char *path, int open_flags,
     dict_db->dict.stat_fd = dbfd;
     if (fstat(dict_db->dict.stat_fd, &st) < 0)
        msg_fatal("dict_db_open: fstat: %m");
-    dict_db->dict.mtime = st.st_mtime;
+    if (open_flags == O_RDONLY)
+       dict_db->dict.mtime = st.st_mtime;
     dict_db->dict.owner.uid = st.st_uid;
     dict_db->dict.owner.status = (st.st_uid != 0);
 
index 0b81134d7641b127810ae9003f966972a51189bb..9263c78cc5e2f3b855695afa419b1c24b325b70c 100644 (file)
@@ -472,7 +472,8 @@ DICT   *dict_dbm_open(const char *path, int open_flags, int dict_flags)
        msg_fatal("open database %s: cannot support GDBM", path);
     if (fstat(dict_dbm->dict.stat_fd, &st) < 0)
        msg_fatal("dict_dbm_open: fstat: %m");
-    dict_dbm->dict.mtime = st.st_mtime;
+    if (open_mode == O_RDONLY)
+       dict_dbm->dict.mtime = st.st_mtime;
     dict_dbm->dict.owner.uid = st.st_uid;
     dict_dbm->dict.owner.status = (st.st_uid != 0);
 
index 88e4a03bf49ca321161fb0461398ecfd25129d4f..9bf3c50eadc7ebbe2ecec02450d2a5df1cc22208 100644 (file)
@@ -653,7 +653,8 @@ DICT   *dict_lmdb_open(const char *path, int open_flags, int dict_flags)
        msg_fatal("dict_lmdb_open: fstat: %m");
     dict_lmdb->dict.lock_fd = dict_lmdb->dict.stat_fd = db_fd;
     dict_lmdb->dict.lock_type = MYFLOCK_STYLE_FCNTL;
-    dict_lmdb->dict.mtime = st.st_mtime;
+    if (open_flags == O_RDONLY)
+       dict_lmdb->dict.mtime = st.st_mtime;
     dict_lmdb->dict.owner.uid = st.st_uid;
     dict_lmdb->dict.owner.status = (st.st_uid != 0);
 
index f6644138ee2f535bbae950a7ab357bb8c8bccca1..33ce6aae8a898daedb35488eec29137d9d584e9c 100644 (file)
@@ -449,7 +449,8 @@ DICT   *dict_sdbm_open(const char *path, int open_flags, int dict_flags)
     dict_sdbm->dict.stat_fd = sdbm_pagfno(dbm);
     if (fstat(dict_sdbm->dict.stat_fd, &st) < 0)
        msg_fatal("dict_sdbm_open: fstat: %m");
-    dict_sdbm->dict.mtime = st.st_mtime;
+    if (open_flags == O_RDONLY)
+       dict_sdbm->dict.mtime = st.st_mtime;
     dict_sdbm->dict.owner.uid = st.st_uid;
     dict_sdbm->dict.owner.status = (st.st_uid != 0);
 
index 5d659aa18191236ea61e6da66649ad6ad233e174..f069b7cdef8ae0fc68317be9f0539897f50b73b0 100644 (file)
@@ -93,8 +93,7 @@
 /*     htable_sequence() returns the first or next element depending
 /*     on the value of the "how" argument.  Specify HTABLE_SEQ_FIRST
 /*     to start a new sequence, HTABLE_SEQ_NEXT to continue, and
-/*     HTABLE_SEQ_STOP to terminate a sequence early.  The caller
-/*     must not delete an element before it is visited.
+/*     HTABLE_SEQ_STOP to terminate a sequence early.
 /* RESTRICTIONS
 /*     A callback function should not modify the hash table that is
 /*     specified to its caller.
@@ -272,7 +271,7 @@ HTABLE_INFO *htable_locate(HTABLE *table, const char *key)
 void    htable_delete(HTABLE *table, const char *key, void (*free_fn) (void *))
 {
     if (table) {
-       HTABLE_INFO *ht;
+       HTABLE_INFO *ht, **sp;
        HTABLE_INFO **h = table->data + htable_hash(key, table->size);
 
 #define        STREQ(x,y) (x == y || (x[0] == y[0] && strcmp(x,y) == 0))
@@ -290,6 +289,14 @@ void    htable_delete(HTABLE *table, const char *key, void (*free_fn) (void *))
                if (free_fn && ht->value)
                    (*free_fn) (ht->value);
                myfree((void *) ht);
+               /* In case the first/next iterator has not yet visited it */
+               for (sp = table->seq_element; sp && *sp; sp++) {
+                   if (*sp == ht) {
+                       while ((*sp = sp[1]) != 0)
+                           sp += 1;
+                       break;
+                   }
+               }
                return;
            }
        }
@@ -374,7 +381,7 @@ HTABLE_INFO *htable_sequence(HTABLE *table, int how)
            myfree((void *) table->seq_bucket);
        table->seq_bucket = htable_list(table);
        table->seq_element = table->seq_bucket;
-       return (*(table->seq_element)++);
+       /* FALLTHROUGH */
     case HTABLE_SEQ_NEXT:                      /* next element */
        if (table->seq_element && *table->seq_element)
            return (*(table->seq_element)++);