summaryrefslogtreecommitdiff
path: root/usr.sbin/smtpd/queue.c
diff options
context:
space:
mode:
authorJacek Masiulaniec <jacekm@cvs.openbsd.org>2009-01-12 19:54:38 +0000
committerJacek Masiulaniec <jacekm@cvs.openbsd.org>2009-01-12 19:54:38 +0000
commit804baf80997663515e2df25cec9c289468eded8a (patch)
treef25c7ac70bb186b917750d08a664938ec05111dd /usr.sbin/smtpd/queue.c
parent6e2a318ba34b89a014a706440792cddf8d0b758d (diff)
more checks in queue_record_incoming_envelope; ok gilles@
Diffstat (limited to 'usr.sbin/smtpd/queue.c')
-rw-r--r--usr.sbin/smtpd/queue.c74
1 files changed, 36 insertions, 38 deletions
diff --git a/usr.sbin/smtpd/queue.c b/usr.sbin/smtpd/queue.c
index 48ef05d398f..2463ca6f978 100644
--- a/usr.sbin/smtpd/queue.c
+++ b/usr.sbin/smtpd/queue.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: queue.c,v 1.44 2009/01/06 20:17:23 jacekm Exp $ */
+/* $OpenBSD: queue.c,v 1.45 2009/01/12 19:54:37 jacekm Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -694,54 +694,52 @@ queue_delete_incoming_message(char *msgid)
int
queue_record_incoming_envelope(struct message *message)
{
- char evpdir[MAXPATHLEN];
char evpname[MAXPATHLEN];
- char message_uid[MAXPATHLEN];
- int fd;
- int mode = O_CREAT|O_WRONLY|O_EXCL|O_SYNC;
FILE *fp;
- int ret;
+ int fd;
- if (! bsnprintf(evpdir, MAXPATHLEN, "%s/%s%s", PATH_INCOMING,
- message->message_id, PATH_ENVELOPES))
- fatal("queue_record_incoming_envelope: snprintf");
+again:
+ if (! bsnprintf(evpname, MAXPATHLEN, "%s/%s%s/%s.%qu", PATH_INCOMING,
+ message->message_id, PATH_ENVELOPES, message->message_id,
+ (u_int64_t)arc4random()))
+ fatalx("queue_record_incoming_envelope: snprintf");
- for (;;) {
- if (! bsnprintf(evpname, MAXPATHLEN, "%s/%s.%qu", evpdir,
- message->message_id, (u_int64_t)arc4random()))
- fatal("queue_record_incoming_envelope: snprintf");
+ fd = open(evpname, O_WRONLY|O_CREAT|O_EXCL, 0600);
+ if (fd == -1) {
+ if (errno == EEXIST)
+ goto again;
+ if (errno == ENOSPC || errno == ENFILE)
+ goto tempfail;
+ fatal("queue_record_incoming_envelope: open");
+ }
- (void)strlcpy(message_uid, evpname + strlen(evpdir) + 1, MAXPATHLEN);
+ fp = fdopen(fd, "w");
+ if (fp == NULL)
+ fatal("queue_record_incoming_envelope: fdopen");
- fd = open(evpname, mode, 0600);
- if (fd == -1) {
- if (errno == EEXIST)
- continue;
- return 0;
- }
+ message->creation = time(NULL);
+ if (strlcpy(message->message_uid, strrchr(evpname, '/') + 1, MAXPATHLEN)
+ >= MAXPATHLEN)
+ fatalx("queue_record_incoming_envelope: truncation");
- fp = fdopen(fd, "w");
- if (fp == NULL)
- fatal("fdopen");
+ if (fwrite(message, sizeof (struct message), 1, fp) != 1) {
+ if (errno == ENOSPC)
+ goto tempfail;
+ fatal("queue_record_incoming_envelope: write");
+ }
- if (strlcpy(message->message_uid, message_uid, MAXPATHLEN)
- >= MAXPATHLEN)
- fatal("queue_record_incoming_envelope: strlcpy");
+ if (! safe_fclose(fp))
+ goto tempfail;
- message->creation = time(NULL);
+ return 1;
- if ((ret = fwrite(message, sizeof (struct message), 1, fp)) != 1) {
- fclose(fp);
- unlink(evpname);
- return 0;
- }
- fflush(fp);
- fsync(fd);
- fclose(fp);
+tempfail:
+ unlink(evpname);
+ close(fd);
+ message->creation = 0;
+ message->message_uid[0] = '\0';
- break;
- }
- return 1;
+ return 0;
}
int