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 <[email protected]>
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 -- [email protected]
To unsubscribe send an email to [email protected]