Example #1
0
int mboxkey_merge(const char *tmpfile, const char *tgtfile) 
{
    int r = 0;
    struct db *tmp = NULL, *tgt = NULL;
    struct mboxkey_merge_rock rock;

    /* xxx does this need to be CYRUSDB_CREATE? */
    r = cyrusdb_open(DB, tmpfile, CYRUSDB_CREATE, &tmp);
    if(r) goto done;
	    
    r = cyrusdb_open(DB, tgtfile, CYRUSDB_CREATE, &tgt);
    if(r) goto done;

    rock.db = tgt;
    rock.tid = NULL;
    
    r = cyrusdb_foreach(tmp, "", 0, NULL, mboxkey_merge_cb, &rock, &rock.tid);

    if(r) cyrusdb_abort(rock.db, rock.tid);
    else cyrusdb_commit(rock.db, rock.tid);

 done:

    if(tgt) cyrusdb_close(tgt);
    if(tmp) cyrusdb_close(tmp);
    
    return r;
}
Example #2
0
/*
 * 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;
}
Example #3
0
/* 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;
}
Example #4
0
/* 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;
}
Example #5
0
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;
}
Example #6
0
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;
}
Example #7
0
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;
}
Example #8
0
/* we want to merge records from "newfile" into
 * the already existing "currentfile", but only
 * if the record in newfile is actually newer
 * (or doesn't exist in currentfile yet)  */
