/* * 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; }
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; }
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); }