summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacek Masiulaniec <jacekm@cvs.openbsd.org>2009-01-06 20:17:24 +0000
committerJacek Masiulaniec <jacekm@cvs.openbsd.org>2009-01-06 20:17:24 +0000
commit57beca5400c36e5f3003e1652339d8c4b45bf7b3 (patch)
treeb6b6a70cb108b1e0286a6ecb5b467a56324afe99
parent2c1947e29aa50541dced600f4de43d3acebca486 (diff)
make file update in queue_update_envelope atomic; ok gilles@
-rw-r--r--usr.sbin/smtpd/queue.c42
-rw-r--r--usr.sbin/smtpd/runner.c13
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);