I'm posting the source, as the patches would be too hard to read

I've split up the single apr_dbm.c into 2 parts.
a logical interface, (apr_dbm.c)
and a implementation. (apr_dbm_[SDBM/DB].c)

by doing this It allows:
* other DB types to be added easily externally by other people
* allows a 'default' db type for developers who just want a 'db'
* allows developers to specify which DB they want
* allows people to have multiple DB-types running at the same type.

If I could get some +1 votes I'll commit the changes
(and get a GDBM version working)

..Ian
/* ====================================================================
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2000-2001 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Apache" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact [EMAIL PROTECTED]
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

#include "apr.h"
#include "apr_errno.h"
#include "apr_pools.h"
#include "apr_strings.h"
#define APR_WANT_MEMFUNC
#define APR_WANT_STRFUNC
#include "apr_want.h"

#include "apu_select_dbm.h"
#include "apr_dbm.h"

/* this is so we can select a 'default' open/getnames */
#if APU_USE_SDBM
#include "apr_dbm_sdbm.h"
#elif APU_USE_DB
#include "apr_dbm_db.h"
#elif APU_USE_GDBM
#include "gdbm.h"
#include "gdbmerrno.h"
#endif

#include "dbm_private.h"


/* Most DBM libraries take a POSIX mode for creating files.  Don't trust
 * the mode_t type, some platforms may not support it, int is safe.
 */
APU_DECLARE(int) apr_posix_perms2mode(apr_fileperms_t perm) 
{
    int mode = 0;

    mode |= 0700 & (perm >> 2); /* User  is off-by-2 bits */
    mode |= 0070 & (perm >> 1); /* Group is off-by-1 bit */
    mode |= 0007 & (perm);      /* World maps 1 for 1 */
    return mode;
}



APU_DECLARE(apr_status_t) apr_dbm_open(apr_dbm_t **pdb, const char *pathname, 
                                       apr_int32_t mode, apr_fileperms_t perm,
                                       apr_pool_t *pool)
{
#if APU_USE_SDBM 
        return apr_dbm_open_sdbm(pdb,pathname,mode,perm,pool);
#elif APU_USE_DB
        return apr_dbm_open_db(pdb,pathname,mode,perm,pool);
#else
        return APR_ENOTAVAIL;
#endif
}
APU_DECLARE(void) apr_dbm_close(apr_dbm_t *dbm)
{
        dbm->close (dbm);
}

APU_DECLARE(apr_status_t) apr_dbm_fetch(apr_dbm_t *dbm, apr_datum_t key,
                                        apr_datum_t *pvalue)
{
        return dbm->fetch (dbm,key,pvalue);
}

APU_DECLARE(apr_status_t) apr_dbm_store(apr_dbm_t *dbm, apr_datum_t key,
                                        apr_datum_t value)
{
        return dbm->store (dbm,key,value);
}

APU_DECLARE(apr_status_t) apr_dbm_delete(apr_dbm_t *dbm, apr_datum_t key)
{
        return dbm->del (dbm,key);
}

APU_DECLARE(int) apr_dbm_exists(apr_dbm_t *dbm, apr_datum_t key)
{
        return dbm->exists (dbm,key);
}

APU_DECLARE(apr_status_t) apr_dbm_firstkey(apr_dbm_t *dbm, apr_datum_t *pkey)
{
        return dbm->firstkey (dbm,pkey);
}

APU_DECLARE(apr_status_t) apr_dbm_nextkey(apr_dbm_t *dbm, apr_datum_t *pkey)
{
        return dbm->nextkey(dbm,pkey);
}

APU_DECLARE(void) apr_dbm_freedatum(apr_dbm_t *dbm, apr_datum_t data)
{
        dbm->freedatum (dbm,data);
}


APU_DECLARE(char *) apr_dbm_geterror(apr_dbm_t *dbm, int *errcode,
                                     char *errbuf, apr_size_t errbufsize)
{
        return dbm->geterror(dbm,errcode,errbuf,errbufsize);
}

