diff options
author | Jacek Masiulaniec <jacekm@cvs.openbsd.org> | 2009-01-06 20:17:24 +0000 |
---|---|---|
committer | Jacek Masiulaniec <jacekm@cvs.openbsd.org> | 2009-01-06 20:17:24 +0000 |
commit | 57beca5400c36e5f3003e1652339d8c4b45bf7b3 (patch) | |
tree | b6b6a70cb108b1e0286a6ecb5b467a56324afe99 | |
parent | 2c1947e29aa50541dced600f4de43d3acebca486 (diff) |
make file update in queue_update_envelope atomic; ok gilles@
-rw-r--r-- | usr.sbin/smtpd/queue.c | 42 | ||||
-rw-r--r-- | usr.sbin/smtpd/runner.c | 13 |
2 files changed, 43 insertions, 12 deletions
diff --git a/usr.sbin/smtpd/queue.c b/usr.sbin/smtpd/queue.c index b8ef27480d6..48ef05d398f 100644 --- a/usr.sbin/smtpd/queue.c +++ b/usr.sbin/smtpd/queue.c @@ -1,4 +1,4 @@ -/* $OpenBSD: queue.c,v 1.43 2009/01/04 00:58:59 gilles Exp $ */ +/* $OpenBSD: queue.c,v 1.44 2009/01/06 20:17:23 jacekm Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -836,26 +836,48 @@ queue_remove_envelope(struct message *messagep) int queue_update_envelope(struct message *messagep) { - char pathname[MAXPATHLEN]; + char temp[MAXPATHLEN]; + char dest[MAXPATHLEN]; FILE *fp; - if (! bsnprintf(pathname, MAXPATHLEN, "%s/%d/%s%s/%s", PATH_QUEUE, + if (! bsnprintf(temp, MAXPATHLEN, "%s/envelope.tmp", PATH_INCOMING)) + fatalx("queue_update_envelope"); + + if (! bsnprintf(dest, MAXPATHLEN, "%s/%d/%s%s/%s", PATH_QUEUE, queue_hash(messagep->message_id), messagep->message_id, PATH_ENVELOPES, messagep->message_uid)) fatal("queue_update_envelope: snprintf"); - fp = fopen(pathname, "w"); - if (fp == NULL) + fp = fopen(temp, "w"); + if (fp == NULL) { + if (errno == ENOSPC || errno == ENFILE) + goto tempfail; fatal("queue_update_envelope: open"); - if (flock(fileno(fp), LOCK_EX) == -1) - fatal("queue_update_envelope: flock"); - + } if (fwrite(messagep, sizeof(struct message), 1, fp) != 1) { if (errno == ENOSPC) - return 0; + goto tempfail; fatal("queue_update_envelope: fwrite"); } - return safe_fclose(fp); + if (! safe_fclose(fp)) + goto tempfail; + + if (rename(temp, dest) == -1) { + if (errno == ENOSPC) + goto tempfail; + fatal("queue_update_envelope: rename"); + } + + return 1; + +tempfail: + if (unlink(temp) == -1) + if (errno != ENOENT) + fatal("queue_update_envelope: unlink"); + if (fp) + fclose(fp); + + return 0; } int diff --git a/usr.sbin/smtpd/runner.c b/usr.sbin/smtpd/runner.c index 2f5de6426f9..40d4efbd2fd 100644 --- a/usr.sbin/smtpd/runner.c +++ b/usr.sbin/smtpd/runner.c @@ -1,4 +1,4 @@ -/* $OpenBSD: runner.c,v 1.19 2009/01/04 22:35:09 gilles Exp $ */ +/* $OpenBSD: runner.c,v 1.20 2009/01/06 20:17:23 jacekm Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -802,7 +802,16 @@ runner_purge_run(void) strcmp(dp->d_name, "..") == 0) { continue; } - runner_purge_message(dp->d_name); + if (strcmp(dp->d_name, "envelope.tmp") == 0) { + char path[MAXPATHLEN]; + + if (! bsnprintf(path, MAXPATHLEN, "%s/envelope.tmp", + PATH_PURGE)) + fatalx("runner_purge_run: snprintf"); + if (unlink(path) == -1) + fatal("runner_purge_run: unlink"); + } else + runner_purge_message(dp->d_name); } closedir(dirp); |