int seen_merge(struct seen *seendb, const char *newfile)
{
    int r = 0;
    struct db *newdb = NULL;

    r = cyrusdb_open(DB, newfile, 0, &newdb);
    /* if it doesn't exist, there's nothing
     * to do, so abort without an error */
    if (r == CYRUSDB_NOTFOUND) return 0;

    if (!r) r = cyrusdb_foreach(newdb, "", 0, NULL, seen_merge_cb, seendb, NULL);

    if (newdb) cyrusdb_close(newdb);

    return r;
}
Example #9
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);
}
Example #10
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;
}
Example #11
0
/* Returns 0 on success */
static int ptload(const char *identifier, struct auth_state **state)
{
    struct auth_state *fetched = NULL;
    size_t id_len;
    const char *data = NULL;
    size_t dsize;
    const char *fname = NULL;
    char *tofree = NULL;
    struct db *ptdb;
    int s;
    struct sockaddr_un srvaddr;
    int r, rc=0;
    static char response[1024];
    struct iovec iov[10];
    int niov, n;
    unsigned int start;
    const char *config_dir =
        libcyrus_config_getstring(CYRUSOPT_CONFIG_DIR);

    /* xxx this sucks, but it seems to be the only way to satisfy the linker */
    if(the_ptscache_db == NULL) {
        the_ptscache_db = libcyrus_config_getstring(CYRUSOPT_PTSCACHE_DB);
    }

    if(!state || *state) {
        fatal("bad state pointer passed to ptload()", EC_TEMPFAIL);
    }

    fname = libcyrus_config_getstring(CYRUSOPT_PTSCACHE_DB_PATH);

    if (!fname) {
        tofree = strconcat(config_dir, PTS_DBFIL, (char *)NULL);
        fname = tofree;
    }
    r = cyrusdb_open(the_ptscache_db, fname, CYRUSDB_CREATE, &ptdb);
    if (r != 0) {
        syslog(LOG_ERR, "DBERROR: opening %s: %s", fname,
               cyrusdb_strerror(ret));
        free(tofree);
        *state = NULL;
        return -1;
    }
    free(tofree);
    tofree = NULL;

    id_len = strlen(identifier);
    if(id_len > PTS_DB_KEYSIZE) {
        syslog(LOG_ERR, "identifier too long in auth_newstate");
        *state = NULL;
        return -1;
    }

    /* fetch the current record for the user */
    r = cyrusdb_fetch(ptdb, identifier, id_len,
                               &data, &dsize, NULL);
    if (r && r != CYRUSDB_NOTFOUND) {
        syslog(LOG_ERR, "auth_newstate: error fetching record: %s",
               cyrusdb_strerror(r));

        rc = -1;
        goto done;
    }

    /* if it's expired (or nonexistent),
     * ask the ptloader to reload it and reread it */
    fetched = (struct auth_state *) data;

    if(fetched) {
        time_t now = time(NULL);
        int timeout = libcyrus_config_getint(CYRUSOPT_PTS_CACHE_TIMEOUT);

        syslog(LOG_DEBUG,
               "ptload(): fetched cache record (%s)" \
               "(mark %ld, current %ld, limit %ld)", identifier,
               fetched->mark, now, now - timeout);

        if (fetched->mark > (now - timeout)) {
            /* not expired; let's return it */
            goto done;
        }
    }

    syslog(LOG_DEBUG, "ptload(): pinging ptloader");

    s = socket(AF_UNIX, SOCK_STREAM, 0);
    if (s == -1) {
        syslog(LOG_ERR,
               "ptload(): unable to create socket for ptloader: %m");
        rc = -1;
        goto done;
    }

    fname = libcyrus_config_getstring(CYRUSOPT_PTLOADER_SOCK);
    if (!fname) {
        tofree = strconcat(config_dir, PTS_DBSOCKET, (char *)NULL);
        fname = tofree;
    }

    if (strlen(fname) >= sizeof(srvaddr.sun_path)) {
        syslog(LOG_ERR, "ptload(): socket filename %s too long for " SIZE_T_FMT "-byte buffer",
                        fname, sizeof(srvaddr.sun_path));
        rc = -1;
        goto done;
    }

    memset((char *)&srvaddr, 0, sizeof(srvaddr));
    srvaddr.sun_family = AF_UNIX;
    strlcpy(srvaddr.sun_path, fname, sizeof(srvaddr.sun_path));
    r = nb_connect(s, (struct sockaddr *)&srvaddr, sizeof(srvaddr), PT_TIMEOUT_SEC);
    free(tofree);

    if (r == -1) {
        syslog(LOG_ERR, "ptload(): can't connect to ptloader server: %m");
        close(s);
        rc = -1;
        goto done;
    }

    syslog(LOG_DEBUG, "ptload(): connected");
    niov = 0;
    WRITEV_ADD_TO_IOVEC(iov, niov, (char *) &id_len, sizeof(id_len));
    WRITEV_ADD_TO_IOVEC(iov, niov, (char *) identifier, id_len);

    if (timeout_select(s, TS_WRITE, PT_TIMEOUT_SEC) < 0) {
      syslog(LOG_ERR, "timeoutselect: writing to ptloader %m");
      rc = -1;
      goto done;
    }
    retry_writev(s, iov, niov);
    syslog(LOG_DEBUG, "ptload sent data");

    start = 0;
    while (start < sizeof(response) - 1) {
      if (timeout_select(s, TS_READ, PT_TIMEOUT_SEC) < 0) {
        syslog(LOG_ERR, "timeout_select: reading from ptloader: %m");
        rc = -1;
        goto done;
      }
      n = read(s, response+start, sizeof(response) - 1 - start);
      if (n < 1) break;
      start += n;
    }
    response[sizeof(response)-1] = '\0';

    close(s);
    syslog(LOG_DEBUG, "ptload read data back");

    if (start <= 1 || strncmp(response, "OK", 2)) {
       if(start > 1) {
           syslog(LOG_ERR,
                  "ptload(): bad response from ptloader server: %s", response);
       } else {
           syslog(LOG_ERR, "ptload(): empty response from ptloader server");
       }
       rc = -1;
       goto done;
    }

    /* fetch the current record for the user */
    r = cyrusdb_fetch(ptdb, identifier, id_len,
                               &data, &dsize, NULL);
    if (r != 0 || !data) {
        syslog(LOG_ERR, "ptload(): error fetching record: %s"
               "(did ptloader add the record?)",
               cyrusdb_strerror(r));
      data = NULL;
      rc = -1;
      goto done;
    }

 done:
    /* ok, we got real data, let's use it */
    if (data != NULL) {
      fetched = (struct auth_state *) data;
    }

    if (fetched == NULL) {
      *state = NULL;
      syslog(LOG_DEBUG, "No data available at all from ptload()");
    } else  {
      /* copy it into our structure */
      *state = (struct auth_state *)xmalloc(dsize);
      memcpy(*state, fetched, dsize);
      syslog(LOG_DEBUG, "ptload returning data");
    }

    /* close and unlock the database */
    (cyrusdb_close)(ptdb);

    return rc;
}
Example #12
0
int main(int argc, char *argv[])
{
    int iter;
    int seed;
    int i;
    char *key;
    char *val;
    struct db *db;
    int r;
    struct txn *txn;
    const char *data;
    int datalen;
    struct timeval t1, t2;
    int initsize;

    if (argc > 1) {
	iter = atoi(argv[1]);
    } else {
      printf("%s [iterations] [rndseed] [initsize]\n", argv[0]);
      printf("if iterations is negative, run forever and report every -iter\n");
      exit(1);
    }
    TRY(DB->init(".", 0));

    if (argc > 2) {
	srand(atoi(argv[2]));
    }

    TRY(cyrusdb_open(DB, "scratch", &db));

    if (cyrusdb_consistent) {
	TRY(cyrusdb_consistent(db));
    }

    if (argc > 3) {
      initsize = atoi(argv[3]);
      
      txn = NULL;
      for (i = 0; i < initsize; i++) {
	/* generate a random key */
	key = genrand(10 + (rand() % 10));
	
	/* generate a random value */
	val = genrand(10 + (rand() % 100));
	
	TRY(cyrusdb_store(db, key, strlen(key), val, strlen(val), &txn));
      }

      TRY(cyrusdb_commit(db, txn));
      if (cyrusdb_consistent) {
	TRY(cyrusdb_consistent(db));
      }
    }

    printf("starting...\n");

    /* repeat for ever if iter < 0 */
    for (i = 0; iter > 0 ? (i < iter) : 1; i++) {
	int oper = rand() % 10;

	if (i > 0 && iter < 0 && ((i % -iter) == 0)) {
	  do_report();
	}

	switch (oper) {
	case 0:
	    /* do an ADD */
	    
	    if (verbose) printf("A");

	    /* insert it */
	    gettimeofday(&t1, NULL);

	    /* generate a random key */
	    key = genrand(10 + (rand() % 10));

	    /* generate a random value */
	    val = genrand(10 + (rand() % 100));

	    txn = NULL;
	    TRY(cyrusdb_store(db, key, strlen(key), val, strlen(val), &txn));
	    TRY(cyrusdb_commit(db, txn));
	    gettimeofday(&t2, NULL);

	    ADDDIFF(t_add, t1, t2);
	    c_add++;

	    free(key);
	    free(val);

	    break;

	case 1: /* do a modify */
	    if (verbose) printf("M");

	    gettimeofday(&t1, NULL);

	    /* pick a random victim */
	    count = 0;
	    victim = NULL;
	    txn = NULL;
	    TRY(cyrusdb_foreach(db, NULL, 0, &countem, NULL, NULL, &txn));
	    
	    if (count == 0) continue;

	    TRY(cyrusdb_foreach(db, NULL, 0, &findvictim, NULL, NULL, &txn));

	    assert(victim != NULL);

	    /* generate a random value */
	    val = genrand(10 + (rand() % 100));
	    
	    /* do an add */
	    TRY(cyrusdb_store(db, victim, strlen(victim), val, strlen(val), &txn));
	    free(val);

	    TRY(cyrusdb_commit(db, txn));
	    free(victim); victim = NULL;

	    gettimeofday(&t2, NULL);

	    ADDDIFF(t_mod, t1, t2);
	    c_mod++;

	    break;

	case 2: /* do a delete */
	    if (verbose) printf("D");

	    gettimeofday(&t1, NULL);

	    /* pick a random victim */
	    count = 0;
	    victim = NULL;
	    txn = NULL;
	    TRY(cyrusdb_foreach(db, NULL, 0, &countem, NULL, NULL, &txn));
	    
	    if (count == 0) continue;

	    TRY(cyrusdb_foreach(db, NULL, 0, &findvictim, NULL, NULL, &txn));
	    assert(victim != NULL);

	    /* delete it */
	    TRY(cyrusdb_delete(db, victim, strlen(victim), &txn, 0));

	    TRY(cyrusdb_commit(db, txn));
	    free(victim); victim = NULL;

	    gettimeofday(&t2, NULL);

	    ADDDIFF(t_del, t1, t2);
	    c_del++;

	    break;
	    
	default:
	    /* do a "read" */
	    if (verbose) printf("R");

	    gettimeofday(&t1, NULL);

	    /* generate a random key */
	    key = genrand(10 + (rand() % 10));

	    txn = NULL;
	    TRY(cyrusdb_fetch(db, key, strlen(key), &data, &datalen, &txn));
	    TRY(cyrusdb_commit(db, txn));

	    gettimeofday(&t2, NULL);

	    ADDDIFF(t_find, t1, t2);
	    c_find++;

	    free(key);
	}

	fflush(stdout);

#if 0
	/* run the consistency function, if any */
	if (cyrusdb_consistent) {
	    TRY(cyrusdb_consistent(db));
	}
#endif
    }

    TRY(cyrusdb_close(db));
    TRY(DB->done());

    do_report();
    return 0;
}
Example #13
0
int mboxkey_open(const char *user,
		 int flags,
		 struct mboxkey **mboxkeydbptr)
{
    struct mboxkey *mboxkeydb;
    struct stat sbuf;
    char *fname = NULL;
    int r;