APU_DECLARE(void) apr_dbm_get_usednames( apr_pool_t *p,
                                        const char *pathname,
                                        const char **used1,
                                        const char **used2)
{
#if APU_USE_SDBM
        apr_dbm_get_usednames_sdbm(p,pathname,used1,used2);
#elif APU_USE_DB
        apr_dbm_get_usednames_db(p,pathname,used1,used2);
#else
        /* default op. no assumptions made */
        fprintf(stderr,"This Database does not implement 
apr_dbm_get_usednames");
        *used1=NULL;
        *used2=NULL;
#endif
}
/* ====================================================================
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2000-2001 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Apache" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact [EMAIL PROTECTED]
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

#include "apr.h"
#include "apr_errno.h"
#include "apr_pools.h"
#include "apr_strings.h"
#define APR_WANT_MEMFUNC
#define APR_WANT_STRFUNC
#include "apr_want.h"

#include "apu_select_dbm.h"
#include "apr_dbm.h"

#include "dbm_private.h"

#if APU_USE_DB
#include "apr_dbm_db.h"
/*
 * We pick up all varieties of Berkeley DB through db.h (included through
 * apu_select_dbm.h). This code has been compiled/tested against DB1,
 * DB_185, DB2, and DB3.
 */

#if   defined(DB_VERSION_MAJOR) && (DB_VERSION_MAJOR == 3)
#define DB_VER 3
#elif defined(DB_VERSION_MAJOR) && (DB_VERSION_MAJOR == 2)
#define DB_VER 2
#else
#define DB_VER 1
#endif

typedef struct {
    DB *bdb;
#if DB_VER != 1
    DBC *curs;
#endif
} apr_berkley_db_t;


#if DB_VER == 1
#include <sys/fcntl.h>
#define APR_DBM_DBMODE_RO       O_RDONLY
#define APR_DBM_DBMODE_RW       O_RDWR
#define APR_DBM_DBMODE_RWCREATE (O_CREAT | O_RDWR)
#else
#define APR_DBM_DBMODE_RO       DB_RDONLY
#define APR_DBM_DBMODE_RW       0
#define APR_DBM_DBMODE_RWCREATE DB_CREATE
#endif



/* map a DB error to an apr_status_t */
static apr_status_t db2s(int dberr)
{
    if (dberr != 0) {
        /* ### need to fix this */
        return APR_OS_START_USEERR+dberr;
    }

    return APR_SUCCESS;
}



/* handle the FIRSTKEY functionality */
static apr_status_t do_firstkey(apr_berkley_db_t *f, DBT *pkey)
{
    int dberr;
    DBT data;

        memset(&data,0,sizeof(DBT));

#if DB_VER == 1
    dberr = (*f->bdb->seq)(f->bdb, pkey, &data, R_FIRST);
#else
    if ((dberr = (*f->bdb->cursor)(f->bdb, NULL, &f->curs
#if DB_VER == 3
                                   , 0
#endif
                                   )) == 0) {
        dberr = (*f->curs->c_get)(f->curs, pkey, &data, DB_FIRST);
        if (dberr == DB_NOTFOUND) {
            memset(pkey, 0, sizeof(*pkey));
            (*f->curs->c_close)(f->curs);
            f->curs = NULL;
            return APR_SUCCESS;
        }
    }
#endif

    return db2s(dberr);
}

/* handle the NEXTKEY functionality 
This function also returns the 'data'
as well as the key.
*/
static apr_status_t do_nextkey(apr_berkley_db_t *f, DBT *pkey, DBT *pdata)
{
    int dberr;

        memset(pdata,0,sizeof(DBT));

#if DB_VER == 1
    dberr = (*f->bdb->seq)(f->bdb, pkey, pdata, R_NEXT);
#else
    if (f->curs == NULL)
        return APR_EINVAL;

    dberr = (*f->curs->c_get)(f->curs, pkey, pdata, DB_NEXT);
    if (dberr == DB_NOTFOUND) {
        memset(pkey, 0, sizeof(*pkey));
                memset(pdata, 0, sizeof(*pdata));
        (*f->curs->c_close)(f->curs);
        f->curs = NULL;
        return APR_SUCCESS;
    }
        
#endif

    return db2s(dberr);
}
static apr_status_t apr_dbm_set_error_db(apr_dbm_t *dbm, apr_status_t dbm_said)
{
    apr_status_t rv = APR_SUCCESS;

    /* ### ignore whatever the DBM said (dbm_said); ask it explicitly */

    if (dbm_said == APR_SUCCESS) {
        dbm->errcode = 0;
        dbm->errmsg = NULL;
    }
    else {
        /* ### need to fix. dberr was tossed in db2s(). */
        /* ### use db_strerror() */
        dbm->errcode = dbm_said;
        dbm->errmsg = db_strerror( dbm_said - APR_OS_START_USEERR);
        rv = dbm_said;
    }
    return rv;
}
static void apr_dbm_close_db(apr_dbm_t *dbm)
{
    //APR_DBM_CLOSE(dbm.file);
        apr_berkley_db_t *real_ptr = dbm->file;
        DB*db;

        if (real_ptr) {
                db = real_ptr->bdb;
#if DB_VER == 1
                db->close(db);
#else
                db->close(db,0);
#endif
                dbm->file=NULL;
        }       
        
}

/* make sure we clean up and close things */
static apr_status_t db_cleanup(void* p)
{
        apr_dbm_t **db=p;

        if (*db) {
                apr_dbm_close_db(*db);
                *db=NULL;
        }

        return APR_SUCCESS;
}
static apr_status_t apr_dbm_fetch_db(apr_dbm_t *dbm, apr_datum_t key,
                                        apr_datum_t *pvalue)
{
    apr_status_t rv;
        apr_berkley_db_t *real_ptr = dbm->file;
        DB*db=real_ptr->bdb;
    DBT ckey;
    DBT rd;
        int dberr;

        memset(&ckey,0,sizeof(DBT));
        memset(&rd,0,sizeof(DBT));

        ckey.data = key.dptr;
        ckey.size = key.dsize;

#if DB_VER == 1
        dberr=db->get(db, &ckey,&rd,0);
        
#else
        dberr=db->get(db, NULL,&ckey,&rd,0);
#endif
        rv = db2s(dberr);
    //rv = APR_DBM_FETCH(dbm->file, ckey, rd);
        pvalue->dptr = rd.data;
        pvalue->dsize =rd.size;


    /* store the error info into DBM, and return a status code. Also, note
       that *pvalue should have been cleared on error. */
    return apr_dbm_set_error_db(dbm, rv);
}

static apr_status_t apr_dbm_store_db(apr_dbm_t *dbm, apr_datum_t key,
                                        apr_datum_t value)
{
    apr_status_t rv;
        int dberr;
        apr_berkley_db_t *real_ptr = dbm->file;
        DB*db=real_ptr->bdb;
    DBT ckey;
    DBT cvalue;

        memset(&ckey,0,sizeof(DBT));
        ckey.data = key.dptr;
        ckey.size=key.dsize;
        memset(&cvalue,0,sizeof(DBT));
        cvalue.data = value.dptr;
        cvalue.size=value.dsize;

//    rv = APR_DBM_STORE(dbm->file, ckey, cvalue);
#if DB_VER == 1
        dberr = db->put(db,&ckey,&cvalue,0);
#else
        dberr = db->put(db,NULL,&ckey,&cvalue,0);
#endif
        rv = db2s(dberr);

    /* store any error info into DBM, and return a status code. */
    return apr_dbm_set_error_db(dbm, rv);

}

static apr_status_t apr_dbm_delete_db(apr_dbm_t *dbm, apr_datum_t key)
{
    apr_status_t rv;
    DBT ckey;
        apr_berkley_db_t *real_ptr = dbm->file;
        DB*db=real_ptr->bdb;
        int dberr;

        memset(&ckey,0,sizeof(DBT));
        ckey.data = key.dptr;
        ckey.size=key.dsize;
#if DB_VER ==1
        dberr = db->del(db,&ckey,0);
#else
        dberr = db->del(db,NULL,&ckey,0);
#endif
    rv = db2s(dberr);

    /* store any error info into DBM, and return a status code. */
    return apr_dbm_set_error_db(dbm, rv);

}

static int apr_dbm_exists_db(apr_dbm_t *dbm, apr_datum_t key)
{
    int exists;
    DBT ckey;
    DBT data;
        apr_berkley_db_t *real_ptr = dbm->file;
        DB*db=real_ptr->bdb;

        int dberr;

//    CONVERT_DATUM(ckey, &key);
        memset(&ckey,0,sizeof(DBT));
        ckey.data = key.dptr;
        ckey.size=key.dsize;

        memset(&data,0,sizeof(DBT));
        data.data = key.dptr;
        data.size=key.dsize;

#if DB_VER ==1
        dberr = db->get(db, &ckey, &data,0);
#else
        dberr = db->get(db, NULL,&ckey, &data, 0);
#endif
        /* DB returns DB_NOTFOUND if it doesn't exist. but we want to say
           that *any* error means it doesn't exist. */
    exists = dberr == 0;
    return exists;
}

static apr_status_t apr_dbm_firstkey_db(apr_dbm_t *dbm, apr_datum_t *pkey)
{
    apr_status_t rv;
    DBT rd;
        apr_berkley_db_t *real_ptr = dbm->file;

    memset(&rd,0,sizeof(DBT));
        rv = do_firstkey(real_ptr,&rd);

    pkey->dptr = rd.data;
        pkey->dsize = rd.size;
    /* store any error info into DBM, and return a status code. */
    return apr_dbm_set_error_db(dbm, rv);
}

static apr_status_t apr_dbm_nextkey_db(apr_dbm_t *dbm, apr_datum_t *pkey)
{
    apr_status_t rv;
    DBT ckey;
    DBT rd;
        apr_berkley_db_t *real_ptr = dbm->file;
    
        memset(&rd,0,sizeof(DBT));
        memset(&ckey,0,sizeof(DBT));
        ckey.data = pkey->dptr;
        ckey.size=pkey->dsize;

        rv = do_nextkey(real_ptr,&ckey,&rd);

        pkey->dptr = ckey.data;
        pkey->dsize =ckey.size; 

    /* store any error info into DBM, and return a status code. */
    return apr_dbm_set_error_db(dbm, APR_SUCCESS);

}

static void apr_dbm_freedatum_noop(apr_dbm_t *dbm, apr_datum_t data)
{
    //APR_DBM_FREEDPTR(data.dptr);
}
static apr_status_t apr_dbm_datum_cleanup_noop(void*x)
{
        return APR_SUCCESS;
}

static char * apr_dbm_geterror_db(apr_dbm_t *dbm, int *errcode,
                                     char *errbuf, apr_size_t errbufsize)
{
    if (errcode != NULL)
        *errcode = dbm->errcode;

    /* assert: errbufsize > 0 */

    if (dbm->errmsg == NULL)
        *errbuf = '\0';
    else
        (void) apr_cpystrn(errbuf, dbm->errmsg, errbufsize);

    return errbuf;

}

APU_DECLARE(void) apr_dbm_get_usednames_db( apr_pool_t *p,
                                        const char *pathname,
                                        const char **used1,
                                        const char **used2)
{
    *used1 = apr_pstrdup(p, pathname);
    *used2 = NULL;
}


APU_DECLARE(apr_status_t) apr_dbm_open_db(apr_dbm_t **pdb, const char 
*pathname, 
                                       apr_int32_t mode, apr_fileperms_t perm,
                                       apr_pool_t *pool)
{
    apr_berkley_db_t *file=apr_palloc(pool,sizeof(apr_berkley_db_t));
    int dbmode;
    int dberr;
    *pdb = NULL;

    switch (mode) {
    case APR_DBM_READONLY:
        dbmode = APR_DBM_DBMODE_RO;
        break;
    case APR_DBM_READWRITE:
        dbmode = APR_DBM_DBMODE_RW;
        break;
    case APR_DBM_RWCREATE:
        dbmode = APR_DBM_DBMODE_RWCREATE;
        break;
    default:
        return APR_EINVAL;
    }
        /* 
         * Allocate the structure before attempting to open
         * the DB.
         * (so we can call a error routine if we fail to open)
         */
        *pdb = apr_pcalloc(pool, sizeof(**pdb));
    (*pdb)->pool = pool;
    (*pdb)->file = file;

        (*pdb)->close = apr_dbm_close_db;
        (*pdb)->set_error = apr_dbm_set_error_db;
        (*pdb)->fetch = apr_dbm_fetch_db;
        (*pdb)->store = apr_dbm_store_db;
        (*pdb)->del = apr_dbm_delete_db;
        (*pdb)->exists = apr_dbm_exists_db;
        (*pdb)->firstkey =apr_dbm_firstkey_db;
        (*pdb)->nextkey =apr_dbm_nextkey_db;

        (*pdb)->geterror =apr_dbm_geterror_db;
        (*pdb)->freedatum =apr_dbm_freedatum_noop;
        (*pdb)->datum_cleanup=apr_dbm_datum_cleanup_noop;
        
#if DB_VER == 3
    if ((dberr = db_create(&file->bdb, NULL, 0)) == 0) {
        if ((dberr = (*file->bdb->open)(file->bdb, pathname, NULL, 
                                       DB_HASH, dbmode, 
                                       apr_posix_perms2mode(perm))) != 0) {
            /* close the DB handler */
            (void) (*file->bdb->close)(file->bdb, 0);
        }
    }
    file->curs = NULL;

#elif DB_VER == 2
    dberr = db_open(pathname, DB_HASH, dbmode, apr_posix_perms2mode(perm),
                    NULL, NULL, &file->bdb);
    file->curs = NULL;
#else
    file->bdb = dbopen(pathname, dbmode, apr_posix_perms2mode(perm),
                      DB_HASH, NULL);

    if (file->bdb == NULL)
        return APR_OS_START_USEERR;      /* ### need a better error */
    dberr = 0;
#endif

    if (dberr != 0)
                return apr_dbm_set_error_db(*pdb, db2s(dberr));

    apr_pool_cleanup_register(pool, pdb, db_cleanup, apr_pool_cleanup_null); 

    return APR_SUCCESS;

}
#endif /* APU_USE_DB */
/* ====================================================================
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2000-2001 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Apache" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact [EMAIL PROTECTED]
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

#include "apr.h"

#include "apr_errno.h"
#include "apr_pools.h"
#include "apr_strings.h"
#define APR_WANT_MEMFUNC
#define APR_WANT_STRFUNC
#include "apr_want.h"

#include "apu_select_dbm.h"
#include "apr_dbm.h"

#include "apu.h"

#include "dbm_private.h"

#if APU_USE_SDBM

#include "apr_sdbm.h"

//typedef apr_sdbm_t *real_file_t;

//typedef apr_sdbm_datum_t *cvt_datum_t;
//#define CONVERT_DATUM(cvt, pinput) ((cvt) = (apr_sdbm_datum_t *)(pinput))

//typedef apr_sdbm_datum_t result_datum_t;
//#define RETURN_DATUM(poutput, rd) (*(poutput) = *(apr_datum_t *)&(rd))

//#define APR_DBM_CLOSE(f)      apr_sdbm_close(f)
//#define APR_DBM_FETCH(f, k, v)        apr_sdbm_fetch(f, &(v), *(k))
//#define APR_DBM_STORE(f, k, v)        apr_sdbm_store(f, *(k), *(v), 
APR_SDBM_REPLACE)
//#define APR_DBM_DELETE(f, k)  apr_sdbm_delete(f, *(k))
//#define APR_DBM_FIRSTKEY(f, k)        apr_sdbm_firstkey(f, &(k))
//#define APR_DBM_NEXTKEY(f, k, nk) apr_sdbm_nextkey(f, &(nk))
//#define APR_DBM_FREEDPTR(dptr)        NOOP_FUNCTION

#define APR_DBM_DBMODE_RO       APR_READ
#define APR_DBM_DBMODE_RW       (APR_READ | APR_WRITE)
#define APR_DBM_DBMODE_RWCREATE (APR_READ | APR_WRITE | APR_CREATE)

static void apr_dbm_close_sdbm(apr_dbm_t *dbm)
{
        apr_sdbm_close((apr_sdbm_t*)dbm->file);
}

static apr_status_t apr_dbm_set_error_sdbm(apr_dbm_t *dbm, apr_status_t 
dbm_said)
{
    apr_status_t rv = APR_SUCCESS;

    /* ### ignore whatever the DBM said (dbm_said); ask it explicitly */

    if ((dbm->errcode = dbm_said) == APR_SUCCESS) {
        dbm->errmsg = NULL;
    }
    else {
        dbm->errmsg = "I/O error occurred.";
        rv = APR_EGENERAL;        /* ### need something better */
    }

    return rv;
}

