diff options
Diffstat (limited to 'usr.sbin/smtpd/queue_fsqueue.c')
-rw-r--r-- | usr.sbin/smtpd/queue_fsqueue.c | 186 |
1 files changed, 71 insertions, 115 deletions
diff --git a/usr.sbin/smtpd/queue_fsqueue.c b/usr.sbin/smtpd/queue_fsqueue.c index 1488b356ff2..f498fbf71aa 100644 --- a/usr.sbin/smtpd/queue_fsqueue.c +++ b/usr.sbin/smtpd/queue_fsqueue.c @@ -1,4 +1,4 @@ -/* $OpenBSD: queue_fsqueue.c,v 1.43 2012/07/02 13:22:14 eric Exp $ */ +/* $OpenBSD: queue_fsqueue.c,v 1.44 2012/07/08 18:13:08 chl Exp $ */ /* * Copyright (c) 2011 Gilles Chehade <gilles@openbsd.org> @@ -42,25 +42,18 @@ #include "smtpd.h" #include "log.h" -enum queue_kind { - Q_INCOMING, - Q_QUEUE, - Q_CORRUPT -}; - -static int fsqueue_envelope_load(enum queue_kind, struct envelope *); -static int fsqueue_envelope_update(enum queue_kind, struct envelope *); -static int fsqueue_envelope_delete(enum queue_kind, struct envelope *); +static int fsqueue_envelope_load(struct envelope *); +static int fsqueue_envelope_update(struct envelope *); +static int fsqueue_envelope_delete(struct envelope *); -static int fsqueue_message_create(enum queue_kind, u_int32_t *); -static int fsqueue_message_commit(enum queue_kind, u_int32_t); -static int fsqueue_message_fd_r(enum queue_kind, u_int32_t); -static int fsqueue_message_fd_rw(enum queue_kind, u_int32_t); -static int fsqueue_message_delete(enum queue_kind, u_int32_t); -static int fsqueue_message_corrupt(enum queue_kind, u_int32_t); +static int fsqueue_message_create(u_int32_t *); +static int fsqueue_message_commit(u_int32_t); +static int fsqueue_message_fd_r(u_int32_t); +static int fsqueue_message_delete(u_int32_t); +static int fsqueue_message_corrupt(u_int32_t); -static int fsqueue_message_path(enum queue_kind, uint32_t, char *, size_t); -static int fsqueue_envelope_path(enum queue_kind, u_int64_t, char *, size_t); +static int fsqueue_message_path(uint32_t, char *, size_t); +static int fsqueue_envelope_path(u_int64_t, char *, size_t); static int fsqueue_envelope_dump_atomic(char *, struct envelope *); static int fsqueue_init(int); @@ -71,13 +64,9 @@ static void *fsqueue_qwalk_new(u_int32_t); static int fsqueue_qwalk(void *, u_int64_t *); static void fsqueue_qwalk_close(void *); -#define PATH_INCOMING "/incoming" #define PATH_QUEUE "/queue" #define PATH_CORRUPT "/corrupt" -#define PATH_MESSAGE "/message" -#define PATH_ENVELOPES "/envelopes" - #define PATH_EVPTMP PATH_INCOMING "/envelope.tmp" struct queue_backend queue_backend_fs = { @@ -90,46 +79,30 @@ struct queue_backend queue_backend_fs = { }; static int -fsqueue_message_path(enum queue_kind qkind, uint32_t msgid, char *buf, size_t len) +fsqueue_message_path(uint32_t msgid, char *buf, size_t len) { - switch (qkind) { - case Q_QUEUE: - return bsnprintf(buf, len, "%s/%03x/%08x", - PATH_QUEUE, - msgid & 0xfff, - msgid); - case Q_INCOMING: - case Q_CORRUPT: - return bsnprintf(buf, len, "%s/%08x", - qkind == Q_INCOMING ? PATH_INCOMING : PATH_CORRUPT, - msgid); - default: - fatalx("fsqueue_message_path: unsupported queue kind."); - } - return (0); + return bsnprintf(buf, len, "%s/%03x/%08x", + PATH_QUEUE, + msgid & 0xfff, + msgid); } static int -fsqueue_envelope_path(enum queue_kind qkind, uint64_t evpid, char *buf, size_t len) +fsqueue_message_corrupt_path(uint32_t msgid, char *buf, size_t len) { - switch (qkind) { - case Q_QUEUE: - return bsnprintf(buf, len, "%s/%03x/%08x%s/%016" PRIx64, - PATH_QUEUE, - evpid_to_msgid(evpid) & 0xfff, - evpid_to_msgid(evpid), - PATH_ENVELOPES, evpid); - case Q_INCOMING: - case Q_CORRUPT: - return bsnprintf(buf, len, "%s/%08x%s/%016" PRIx64, - qkind == Q_INCOMING ? PATH_INCOMING : PATH_CORRUPT, - evpid_to_msgid(evpid), - PATH_ENVELOPES, evpid); - default: - fatalx("fsqueue_envelope_path: unsupported queue kind."); - } + return bsnprintf(buf, len, "%s/%08x", + PATH_CORRUPT, + msgid); +} - return (0); +static int +fsqueue_envelope_path(uint64_t evpid, char *buf, size_t len) +{ + return bsnprintf(buf, len, "%s/%03x/%08x%s/%016" PRIx64, + PATH_QUEUE, + evpid_to_msgid(evpid) & 0xfff, + evpid_to_msgid(evpid), + PATH_ENVELOPES, evpid); } static int @@ -178,7 +151,7 @@ tempfail: } static int -fsqueue_envelope_create(enum queue_kind qkind, struct envelope *ep) +fsqueue_envelope_create(struct envelope *ep) { char evpname[MAXPATHLEN]; u_int64_t evpid; @@ -186,7 +159,11 @@ fsqueue_envelope_create(enum queue_kind qkind, struct envelope *ep) again: evpid = queue_generate_evpid(evpid_to_msgid(ep->id)); - fsqueue_envelope_path(qkind, evpid, evpname, sizeof(evpname)); + if (ep->type == D_BOUNCE) + fsqueue_envelope_path(evpid, evpname, sizeof(evpname)); + else + queue_envelope_incoming_path(evpid, evpname, sizeof(evpname)); + if (stat(evpname, &sb) != -1 || errno != ENOENT) goto again; ep->id = evpid; @@ -195,13 +172,13 @@ again: } static int -fsqueue_envelope_load(enum queue_kind qkind, struct envelope *ep) +fsqueue_envelope_load(struct envelope *ep) { char pathname[MAXPATHLEN]; FILE *fp; int ret; - fsqueue_envelope_path(qkind, ep->id, pathname, sizeof(pathname)); + fsqueue_envelope_path(ep->id, pathname, sizeof(pathname)); fp = fopen(pathname, "r"); if (fp == NULL) { @@ -217,23 +194,23 @@ fsqueue_envelope_load(enum queue_kind qkind, struct envelope *ep) } static int -fsqueue_envelope_update(enum queue_kind qkind, struct envelope *ep) +fsqueue_envelope_update(struct envelope *ep) { char dest[MAXPATHLEN]; - fsqueue_envelope_path(qkind, ep->id, dest, sizeof(dest)); + fsqueue_envelope_path(ep->id, dest, sizeof(dest)); return (fsqueue_envelope_dump_atomic(dest, ep)); } static int -fsqueue_envelope_delete(enum queue_kind qkind, struct envelope *ep) +fsqueue_envelope_delete(struct envelope *ep) { char pathname[MAXPATHLEN]; log_debug("#### %s: queue_envelope_delete: %016" PRIx64, __func__, ep->id); - fsqueue_envelope_path(qkind, ep->id, pathname, sizeof(pathname)); + fsqueue_envelope_path(ep->id, pathname, sizeof(pathname)); if (unlink(pathname) == -1) { log_debug("######: %s [errno: %d]", pathname, errno); @@ -243,13 +220,13 @@ fsqueue_envelope_delete(enum queue_kind qkind, struct envelope *ep) *strrchr(pathname, '/') = '\0'; if (rmdir(pathname) != -1) - fsqueue_message_delete(qkind, evpid_to_msgid(ep->id)); + fsqueue_message_delete(evpid_to_msgid(ep->id)); return 1; } static int -fsqueue_message_create(enum queue_kind qkind, u_int32_t *msgid) +fsqueue_message_create(u_int32_t *msgid) { char rootdir[MAXPATHLEN]; char evpdir[MAXPATHLEN]; @@ -259,11 +236,11 @@ again: *msgid = queue_generate_msgid(); /* prevent possible collision later when moving to Q_QUEUE */ - fsqueue_message_path(Q_QUEUE, *msgid, rootdir, sizeof(rootdir)); + fsqueue_message_path(*msgid, rootdir, sizeof(rootdir)); if (stat(rootdir, &sb) != -1 || errno != ENOENT) goto again; - fsqueue_message_path(qkind, *msgid, rootdir, sizeof(rootdir)); + queue_message_incoming_path(*msgid, rootdir, sizeof(rootdir)); if (mkdir(rootdir, 0700) == -1) { if (errno == EEXIST) goto again; @@ -291,14 +268,14 @@ again: } static int -fsqueue_message_commit(enum queue_kind qkind, u_int32_t msgid) +fsqueue_message_commit(u_int32_t msgid) { - char rootdir[MAXPATHLEN]; + char incomingdir[MAXPATHLEN]; char queuedir[MAXPATHLEN]; char msgdir[MAXPATHLEN]; - fsqueue_message_path(qkind, msgid, rootdir, sizeof(rootdir)); - fsqueue_message_path(Q_QUEUE, msgid, msgdir, sizeof(msgdir)); + queue_message_incoming_path(msgid, incomingdir, sizeof(incomingdir)); + fsqueue_message_path(msgid, msgdir, sizeof(msgdir)); strlcpy(queuedir, msgdir, sizeof(queuedir)); *strrchr(queuedir, '/') = '\0'; @@ -309,7 +286,7 @@ fsqueue_message_commit(enum queue_kind qkind, u_int32_t msgid) fatal("fsqueue_message_commit: mkdir"); } - if (rename(rootdir, msgdir) == -1) { + if (rename(incomingdir, msgdir) == -1) { if (errno == ENOSPC) return 0; fatal("fsqueue_message_commit: rename"); @@ -319,12 +296,12 @@ fsqueue_message_commit(enum queue_kind qkind, u_int32_t msgid) } static int -fsqueue_message_fd_r(enum queue_kind qkind, u_int32_t msgid) +fsqueue_message_fd_r(u_int32_t msgid) { int fd; char path[MAXPATHLEN]; - fsqueue_message_path(qkind, msgid, path, sizeof(path)); + fsqueue_message_path(msgid, path, sizeof(path)); strlcat(path, PATH_MESSAGE, sizeof(path)); if ((fd = open(path, O_RDONLY)) == -1) @@ -334,22 +311,12 @@ fsqueue_message_fd_r(enum queue_kind qkind, u_int32_t msgid) } static int -fsqueue_message_fd_rw(enum queue_kind qkind, u_int32_t msgid) -{ - char path[MAXPATHLEN]; - - fsqueue_message_path(qkind, msgid, path, sizeof(path)); - strlcat(path, PATH_MESSAGE, sizeof(path)); - - return open(path, O_CREAT|O_EXCL|O_RDWR, 0600); -} - -static int -fsqueue_message_delete(enum queue_kind qkind, u_int32_t msgid) +fsqueue_message_delete(u_int32_t msgid) { char rootdir[MAXPATHLEN]; - fsqueue_message_path(qkind, msgid, rootdir, sizeof(rootdir)); + if (! fsqueue_message_path(msgid, rootdir, sizeof(rootdir))) + fatal("fsqueue_message_delete: snprintf"); if (rmtree(rootdir, 0) == -1) fatal("fsqueue_message_delete: rmtree"); @@ -358,7 +325,7 @@ fsqueue_message_delete(enum queue_kind qkind, u_int32_t msgid) } static int -fsqueue_message_corrupt(enum queue_kind qkind, u_int32_t msgid) +fsqueue_message_corrupt(u_int32_t msgid) { struct stat sb; char rootdir[MAXPATHLEN]; @@ -366,11 +333,12 @@ fsqueue_message_corrupt(enum queue_kind qkind, u_int32_t msgid) char buf[64]; int retry = 0; - fsqueue_message_path(qkind, msgid, rootdir, sizeof(rootdir)); - fsqueue_message_path(Q_CORRUPT, msgid, corruptdir, sizeof(corruptdir)); + fsqueue_message_path(msgid, rootdir, sizeof(rootdir)); + fsqueue_message_corrupt_path(msgid, corruptdir, sizeof(corruptdir)); + again: if (stat(corruptdir, &sb) != -1 || errno != ENOENT) { - fsqueue_message_path(Q_CORRUPT, msgid, corruptdir, sizeof(corruptdir)); + fsqueue_message_corrupt_path(msgid, corruptdir, sizeof(corruptdir)); snprintf(buf, sizeof(buf), ".%i", retry++); strlcat(corruptdir, buf, sizeof(corruptdir)); goto again; @@ -386,17 +354,12 @@ static int fsqueue_init(int server) { unsigned int n; - char *paths[] = { PATH_INCOMING, PATH_QUEUE, PATH_CORRUPT }; + char *paths[] = { PATH_QUEUE, PATH_CORRUPT }; char path[MAXPATHLEN]; int ret; - if (!fsqueue_envelope_path(Q_QUEUE, 0, path, sizeof(path))) + if (!fsqueue_envelope_path(0, path, sizeof(path))) errx(1, "cannot store envelope path in %s", PATH_QUEUE); - if (!fsqueue_envelope_path(Q_INCOMING, 0, path, sizeof(path))) - errx(1, "cannot store envelope path in %s", PATH_INCOMING); - - if (server) - mvpurge(PATH_SPOOL PATH_INCOMING, PATH_SPOOL PATH_PURGE); ret = 1; for (n = 0; n < nitems(paths); n++) { @@ -416,22 +379,19 @@ fsqueue_message(enum queue_op qop, u_int32_t *msgid) { switch (qop) { case QOP_CREATE: - return fsqueue_message_create(Q_INCOMING, msgid); + return fsqueue_message_create(msgid); case QOP_DELETE: - return fsqueue_message_delete(Q_INCOMING, *msgid); + return fsqueue_message_delete(*msgid); case QOP_COMMIT: - return fsqueue_message_commit(Q_INCOMING, *msgid); + return fsqueue_message_commit(*msgid); case QOP_FD_R: - return fsqueue_message_fd_r(Q_QUEUE, *msgid); - - case QOP_FD_RW: - return fsqueue_message_fd_rw(Q_INCOMING, *msgid); + return fsqueue_message_fd_r(*msgid); case QOP_CORRUPT: - return fsqueue_message_corrupt(Q_QUEUE, *msgid); + return fsqueue_message_corrupt(*msgid); default: fatalx("queue_fsqueue_message: unsupported operation."); @@ -445,20 +405,16 @@ fsqueue_envelope(enum queue_op qop, struct envelope *m) { switch (qop) { case QOP_CREATE: - /* currently, only bounce envelopes are created in queued - * messages - */ - return fsqueue_envelope_create( - m->type == D_BOUNCE ? Q_QUEUE : Q_INCOMING, m); + return fsqueue_envelope_create(m); case QOP_DELETE: - return fsqueue_envelope_delete(Q_QUEUE, m); + return fsqueue_envelope_delete(m); case QOP_LOAD: - return fsqueue_envelope_load(Q_QUEUE, m); + return fsqueue_envelope_load(m); case QOP_UPDATE: - return fsqueue_envelope_update(Q_QUEUE, m); + return fsqueue_envelope_update(m); default: fatalx("queue_fsqueue_envelope: unsupported operation."); |