From: Jeremy Harris Date: Tue, 16 Jul 2024 20:24:48 +0000 (+0100) Subject: Use explicit O_CREAT for dbfn_open() X-Git-Url: https://git.exim.org/exim.git/commitdiff_plain/4cbf0dff96031f9b53cf6d8a3c4b2001d467a57d?hp=e790c070e6b3a0471642fa182948778304751c8d Use explicit O_CREAT for dbfn_open() --- diff --git a/src/src/acl.c b/src/src/acl.c index 0aa789dbf..69777cf9c 100644 --- a/src/src/acl.c +++ b/src/src/acl.c @@ -2584,7 +2584,7 @@ if ((t = tree_search(*anchor, key))) /* We aren't using a pre-computed rate, so get a previously recorded rate from the database, which will be updated and written back if required. */ -if (!(dbm = dbfn_open(US"ratelimit", O_RDWR, &dbblock, TRUE, TRUE))) +if (!(dbm = dbfn_open(US"ratelimit", O_RDWR|O_CREAT, &dbblock, TRUE, TRUE))) { store_pool = old_pool; sender_rate = NULL; @@ -2966,7 +2966,7 @@ while ((ele = string_nextinlist(&list, &slash, NULL, 0))) else goto badopt; -if (!(dbm = dbfn_open(US"seen", O_RDWR, &dbblock, TRUE, TRUE))) +if (!(dbm = dbfn_open(US"seen", O_RDWR|O_CREAT, &dbblock, TRUE, TRUE))) { HDEBUG(D_acl) debug_printf_indent("database for 'seen' not available\n"); *log_msgptr = US"database for 'seen' not available"; diff --git a/src/src/dbfn.c b/src/src/dbfn.c index d64f1927b..c2c92cf44 100644 --- a/src/src/dbfn.c +++ b/src/src/dbfn.c @@ -128,7 +128,7 @@ return TRUE; Arguments: name The single-component name of one of Exim's database files. flags Either O_RDONLY or O_RDWR, indicating the type of open required; - O_RDWR implies "create if necessary" + optionally O_CREAT dbblock Points to an open_db block to be filled in. lof If TRUE, write to the log for actual open failures (locking failures are always logged). @@ -165,16 +165,16 @@ unnecessarily, because usually the lock file will be there. If the directory exists, there is no error. */ dlen = snprintf(CS dirname, sizeof(dirname), "%s/db", spool_directory); -flen = Ustrlen(name); -snprintf(CS filename, sizeof(filename), "%.*s/%.*s.lockfile", - (int)sizeof(filename) - dlen - flen - 11, dirname, - flen, name); dbblock->lockfd = -1; if (!exim_lockfile_needed()) db_dir_make(panic); else { + flen = Ustrlen(name); + snprintf(CS filename, sizeof(filename), "%.*s/%.*s.lockfile", + (int)sizeof(filename) - dlen - flen - 11, dirname, + flen, name); if (!lockfile_take(dbblock, filename, flags == O_RDONLY, panic)) { DEBUG(D_hints_lookup) acl_level--; @@ -191,16 +191,15 @@ databases - often this is caused by non-matching db.h and the library. To make it easy to pin this down, there are now debug statements on either side of the open call. */ -flags &= O_RDONLY | O_RDWR; snprintf(CS filename, sizeof(filename), "%.*s/%s", dlen, dirname, name); priv_drop_temp(exim_uid, exim_gid); -dbblock->dbptr = exim_dbopen(filename, dirname, flags, EXIMDB_MODE); -if (!dbblock->dbptr && errno == ENOENT && flags == O_RDWR) +dbblock->dbptr = exim_dbopen(filename, dirname, flags & O_ACCMODE, EXIMDB_MODE); +if (!dbblock->dbptr && errno == ENOENT && flags & O_CREAT) { DEBUG(D_hints_lookup) debug_printf_indent("%s appears not to exist: trying to create\n", filename); - dbblock->dbptr = exim_dbopen(filename, dirname, flags|O_CREAT, EXIMDB_MODE); + dbblock->dbptr = exim_dbopen(filename, dirname, flags, EXIMDB_MODE); } save_errno = errno; priv_restore(); @@ -227,10 +226,11 @@ if (!dbblock->dbptr) } DEBUG(D_hints_lookup) - debug_printf_indent("opened hints database %s: flags=%s\n", filename, - flags == O_RDONLY ? "O_RDONLY" - : flags == O_RDWR ? "O_RDWR" - : "??"); + debug_printf_indent("opened hints database %s: flags=%s%s\n", filename, + (flags & O_ACCMODE) == O_RDONLY ? "O_RDONLY" + : (flags & O_ACCMODE) == O_RDWR ? "O_RDWR" + : "??", + flags & O_CREAT ? "|O_CREAT" : ""); /* Pass back the block containing the opened database handle and the open fd for the lock. */ @@ -260,12 +260,12 @@ dlen = snprintf(CS dirname, sizeof(dirname), "%s/db", spool_directory); snprintf(CS filename, sizeof(filename), "%.*s/%s", dlen, dirname, name); priv_drop_temp(exim_uid, exim_gid); -dbblock->dbptr = exim_dbopen_multi(filename, dirname, flags, EXIMDB_MODE); -if (!dbblock->dbptr && errno == ENOENT && flags == O_RDWR) +dbblock->dbptr = exim_dbopen_multi(filename, dirname, flags & O_ACCMODE, EXIMDB_MODE); +if (!dbblock->dbptr && errno == ENOENT && flags & O_CREAT) { DEBUG(D_hints_lookup) debug_printf_indent("%s appears not to exist: trying to create\n", filename); - dbblock->dbptr = exim_dbopen_multi(filename, dirname, O_RDWR|O_CREAT, EXIMDB_MODE); + dbblock->dbptr = exim_dbopen_multi(filename, dirname, flags, EXIMDB_MODE); } save_errno = errno; priv_restore(); @@ -289,8 +289,13 @@ if (!dbblock->dbptr) return NULL; } -DEBUG(D_hints_lookup) debug_printf_indent( - "opened hints database %s for transactions: NOLOCK flags=O_RDWR\n", filename); +DEBUG(D_hints_lookup) + debug_printf_indent("opened hints database %s for transactions: NOLOCK flags=%s%s\n", + filename, + (flags & O_ACCMODE) == O_RDONLY ? "O_RDONLY" + : (flags & O_ACCMODE) == O_RDWR ? "O_RDWR" + : "??", + flags & O_CREAT ? "|O_CREAT" : ""); /* Pass back the block containing the opened database handle */ @@ -660,7 +665,7 @@ while (Ufgets(buffer, 256, stdin) != NULL) } start = clock(); - odb = dbfn_open(s, O_RDWR, dbblock + i, TRUE, TRUE); + odb = dbfn_open(s, O_RDWR|O_CREAT, dbblock + i, TRUE, TRUE); stop = clock(); if (odb) diff --git a/src/src/deliver.c b/src/src/deliver.c index 7576682f4..b04fe6f12 100644 --- a/src/src/deliver.c +++ b/src/src/deliver.c @@ -7453,7 +7453,7 @@ while (addr_new) /* Loop until all addresses dealt with */ } else if (!exim_lockfile_needed() && continue_transport) { - dbm_file = dbfn_open_multi(US"retry", O_RDONLY, &dbblock); + dbm_file = dbfn_open_multi(US"retry", O_RDWR, &dbblock); continue_retry_db = dbm_file ? dbm_file : (open_db *)-1; } else diff --git a/src/src/enq.c b/src/src/enq.c index 43f53a585..057dffae1 100644 --- a/src/src/enq.c +++ b/src/src/enq.c @@ -44,12 +44,9 @@ open_db *dbm_file; DEBUG(D_transport) debug_printf("check serialized: %s\n", key); -/* Open and lock the waiting information database. The absence of O_CREAT is -deliberate; the dbfn_open() function - which is an Exim function - always tries -to create if it can't open a read/write file. It expects only O_RDWR or -O_RDONLY as its argument. */ +/* Open and lock the waiting information database. */ -if (!(dbm_file = dbfn_open(US"misc", O_RDWR, &dbblock, TRUE, TRUE))) +if (!(dbm_file = dbfn_open(US"misc", O_RDWR|O_CREAT, &dbblock, TRUE, TRUE))) return FALSE; /* See if there is a record for this host or queue run; if there is, we cannot diff --git a/src/src/exim_dbutil.c b/src/src/exim_dbutil.c index d3d854dd5..dd1444593 100644 --- a/src/src/exim_dbutil.c +++ b/src/src/exim_dbutil.c @@ -271,7 +271,7 @@ the lock file. Arguments: name The single-component name of one of Exim's database files. - flags O_RDONLY or O_RDWR + flags O_RDONLY or O_RDWR, O_CREAT dbblock Points to an open_db block to be filled in. lof Unused. panic Unused @@ -340,8 +340,6 @@ if (exim_lockfile_needed()) if (asprintf(CSS &filename, "%s/%s", dirname, name) < 0) return NULL; -if (flags & O_RDWR) flags |= O_CREAT; - if (!(dbblock->dbptr = exim_dbopen(filename, dirname, flags, 0))) { printf("** Failed to open hintsdb file %s for %s: %s%s\n", filename, @@ -846,7 +844,7 @@ for(; (reset_point = store_mark()); store_reset(reset_point)) { int verify = 1; - if (!(dbm = dbfn_open(aname, O_RDWR, &dbblock, FALSE, TRUE))) + if (!(dbm = dbfn_open(aname, O_RDWR|O_CREAT, &dbblock, FALSE, TRUE))) continue; if (Ustrcmp(field, "d") == 0) @@ -1209,7 +1207,7 @@ oldest = time(NULL) - maxkeep; printf("Tidying Exim hints database %s/db/%s\n", argv[1], argv[2]); spool_directory = argv[1]; -if (!(dbm = dbfn_open(argv[2], O_RDWR, &dbblock, FALSE, TRUE))) +if (!(dbm = dbfn_open(argv[2], O_RDWR|O_CREAT, &dbblock, FALSE, TRUE))) exit(EXIT_FAILURE); /* Prepare for building file names */ diff --git a/src/src/retry.c b/src/src/retry.c index 071c94cd8..e86b1afe8 100644 --- a/src/src/retry.c +++ b/src/src/retry.c @@ -617,7 +617,7 @@ for (int i = 0; i < 3; i++) reached their retry next try time. */ if (!dbm_file) - dbm_file = dbfn_open(US"retry", O_RDWR, &dbblock, TRUE, TRUE); + dbm_file = dbfn_open(US"retry", O_RDWR|O_CREAT, &dbblock, TRUE, TRUE); if (!dbm_file) { diff --git a/src/src/tls-gnu.c b/src/src/tls-gnu.c index f443a6e27..25690aed2 100644 --- a/src/src/tls-gnu.c +++ b/src/src/tls-gnu.c @@ -3385,7 +3385,7 @@ if (gnutls_session_get_flags(session) & GNUTLS_SFLAGS_SESSION_TICKET) memcpy(dt->session, tkt.data, tkt.size); gnutls_free(tkt.data); - if ((dbm_file = dbfn_open(US"tls", O_RDWR, &dbblock, FALSE, FALSE))) + if ((dbm_file = dbfn_open(US"tls", O_RDWR|O_CREAT, &dbblock, FALSE, FALSE))) { /* key for the db is the IP */ dbfn_write(dbm_file, tlsp->resume_index, dt, dlen); diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c index c97106fe0..0a5e2a7a0 100644 --- a/src/src/tls-openssl.c +++ b/src/src/tls-openssl.c @@ -3933,7 +3933,7 @@ if (tlsp->host_resumable) tlsp->resumption |= RESUME_CLIENT_REQUESTED; DEBUG(D_tls) debug_printf("checking for resumable session for %s\n", tlsp->resume_index); - if ((dbm_file = dbfn_open(US"tls", O_RDWR, &dbblock, FALSE, FALSE))) + if ((dbm_file = dbfn_open(US"tls", O_RDWR|O_CREAT, &dbblock, FALSE, FALSE))) { if ((dt = dbfn_read_with_length(dbm_file, tlsp->resume_index, &len))) { @@ -4016,7 +4016,7 @@ if (SSL_SESSION_is_resumable(ss)) /* 1.1.1 */ dt->ocsp = tlsp->ocsp; (void) i2d_SSL_SESSION(ss, &s); /* s gets bumped to end */ - if ((dbm_file = dbfn_open(US"tls", O_RDWR, &dbblock, FALSE, FALSE))) + if ((dbm_file = dbfn_open(US"tls", O_RDWR|O_CREAT, &dbblock, FALSE, FALSE))) { dbfn_write(dbm_file, tlsp->resume_index, dt, dlen); dbfn_close(dbm_file); diff --git a/src/src/transport.c b/src/src/transport.c index 398022354..170997172 100644 --- a/src/src/transport.c +++ b/src/src/transport.c @@ -1516,7 +1516,7 @@ DEBUG(D_transport) debug_printf("updating wait-%s database\n", tpname); if ( continue_wait_db ? !dbfn_transaction_start(dbp = continue_wait_db) : !(dbp = dbfn_open(string_sprintf("wait-%.200s", tpname), - O_RDWR, &dbblock, TRUE, TRUE)) + O_RDWR|O_CREAT, &dbblock, TRUE, TRUE)) ) return; diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c index 581e94f76..5b54fa1ae 100644 --- a/src/src/transports/smtp.c +++ b/src/src/transports/smtp.c @@ -913,7 +913,7 @@ sx->ehlo_resp.limit_rcpt = sx->peer_limit_rcpt; sx->ehlo_resp.limit_rcptdom = sx->peer_limit_rcptdom; # endif -if ((dbm_file = dbfn_open(US"misc", O_RDWR, &dbblock, TRUE, TRUE))) +if ((dbm_file = dbfn_open(US"misc", O_RDWR|O_CREAT, &dbblock, TRUE, TRUE))) { uschar * ehlo_resp_key = ehlo_cache_key(sx); dbdata_ehlo_resp er = { .data = sx->ehlo_resp }; @@ -943,7 +943,7 @@ invalidate_ehlo_cache_entry(smtp_context * sx) open_db dbblock, * dbm_file; if ( sx->early_pipe_active - && (dbm_file = dbfn_open(US"misc", O_RDWR, &dbblock, TRUE, TRUE))) + && (dbm_file = dbfn_open(US"misc", O_RDWR|O_CREAT, &dbblock, TRUE, TRUE))) { uschar * ehlo_resp_key = ehlo_cache_key(sx); HDEBUG(D_transport) @@ -981,7 +981,7 @@ else { DEBUG(D_transport) debug_printf("ehlo-resp record too old\n"); dbfn_close(dbm_file); - if ((dbm_file = dbfn_open(US"misc", O_RDWR, &dbblock, TRUE, TRUE))) + if ((dbm_file = dbfn_open(US"misc", O_RDWR|O_CREAT, &dbblock, TRUE, TRUE))) dbfn_delete(dbm_file, ehlo_resp_key); } else diff --git a/src/src/verify.c b/src/src/verify.c index ab56ed374..25fc700f9 100644 --- a/src/src/verify.c +++ b/src/src/verify.c @@ -121,7 +121,7 @@ if (options & vopt_callout_no_cache) { HDEBUG(D_verify) debug_printf_indent("callout cache: disabled by no_cache\n"); } -else if (!(dbm_file = dbfn_open(US"callout", O_RDWR, &dbblock, FALSE, TRUE))) +else if (!(dbm_file = dbfn_open(US"callout", O_RDWR|O_CREAT, &dbblock, FALSE, TRUE))) { HDEBUG(D_verify) debug_printf_indent("callout cache: not available\n"); } @@ -294,7 +294,7 @@ implying some kind of I/O error. We don't want to write the cache in that case. Otherwise the value is ccache_accept, ccache_reject, or ccache_reject_mfnull. */ if (dom_rec->result != ccache_unknown) - if (!(dbm_file = dbfn_open(US"callout", O_RDWR, &dbblock, FALSE, TRUE))) + if (!(dbm_file = dbfn_open(US"callout", O_RDWR|O_CREAT, &dbblock, FALSE, TRUE))) { HDEBUG(D_verify) debug_printf_indent("callout cache: not available\n"); } @@ -316,7 +316,7 @@ is disabled. */ if (done && addr_rec->result != ccache_unknown) { if (!dbm_file) - dbm_file = dbfn_open(US"callout", O_RDWR, &dbblock, FALSE, TRUE); + dbm_file = dbfn_open(US"callout", O_RDWR|O_CREAT, &dbblock, FALSE, TRUE); if (!dbm_file) { HDEBUG(D_verify) debug_printf_indent("no callout cache available\n"); @@ -3497,7 +3497,7 @@ dbdata_callout_cache_address * cache_address_record; if (!pos_cache && !neg_cache) return FALSE; -if (!(dbm_file = dbfn_open(US"callout", O_RDWR, &dbblock, FALSE, TRUE))) +if (!(dbm_file = dbfn_open(US"callout", O_RDWR|O_CREAT, &dbblock, FALSE, TRUE))) { HDEBUG(D_verify) debug_printf_indent("quota cache: not available\n"); return FALSE; @@ -3525,7 +3525,7 @@ dbdata_callout_cache_address cache_address_record; if (!pos_cache && !neg_cache) return; -if (!(dbm_file = dbfn_open(US"callout", O_RDWR, &dbblock, FALSE, TRUE))) +if (!(dbm_file = dbfn_open(US"callout", O_RDWR|O_CREAT, &dbblock, FALSE, TRUE))) { HDEBUG(D_verify) debug_printf_indent("quota cache: not available\n"); return; diff --git a/test/stderr/0388 b/test/stderr/0388 index 7aa897242..152c91a27 100644 --- a/test/stderr/0388 +++ b/test/stderr/0388 @@ -154,7 +154,7 @@ Processing retry items x@y ╎EXIM_DBOPEN: file dir flags=O_RDWR ╎returned from EXIM_DBOPEN: 0xAAAAAAAA - ╎opened hints database TESTSUITE/spool/db/retry: flags=O_RDWR + ╎opened hints database TESTSUITE/spool/db/retry: flags=O_RDWR|O_CREAT ╎x@y in "*"? ╎ list element: * ╎ address match test: subject=x@y pattern=* diff --git a/test/stderr/0398 b/test/stderr/0398 index bb31becd4..169c332ad 100644 --- a/test/stderr/0398 +++ b/test/stderr/0398 @@ -141,7 +141,7 @@ routed by r2 router Attempting full verification using callout EXIM_DBOPEN: file dir flags=O_RDWR returned from EXIM_DBOPEN: 0xAAAAAAAA - opened hints database TESTSUITE/spool/db/callout: flags=O_RDWR + opened hints database TESTSUITE/spool/db/callout: flags=O_RDWR|O_CREAT dbfn_read: key=remote dbfn_read: size nnn return callout cache: found domain record for remote @@ -177,7 +177,7 @@ cmd buf flush ddd bytes cmdlog: '220:EHLO:250:MAIL:250:RCPT:550:QUIT:250' EXIM_DBOPEN: file dir flags=O_RDWR returned from EXIM_DBOPEN: 0xAAAAAAAA - opened hints database TESTSUITE/spool/db/callout: flags=O_RDWR + opened hints database TESTSUITE/spool/db/callout: flags=O_RDWR|O_CREAT dbfn_write: key=remote datalen nn wrote callout cache domain record for remote: result=1 postmaster=0 random=0 @@ -274,7 +274,7 @@ routed by r2 router Attempting full verification using callout EXIM_DBOPEN: file dir flags=O_RDWR returned from EXIM_DBOPEN: 0xAAAAAAAA - opened hints database TESTSUITE/spool/db/callout: flags=O_RDWR + opened hints database TESTSUITE/spool/db/callout: flags=O_RDWR|O_CREAT dbfn_read: key=remote dbfn_read: size nnn return callout cache: found domain record for remote diff --git a/test/stderr/0432 b/test/stderr/0432 index 1f17d175d..162877b7a 100644 --- a/test/stderr/0432 +++ b/test/stderr/0432 @@ -94,7 +94,7 @@ get[host|ipnode]byname[2] looked up these IP addresses: Attempting full verification using callout EXIM_DBOPEN: file dir flags=O_RDWR returned from EXIM_DBOPEN: 0xAAAAAAAA - opened hints database TESTSUITE/spool/db/callout: flags=O_RDWR + opened hints database TESTSUITE/spool/db/callout: flags=O_RDWR|O_CREAT dbfn_read: key=y dbfn_read: null return callout cache: no domain record found for y @@ -130,7 +130,7 @@ cmd buf flush ddd bytes cmdlog: '220:EHLO:250:MAIL:250:RCPT:250:QUIT:220' EXIM_DBOPEN: file dir flags=O_RDWR returned from EXIM_DBOPEN: 0xAAAAAAAA - opened hints database TESTSUITE/spool/db/callout: flags=O_RDWR + opened hints database TESTSUITE/spool/db/callout: flags=O_RDWR|O_CREAT dbfn_write: key=y datalen nn wrote callout cache domain record for y: result=1 postmaster=0 random=0 @@ -216,7 +216,7 @@ get[host|ipnode]byname[2] looked up these IP addresses: Attempting full verification using callout EXIM_DBOPEN: file dir flags=O_RDWR returned from EXIM_DBOPEN: 0xAAAAAAAA - opened hints database TESTSUITE/spool/db/callout: flags=O_RDWR + opened hints database TESTSUITE/spool/db/callout: flags=O_RDWR|O_CREAT dbfn_read: key=y dbfn_read: size nnn return callout cache: found domain record for y diff --git a/test/stderr/5005 b/test/stderr/5005 index 603ad30f6..2e1c3b08d 100644 --- a/test/stderr/5005 +++ b/test/stderr/5005 @@ -552,7 +552,7 @@ Processing retry items userx@test.ex ╎EXIM_DBOPEN: file dir flags=O_RDWR ╎returned from EXIM_DBOPEN: 0xAAAAAAAA - ╎opened hints database TESTSUITE/spool/db/retry: flags=O_RDWR + ╎opened hints database TESTSUITE/spool/db/retry: flags=O_RDWR|O_CREAT ╎userx@test.ex in "*"? ╎ list element: * ╎ address match test: subject=userx@test.ex pattern=* @@ -752,7 +752,7 @@ Processing retry items userx@test.ex ╎EXIM_DBOPEN: file dir flags=O_RDWR ╎returned from EXIM_DBOPEN: 0xAAAAAAAA - ╎opened hints database TESTSUITE/spool/db/retry: flags=O_RDWR + ╎opened hints database TESTSUITE/spool/db/retry: flags=O_RDWR|O_CREAT ╎userx@test.ex in "*"? ╎ list element: * ╎ address match test: subject=userx@test.ex pattern=*