static apr_status_t  apr_dbm_fetch_sdbm(apr_dbm_t *dbm, apr_datum_t key,
                                        apr_datum_t *pvalue)
{
    apr_status_t rv;
    apr_sdbm_datum_t *ckey;
    apr_sdbm_datum_t rd;

        ckey = (apr_sdbm_datum_t *)&key;

        rd.dptr=NULL;
        rd.dsize =-1;

    rv = apr_sdbm_fetch(dbm->file, &rd, *ckey);
        
//      rv = apr_sdbm_fetch(dbm->file , &ckey, *rd);

        *(pvalue) = *(apr_datum_t *)&rd;

    
//    REGISTER_CLEANUP(dbm, pvalue);

    /* store the error info into DBM, and return a status code. Also, note
       that *pvalue should have been cleared on error. */
    return apr_dbm_set_error_sdbm(dbm, rv);
}
static apr_status_t apr_dbm_store_sdbm(apr_dbm_t *dbm, apr_datum_t key,
                                        apr_datum_t value)
{
    apr_status_t rv;
    apr_sdbm_datum_t *ckey;
    apr_sdbm_datum_t *cvalue;

//    CONVERT_DATUM(ckey, &key);
        ckey = (apr_sdbm_datum_t*)&key;
        cvalue = (apr_sdbm_datum_t*)&value;
//    CONVERT_DATUM(cvalue, &value);
    rv = apr_sdbm_store(dbm->file, *ckey, *cvalue,APR_SDBM_REPLACE);

    /* store any error info into DBM, and return a status code. */
    return apr_dbm_set_error_sdbm(dbm, rv);
}
static apr_status_t apr_dbm_delete_sdbm(apr_dbm_t *dbm, apr_datum_t key)
{
    apr_status_t rv;
    apr_sdbm_datum_t *ckey;

//    CONVERT_DATUM(ckey, &key);
        ckey = (apr_sdbm_datum_t*)&key;
    rv = apr_sdbm_delete(dbm->file, *ckey);

    /* store any error info into DBM, and return a status code. */
    return apr_dbm_set_error_sdbm(dbm, rv);
}
static int apr_dbm_exists_sdbm(apr_dbm_t *dbm, apr_datum_t key)
{
    int exists;
    apr_sdbm_datum_t *ckey;
        apr_sdbm_datum_t value;

//    CONVERT_DATUM(ckey, &key);
        ckey = (apr_sdbm_datum_t*)&key;
    if (apr_sdbm_fetch(dbm->file, &value, *ckey) != APR_SUCCESS) {
            exists = 0;
        }
        else {
        exists = value.dptr != NULL;
    }

    return exists;
}
static apr_status_t apr_dbm_firstkey_sdbm(apr_dbm_t *dbm, apr_datum_t *pkey)
{
    apr_status_t rv;
    apr_sdbm_datum_t rd;

    rv = apr_sdbm_firstkey(dbm->file, &rd);
//    RETURN_DATUM(pkey, rd);
        *pkey=*(apr_datum_t *)&rd;
//    REGISTER_CLEANUP(dbm, pkey);

    /* store any error info into DBM, and return a status code. */
    return apr_dbm_set_error_sdbm(dbm, rv);
}