    /* try to reuse the last db handle */
    mboxkeydb = lastmboxkey;
    lastmboxkey = NULL;
    if (MBOXKEY_DEBUG) {
	syslog(LOG_DEBUG, "mboxkey_db: mboxkey_open(%s)", user);
    }

    /* if this is the db we've already opened, return it */
    if (mboxkeydb && !strcmp(mboxkeydb->user, user) &&
	!stat(mboxkeydb->fname, &sbuf)) {
	abortcurrent(mboxkeydb);
	*mboxkeydbptr = mboxkeydb;
	return 0;
    }

    *mboxkeydbptr = NULL;
    /* otherwise, close the existing database */
    if (mboxkeydb) {
	abortcurrent(mboxkeydb);
	r = cyrusdb_close(mboxkeydb->db);
	if (r) {
	    syslog(LOG_ERR, "DBERROR: error closing mboxkeydb: %s", 
		   cyrusdb_strerror(r));
	}
	free(mboxkeydb->user);
	free(mboxkeydb->fname);
    } else {
	/* create mboxkeydb */
	mboxkeydb = (struct mboxkey *) xmalloc(sizeof(struct mboxkey));
    }

    /* open the mboxkeydb corresponding to user */
    fname = mboxkey_getpath(user);
    r = cyrusdb_open(DB, fname, (flags & MBOXKEY_CREATE) ? CYRUSDB_CREATE : 0,
		 &mboxkeydb->db);
    if (r != 0) {
	int level = (flags & MBOXKEY_CREATE) ? LOG_ERR : LOG_DEBUG;
	syslog(level, "DBERROR: opening %s: %s", fname, 
	       cyrusdb_strerror(r));
	r = IMAP_IOERROR;
	free(mboxkeydb);
	free(fname);
	return r;
    }
    syslog(LOG_DEBUG, "mboxkey_db: user %s opened %s", user, fname);

    mboxkeydb->tid = NULL;
    mboxkeydb->user = xstrdup(user);
    mboxkeydb->fname = fname;

    *mboxkeydbptr = mboxkeydb;
    return r;
}