Exemplo n.º 1
0
static int do_unuser(const char *userid)
{
    const char *cmd = "UNUSER";
    struct mailbox *mailbox = NULL;
    char buf[MAX_MAILBOX_BUFFER];
    struct dlist *kl;
    int r;

    /* check local mailbox first */
    (sync_namespace.mboxname_tointernal)(&sync_namespace, "INBOX",
					  userid, buf);
    r = mailbox_open_irl(buf, &mailbox);

    /* only remove from server if there's no local mailbox */
    if (r == IMAP_MAILBOX_NONEXISTENT) {
	kl = dlist_setatom(NULL, cmd, userid);
	sync_send_apply(kl, sync_out);
	dlist_free(&kl);

	r = sync_parse_response(cmd, sync_in, NULL);
	if (r == IMAP_MAILBOX_NONEXISTENT) r = 0;
    }

    mailbox_close(&mailbox);

    return r;
}
Exemplo n.º 2
0
static int do_unuser(const char *userid)
{
    const char *cmd = "UNUSER";
    struct mailbox *mailbox = NULL;
    struct dlist *kl;
    int r;

    /* nothing to do if there's no userid */
    if (!userid || !userid[0]) {
        syslog(LOG_WARNING, "ignoring attempt to %s() without userid", __func__);
        return 0;
    }

    /* check local mailbox first */
    char *inbox = mboxname_user_mbox(userid, NULL);
    r = mailbox_open_irl(inbox, &mailbox);

    /* only remove from server if there's no local mailbox */
    if (r == IMAP_MAILBOX_NONEXISTENT) {
        kl = dlist_setatom(NULL, cmd, userid);
        sync_send_apply(kl, sync_out);
        dlist_free(&kl);

        r = sync_parse_response(cmd, sync_in, NULL);
        if (r == IMAP_MAILBOX_NONEXISTENT) r = 0;
    }

    mailbox_close(&mailbox);
    free(inbox);

    return r;
}
Exemplo n.º 3
0
static int do_restart()
{
    static int restartcnt = 0;

    if (sync_out->userdata) {
	/* IMAP flavor (w/ tag) */
	prot_printf(sync_out, "R%d SYNC", restartcnt++);
    }
    prot_printf(sync_out, "RESTART\r\n");
    prot_flush(sync_out);
    return sync_parse_response("RESTART", sync_in, NULL);
}
Exemplo n.º 4
0
static int do_restart()
{
    static int restartcnt = 0;

    if (sync_out->userdata) {
        /* IMAP flavor (w/ tag) */
        struct buf *tag = (struct buf *) sync_out->userdata;
        buf_reset(tag);
        buf_printf(tag, "R%d", restartcnt++);
        prot_printf(sync_out, "%s SYNC", buf_cstring(tag));
    }
    prot_printf(sync_out, "RESTART\r\n");
    prot_flush(sync_out);
    return sync_parse_response("RESTART", sync_in, NULL);
}
Exemplo n.º 5
0
static void replica_connect(const char *channel)
{
    int wait;
    struct protoent *proto;
    sasl_callback_t *cb;
    int timeout;
    const char *port, *auth_status = NULL;

    cb = mysasl_callbacks(NULL,
                          get_config(channel, "sync_authname"),
                          get_config(channel, "sync_realm"),
                          get_config(channel, "sync_password"));

    /* get the right port */
    port = get_config(channel, "sync_port");
    if (port) {
        imap_csync_protocol.service = port;
        csync_protocol.service = port;
    }

    for (wait = 15;; wait *= 2) {
        sync_backend = backend_connect(sync_backend, servername,
                                       &imap_csync_protocol, "", cb, &auth_status,
                                       (verbose > 1 ? fileno(stderr) : -1));

        if (sync_backend) {
            if (sync_backend->capability & CAPA_REPLICATION) {
                /* attach our IMAP tag buffer to our protstreams as userdata */
                sync_backend->in->userdata = sync_backend->out->userdata = &tagbuf;
                break;
            }
            else {
                backend_disconnect(sync_backend);
                sync_backend = NULL;
            }
        }

        sync_backend = backend_connect(sync_backend, servername,
                                       &csync_protocol, "", cb, NULL,
                                       (verbose > 1 ? fileno(stderr) : -1));

        if (sync_backend || auth_status || connect_once || wait > 1000) break;

        fprintf(stderr,
                "Can not connect to server '%s', retrying in %d seconds\n",
                servername, wait);
        sleep(wait);
    }

    free_callbacks(cb);
    cb = NULL;

    if (!sync_backend) {
        fprintf(stderr, "Can not connect to server '%s'\n",
                servername);
        syslog(LOG_ERR, "Can not connect to server '%s'", servername);
        _exit(1);
    }

    /* Disable Nagle's Algorithm => increase throughput
     *
     * http://en.wikipedia.org/wiki/Nagle's_algorithm
     */
    if (servername[0] != '/') {
        if (sync_backend->sock >= 0 && (proto = getprotobyname("tcp")) != NULL) {
            int on = 1;

            if (setsockopt(sync_backend->sock, proto->p_proto, TCP_NODELAY,
                           (void *) &on, sizeof(on)) != 0) {
                syslog(LOG_ERR, "unable to setsocketopt(TCP_NODELAY): %m");
            }

            /* turn on TCP keepalive if set */
            if (config_getswitch(IMAPOPT_TCP_KEEPALIVE)) {
                int r;
                int optval = 1;
                socklen_t optlen = sizeof(optval);
                struct protoent *proto = getprotobyname("TCP");

                r = setsockopt(sync_backend->sock, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen);
                if (r < 0) {
                    syslog(LOG_ERR, "unable to setsocketopt(SO_KEEPALIVE): %m");
                }
#ifdef TCP_KEEPCNT
                optval = config_getint(IMAPOPT_TCP_KEEPALIVE_CNT);
                if (optval) {
                    r = setsockopt(sync_backend->sock, proto->p_proto, TCP_KEEPCNT, &optval, optlen);
                    if (r < 0) {
                        syslog(LOG_ERR, "unable to setsocketopt(TCP_KEEPCNT): %m");
                    }
                }
#endif
#ifdef TCP_KEEPIDLE
                optval = config_getint(IMAPOPT_TCP_KEEPALIVE_IDLE);
                if (optval) {
                    r = setsockopt(sync_backend->sock, proto->p_proto, TCP_KEEPIDLE, &optval, optlen);
                    if (r < 0) {
                        syslog(LOG_ERR, "unable to setsocketopt(TCP_KEEPIDLE): %m");
                    }
                }
#endif
#ifdef TCP_KEEPINTVL
                optval = config_getint(IMAPOPT_TCP_KEEPALIVE_INTVL);
                if (optval) {
                    r = setsockopt(sync_backend->sock, proto->p_proto, TCP_KEEPINTVL, &optval, optlen);
                    if (r < 0) {
                        syslog(LOG_ERR, "unable to setsocketopt(TCP_KEEPINTVL): %m");
                    }
                }
#endif
            }
        } else {
            syslog(LOG_ERR, "unable to getprotobyname(\"tcp\"): %m");
        }
    }

#ifdef HAVE_ZLIB
    /* Does the backend support compression? */
    if (CAPA(sync_backend, CAPA_COMPRESS)) {
        prot_printf(sync_backend->out, "%s\r\n",
                    sync_backend->prot->u.std.compress_cmd.cmd);
        prot_flush(sync_backend->out);

        if (sync_parse_response("COMPRESS", sync_backend->in, NULL)) {
            if (do_compress) fatal("Failed to enable compression, aborting", EC_SOFTWARE);
            syslog(LOG_NOTICE, "Failed to enable compression, continuing uncompressed");
        }
        else {
            prot_setcompress(sync_backend->in);
            prot_setcompress(sync_backend->out);
        }
    }
    else if (do_compress) fatal("Backend does not support compression, aborting", EC_SOFTWARE);
#endif

    /* links to sockets */
    sync_in = sync_backend->in;
    sync_out = sync_backend->out;

    if (verbose > 1) {
        prot_setlog(sync_in, fileno(stderr));
        prot_setlog(sync_out, fileno(stderr));
    }

    /* Set inactivity timer */
    timeout = config_getint(IMAPOPT_SYNC_TIMEOUT);
    if (timeout < 3) timeout = 3;
    prot_settimeout(sync_in, timeout);

    /* Force use of LITERAL+ so we don't need two way communications */
    prot_setisclient(sync_in, 1);
    prot_setisclient(sync_out, 1);
}
Exemplo n.º 6
0
static void replica_connect(const char *channel)
{
    int wait;
    sasl_callback_t *cb;
    int timeout;
    const char *port, *auth_status = NULL;

    cb = mysasl_callbacks(NULL,
                          get_config(channel, "sync_authname"),
                          get_config(channel, "sync_realm"),
                          get_config(channel, "sync_password"));

    /* get the right port */
    port = get_config(channel, "sync_port");
    if (port) {
        imap_csync_protocol.service = port;
        csync_protocol.service = port;
    }

    for (wait = 15;; wait *= 2) {
        sync_backend = backend_connect(sync_backend, servername,
                                       &imap_csync_protocol, "", cb, &auth_status,
                                       (verbose > 1 ? fileno(stderr) : -1));

        if (sync_backend) {
            if (sync_backend->capability & CAPA_REPLICATION) {
                /* attach our IMAP tag buffer to our protstreams as userdata */
                sync_backend->in->userdata = sync_backend->out->userdata = &tagbuf;
                break;
            }
            else {
                backend_disconnect(sync_backend);
                sync_backend = NULL;
            }
        }

        sync_backend = backend_connect(sync_backend, servername,
                                       &csync_protocol, "", cb, NULL,
                                       (verbose > 1 ? fileno(stderr) : -1));

        if (sync_backend || auth_status || connect_once || wait > 1000) break;

        fprintf(stderr,
                "Can not connect to server '%s', retrying in %d seconds\n",
                servername, wait);
        sleep(wait);
    }

    free_callbacks(cb);
    cb = NULL;

    if (!sync_backend) {
        fprintf(stderr, "Can not connect to server '%s'\n",
                servername);
        syslog(LOG_ERR, "Can not connect to server '%s'", servername);
        _exit(1);
    }

    if (servername[0] != '/' && sync_backend->sock >= 0) {
        tcp_disable_nagle(sync_backend->sock);
        tcp_enable_keepalive(sync_backend->sock);
    }

#ifdef HAVE_ZLIB
    /* Does the backend support compression? */
    if (CAPA(sync_backend, CAPA_COMPRESS)) {
        prot_printf(sync_backend->out, "%s\r\n",
                    sync_backend->prot->u.std.compress_cmd.cmd);
        prot_flush(sync_backend->out);

        if (sync_parse_response("COMPRESS", sync_backend->in, NULL)) {
            if (do_compress) fatal("Failed to enable compression, aborting", EC_SOFTWARE);
            syslog(LOG_NOTICE, "Failed to enable compression, continuing uncompressed");
        }
        else {
            prot_setcompress(sync_backend->in);
            prot_setcompress(sync_backend->out);
        }
    }
    else if (do_compress) fatal("Backend does not support compression, aborting", EC_SOFTWARE);
#endif

    /* links to sockets */
    sync_in = sync_backend->in;
    sync_out = sync_backend->out;

    if (verbose > 1) {
        prot_setlog(sync_in, fileno(stderr));
        prot_setlog(sync_out, fileno(stderr));
    }

    /* Set inactivity timer */
    timeout = config_getint(IMAPOPT_SYNC_TIMEOUT);
    if (timeout < 3) timeout = 3;
    prot_settimeout(sync_in, timeout);

    /* Force use of LITERAL+ so we don't need two way communications */
    prot_setisclient(sync_in, 1);
    prot_setisclient(sync_out, 1);
}
Exemplo n.º 7
0
static int do_restart()
{
    sync_send_restart(sync_out);

    return sync_parse_response("RESTART", sync_in, NULL);
}
Exemplo n.º 8
0
static struct backend *restore_connect(const char *servername,
                                       struct buf *tagbuf,
                                       const struct restore_options *options)
{
    struct backend *backend = NULL;
    sasl_callback_t *cb;
    int timeout;
    const char *auth_status = NULL;

    cb = mysasl_callbacks(NULL,
                          config_getstring(IMAPOPT_RESTORE_AUTHNAME),
                          config_getstring(IMAPOPT_RESTORE_REALM),
                          config_getstring(IMAPOPT_RESTORE_PASSWORD));

    /* try to connect over IMAP */
    backend = backend_connect(backend, servername,
                              &imap_csync_protocol, "", cb, &auth_status,
                              (options->verbose > 1 ? fileno(stderr) : -1));

    if (backend) {
        if (backend->capability & CAPA_REPLICATION) {
            /* attach our IMAP tag buffer to our protstreams as userdata */
            backend->in->userdata = backend->out->userdata = tagbuf;
        }
        else {
            backend_disconnect(backend);
            backend = NULL;
        }
    }

    /* if that didn't work, fall back to csync */
    if (!backend) {
        backend = backend_connect(backend, servername,
                                  &csync_protocol, "", cb, NULL,
                                  (options->verbose > 1 ? fileno(stderr) : -1));
    }

    free_callbacks(cb);
    cb = NULL;

    if (!backend) {
        fprintf(stderr, "Can not connect to server '%s'\n", servername);
        syslog(LOG_ERR, "Can not connect to server '%s'", servername);
        return NULL;
    }

    if (servername[0] != '/' && backend->sock >= 0) {
        tcp_disable_nagle(backend->sock);
        tcp_enable_keepalive(backend->sock);
    }

#ifdef HAVE_ZLIB
    /* Does the backend support compression? */
    if (CAPA(backend, CAPA_COMPRESS)) {
        prot_printf(backend->out, "%s\r\n",
                    backend->prot->u.std.compress_cmd.cmd);
        prot_flush(backend->out);

        if (sync_parse_response("COMPRESS", backend->in, NULL)) {
            if (options->require_compression)
                fatal("Failed to enable compression, aborting", EX_SOFTWARE);
            syslog(LOG_NOTICE, "Failed to enable compression, continuing uncompressed");
        }
        else {
            prot_setcompress(backend->in);
            prot_setcompress(backend->out);
        }
    }
    else if (options->require_compression) {
        fatal("Backend does not support compression, aborting", EX_SOFTWARE);
    }
#endif

    if (options->verbose > 1) {
        /* XXX did we do this during backend_connect already? */
        prot_setlog(backend->in, fileno(stderr));
        prot_setlog(backend->out, fileno(stderr));
    }

    /* Set inactivity timer */
    timeout = config_getint(IMAPOPT_SYNC_TIMEOUT);
    if (timeout < 3) timeout = 3;
    prot_settimeout(backend->in, timeout);

    /* Force use of LITERAL+ so we don't need two way communications */
    prot_setisclient(backend->in, 1);
    prot_setisclient(backend->out, 1);

    return backend;
}
Exemplo n.º 9
0
int main(int argc, char **argv)
{
    save_argv0(argv[0]);

    const char *alt_config = NULL;
    const char *input_file = NULL;
    const char *backup_name = NULL;
    const char *servername = NULL;
    enum restore_mode mode = RESTORE_MODE_UNSPECIFIED;
    int local_only = 0;
    int wait = 0;
    int do_nothing = 0;
    int do_all_mailboxes = 0;

    struct restore_options options = {0};
    options.expunged_mode = RESTORE_EXPUNGED_OKAY;
    options.trim_deletedprefix = 1;

    struct backup *backup = NULL;
    mbname_t *mbname = NULL;
    struct backup_mailbox_list *mailbox_list = NULL;
    struct sync_folder_list *reserve_folder_list = NULL;
    struct sync_reserve_list *reserve_list = NULL;
    struct buf tagbuf = BUF_INITIALIZER;
    struct backend *backend = NULL;
    struct dlist *upload = NULL;
    int opt, r;

    while ((opt = getopt(argc, argv, ":A:C:DF:LM:P:UXaf:m:nru:vw:xz")) != EOF) {
        switch (opt) {
        case 'A':
            if (options.keep_uidvalidity) usage();
            options.override_acl = optarg;
            break;
        case 'C':
            alt_config = optarg;
            break;
        case 'D':
            /* XXX does this clash with keep_uidvalidity? */
            options.trim_deletedprefix = 0;
            break;
        case 'F':
            if (do_all_mailboxes) usage();
            input_file = optarg;
            break;
        case 'L':
            local_only = 1;
            break;
        case 'M':
            if (options.keep_uidvalidity) usage();
            options.override_mboxname = optarg;
            break;
        case 'P':
            if (options.keep_uidvalidity) usage();
            options.override_partition = optarg;
            break;
        case 'U':
            if (options.override_acl || options.override_mboxname || options.override_partition)
                usage();
            options.keep_uidvalidity = 1;
            break;
        case 'X':
            if (options.expunged_mode != RESTORE_EXPUNGED_OKAY) usage();
            options.expunged_mode = RESTORE_EXPUNGED_EXCLUDE;
            break;
        case 'a':
            if (input_file) usage();
            do_all_mailboxes = 1;
            break;
        case 'f':
            if (mode != RESTORE_MODE_UNSPECIFIED) usage();
            mode = RESTORE_MODE_FILENAME;
            backup_name = optarg;
            break;
        case 'm':
            if (mode != RESTORE_MODE_UNSPECIFIED) usage();
            mode = RESTORE_MODE_MBOXNAME;
            backup_name = optarg;
            break;
        case 'n':
            do_nothing = 1;
            break;
        case 'r':
            options.do_submailboxes = 1;
            break;
        case 'u':
            if (mode != RESTORE_MODE_UNSPECIFIED) usage();
            mode = RESTORE_MODE_USERNAME;
            backup_name = optarg;
            break;
        case 'v':
            options.verbose++;
            break;
        case 'w':
            wait = atoi(optarg);
            if (wait < 0) usage();
            break;
        case 'x':
            if (options.expunged_mode != RESTORE_EXPUNGED_OKAY) usage();
            options.expunged_mode = RESTORE_EXPUNGED_ONLY;
            break;
        case 'z':
            options.require_compression = 1;
            break;
        case ':':
            if (optopt == 'A') options.override_acl = "";
            else usage();
            break;
        default:
            usage();
            break;
        }
    }

    /* we need a server name */
    if (optind == argc) usage();
    servername = argv[optind++];

    /* we need a source of backup data */
    if (mode == RESTORE_MODE_UNSPECIFIED) {
        if (optind == argc) usage();
        backup_name = argv[optind++];
        mode = RESTORE_MODE_USERNAME;
    }

    /* we need either an input file or some objects to restore */
    if (!do_all_mailboxes && !input_file && optind == argc) usage();
    /* and we can't have both because i said */
    if ((input_file || do_all_mailboxes) && optind < argc) usage();

    /* okay, arguments seem sane, we are go */
    cyrus_init(alt_config, "restore", 0, 0);

    /* load the SASL plugins */
    global_sasl_init(1, 0, mysasl_cb);

    /* wait here for gdb attach */
    if (wait) {
        fprintf(stderr, "Waiting for %d seconds for gdb attach...\n", wait);
        sleep(wait);
    }

    /* open backup */
    switch (mode) {
    case RESTORE_MODE_FILENAME:
        r = backup_open_paths(&backup, backup_name, NULL,
                              BACKUP_OPEN_NONBLOCK, BACKUP_OPEN_NOCREATE);
        break;
    case RESTORE_MODE_MBOXNAME:
        mbname = mbname_from_intname(backup_name);
        if (!mbname) usage();
        r = backup_open(&backup, mbname,
                        BACKUP_OPEN_NONBLOCK, BACKUP_OPEN_NOCREATE);
        mbname_free(&mbname);
        break;
    case RESTORE_MODE_USERNAME:
        mbname = mbname_from_userid(backup_name);
        if (!mbname) usage();
        r = backup_open(&backup, mbname,
                        BACKUP_OPEN_NONBLOCK, BACKUP_OPEN_NOCREATE);
        mbname_free(&mbname);
        break;
    default:
        usage();
        break;
    }

    if (r) goto done;

    /* scan for objects to restore:
     *   mailboxes will have all messages added, modulo expunged_mode
     *   messages will be added individually with appropriate folder
     */
    mailbox_list = xzmalloc(sizeof *mailbox_list);
    reserve_folder_list = restore_make_reserve_folder_list(backup);
    reserve_list = sync_reserve_list_create(SYNC_MSGID_LIST_HASH_SIZE);

    if (input_file) {
        char buf[MAX_MAILBOX_NAME + 2]; // \n\0
        size_t len;
        FILE *f;

        if (0 != strcmp(input_file, "-")) {
            f = fopen(input_file, "r");
            if (!f) {
                fprintf(stderr, "fopen %s: %s\n", input_file, strerror(errno));
                goto done;// FIXME shut_down?
            }
        }
        else {
            f = stdin;
        }

        while (fgets(buf, sizeof(buf), f)) {
            len = strlen(buf);

            if (len > 0 && buf[len - 1] == '\n')
                buf[--len] = '\0';

            if (len == 0 || buf[0] == '#')
                continue;

            r = restore_add_object(buf, &options, backup, mailbox_list,
                                   reserve_folder_list, reserve_list);

            // FIXME r
        }
        fclose(f);
    }
    else if (do_all_mailboxes) {
        struct backup_mailbox_list *all_mailboxes;
        struct backup_mailbox *mailbox;

        all_mailboxes = backup_get_mailboxes(backup, 0,
                                             BACKUP_MAILBOX_ALL_RECORDS);

        for (mailbox = all_mailboxes->head; mailbox; mailbox = mailbox->next) {
            restore_add_mailbox(mailbox, &options, mailbox_list,
                                reserve_folder_list, reserve_list);
        }

        backup_mailbox_list_empty(all_mailboxes);
        free(all_mailboxes);
    }
    else {
        int i;

        for (i = optind; i < argc; i++) {
            r = restore_add_object(argv[i], &options, backup, mailbox_list,
                                   reserve_folder_list, reserve_list);

            // FIXME r
        }
    }

    if (do_nothing) {
        if (options.verbose)
            fprintf(stderr, "do nothing (-n) specified, exiting now\n");
        goto done;
    }

    /* connect to destination */
    backend = restore_connect(servername, &tagbuf, &options);

    if (!backend) {
        // FIXME
        r = -1;
        goto done;
    }

    /* do the restore */
    struct sync_reserve *reserve;
    for (reserve = reserve_list->head; reserve; reserve = reserve->next) {
        /* send APPLY RESERVE and parse missing lists */
        r = sync_reserve_partition(reserve->part,
                                   reserve_folder_list,
                                   reserve->list,
                                   backend);
        if (r) goto done;

        /* send APPLY MESSAGEs */
        r = backup_prepare_message_upload(backup,
                                          reserve->part,
                                          reserve->list,
                                          &sync_msgid_lookup,
                                          &upload);
        if (r) goto done;
        /* upload in small(ish) blocks to avoid timeouts */
        while (upload->head) {
            struct dlist *block = dlist_splice(upload, 1024);
            sync_send_apply(block, backend->out);
            r = sync_parse_response("MESSAGE", backend->in, NULL);
            dlist_unlink_files(block);
            dlist_free(&block);
            if (r) goto done;
        }
    }

    /* sync_prepare_dlists needs to upload messages per-mailbox, because
     * it needs the mailbox to find the filename for the message.  but
     * we have no such limitation, so we can upload messages while
     * looping over the reserve_list instead, above.
     *
     * alternatively, if we do it on a per-mailbox basis then we can limit
     * the hit on the staging directory to only a mailbox worth of messages
     * at a time.  but we don't have a logical grouping that would make
     * this coherent
     */

    /* send RESTORE MAILBOXes */
    struct backup_mailbox *mailbox;
    for (mailbox = mailbox_list->head; mailbox; mailbox = mailbox->next) {
        /* XXX filter the mailbox records based on reserve/missing/upload */

        /* XXX does this sensibly handle mailbox objs with empty values? */
        struct dlist *dl = backup_mailbox_to_dlist(mailbox);
        if (!dl) continue;

        if (local_only) {
            free(dl->name);
            dl->name = xstrdup("LOCAL_MAILBOX");
        }

        sync_send_restore(dl, backend->out);
        r = sync_parse_response("MAILBOX", backend->in, NULL);
        dlist_free(&dl);
        if (r) goto done;
    }

done:
    if (r)
        fprintf(stderr, "%s: %s\n", backup_name, error_message(r));

    /* release lock asap */
    if (backup)
        backup_close(&backup);

    if (backend)
        backend_disconnect(backend);

    if (upload) {
        dlist_unlink_files(upload);
        dlist_free(&upload);
    }

    if (mailbox_list) {
        backup_mailbox_list_empty(mailbox_list);
        free(mailbox_list);
    }

    if (reserve_folder_list)
        sync_folder_list_free(&reserve_folder_list);

    if (reserve_list)
        sync_reserve_list_free(&reserve_list);

    buf_free(&tagbuf);

    backup_cleanup_staging_path();
    cyrus_done();

    exit(r ? EX_TEMPFAIL : EX_OK);
}