static apr_status_t apr_dbm_nextkey_sdbm(apr_dbm_t *dbm, apr_datum_t *pkey)
{
    apr_status_t rv;
    apr_sdbm_datum_t *ckey;
    apr_sdbm_datum_t rd;


        ckey = (apr_sdbm_datum_t*)pkey;
    rv = apr_sdbm_nextkey(dbm->file, &rd);
        *pkey=*(apr_datum_t *)&rd;

//    REGISTER_CLEANUP(dbm, pkey);

    /* store any error info into DBM, and return a status code. */
    return apr_dbm_set_error_sdbm(dbm, APR_SUCCESS);
}


APU_DECLARE(void) apr_dbm_get_usednames_sdbm( apr_pool_t *p,
                                        const char *pathname,
                                        const char **used1,
                                        const char **used2)
{
    char *work;

    *used1 = apr_pstrcat(p, pathname, APR_SDBM_DIRFEXT, NULL);
    *used2 = work = apr_pstrdup(p, *used1);

    /* we know the extension is 4 characters */
    memcpy(&work[strlen(work) - 4], APR_SDBM_PAGFEXT, 4);

}

static void apr_dbm_freedatum_noop(apr_dbm_t *dbm, apr_datum_t data)
{

}
static apr_status_t apr_dbm_datum_cleanup_noop(void*x)
{
        return APR_SUCCESS;
}
static char * apr_dbm_geterror_sdbm(apr_dbm_t *dbm, int *errcode,
                                     char *errbuf, apr_size_t errbufsize)
{
    if (errcode != NULL)
        *errcode = dbm->errcode;

    /* assert: errbufsize > 0 */

    if (dbm->errmsg == NULL)
        *errbuf = '\0';
    else
        (void) apr_cpystrn(errbuf, dbm->errmsg, errbufsize);
    return errbuf;
}

