예제 #1
0
/*
 * Write out the quota entry 'quota'
 */
EXPORTED int quota_write(struct quota *quota, struct txn **tid)
{
    int r;
    int qrlen;
    int res;
    struct buf buf = BUF_INITIALIZER;
    struct dlist *dl = NULL;

    if (!quota->root) return IMAP_QUOTAROOT_NONEXISTENT;

    qrlen = strlen(quota->root);
    if (!qrlen) return IMAP_QUOTAROOT_NONEXISTENT;

    dl = dlist_newkvlist(NULL, NULL);

    for (res = 0; res < QUOTA_NUMRESOURCES; res++) {
        struct dlist *item = dlist_newlist(dl, quota_db_names[res]);
        dlist_setnum64(item, NULL, quota->useds[res]);
        if (quota->limits[res] != QUOTA_UNLIMITED)
            dlist_setnum64(item, NULL, quota->limits[res]);
    }

    if (quota->scanmbox) {
        struct dlist *scan = dlist_newkvlist(dl, "SCAN");
        dlist_setatom(scan, "MBOX", quota->scanmbox);
        for (res = 0; res < QUOTA_NUMRESOURCES; res++)
            dlist_setnum64(scan, quota_db_names[res], quota->scanuseds[res]);
    }

    dlist_printbuf(dl, 0, &buf);

    r = cyrusdb_store(qdb, quota->root, qrlen, buf.s, buf.len, tid);

    switch (r) {
    case CYRUSDB_OK:
        r = 0;
        break;

    case CYRUSDB_AGAIN:
        r = IMAP_AGAIN;
        break;

    default:
        syslog(LOG_ERR, "DBERROR: error storing %s: %s",
               quota->root, cyrusdb_strerror(r));
        r = IMAP_IOERROR;
        break;
    }

    dlist_free(&dl);
    buf_free(&buf);
    return r;
}
예제 #2
0
HIDDEN int backup_index(struct backup *backup, struct dlist *dlist,
                        time_t ts, off_t start, size_t len)
{
    int r = IMAP_PROTOCOL_ERROR;

    if (strcmp(dlist->name, "EXPUNGE") == 0)
        r = _index_expunge(backup, dlist, ts, start);
    else if (strcmp(dlist->name, "MAILBOX") == 0)
        r = _index_mailbox(backup, dlist, ts, start);
    else if (strcmp(dlist->name, "UNMAILBOX") == 0)
        r = _index_unmailbox(backup, dlist, ts, start);
    else if (strcmp(dlist->name, "MESSAGE") == 0)
        r = _index_message(backup, dlist, ts, start, len);
    else if (strcmp(dlist->name, "RENAME") == 0)
        r = _index_rename(backup, dlist, ts, start);
    else if (strcmp(dlist->name, "RESERVE") == 0)
        r = 0; /* nothing to index for a reserve, just return success */
    else if (strcmp(dlist->name, "SEEN") == 0)
        r = _index_seen(backup, dlist, ts, start);
    else if (strcmp(dlist->name, "SUB") == 0)
        r = _index_sub(backup, dlist, ts, start);
    else if (strcmp(dlist->name, "UNSUB") == 0)
        r = _index_sub(backup, dlist, ts, start);
    else if (strcmp(dlist->name, "SIEVE") == 0)
        r = _index_sieve(backup, dlist, ts, start);
    else if (strcmp(dlist->name, "UNSIEVE") == 0)
        r = _index_sieve(backup, dlist, ts, start);
    else if (config_debug) {
        struct buf tmp = BUF_INITIALIZER;
        dlist_printbuf(dlist, 1, &tmp);
        syslog(LOG_DEBUG, "ignoring unrecognised dlist: %s\n", buf_cstring(&tmp));
        buf_free(&tmp);
    }

    return r;
}
예제 #3
0
EXPORTED const char *dlist_print_iter_step(struct dlist_print_iter *iter, struct buf *outbuf)
{
    /* already finished */
    if (!iter->next) return NULL;

    buf_reset(outbuf);

    /* Bundle short steps together to minimise call overhead.
     * Note that outbuf can grow significantly longer than this limit, if a
     * single item in the dlist is very long (e.g. a message), but then it
     * won't bundle up more than that.
     */
    while (iter->next != NULL && buf_len(outbuf) < 1024) {
        const struct dlist *curr = iter->next;
        struct dlist_stack_node *parent = NULL;
        int descend = 0;

        /* output */
        switch (curr->type) {
        case DL_KVLIST:
        case DL_ATOMLIST:
            // XXX should use equiv to "prot_printastring" for curr->name
            if (iter->printkeys)
                buf_printf(outbuf, "%s ", curr->name);

            buf_appendcstr(outbuf, curr->type == DL_KVLIST ? "%(" : "(");

            if (curr->head) {
                descend = 1;
            }
            else {
                buf_putc(outbuf, ')');
                if (curr->next)
                    buf_putc(outbuf, ' ');
            }
            break;

        default:
            dlist_printbuf(curr, iter->printkeys, outbuf);
            if (curr->next)
                buf_putc(outbuf, ' ');
            break;
        }

        /* increment */
        if (descend) {
            parent = xmalloc(sizeof *parent);
            parent->printkeys = iter->printkeys;
            parent->dl = curr;
            parent->next = iter->parent;
            iter->parent = parent;
            iter->next = curr->head;
            // XXX can this always be 1? we know an atom list here is non-empty
            iter->printkeys = curr->type == DL_KVLIST ? 1 : curr->nval;
        }
        else if (curr->next) {
            iter->next = curr->next;
        }
        else if (iter->parent) {
            /* multiple parents might be ending at the same point
             * don't mistake one parent ending for end of entire tree
             */
            do {
                buf_putc(outbuf, ')');

                parent = iter->parent;

                iter->parent = iter->parent->next;
                iter->next = parent->dl->next;
                iter->printkeys = parent->printkeys;

                free(parent);

                if (iter->next) {
                    /* found an unfinished dlist, stop closing parents */
                    buf_putc(outbuf, ' ');
                    break;
                }
            } while (iter->parent);
        }
        else {
            iter->next = NULL;
        }
    }

    /* and return */
    return buf_cstringnull(outbuf);
}