diff --git a/postfix/.indent.pro b/postfix/.indent.pro index c5594a1c5..3da9d6444 100644 --- a/postfix/.indent.pro +++ b/postfix/.indent.pro @@ -93,6 +93,8 @@ -TMIME_STATE -TMIME_TOKEN -TMKMAP +-TMKMAP_DB +-TMKMAP_DBM -TMKMAP_OPEN_INFO -TMULTI_SERVER -TMVECT diff --git a/postfix/HISTORY b/postfix/HISTORY index 6f4b7c3eb..f4c4660a4 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -7145,6 +7145,10 @@ Apologies for any names omitted. records for finished recipients. Files: *qmgr/qmgr_message.c, cleanup/cleanup_envelope.c, cleanup/cleanup_extracted.c. + Cleanup: further simplified the mkmap wrapper (used by + postmap and postalias only) to remove some hurdles for + Michael Tokarev's CDB support. Files: global/mkmap*.[hc]. + Open problems: Low: revise other local delivery agent duplicate filters. diff --git a/postfix/README_FILES/VIRTUAL_README b/postfix/README_FILES/VIRTUAL_README index 2f8439dd7..e783d12f6 100644 --- a/postfix/README_FILES/VIRTUAL_README +++ b/postfix/README_FILES/VIRTUAL_README @@ -135,7 +135,7 @@ virtual_mailbox_lock requires that the recipient UID or GID has write access to the parent directory of the mailbox file. - Use the "postconf -m" command to find out what locking methods + Use the "postconf -l" command to find out what locking methods Postfix supports on your system. virtual_mailbox_limit diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 1daffa041..e87391dfe 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,7 +20,7 @@ * Patches change the patchlevel and the release date. Snapshots change the * release date only, unless they include the same bugfix as a patch release. */ -#define MAIL_RELEASE_DATE "20021101" +#define MAIL_RELEASE_DATE "20021104" #define VAR_MAIL_VERSION "mail_version" #define DEF_MAIL_VERSION "1.1.11-" MAIL_RELEASE_DATE diff --git a/postfix/src/global/mkmap.h b/postfix/src/global/mkmap.h index e1a443d19..fc23d64d5 100644 --- a/postfix/src/global/mkmap.h +++ b/postfix/src/global/mkmap.h @@ -25,15 +25,16 @@ typedef struct MKMAP { struct DICT *(*open) (const char *, int, int); /* dict_xx_open() */ struct DICT *dict; /* dict_xx_open() result */ - char *lock_file; /* lock file name */ - int lock_fd; /* locked open file, or -1 */ void (*after_open) (struct MKMAP *); /* may be null */ + void (*after_close) (struct MKMAP *); /* may be null */ } MKMAP; extern MKMAP *mkmap_open(const char *, const char *, int, int); extern void mkmap_append(MKMAP *, const char *, const char *); extern void mkmap_close(MKMAP *); +#define mkmap_append(map, key, val) dict_put((map)->dict, (key), (val)) + extern MKMAP *mkmap_dbm_open(const char *); extern MKMAP *mkmap_hash_open(const char *); extern MKMAP *mkmap_btree_open(const char *); diff --git a/postfix/src/global/mkmap_db.c b/postfix/src/global/mkmap_db.c index cfc07a42d..704fa342a 100644 --- a/postfix/src/global/mkmap_db.c +++ b/postfix/src/global/mkmap_db.c @@ -63,10 +63,29 @@ #include #endif +typedef struct MKMAP_DB { + MKMAP mkmap; /* parent class */ + char *lock_file; /* path name */ + int lock_fd; /* -1 or open locked file */ +} MKMAP_DB; + +/* mkmap_db_after_close - clean up after closing database */ + +static void mkmap_db_after_close(MKMAP *mp) +{ + MKMAP_DB *mkmap = (MKMAP_DB *) mp; + + if (mkmap->lock_fd >= 0 && close(mkmap->lock_fd) < 0) + msg_warn("close %s: %m", mkmap->lock_file); + myfree(mkmap->lock_file); +} + /* mkmap_db_after_open - lock newly created database */ -static void mkmap_db_after_open(MKMAP *mkmap) +static void mkmap_db_after_open(MKMAP *mp) { + MKMAP_DB *mkmap = (MKMAP_DB *) mp; + if (mkmap->lock_fd < 0) { if ((mkmap->lock_fd = open(mkmap->lock_file, O_RDWR, 0644)) < 0) msg_fatal("open lockfile %s: %m", mkmap->lock_file); @@ -80,7 +99,7 @@ static void mkmap_db_after_open(MKMAP *mkmap) static MKMAP *mkmap_db_before_open(const char *path, DICT *(*db_open) (const char *, int, int)) { - MKMAP *mkmap = (MKMAP *) mymalloc(sizeof(*mkmap)); + MKMAP_DB *mkmap = (MKMAP_DB *) mymalloc(sizeof(*mkmap)); struct stat st; /* @@ -107,8 +126,9 @@ static MKMAP *mkmap_db_before_open(const char *path, * Fill in the generic members. */ mkmap->lock_file = concatenate(path, ".db", (char *) 0); - mkmap->open = db_open; - mkmap->after_open = mkmap_db_after_open; + mkmap->mkmap.open = db_open; + mkmap->mkmap.after_open = mkmap_db_after_open; + mkmap->mkmap.after_close = mkmap_db_after_close; /* * Unfortunately, not all systems that might support db databases do @@ -150,7 +170,7 @@ static MKMAP *mkmap_db_before_open(const char *path, } } - return (mkmap); + return (&mkmap->mkmap); } /* mkmap_hash_open - create or open hashed DB file */ diff --git a/postfix/src/global/mkmap_dbm.c b/postfix/src/global/mkmap_dbm.c index 968e76ac4..1db588bab 100644 --- a/postfix/src/global/mkmap_dbm.c +++ b/postfix/src/global/mkmap_dbm.c @@ -55,11 +55,28 @@ #include #endif +typedef struct MKMAP_DBM { + MKMAP mkmap; /* parent class */ + char *lock_file; /* path name */ + int lock_fd; /* -1 or open locked file */ +} MKMAP_DBM; + +/* mkmap_dbm_after_close - clean up after closing database */ + +static void mkmap_dbm_after_close(MKMAP *mp) +{ + MKMAP_DBM *mkmap = (MKMAP_DBM *) mp; + + if (mkmap->lock_fd >= 0 && close(mkmap->lock_fd) < 0) + msg_warn("close %s: %m", mkmap->lock_file); + myfree(mkmap->lock_file); +} + /* mkmap_dbm_open - create or open database */ MKMAP *mkmap_dbm_open(const char *path) { - MKMAP *mkmap = (MKMAP *) mymalloc(sizeof(*mkmap)); + MKMAP_DBM *mkmap = (MKMAP_DBM *) mymalloc(sizeof(*mkmap)); char *pag_file; int pag_fd; @@ -67,8 +84,9 @@ MKMAP *mkmap_dbm_open(const char *path) * Fill in the generic members. */ mkmap->lock_file = concatenate(path, ".dir", (char *) 0); - mkmap->open = dict_dbm_open; - mkmap->after_open = 0; + mkmap->mkmap.open = dict_dbm_open; + mkmap->mkmap.after_open = 0; + mkmap->mkmap.after_close = mkmap_dbm_after_close; /* * Unfortunately, not all systems support locking on open(), so we open @@ -90,9 +108,9 @@ MKMAP *mkmap_dbm_open(const char *path) * have any spectators. */ if (myflock(mkmap->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0) - msg_fatal("lock %s: %m", mkmap->lock_file); + msg_fatal("lock %s: %m", mkmap->lock_file); - return (mkmap); + return (&mkmap->mkmap); } #endif diff --git a/postfix/src/global/mkmap_open.c b/postfix/src/global/mkmap_open.c index bf3097dd4..dd6f6e642 100644 --- a/postfix/src/global/mkmap_open.c +++ b/postfix/src/global/mkmap_open.c @@ -22,6 +22,8 @@ /* MKMAP *mkmap; /* DESCRIPTION /* This module implements support for creating Postfix databases. +/* It is a dict(3) wrapper that adds global locking to dict-level +/* routines where appropriate. /* /* mkmap_open() creates or truncates the named database, after /* appending the appropriate suffixes to the specified filename. @@ -91,6 +93,8 @@ MKMAP_OPEN_INFO mkmap_types[] = { /* mkmap_append - append entry to map */ +#undef mkmap_append + void mkmap_append(MKMAP *mkmap, const char *key, const char *value) { dict_put(mkmap->dict, key, value); @@ -102,11 +106,19 @@ void mkmap_close(MKMAP *mkmap) { /* - * Close the database and the locking file descriptor. + * Close the database. */ dict_close(mkmap->dict); - if (close(mkmap->lock_fd) < 0) - msg_warn("close %s: %m", mkmap->lock_file); + + /* + * Do whatever special processing is needed after closing the database, + * such as releasing a global exclusive lock on the database file. + * Individual Postfix dict modules implement locking only for individual + * record operations, because most Postfix applications don't need global + * exclusive locks. + */ + if (mkmap->after_close) + mkmap->after_close(mkmap); /* * Resume signal delivery. @@ -116,7 +128,6 @@ void mkmap_close(MKMAP *mkmap) /* * Cleanup. */ - myfree(mkmap->lock_file); myfree((char *) mkmap); } @@ -141,7 +152,10 @@ MKMAP *mkmap_open(const char *type, const char *path, msg_info("open %s %s", type, path); /* - * Do whatever before-open initialization is needed. + * Do whatever before-open initialization is needed, such as acquiring a + * global exclusive lock on an existing database file. Individual Postfix + * dict modules implement locking only for individual record operations, + * because most Postfix applications don't need global exclusive locks. */ mkmap = mp->before_open(path); @@ -161,7 +175,11 @@ MKMAP *mkmap_open(const char *type, const char *path, mkmap->dict->flags |= DICT_FLAG_DUP_WARN; /* - * Do whatever post-open initialization is needed. + * Do whatever post-open initialization is needed, such as acquiring a + * global exclusive lock on a database file that did not exist. + * Individual Postfix dict modules implement locking only for individual + * record operations, because most Postfix applications don't need global + * exclusive locks. */ if (mkmap->after_open) mkmap->after_open(mkmap);