APU_DECLARE(apr_status_t) apr_dbm_open_sdbm(apr_dbm_t **pdb, const char 
*pathname, 
                                       apr_int32_t mode, apr_fileperms_t perm,
                                       apr_pool_t *pool)
{
    apr_sdbm_t *file;
    apr_status_t rv;
    int dbmode;

    *pdb = NULL;

    switch (mode) {
    case APR_DBM_READONLY:
        dbmode = APR_DBM_DBMODE_RO;
        break;
    case APR_DBM_READWRITE:
        dbmode = APR_DBM_DBMODE_RW;
        break;
    case APR_DBM_RWCREATE:
        dbmode = APR_DBM_DBMODE_RWCREATE;
        break;
    default:
        return APR_EINVAL;
    }

    rv = apr_sdbm_open(&file, pathname, dbmode, perm, pool);
    if (rv != APR_SUCCESS)
        return rv;
    
    *pdb = apr_pcalloc(pool, sizeof(**pdb));
    (*pdb)->pool = pool;
    (*pdb)->file = file;

        (*pdb)->close = apr_dbm_close_sdbm;
        (*pdb)->set_error = apr_dbm_set_error_sdbm;
        (*pdb)->fetch = apr_dbm_fetch_sdbm;
        (*pdb)->store = apr_dbm_store_sdbm;
        (*pdb)->del = apr_dbm_delete_sdbm;
        (*pdb)->exists = apr_dbm_exists_sdbm;
        (*pdb)->firstkey =apr_dbm_firstkey_sdbm;
        (*pdb)->nextkey =apr_dbm_nextkey_sdbm;

        (*pdb)->geterror =apr_dbm_geterror_sdbm;
        (*pdb)->freedatum =apr_dbm_freedatum_noop;
        (*pdb)->datum_cleanup=apr_dbm_datum_cleanup_noop;
        
   
/* we have an open database... return it */
    return APR_SUCCESS;

}
#endif /* APU_USE_SDBM */
#ifndef _DBM_PRIVATE_H 
#define _DBM_PRIVATE_H 1

/* this is used in a few places to define a noop "function". it is needed
   to stop "no effect" warnings from GCC. */


#define NOOP_FUNCTION if (0) ; else

/* Most DBM libraries take a POSIX mode for creating files.  Don't trust
 * the mode_t type, some platforms may not support it, int is safe.
 */
APU_DECLARE(int) apr_posix_perms2mode(apr_fileperms_t perm);


struct apr_dbm_t
{
    apr_pool_t *pool;
        /** XXX: pointer to DB Implementation Specific data */
    void* file;

    int errcode;
    const char *errmsg;
        apr_status_t (*set_error)       (apr_dbm_t*dbm, apr_status_t dbm_said);
        void         (*close)           (apr_dbm_t*dbm);
        apr_status_t (*fetch)           (apr_dbm_t *dbm, apr_datum_t 
key,apr_datum_t 
                                                                         
*pvalue);
        apr_status_t (*store)           (apr_dbm_t *dbm, apr_datum_t key,
                                      apr_datum_t value);
        apr_status_t (*del)                     (apr_dbm_t *dbm, apr_datum_t 
key);
        int                      (*exists)              (apr_dbm_t *dbm, 
apr_datum_t key);
        apr_status_t (*firstkey)        (apr_dbm_t *dbm, apr_datum_t *pkey);
        apr_status_t (*nextkey)         (apr_dbm_t *dbm, apr_datum_t *pkey);
        char*            (*geterror)    (apr_dbm_t *dbm, int *errcode,
                                     char *errbuf, apr_size_t errbufsize);

        /** if a DBM needs to call something free data */
        apr_status_t (*datum_cleanup) (void*); 
        void             (*freedatum)   (apr_dbm_t *dbm, apr_datum_t data);


};

#endif /* _DBM_PRIVATE_H */
/* ====================================================================
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2000-2001 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Apache" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact [EMAIL PROTECTED]
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

#ifndef APR_DBM_H
#define APR_DBM_H

#include "apu.h"
#include "apr.h"
#include "apr_errno.h"
#include "apr_pools.h"
#include "apr_file_info.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
 * @package APR-UTIL DBM library
 */

/**
 * Structure for referencing a dbm
 * @defvar apr_dbm_t
 */
typedef struct apr_dbm_t apr_dbm_t;

/**
 * Structure for referencing the datum record within a dbm
 * @defvar apr_datum_t
 */
typedef struct
{
    char *dptr;
    apr_size_t dsize;
} apr_datum_t;

/* modes to open the DB */
#define APR_DBM_READONLY        1       /* open for read-only access */
#define APR_DBM_READWRITE       2       /* open for read-write access */
#define APR_DBM_RWCREATE        3       /* open for r/w, create if needed */

