/* must be called after cyrus_init */ static int newsrc_init(const char *fname, int myflags __attribute__((unused))) { char buf[1024]; int r = 0; if (r != 0) syslog(LOG_ERR, "DBERROR: init %s: %s", buf, cyrusdb_strerror(r)); else { char *tofree = NULL; if (!fname) fname = config_getstring(IMAPOPT_NEWSRC_DB_PATH); /* create db file name */ if (!fname) { tofree = strconcat(config_dir, FNAME_NEWSRCDB, (char *)NULL); fname = tofree; } r = cyrusdb_open(DB, fname, CYRUSDB_CREATE, &newsrc_db); if (r != 0) syslog(LOG_ERR, "DBERROR: opening %s: %s", fname, cyrusdb_strerror(r)); else newsrc_dbopen = 1; free(tofree); } return r; }
/* must be called after cyrus_init */ int newsrc_init(char *fname, int myflags __attribute__((unused))) { char buf[1024]; int r = 0; if (r != 0) syslog(LOG_ERR, "DBERROR: init %s: %s", buf, cyrusdb_strerror(r)); else { char *tofree = NULL; /* create db file name */ if (!fname) { fname = xmalloc(strlen(config_dir)+sizeof(FNAME_NEWSRCDB)); tofree = fname; strcpy(fname, config_dir); strcat(fname, FNAME_NEWSRCDB); } r = DB->open(fname, CYRUSDB_CREATE, &newsrc_db); if (r != 0) syslog(LOG_ERR, "DBERROR: opening %s: %s", fname, cyrusdb_strerror(r)); else newsrc_dbopen = 1; if (tofree) free(tofree); } return r; }
void statuscache_open(const char *fname) { int ret; char *tofree = NULL; if (!fname) fname = config_getstring(IMAPOPT_STATUSCACHE_DB_PATH); /* create db file name */ if (!fname) { tofree = strconcat(config_dir, FNAME_STATUSCACHEDB, (char *)NULL); fname = tofree; } ret = cyrusdb_open(DB, fname, CYRUSDB_CREATE, &statuscachedb); if (ret != 0) { syslog(LOG_ERR, "DBERROR: opening %s: %s", fname, cyrusdb_strerror(ret)); syslog(LOG_ERR, "statuscache in degraded mode"); return; } free(tofree); statuscache_dbopen = 1; }
static int statuscache_update_txn(const char *mboxname, struct statusdata *sdata, struct txn **tidptr) { char data[250]; /* enough room for 11*(UULONG + SP) */ size_t keylen, datalen; char *key = statuscache_buildkey(mboxname, sdata->userid, &keylen); int r; /* Don't access DB if it hasn't been opened */ if (!statuscache_dbopen) return 0; /* The trailing whitespace is necessary because we * use non-length-based functions to parse the values. * Any non-digit char would be fine, but whitespace * looks less ugly in dbtool output */ datalen = snprintf(data, sizeof(data), "%u %u %u %u %u %u %u " MODSEQ_FMT " ", STATUSCACHE_VERSION, sdata->statusitems, sdata->messages, sdata->recent, sdata->uidnext, sdata->uidvalidity, sdata->unseen, sdata->highestmodseq); r = cyrusdb_store(statuscachedb, key, keylen, data, datalen, tidptr); if (r != CYRUSDB_OK) { syslog(LOG_ERR, "DBERROR: error updating database: %s (%s)", mboxname, cyrusdb_strerror(r)); } return r; }
void denydb_open(const char *fname) { int ret; char *tofree = NULL; if (!fname) fname = config_getstring(IMAPOPT_USERDENY_DB_PATH); /* create db file name */ if (!fname) { tofree =strconcat(config_dir, FNAME_USERDENYDB, (char *)NULL); fname = tofree; } ret = (DENYDB->open)(fname, 0, &denydb); if (ret == CYRUSDB_OK) { deny_dbopen = 1; } else if (errno != ENOENT) { /* ignore non-existent DB, report all other errors */ syslog(LOG_WARNING, "DENYDB_ERROR: opening %s: %s", fname, cyrusdb_strerror(ret)); } free(tofree); }
EXPORTED void quotadb_open(const char *fname) { int ret; char *tofree = NULL; int flags = CYRUSDB_CREATE; if (!fname) fname = config_getstring(IMAPOPT_QUOTA_DB_PATH); /* create db file name */ if (!fname) { tofree = strconcat(config_dir, FNAME_QUOTADB, (char *)NULL); fname = tofree; } if (config_getswitch(IMAPOPT_IMPROVED_MBOXLIST_SORT)) flags |= CYRUSDB_MBOXSORT; ret = cyrusdb_open(QDB, fname, flags, &qdb); if (ret != 0) { syslog(LOG_ERR, "DBERROR: opening %s: %s", fname, cyrusdb_strerror(ret)); /* Exiting TEMPFAIL because Sendmail thinks this EC_OSFILE == permanent failure. */ fatal("can't read quotas file", EC_TEMPFAIL); } free(tofree); quota_dbopen = 1; }
/* must be called after cyrus_init */ EXPORTED int duplicate_init(const char *fname) { int r = 0; char *tofree = NULL; if (!fname) fname = config_getstring(IMAPOPT_DUPLICATE_DB_PATH); /* create db file name */ if (!fname) { tofree = strconcat(config_dir, FNAME_DELIVERDB, (char *)NULL); fname = tofree; } r = cyrusdb_open(DB, fname, CYRUSDB_CREATE, &dupdb); if (r != 0) { syslog(LOG_ERR, "DBERROR: opening %s: %s", fname, cyrusdb_strerror(r)); goto out; } duplicate_dbopen = 1; out: free(tofree); return r; }
/* * Remove a deny DB record; this has the effect of allowing the given * user access to all services. Returns an IMAP error code or 0 on * success. It is not an error to remove an non-existant record. */ EXPORTED int denydb_delete(const char *user) { struct txn *txn = NULL; int r = 0; if (!denydb) return 0; if (!user) return r; /* remove the record */ do { r = cyrusdb_delete(denydb, user, strlen(user), &txn, /*force*/1); } while (r == CYRUSDB_AGAIN); if (r) { syslog(LOG_ERR, "IOERROR: couldn't delete denydb record for %s: %s", user, cyrusdb_strerror(r)); r = IMAP_IOERROR; } if (txn) { if (r) cyrusdb_abort(denydb, txn); else cyrusdb_commit(denydb, txn); } return r; }
/* * Open the user deny database. If 'create' is true and the database * does not exist, create it. Returns 0 on success or an IMAP error * code. */ EXPORTED int denydb_open(int create) { const char *fname; int ret; char *tofree = NULL; fname = config_getstring(IMAPOPT_USERDENY_DB_PATH); /* create db file name */ if (!fname) { tofree = strconcat(config_dir, FNAME_USERDENYDB, (char *)NULL); fname = tofree; } ret = cyrusdb_open(DENYDB, fname, (create ? CYRUSDB_CREATE : 0), &denydb); if (ret == CYRUSDB_NOTFOUND) { /* ignore non-existent DB, report all other errors */ ret = ENOENT; } else if (ret != CYRUSDB_OK) { syslog(LOG_WARNING, "DENYDB_ERROR: opening %s: %s", fname, cyrusdb_strerror(ret)); ret = IMAP_IOERROR; } free(tofree); return ret; }
EXPORTED int jmapauth_open(struct db **dbptr, int db_flags, const char *fname) { int r = 0; char *tofree = NULL; assert(dbptr); if (!fname) { fname = config_getstring(IMAPOPT_JMAPAUTH_DB_PATH); } /* create db file name */ if (!fname) { tofree = strconcat(config_dir, FNAME_JMAPAUTH, (char*)NULL); fname = tofree; } /* open the database */ r = cyrusdb_open(DB, fname, db_flags, dbptr); if (r) { if (r != CYRUSDB_NOTFOUND) { syslog(LOG_ERR, "JMAP auth: cannot open db %s: %s", fname, cyrusdb_strerror(r)); } return r; } free(tofree); return r; }
static void abortcurrent(struct mboxkey *s) { if (s && s->tid) { int r = cyrusdb_abort(s->db, s->tid); if (r) { syslog(LOG_ERR, "DBERROR: error aborting txn: %s", cyrusdb_strerror(r)); } s->tid = NULL; } }
/* * 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; }
int mboxkey_close(struct mboxkey *mboxkeydb) { int r; if (MBOXKEY_DEBUG) { syslog(LOG_DEBUG, "mboxkey_db: mboxkey_close(%s)", mboxkeydb->user); } if (mboxkeydb->tid) { r = cyrusdb_commit(mboxkeydb->db, mboxkeydb->tid); if (r != CYRUSDB_OK) { syslog(LOG_ERR, "DBERROR: error committing mboxkey txn; " "mboxkey state lost: %s", cyrusdb_strerror(r)); } mboxkeydb->tid = NULL; } if (lastmboxkey) { int r; /* free the old database hanging around */ abortcurrent(lastmboxkey); r = cyrusdb_close(lastmboxkey->db); if (r != CYRUSDB_OK) { syslog(LOG_ERR, "DBERROR: error closing lastmboxkey: %s", cyrusdb_strerror(r)); r = IMAP_IOERROR; } if(!r) lastmboxkey->db = NULL; free(lastmboxkey->user); free(lastmboxkey->fname); free(lastmboxkey); lastmboxkey = NULL; } /* this database can now be reused */ lastmboxkey = mboxkeydb; return 0; }
void statuscache_close(void) { int r; if (statuscache_dbopen) { r = cyrusdb_close(statuscachedb); if (r) { syslog(LOG_ERR, "DBERROR: error closing statuscache: %s", cyrusdb_strerror(r)); } statuscache_dbopen = 0; } }
EXPORTED void quotadb_close(void) { int r; if (quota_dbopen) { r = cyrusdb_close(qdb); if (r) { syslog(LOG_ERR, "DBERROR: error closing quotas: %s", cyrusdb_strerror(r)); } quota_dbopen = 0; } }
EXPORTED void denydb_close(void) { int r; if (denydb) { r = cyrusdb_close(denydb); if (r) { syslog(LOG_ERR, "DENYDB_ERROR: error closing: %s", cyrusdb_strerror(r)); } denydb = NULL; } }
void denydb_close(void) { int r; if (deny_dbopen) { r = (DENYDB->close)(denydb); if (r) { syslog(LOG_ERR, "DENYDB_ERROR: error closing: %s", cyrusdb_strerror(r)); } deny_dbopen = 0; } }
static int newsrc_done(void) { int r = 0; if (newsrc_dbopen) { r = cyrusdb_close(newsrc_db); if (r) { syslog(LOG_ERR, "DBERROR: error closing fetchnews.db: %s", cyrusdb_strerror(r)); } newsrc_dbopen = 0; } return r; }
int seen_close(struct seen **seendbptr) { struct seen *seendb = *seendbptr; int r; if (!seendb) return 0; if (SEEN_DEBUG) { syslog(LOG_DEBUG, "seen_db: seen_close(%s)", seendb->user); } if (seendb->tid) { if (SEEN_DEBUG) { syslog(LOG_DEBUG, "seen_db: committing changes for %s", seendb->user); } r = cyrusdb_commit(seendb->db, seendb->tid); if (r != CYRUSDB_OK) { syslog(LOG_ERR, "DBERROR: error committing seen txn; " "seen state lost: %s", cyrusdb_strerror(r)); } seendb->tid = NULL; } r = cyrusdb_close(seendb->db); if (r) { syslog(LOG_ERR, "DBERROR: error closing: %s", cyrusdb_strerror(r)); r = IMAP_IOERROR; } free(seendb->user); free(seendb); *seendbptr = NULL; return 0; }
/* * Add an entry to the deny DB. Message 'msg' may be NULL, resulting * in a default message being used. Service name 'service' may be NULL, * resulting in all services being blocked for the user. The username * 'user' is a required argument. Returns an IMAP error code or 0 on * success. */ EXPORTED int denydb_set(const char *user, const char *service, const char *msg) { struct txn *txn = NULL; struct buf data = BUF_INITIALIZER; int r = 0; if (!denydb) { r = IMAP_INTERNAL; goto out; } if (!service) service = "*"; if (!user || strchr(service, '\t')) { /* the service field may not contain a TAB, it's the field separator */ r = IMAP_INVALID_IDENTIFIER; goto out; } /* compose the record */ buf_printf(&data, "%u\t", USERDENY_VERSION); buf_appendcstr(&data, service); buf_putc(&data, '\t'); buf_appendcstr(&data, (msg ? msg : default_message)); /* write the record */ do { r = cyrusdb_store(denydb, user, strlen(user), data.s, data.len, &txn); } while (r == CYRUSDB_AGAIN); if (r) { syslog(LOG_ERR, "IOERROR: couldn't store denydb record for %s: %s", user, cyrusdb_strerror(r)); r = IMAP_IOERROR; } out: if (txn) { if (r) cyrusdb_abort(denydb, txn); else cyrusdb_commit(denydb, txn); } buf_free(&data); return r; }
static int mboxkey_readit(struct mboxkey *mboxkeydb, const char *mailbox, const char **mboxkey, size_t *mboxkeylen, int rw) { int r; const char *data; size_t datalen; unsigned short version, s; assert(mboxkeydb && mailbox); if (rw || mboxkeydb->tid) { r = cyrusdb_fetchlock(mboxkeydb->db, mailbox, strlen(mailbox), &data, &datalen, &mboxkeydb->tid); } else { r = cyrusdb_fetch(mboxkeydb->db, mailbox, strlen(mailbox), &data, &datalen, NULL); } switch (r) { case 0: break; case CYRUSDB_AGAIN: syslog(LOG_DEBUG, "deadlock in mboxkey database for '%s/%s'", mboxkeydb->user, mailbox); return IMAP_AGAIN; break; case CYRUSDB_IOERROR: syslog(LOG_ERR, "DBERROR: error fetching txn %s", cyrusdb_strerror(r)); return IMAP_IOERROR; break; case CYRUSDB_NOTFOUND: *mboxkey = NULL; *mboxkeylen = 0; return 0; break; } /* 'data' is <version><mboxkey> */ memcpy(&s, data, sizeof(s)); version = ntohs(s); assert(version == MBOXKEY_VERSION); *mboxkey = data + sizeof(s); *mboxkeylen = datalen - sizeof(s); return 0; }
EXPORTED void statuscache_open(void) { char *fname = statuscache_filename(); int ret; ret = cyrusdb_open(DB, fname, CYRUSDB_CREATE, &statuscachedb); if (ret != 0) { syslog(LOG_ERR, "DBERROR: opening %s: %s", fname, cyrusdb_strerror(ret)); syslog(LOG_ERR, "statuscache in degraded mode"); goto out; } statuscache_dbopen = 1; out: free(fname); }
int mboxkey_write(struct mboxkey *mboxkeydb, const char *mailbox, const char *mboxkey, size_t mboxkeylen) { int r; assert(mboxkeydb && mailbox); /* assert(mboxkeydb->tid);*/ if (MBOXKEY_DEBUG) { syslog(LOG_DEBUG, "mboxkey_db: mboxkey_write(%s, %s, %s)", mboxkeydb->user, mailbox, mboxkey ? "KEY" : "NIL"); } if (!mboxkey) { r = cyrusdb_delete(mboxkeydb->db, mailbox, strlen(mailbox), &mboxkeydb->tid, 1); } else { unsigned short version = MBOXKEY_VERSION, s; int datalen = sizeof(s) + mboxkeylen; char *data = xmalloc(datalen); s = htons(version); memcpy(data, &s, sizeof(s)); memcpy(data+sizeof(s), mboxkey, mboxkeylen); r = cyrusdb_store(mboxkeydb->db, mailbox, strlen(mailbox), data, datalen, &mboxkeydb->tid); free(data); } switch (r) { case CYRUSDB_OK: break; case CYRUSDB_IOERROR: r = IMAP_AGAIN; break; default: syslog(LOG_ERR, "DBERROR: error updating database: %s", cyrusdb_strerror(r)); r = IMAP_IOERROR; break; } return r; }
/* * Read the quota entry 'quota' */ EXPORTED int quota_read(struct quota *quota, struct txn **tid, int wrlock) { int r; size_t qrlen; const char *data; size_t datalen; if (!quota->root || !(qrlen = strlen(quota->root))) return IMAP_QUOTAROOT_NONEXISTENT; if (wrlock) r = cyrusdb_fetchlock(qdb, quota->root, qrlen, &data, &datalen, tid); else r = cyrusdb_fetch(qdb, quota->root, qrlen, &data, &datalen, tid); if (!datalen) /* zero byte file can cause no data to be mapped */ return IMAP_QUOTAROOT_NONEXISTENT; switch (r) { case CYRUSDB_OK: if (!*data) return IMAP_QUOTAROOT_NONEXISTENT; r = quota_parseval(data, datalen, quota, wrlock); if (r) { syslog(LOG_ERR, "DBERROR: error fetching quota " "root=<%s> value=<%s>", quota->root, data); return r; } break; case CYRUSDB_AGAIN: return IMAP_AGAIN; case CYRUSDB_NOTFOUND: return IMAP_QUOTAROOT_NONEXISTENT; } if (r) { syslog(LOG_ERR, "DBERROR: error fetching quota %s: %s", quota->root, cyrusdb_strerror(r)); return IMAP_IOERROR; } return 0; }
static int seen_readit(struct seen *seendb, const char *uniqueid, struct seendata *sd, int rw) { int r; const char *data; size_t datalen; assert(seendb && uniqueid); if (rw || seendb->tid) { r = cyrusdb_fetchlock(seendb->db, uniqueid, strlen(uniqueid), &data, &datalen, &seendb->tid); } else { r = cyrusdb_fetch(seendb->db, uniqueid, strlen(uniqueid), &data, &datalen, NULL); } switch (r) { case 0: break; case CYRUSDB_AGAIN: syslog(LOG_DEBUG, "deadlock in seen database for '%s/%s'", seendb->user, uniqueid); return IMAP_AGAIN; break; case CYRUSDB_NOTFOUND: memset(sd, 0, sizeof(struct seendata)); sd->seenuids = xstrdup(""); return 0; break; default: syslog(LOG_ERR, "DBERROR: error fetching txn %s", cyrusdb_strerror(r)); return IMAP_IOERROR; break; } parse_data(data, datalen, sd); if (sd->seenuids[0] && !imparse_issequence(sd->seenuids)) { syslog(LOG_ERR, "DBERROR: invalid sequence <%s> for %s %s - nuking", sd->seenuids, seendb->user, uniqueid); free(sd->seenuids); sd->seenuids = xstrdup(""); } return 0; }
int seen_open(const char *user, int flags, struct seen **seendbptr) { struct seen *seendb = NULL; char *fname = NULL; int dbflags = (flags & SEEN_CREATE) ? CYRUSDB_CREATE : 0; int r; assert(user); assert(*seendbptr == NULL); /* create seendb */ seendb = (struct seen *) xmalloc(sizeof(struct seen)); if (SEEN_DEBUG) { syslog(LOG_DEBUG, "seen_db: seen_open(%s)", user); } /* open the seendb corresponding to user */ fname = seen_getpath(user); if (flags & SEEN_CREATE) cyrus_mkdir(fname, 0755); r = cyrusdb_open(DB, fname, dbflags, &seendb->db); if (r) { if (!(flags & SEEN_SILENT)) { int level = (flags & SEEN_CREATE) ? LOG_ERR : LOG_DEBUG; syslog(level, "DBERROR: opening %s: %s", fname, cyrusdb_strerror(r)); } r = IMAP_IOERROR; free(seendb); free(fname); return r; } syslog(LOG_DEBUG, "seen_db: user %s opened %s", user, fname); free(fname); seendb->tid = NULL; seendb->user = xstrdup(user); *seendbptr = seendb; return r; }
EXPORTED time_t duplicate_check(const duplicate_key_t *dkey) { struct buf key = BUF_INITIALIZER; int r; const char *data = NULL; size_t len = 0; time_t mark = 0; if (!duplicate_dbopen) return 0; r = make_key(&key, dkey); if (r) return 0; do { r = cyrusdb_fetch(dupdb, key.s, key.len, &data, &len, NULL); } while (r == CYRUSDB_AGAIN); if (!r && data) { assert((len == sizeof(time_t)) || (len == sizeof(time_t) + sizeof(unsigned long))); /* found the record */ memcpy(&mark, data, sizeof(time_t)); } else if (r != CYRUSDB_OK) { if (r != CYRUSDB_NOTFOUND) { syslog(LOG_ERR, "duplicate_check: error looking up %s/%s/%s: %s", dkey->id, dkey->to, dkey->date, cyrusdb_strerror(r)); } mark = 0; } #if DEBUG syslog(LOG_DEBUG, "duplicate_check: %-40s %-20s %-40s %ld", dkey->id, dkey->to, dkey->date, mark); #endif buf_free(&key); return mark; }
/* database better have been locked before this ! */ int mboxkey_unlock(struct mboxkey *mboxkeydb) { int r; assert(mboxkeydb); if (!mboxkeydb->tid) return 0; if (MBOXKEY_DEBUG) { syslog(LOG_DEBUG, "mboxkey_db: mboxkey_unlock(%s)", mboxkeydb->user); } r = cyrusdb_commit(mboxkeydb->db, mboxkeydb->tid); if (r != CYRUSDB_OK) { syslog(LOG_ERR, "DBERROR: error committing mboxkey txn; " "mboxkey state lost: %s", cyrusdb_strerror(r)); } mboxkeydb->tid = NULL; return 0; }
int seen_write(struct seen *seendb, const char *uniqueid, struct seendata *sd) { int sz = strlen(sd->seenuids) + 50; char *data = xmalloc(sz); int datalen; int r; assert(seendb && uniqueid); if (SEEN_DEBUG) { syslog(LOG_DEBUG, "seen_db: seen_write %s (%s)", seendb->user, uniqueid); } snprintf(data, sz, "%d %lu %u %lu %s", SEEN_VERSION, sd->lastread, sd->lastuid, sd->lastchange, sd->seenuids); datalen = strlen(data); r = cyrusdb_store(seendb->db, uniqueid, strlen(uniqueid), data, datalen, &seendb->tid); switch (r) { case CYRUSDB_OK: break; case CYRUSDB_IOERROR: r = IMAP_AGAIN; break; default: syslog(LOG_ERR, "DBERROR: error updating database: %s", cyrusdb_strerror(r)); r = IMAP_IOERROR; break; } free(data); sync_log_seen(seendb->user, uniqueid); return r; }
int mboxkey_done(void) { int r = 0; if (MBOXKEY_DEBUG) { syslog(LOG_DEBUG, "mboxkey_db: mboxkey_done()"); } if (lastmboxkey) { abortcurrent(lastmboxkey); r = cyrusdb_close(lastmboxkey->db); if (r) { syslog(LOG_ERR, "DBERROR: error closing lastmboxkey: %s", cyrusdb_strerror(r)); r = IMAP_IOERROR; } free(lastmboxkey->user); free(lastmboxkey->fname); free(lastmboxkey); } return r; }