Currently, postfix creates (empty, table-less) sqlite database if not exists, which is kinda unexpected provided postfix can not even load data to it. Also, the database is always open in read-write mode, despite postfix only performs queries.
Also, when open actually fails, the error message is unhelpful: Unfortunately, sqlite does not give good hint about the reason why the database can't be open, for example: fatal: sqlite:/etc/postfix/db.cf: Can't open database: \ unable to open database file? Obviously this is an sqlite omission/defect, but we can work around it in postfix by also providing the strerror(errno) here. This patch does a few things: 1. It changes sqlite3_open() into sqlite3_open_v2() which accepts 2 more arguments, notable open flags (similar to open(2)) - where we only pass SQLITE_OPEN_READONLY, without SQLITE_OPEN_CREATE. 2. It replaces msg_fatal() call when we weren't able to open the database file into dict_surrogate() like in other places when open error occurs, and continues. 3. it calls a new common function dict_sqlite_free() to free the just allocated DICT_SQLITE, in the same manner as dict_sqlite_close() does (the function is copied from there). 4. It makes the error message much more useful by including the database file name it tried to open, and strerror(errno) (%m), so the error message (when attempting to use the dict_surrogate) becomes: fatal: sqlite:/etc/postfix/db.cf: open database t.dbx: \ unable to open database file: No such file or directory sqlite3_open_v2() is available since sqlite version 3.5.0 (see https://www.sqlite.org/34to35.html), and compatibility wrapper is provided for older releases, exactly like sqlite3_prepare_v2(). Signed-off-by: Michael Tokarev <m...@tls.msk.ru> diff --git a/src/global/dict_sqlite.c b/src/global/dict_sqlite.c index 7d6608a6..c26d4045 100644 --- a/src/global/dict_sqlite.c +++ b/src/global/dict_sqlite.c @@ -59,6 +59,9 @@ #if !defined(SQLITE_VERSION_NUMBER) || (SQLITE_VERSION_NUMBER < 3005004) #define sqlite3_prepare_v2 sqlite3_prepare #endif +#if !defined(SQLITE_VERSION_NUMBER) || (SQLITE_VERSION_NUMBER < 3005000) +#define sqlite3_open_v2(fname,ppDB,flags,zVfs) sqlite_open(fname,ppDB) +#endif /* Utility library. */ @@ -102,6 +105,21 @@ static void dict_sqlite_quote(DICT *dict, const char *raw_text, VSTRING *result) sqlite3_free(quoted_text); } +/* dict_sqlite_free - free the database-related fields */ + +static void dict_sqlite_free(DICT_SQLITE *dict_sqlite) +{ + cfg_parser_free(dict_sqlite->parser); + myfree(dict_sqlite->dbpath); + myfree(dict_sqlite->query); + myfree(dict_sqlite->result_format); + if (dict_sqlite->ctx) + db_common_free_ctx(dict_sqlite->ctx); + if (dict_sqlite->dict.fold_buf) + vstring_free(dict_sqlite->dict.fold_buf); + dict_free(&dict_sqlite->dict); +} + /* dict_sqlite_close - close the database */ static void dict_sqlite_close(DICT *dict) @@ -114,15 +132,8 @@ static void dict_sqlite_close(DICT *dict) if (sqlite3_close(dict_sqlite->db) != SQLITE_OK) msg_fatal("%s: close %s failed", myname, dict_sqlite->parser->name); - cfg_parser_free(dict_sqlite->parser); - myfree(dict_sqlite->dbpath); - myfree(dict_sqlite->query); - myfree(dict_sqlite->result_format); - if (dict_sqlite->ctx) - db_common_free_ctx(dict_sqlite->ctx); - if (dict->fold_buf) - vstring_free(dict->fold_buf); - dict_free(dict); + + dict_sqlite_free(dict_sqlite); } /* dict_sqlite_lookup - find database entry */ @@ -320,9 +331,15 @@ DICT *dict_sqlite_open(const char *name, int open_flags, int dict_flags) dict_sqlite->parser = parser; sqlite_parse_config(dict_sqlite, name); - if (sqlite3_open(dict_sqlite->dbpath, &dict_sqlite->db)) - msg_fatal("%s:%s: Can't open database: %s\n", - DICT_TYPE_SQLITE, name, sqlite3_errmsg(dict_sqlite->db)); + if (sqlite3_open_v2(dict_sqlite->dbpath, &dict_sqlite->db, + SQLITE_OPEN_READONLY, NULL)) { + DICT *dict = dict_surrogate(DICT_TYPE_SQLITE, name, open_flags, + dict_flags, "%s:%s: open database %s: %s: %m", + DICT_TYPE_SQLITE, name, dict_sqlite->dbpath, + sqlite3_errmsg(dict_sqlite->db)); + dict_sqlite_free(dict_sqlite); + return dict; + } dict_sqlite->dict.owner = cfg_get_owner(dict_sqlite->parser); _______________________________________________ Postfix-devel mailing list -- postfix-devel@postfix.org To unsubscribe send an email to postfix-devel-le...@postfix.org