/**
 * Open a dbm file by file name
 * @param dbm The newly opened database
 * @param name The dbm file name to open
 * @param mode The flag value
 * <PRE>
 *           APR_DBM_READONLY   open for read-only access
 *           APR_DBM_READWRITE  open for read-write access
 *           APR_DBM_RWCREATE   open for r/w, create if needed
 * </PRE>
 * @param perm Permissions to apply to if created
 * @param cntxt The pool to use when creating the dbm
 * @deffunc apr_status_t apr_dbm_open(apr_dbm_t **dbm, const char *name, int 
mode
 * @tip The dbm name may not be a true file name, as many dbm packages
 * append suffixes for seperate data and index files.
 */
APU_DECLARE(apr_status_t) apr_dbm_open(apr_dbm_t **dbm, const char *name, 
                                       apr_int32_t mode, apr_fileperms_t perm,
                                       apr_pool_t *cntxt);

/**
 * Close a dbm file previously opened by apr_dbm_open
 * @param dbm The database to close
 * @deffunc void apr_dbm_close(apr_dbm_t *dbm)
 */
APU_DECLARE(void) apr_dbm_close(apr_dbm_t *dbm);

/**
 * Fetch a dbm record value by key
 * @param dbm The database 
 * @param key The key datum to find this record
 * @param value The value datum retrieved for this record
 * @deffunc apr_status_t apr_dbm_fetch(apr_dbm_t *dbm, apr_datum_t key
 */
APU_DECLARE(apr_status_t) apr_dbm_fetch(apr_dbm_t *dbm, apr_datum_t key,
                                        apr_datum_t *pvalue);
/**
 * Store a dbm record value by key
 * @param dbm The database 
 * @param key The key datum to store this record by
 * @param value The value datum to store in this record
 * @deffunc apr_status_t apr_dbm_store(apr_dbm_t *dbm, apr_datum_t key, 
apr_datum_t value)
 */
APU_DECLARE(apr_status_t) apr_dbm_store(apr_dbm_t *dbm, apr_datum_t key, 
                                        apr_datum_t value);

/**
 * Delete a dbm record value by key
 * @param dbm The database 
 * @param key The key datum of the record to delete
 * @deffunc apr_status_t apr_dbm_delete(apr_dbm_t *dbm, apr_datum_t key)
 * @tip It is not an error to delete a non-existent record.
 */
APU_DECLARE(apr_status_t) apr_dbm_delete(apr_dbm_t *dbm, apr_datum_t key);

/**
 * Search for a key within the dbm
 * @param dbm The database 
 * @param key The datum describing a key to test
 * @deffunc int apr_dbm_exists(apr_dbm_t *dbm, apr_datum_t key)
 */
APU_DECLARE(int) apr_dbm_exists(apr_dbm_t *dbm, apr_datum_t key);

/**
 * Retrieve the first record key from a dbm
 * @param dbm The database 
 * @param key The key datum of the first record
 * @deffunc apr_status_t apr_dbm_firstkey(apr_dbm_t *dbm, apr_datum_t *pkey)
 */
APU_DECLARE(apr_status_t) apr_dbm_firstkey(apr_dbm_t *dbm, apr_datum_t *pkey);

/**
 * Retrieve the next record key from a dbm
 * @param dbm The database 
 * @param key The key datum of the next record
 * @deffunc apr_status_t apr_dbm_nextkey(apr_dbm_t *dbm, apr_datum_t *pkey)
 */
APU_DECLARE(apr_status_t) apr_dbm_nextkey(apr_dbm_t *dbm, apr_datum_t *pkey);

/**
 * Proactively toss any memory associated with the apr_datum_t.
 * @param dbm The database 
 * @param data The datum to free.
 * @deffunc void apr_dbm_freedatum(apr_dbm_t *dbm, apr_datum_t data)
 */
APU_DECLARE(void) apr_dbm_freedatum(apr_dbm_t *dbm, apr_datum_t data);

/**
 * Report more information when an apr_dbm function fails.
 * @param dbm The database
 * @param errcode A DBM-specific value for the error (for logging). If this
 *                isn't needed, it may be NULL.
 * @param errbuf Location to store the error text
 * @param errbufsize The size of the provided buffer
 * @return The errbuf parameter, for convenience.
 * @deffunc const char * apr_dbm_geterror(apr_dbm_t *dbm, int *errcode, char 
*errbuf, apr_size_t errbufsize)
 */
APU_DECLARE(char *) apr_dbm_geterror(apr_dbm_t *dbm, int *errcode,
                                     char *errbuf, apr_size_t errbufsize);

/**
 * If the specified file/path were passed to apr_dbm_open(), return the
 * actual file/path names which would be (created and) used. At most, two
 * files may be used; used2 may be NULL if only one file is used.
 * @param pool The pool for allocating used1 and used2.
 * @param pathname The path name to generate used-names from.
 * @param used1 The first pathname used by the apr_dbm implementation.
 * @param used2 The second pathname used by apr_dbm. If only one file is
 *              used by the specific implementation, this will be set to NULL.
 */
APU_DECLARE(void) apr_dbm_get_usednames(apr_pool_t *pool,
                                        const char *pathname,
                                        const char **used1,
                                        const char **used2);

#ifdef __cplusplus
}
#endif

#endif  /* !APR_DBM_H */
/* ====================================================================
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2000-2001 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Apache" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact [EMAIL PROTECTED]
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

#ifndef APR_DBM_SDBM_H
#define APR_DBM_SDBM_H 1

#include "apr.h"
#include "apr_dbm.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
 * Open a SDBM file by file name
 * @param dbm The newly opened database
 * @param name The dbm file name to open
 * @param mode The flag value
 * <PRE>
 *           APR_DBM_READONLY   open for read-only access
 *           APR_DBM_READWRITE  open for read-write access
 *           APR_DBM_RWCREATE   open for r/w, create if needed
 * </PRE>
 * @param perm Permissions to apply to if created
 * @param cntxt The pool to use when creating the dbm
 * @deffunc apr_status_t apr_dbm_open(apr_dbm_t **dbm, const char *name, int 
mode
 * @tip The dbm name may not be a true file name, as many dbm packages
 * append suffixes for seperate data and index files.
 */
