X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/f9ba5e2255cf18092750fffacb6a9603571a2be5..a85c067ba6c6940512cf57ec213277a370d87e70:/src/src/spool_mbox.c diff --git a/src/src/spool_mbox.c b/src/src/spool_mbox.c index 749484f2b..d9767ec3c 100644 --- a/src/src/spool_mbox.c +++ b/src/src/spool_mbox.c @@ -4,7 +4,8 @@ /* Copyright (c) Tom Kistner 2003 - 2015 * License: GPL - * Copyright (c) The Exim Maintainers 2016 - 2018 + * Copyright (c) The Exim Maintainers 2016 - 2021 + * SPDX-License-Identifier: GPL-2.0-only */ /* Code for setting up a MBOX style spool file inside a /scan/ @@ -35,19 +36,16 @@ uschar message_subdir[2]; uschar buffer[16384]; uschar *temp_string; uschar *mbox_path; -FILE *mbox_file = NULL; -FILE *data_file = NULL; -FILE *yield = NULL; -header_line *my_headerlist; +FILE *mbox_file = NULL, *l_data_file = NULL, *yield = NULL; struct stat statbuf; -int i, j; -void *reset_point; +int j; +rmark reset_point; mbox_path = string_sprintf("%s/scan/%s/%s.eml", spool_directory, message_id, message_id); if (mbox_fname) *mbox_fname = mbox_path; -reset_point = store_get(0); +reset_point = store_mark(); /* Skip creation if already spooled out as mbox file */ if (!spool_mbox_ok) @@ -56,8 +54,8 @@ if (!spool_mbox_ok) temp_string = string_sprintf("scan/%s", message_id); if (!directory_make(spool_directory, temp_string, 0750, FALSE)) { - log_write(0, LOG_MAIN|LOG_PANIC, "%s", string_open_failed(errno, - "scan directory %s/scan/%s", spool_directory, temp_string)); + log_write(0, LOG_MAIN|LOG_PANIC, "%s", + string_open_failed("scan directory %s/scan/%s", spool_directory, temp_string)); goto OUT; } @@ -65,8 +63,8 @@ if (!spool_mbox_ok) if (!(mbox_file = modefopen(mbox_path, "wb", SPOOL_MODE))) { - log_write(0, LOG_MAIN|LOG_PANIC, "%s", string_open_failed(errno, - "scan file %s", mbox_path)); + log_write(0, LOG_MAIN|LOG_PANIC, "%s", + string_open_failed("scan file %s", mbox_path)); goto OUT; } @@ -90,7 +88,7 @@ if (!spool_mbox_ok) /* write all non-deleted header lines to mbox file */ - for (my_headerlist = header_list; my_headerlist; + for (header_line * my_headerlist = header_list; my_headerlist; my_headerlist = my_headerlist->next) if (my_headerlist->type != '*') if (fwrite(my_headerlist->text, my_headerlist->slen, 1, mbox_file) != 1) @@ -108,21 +106,25 @@ if (!spool_mbox_ok) goto OUT; } - /* copy body file */ - if (!source_file_override) + /* Copy body file. If the main receive still has it open then it is holding + a lock, and we must not close it (which releases the lock), so just use the + global file handle. */ + if (source_file_override) + l_data_file = Ufopen(source_file_override, "rb"); + else if (spool_data_file) + l_data_file = spool_data_file; + else { message_subdir[1] = '\0'; - for (i = 0; i < 2; i++) + for (int i = 0; i < 2; i++) { - message_subdir[0] = split_spool_directory == (i == 0) ? message_id[5] : 0; + set_subdir_str(message_subdir, message_id, i); temp_string = spool_fname(US"input", message_subdir, message_id, US"-D"); - if ((data_file = Ufopen(temp_string, "rb"))) break; + if ((l_data_file = Ufopen(temp_string, "rb"))) break; } } - else - data_file = Ufopen(source_file_override, "rb"); - if (!data_file) + if (!l_data_file) { log_write(0, LOG_MAIN|LOG_PANIC, "Could not open datafile for message %s", message_id); @@ -131,7 +133,7 @@ if (!spool_mbox_ok) /* The code used to use this line, but it doesn't work in Cygwin. - (void)fread(data_buffer, 1, 18, data_file); + (void)fread(data_buffer, 1, 18, l_data_file); What's happening is that spool_mbox used to use an fread to jump over the file header. That fails under Cygwin because the header is locked, but @@ -139,23 +141,23 @@ if (!spool_mbox_ok) explicitly, because the one in the file is parted of the locked area. */ if (!source_file_override) - (void)fseek(data_file, SPOOL_DATA_START_OFFSET, SEEK_SET); + (void)fseek(l_data_file, SPOOL_DATA_START_OFFSET, SEEK_SET); do { uschar * s; - if (!spool_file_wireformat || source_file_override) - j = fread(buffer, 1, sizeof(buffer), data_file); + if (!f.spool_file_wireformat || source_file_override) + j = fread(buffer, 1, sizeof(buffer), l_data_file); else /* needs CRLF -> NL */ - if ((s = US fgets(CS buffer, sizeof(buffer), data_file))) + if ((s = US fgets(CS buffer, sizeof(buffer), l_data_file))) { uschar * p = s + Ustrlen(s) - 1; if (*p == '\n' && p[-1] == '\r') *--p = '\n'; else if (*p == '\r') - ungetc(*p--, data_file); + ungetc(*p--, l_data_file); j = p - buffer; } @@ -184,13 +186,13 @@ if (!spool_mbox_ok) if ( !(yield = Ufopen(mbox_path,"rb")) || fstat(fileno(yield), &statbuf) != 0 ) - log_write(0, LOG_MAIN|LOG_PANIC, "%s", string_open_failed(errno, - "scan file %s", mbox_path)); + log_write(0, LOG_MAIN|LOG_PANIC, "%s", + string_open_failed( "scan file %s", mbox_path)); else *mbox_file_size = statbuf.st_size; OUT: -if (data_file) (void)fclose(data_file); +if (l_data_file && !spool_data_file) (void)fclose(l_data_file); if (mbox_file) (void)fclose(mbox_file); store_reset(reset_point); return yield; @@ -207,39 +209,38 @@ unspool_mbox(void) spam_ok = 0; malware_ok = 0; -if (spool_mbox_ok && !no_mbox_unspool) +if (spool_mbox_ok && !f.no_mbox_unspool) { - uschar *mbox_path; uschar *file_path; - struct dirent *entry; DIR *tempdir; + rmark reset_point = store_mark(); + uschar * mbox_path = string_sprintf("%s/scan/%s", spool_directory, spooled_message_id); - mbox_path = string_sprintf("%s/scan/%s", spool_directory, spooled_message_id); - - if (!(tempdir = opendir(CS mbox_path))) + if (!(tempdir = exim_opendir(mbox_path))) { debug_printf("Unable to opendir(%s): %s\n", mbox_path, strerror(errno)); /* Just in case we still can: */ - rmdir(CS mbox_path); + (void) rmdir(CS mbox_path); return; } /* loop thru dir & delete entries */ - while((entry = readdir(tempdir))) + for (struct dirent *entry; entry = readdir(tempdir); ) { uschar *name = US entry->d_name; - int dummy; if (Ustrcmp(name, US".") == 0 || Ustrcmp(name, US"..") == 0) continue; file_path = string_sprintf("%s/%s", mbox_path, name); debug_printf("unspool_mbox(): unlinking '%s'\n", file_path); - dummy = unlink(CS file_path); dummy = dummy; /* compiler quietening */ + if (unlink(CS file_path) != 0) + log_write(0, LOG_MAIN|LOG_PANIC, "unlink(%s): %s", file_path, strerror(errno)); } closedir(tempdir); /* remove directory */ - rmdir(CS mbox_path); - store_reset(mbox_path); + if (rmdir(CS mbox_path) != 0) + log_write(0, LOG_MAIN|LOG_PANIC, "rmdir(%s): %s", mbox_path, strerror(errno)); + store_reset(reset_point); } spool_mbox_ok = 0; }