X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/6b46ecc6a8f5e3ab97c62451646a6d6045205bb1..d291c7670e4c370cdc4f631ea58f82c7f4f87823:/src/src/transports/appendfile.c diff --git a/src/src/transports/appendfile.c b/src/src/transports/appendfile.c index c9d150525..56200710f 100644 --- a/src/src/transports/appendfile.c +++ b/src/src/transports/appendfile.c @@ -234,7 +234,9 @@ appendfile_transport_options_block appendfile_transport_option_defaults = { FALSE, /* mailstore_format */ FALSE, /* mbx_format */ FALSE, /* quota_warn_threshold_is_percent */ - TRUE /* quota_is_inclusive */ + TRUE, /* quota_is_inclusive */ + FALSE, /* quota_no_check */ + FALSE /* quota_filecount_no_check */ }; @@ -285,9 +287,11 @@ mailbox_filecount */ for (i = 0; i < 5; i++) { double d; + int no_check = 0; uschar *which = NULL; - if (q == NULL) d = default_value; else + if (q == NULL) d = default_value; + else { uschar *rest; uschar *s = expand_string(q); @@ -321,12 +325,21 @@ for (i = 0; i < 5; i++) rest++; } + + /* For quota and quota_filecount there may be options + appended. Currently only "no_check", so we can be lazy parsing it */ + if (i < 2 && Ustrstr(rest, "/no_check") == rest) + { + no_check = 1; + rest += sizeof("/no_check") - 1; + } + while (isspace(*rest)) rest++; if (*rest != 0) { *errmsg = string_sprintf("Malformed value \"%s\" (expansion of \"%s\") " - "in %s transport", s, q, tblock->name); + "in %s transport [%s]", s, q, tblock->name); return FAIL; } } @@ -338,12 +351,14 @@ for (i = 0; i < 5; i++) case 0: if (d >= 2.0*1024.0*1024.0*1024.0 && sizeof(off_t) <= 4) which = US"quota"; ob->quota_value = (off_t)d; + ob->quota_no_check = no_check; q = ob->quota_filecount; break; case 1: if (d >= 2.0*1024.0*1024.0*1024.0) which = US"quota_filecount"; ob->quota_filecount_value = (int)d; + ob->quota_filecount_no_check = no_check; q = ob->quota_warn_threshold; break; @@ -619,19 +634,18 @@ if (host_find_byname(&host, NULL, 0, NULL, FALSE) == HOST_FIND_FAILED) host.address = US"127.0.0.1"; -for (h = &host; h != NULL; h = h->next) +for (h = &host; h; h = h->next) { int sock, rc; - int host_af = (Ustrchr(h->address, ':') != NULL)? AF_INET6 : AF_INET; + int host_af = Ustrchr(h->address, ':') != NULL ? AF_INET6 : AF_INET; DEBUG(D_transport) debug_printf("calling comsat on %s\n", h->address); - sock = ip_socket(SOCK_DGRAM, host_af); - if (sock < 0) continue; + if ((sock = ip_socket(SOCK_DGRAM, host_af)) < 0) continue; /* Connect never fails for a UDP socket, so don't set a timeout. */ - (void)ip_connect(sock, host_af, h->address, ntohs(sp->s_port), 0); + (void)ip_connect(sock, host_af, h->address, ntohs(sp->s_port), 0, FALSE); rc = send(sock, buffer, Ustrlen(buffer) + 1, 0); (void)close(sock); @@ -917,6 +931,9 @@ copy_mbx_message(int to_fd, int from_fd, off_t saved_size) int used; off_t size; struct stat statbuf; +transport_ctx tctx = {0}; + +tctx.u.fd = to_fd; /* If the current mailbox size is zero, write a header block */ @@ -929,7 +946,7 @@ if (saved_size == 0) (long int)time(NULL)); for (i = 0; i < MBX_NUSERFLAGS; i++) sprintf (CS(s += Ustrlen(s)), "\015\012"); - if (!transport_write_block (to_fd, deliver_out_buffer, MBX_HDRSIZE)) + if (!transport_write_block (&tctx, deliver_out_buffer, MBX_HDRSIZE, FALSE)) return DEFER; } @@ -947,7 +964,7 @@ used = Ustrlen(deliver_out_buffer); /* Rewind the temporary file, and copy it over in chunks. */ -lseek(from_fd, 0 , SEEK_SET); +if (lseek(from_fd, 0 , SEEK_SET) < 0) return DEFER; while (size > 0) { @@ -958,7 +975,7 @@ while (size > 0) if (len == 0) errno = ERRNO_MBXLENGTH; return DEFER; } - if (!transport_write_block(to_fd, deliver_out_buffer, used + len)) + if (!transport_write_block(&tctx, deliver_out_buffer, used + len, FALSE)) return DEFER; size -= len; used = 0; @@ -1147,7 +1164,7 @@ directory name) is given, that is, when appending to a single file: Open with O_WRONLY + O_EXCL + O_CREAT with configured mode, unless we know this is via a symbolic link (only possible if allow_symlinks is set), in - which case don't use O_EXCL, as it dosn't work. + which case don't use O_EXCL, as it doesn't work. If open fails because the file already exists, go to (6f). To avoid looping for ever in a situation where the file is continuously being @@ -1381,10 +1398,13 @@ else DEBUG(D_transport) { debug_printf("appendfile: mode=%o notify_comsat=%d quota=" OFF_T_FMT + "%s" " warning=" OFF_T_FMT "%s\n" " %s=%s format=%s\n message_prefix=%s\n message_suffix=%s\n " "maildir_use_size_file=%s\n", mode, ob->notify_comsat, ob->quota_value, + ob->quota_no_check? " (no_check)" : "", + ob->quota_filecount_no_check? " (no_check_filecount)" : "", ob->quota_warn_threshold_value, ob->quota_warn_threshold_is_percent? "%" : "", isdirectory? "directory" : "file", @@ -2775,21 +2795,33 @@ if (!disable_quota && ob->quota_value > 0) debug_printf(" file count quota = %d count = %d\n", ob->quota_filecount_value, mailbox_filecount); } + if (mailbox_size + (ob->quota_is_inclusive? message_size:0) > ob->quota_value) { - DEBUG(D_transport) debug_printf("mailbox quota exceeded\n"); - yield = DEFER; - errno = ERRNO_EXIMQUOTA; - } - else if (ob->quota_filecount_value > 0 && - mailbox_filecount + (ob->quota_is_inclusive ? 1:0) > - ob->quota_filecount_value) - { - DEBUG(D_transport) debug_printf("mailbox file count quota exceeded\n"); - yield = DEFER; - errno = ERRNO_EXIMQUOTA; - filecount_msg = US" filecount"; + + if (!ob->quota_no_check) + { + DEBUG(D_transport) debug_printf("mailbox quota exceeded\n"); + yield = DEFER; + errno = ERRNO_EXIMQUOTA; + } + else DEBUG(D_transport) debug_printf("mailbox quota exceeded but ignored\n"); + } + + if (ob->quota_filecount_value > 0 + && mailbox_filecount + (ob->quota_is_inclusive ? 1:0) > + ob->quota_filecount_value) + if(!ob->quota_filecount_no_check) + { + DEBUG(D_transport) debug_printf("mailbox file count quota exceeded\n"); + yield = DEFER; + errno = ERRNO_EXIMQUOTA; + filecount_msg = US" filecount"; + } + else DEBUG(D_transport) if (ob->quota_filecount_no_check) + debug_printf("mailbox file count quota exceeded but ignored\n"); + } /* If we are writing in MBX format, what we actually do is to write the message @@ -2875,13 +2907,14 @@ at initialization time. */ if (yield == OK) { transport_ctx tctx = { + fd, tblock, addr, ob->check_string, ob->escape_string, ob->options }; - if (!transport_write_message(fd, &tctx, 0)) + if (!transport_write_message(&tctx, 0)) yield = DEFER; } @@ -3129,7 +3162,7 @@ if (yield != OK) fcntl() call (BSDI & FreeBSD do not). */ if (!isdirectory && ftruncate(fd, saved_size)) - DEBUG(D_transport) debug_printf("Error restting file size\n"); + DEBUG(D_transport) debug_printf("Error resetting file size\n"); } /* Handle successful writing - we want the modification time to be now for