APU_DECLARE(apr_status_t) apr_dbm_open_sdbm(apr_dbm_t **dbm, const char *name, 
                                       apr_int32_t mode, apr_fileperms_t perm,
                                       apr_pool_t *cntxt);

/**
 * If the specified file/path were passed to apr_dbm_open_sdbm(), return the
 * actual file/path names which would be (created and) used. At most, two
 * files may be used; used2 may be NULL if only one file is used.
 * @param pool The pool for allocating used1 and used2.
 * @param pathname The path name to generate used-names from.
 * @param used1 The first pathname used by the apr_dbm implementation.
 * @param used2 The second pathname used by apr_dbm. If only one file is
 *              used by the specific implementation, this will be set to NULL.
 */
APU_DECLARE(void) apr_dbm_get_usednames_sdbm( apr_pool_t *p,
                                        const char *pathname,
                                        const char **used1,
                                        const char **used2);
#ifdef __cplusplus
}
#endif
#endif /* APR_DBM_SDBM_H */
/* ====================================================================
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2000-2001 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Apache" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact [EMAIL PROTECTED]
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

#ifndef APR_DBM_SDBM_H
#define APR_DBM_SDBM_H 1

#include "apr.h"
#include "apr_dbm.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
 * Open a Berkley DB file by file name
 * @param dbm The newly opened database
 * @param name The dbm file name to open
 * @param mode The flag value
 * <PRE>
 *           APR_DBM_READONLY   open for read-only access
 *           APR_DBM_READWRITE  open for read-write access
 *           APR_DBM_RWCREATE   open for r/w, create if needed
 * </PRE>
 * @param perm Permissions to apply to if created
 * @param cntxt The pool to use when creating the dbm
 * @deffunc apr_status_t apr_dbm_open(apr_dbm_t **dbm, const char *name, int 
mode
 * @tip The dbm name may not be a true file name, as many dbm packages
 * append suffixes for seperate data and index files.
 */
APU_DECLARE(apr_status_t) apr_dbm_open_db(apr_dbm_t **dbm, const char *name, 
                                       apr_int32_t mode, apr_fileperms_t perm,
                                       apr_pool_t *cntxt);

/**
 * If the specified file/path were passed to apr_dbm_open_db(), return the
 * actual file/path names which would be (created and) used. At most, two
 * files may be used; used2 may be NULL if only one file is used.
 * @param pool The pool for allocating used1 and used2.
 * @param pathname The path name to generate used-names from.
 * @param used1 The first pathname used by the apr_dbm implementation.
 * @param used2 The second pathname used by apr_dbm. If only one file is
 *              used by the specific implementation, this will be set to NULL.
 */
APU_DECLARE(void) apr_dbm_get_usednames_db( apr_pool_t *p,
                                        const char *pathname,
                                        const char **used1,
                                        const char **used2);
#ifdef __cplusplus
}
#endif
#endif /* APR_DBM_SDBM_H */
/* ====================================================================
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2000-2001 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Apache" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact [EMAIL PROTECTED]
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 *
 * This file came from the SDBM package (written by [EMAIL PROTECTED]).
 * That package was under public domain. This file has been ported to
 * APR, updated to ANSI C and other, newer idioms, and added to the Apache
 * codebase under the above copyright and license.
 */

#include "apr.h"
#include "apr_general.h"
#include "apr_pools.h"
#include "apr_errno.h"
#include "apr_getopt.h"
#include "apr_time.h"

#if APR_HAVE_STDIO_H
#include <stdio.h>
#endif
#if APR_HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <stdlib.h>     /* for atexit(), malloc() */
#include <string.h>

#include "apr_dbm.h"
#include "apr_dbm_sdbm.h"

static const char *progname;
static int rflag;
static const char *usage = "%s [-R] cat | look |... dbmname";

#define DERROR  0
#define DLOOK   1

#define DDELETE 3
#define DCAT    4
#define DBUILD  5
#define DPRESS  6
#define DCREAT  7
#define DNAME   8

#define LINEMAX 8192

typedef struct {
    const char *sname;
    int scode;
    int flags;
} cmd;

static const cmd cmds[] = {

    { "fetch", DLOOK,           APR_DBM_READONLY, },
    { "get", DLOOK,             APR_DBM_READONLY, },
    { "look", DLOOK,            APR_DBM_READONLY, },
    { "add", DBUILD,            APR_DBM_READWRITE, },
    { "insert", DBUILD, APR_DBM_READWRITE, },    
    { "store", DBUILD,          APR_DBM_READWRITE, },
        { "build", DBUILD,              APR_DBM_RWCREATE, },    /** this one 
creates the DB */
    { "delete", DDELETE,        APR_DBM_READWRITE, },
    { "remove", DDELETE,        APR_DBM_READWRITE, },
    { "dump", DCAT,             APR_DBM_READONLY, },
    { "list", DCAT,             APR_DBM_READONLY, },
    { "cat", DCAT,              APR_DBM_READONLY, },
    { "creat", DCREAT,          APR_DBM_RWCREATE , },
    { "new", DCREAT,            APR_DBM_RWCREATE , },
        { "names", DNAME,               APR_DBM_READONLY, },
#if 0
    { "squash", DPRESS,         APR_DBM_READWRITE, },
    { "compact", DPRESS,        APR_DBM_READWRITE, },
    { "compress", DPRESS,       APR_DBM_READWRITE, },
#endif
};

#define CTABSIZ (sizeof (cmds)/sizeof (cmd))

static void doit(const cmd *act, const char *file, apr_pool_t *pool);
static void badk(const char *word);
static const cmd *parse(const char *str);
static void prdatum(FILE *stream, apr_datum_t d);
static void oops(apr_dbm_t *dbm,apr_status_t rv, const char *s1, const char 
*s2);


int main(int argc, const char * const * argv)
{
    apr_pool_t *pool;
    const cmd *act;
    apr_getopt_t *os;
    char optch;
    const char *optarg;

    (void) apr_initialize();
    apr_pool_create(&pool, NULL);
        atexit(apr_terminate);

    (void) apr_getopt_init(&os, pool, argc, argv);

    progname = argv[0];

    while (apr_getopt(os, "R", &optch, &optarg) == APR_SUCCESS)
        switch (optch) {
        case 'R':              /* raw processing  */
            rflag++;
            break;

        default:
            oops(NULL,APR_EGENERAL,"(unknown option) usage: %s", usage);
            break;
        }

    if (os->ind + 2 > argc)
        oops(NULL,APR_EGENERAL,"usage: %s", usage);

    if ((act = parse(argv[os->ind])) == NULL)
        badk(argv[os->ind]);
    os->ind++;
    doit(act, argv[os->ind], pool);

    apr_pool_destroy(pool);
   
    return 0;
}

static void doit(const cmd *act, const char *file, apr_pool_t *pool)
{
    apr_status_t rv;
    apr_datum_t key;
    apr_datum_t val;
    apr_dbm_t *db;
    char *op;
    int n;
    char *line;
        char*use1;
        char*use2;
#ifdef TIME
    long start;
    extern long time();
#endif


        rv =apr_dbm_open(&db, file, act->flags, APR_OS_DEFAULT, pool);
    if (rv != APR_SUCCESS)
        oops(db,rv,"cannot open: %s", file);

    line = (char *) apr_palloc(pool,LINEMAX);
        if ( line == NULL) {
            oops(NULL,APR_EGENERAL,"%s: cannot get memory", "line alloc");
        }

    switch (act->scode) {

    case DLOOK:
        while (fgets(line, LINEMAX, stdin) != NULL) {
            n = strlen(line) - 1;
            line[n] = 0;
                        if (n==0)
                                break;

            key.dptr = line;
            key.dsize = n;
            rv = apr_dbm_fetch(db, key, &val);
            if (rv == APR_SUCCESS) {
                prdatum(stdout, val);
                putchar('\n');
                continue;
            }
            prdatum(stderr, key);
            fprintf(stderr, ": not found.\n");
        }
        break;

    case DDELETE:
        while (fgets(line, LINEMAX, stdin) != NULL) {
            n = strlen(line) - 1;
            line[n] = 0;
                        if (n==0)
                                break;

            key.dptr = line;
            key.dsize = n;
            if (apr_dbm_delete(db, key) != APR_SUCCESS) {
                prdatum(stderr, key);
                fprintf(stderr, ": not found.\n");
            }
        }
        break;
    case DCAT:
                rv =apr_dbm_firstkey(db, &key); 
        if ( rv != APR_SUCCESS)
            oops(db,rv,"could not fetch first key: %s", file);

                while ( key.dptr != NULL ) 
                {
            prdatum(stdout, key);
            putchar('\t');
            rv =  apr_dbm_fetch(db, key, &val);
                        if (rv != APR_SUCCESS)
                                oops(db,rv,"apr_dbm_fetch","failure");
            prdatum(stdout, val);
            putchar('\n');
                        rv = apr_dbm_nextkey( db,&key);
                        if (rv != APR_SUCCESS)
                                oops(db,rv,"NextKey","failure");
                }

        break;
    case DBUILD:
#ifdef TIME
        start = time(0);
#endif
        while (fgets(line, LINEMAX, stdin) != NULL) {
            n = strlen(line) - 1;
            line[n] = 0;
                        if (n==0)
                                break;

            key.dptr = line;
            if ((op = strchr(line, '\t')) != 0) {
                key.dsize = op - line;
                *op++ = 0;
                val.dptr = op;
                val.dsize = line + n - op;
            }
            else { 
                                oops(NULL,APR_EGENERAL,"bad input: %s", line);
                        }
        
                        rv = apr_dbm_store(db, key, val);
            if ( rv != APR_SUCCESS) {
                prdatum(stderr, key);
                fprintf(stderr, ": ");
                oops(db,rv,"store: %s", "failed");
            }
        }
#ifdef TIME
        printf("done: %d seconds.\n", time(0) - start);
#endif
        break;
    case DPRESS:
        break;
    case DCREAT:
        break;
    case DNAME:

                apr_dbm_get_usednames(pool,file,&use1,&use2);
                fprintf( stderr,"%s %s %s",file,use1,use2);
        break;
    }

        apr_dbm_close(db);
}

static void badk(const char *word)
{
    int i;

    if (progname)
        fprintf(stderr, "%s: ", progname);
    fprintf(stderr, "bad keywd %s. use one of\n", word);
    for (i = 0; i < (int)CTABSIZ; i++)
        fprintf(stderr, "%-8s%c", cmds[i].sname,
                ((i + 1) % 6 == 0) ? '\n' : ' ');
    fprintf(stderr, "\n");
    exit(1);
    /*NOTREACHED*/
}

static const cmd *parse(const char *str)
{
    int i = CTABSIZ;
    const cmd *p;
        
    for (p = cmds; i--; p++)
        if (strcmp(p->sname, str) == 0)
            return p;
    return NULL;
}

static void prdatum(FILE *stream, apr_datum_t d)
{
    int c;
    const char *p = d.dptr;
    int n = d.dsize;

    while (n--) {
        c = *p++ & 0377;
        if (c & 0200) {
            fprintf(stream, "M-");
            c &= 0177;
        }
        if (c == 0177 || c < ' ') 
            fprintf(stream, "^%c", (c == 0177) ? '?' : c + '@');
        else
            putc(c, stream);
    }
}

static void oops(apr_dbm_t *dbm, apr_status_t rv, const char *s1, const char 
*s2)
{
        char errbuf[200];


    if (progname)
        fprintf(stderr, "%s: ", progname);
    fprintf(stderr, s1, s2);
    if (errno > 0 && errno < sys_nerr)
        fprintf(stderr, " (%s)", sys_errlist[errno]);
    fprintf(stderr, "\n");
        if (rv != APR_SUCCESS)
        {
                apr_strerror(rv,errbuf,sizeof(errbuf));
                fprintf(stderr,"APR Error %d - %s\n",rv,errbuf);

                if (dbm) {
                        apr_dbm_geterror(dbm,&rv,errbuf,sizeof(errbuf));
                        fprintf(stderr,"APR_DB Error %d - %s\n",rv, errbuf);
                }

        }
    exit(1);
}

Reply via email to