Module Name: src Committed By: christos Date: Fri Nov 29 22:56:19 UTC 2013
Modified Files: src/external/bsd/nvi/dist/common: dbinternal.h vi_db.c vi_db.h src/external/bsd/nvi/usr.bin/nvi: Makefile config.h port.h Added Files: src/external/bsd/nvi/dist/common: db1.c Log Message: Bring back the compatibility db3->db1 code from the old vi. This is selected with -DUSE_DB1 in the Makefile. By default use use the db1 specific code from the current nvi which is enabled using -DUSE_BUNDLED_DB. Unfortunately recovery seems to be broken for both. To generate a diff of this commit: cvs rdiff -u -r0 -r1.1 src/external/bsd/nvi/dist/common/db1.c cvs rdiff -u -r1.1 -r1.2 src/external/bsd/nvi/dist/common/dbinternal.h cvs rdiff -u -r1.4 -r1.5 src/external/bsd/nvi/dist/common/vi_db.c cvs rdiff -u -r1.2 -r1.3 src/external/bsd/nvi/dist/common/vi_db.h cvs rdiff -u -r1.2 -r1.3 src/external/bsd/nvi/usr.bin/nvi/Makefile \ src/external/bsd/nvi/usr.bin/nvi/config.h cvs rdiff -u -r1.1 -r1.2 src/external/bsd/nvi/usr.bin/nvi/port.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/external/bsd/nvi/dist/common/dbinternal.h diff -u src/external/bsd/nvi/dist/common/dbinternal.h:1.1 src/external/bsd/nvi/dist/common/dbinternal.h:1.2 --- src/external/bsd/nvi/dist/common/dbinternal.h:1.1 Fri Nov 22 10:52:05 2013 +++ src/external/bsd/nvi/dist/common/dbinternal.h Fri Nov 29 17:56:19 2013 @@ -1,5 +1,5 @@ -/* $NetBSD: dbinternal.h,v 1.1 2013/11/22 15:52:05 christos Exp $ */ -#ifndef db_env_create +/* $NetBSD: dbinternal.h,v 1.2 2013/11/29 22:56:19 christos Exp $ */ +#if !defined(db_env_create) || defined(USE_DB1) int db_env_create(DB_ENV **, u_int32_t); #endif int db_create(DB **, DB_ENV *, u_int32_t); Index: src/external/bsd/nvi/dist/common/vi_db.c diff -u src/external/bsd/nvi/dist/common/vi_db.c:1.4 src/external/bsd/nvi/dist/common/vi_db.c:1.5 --- src/external/bsd/nvi/dist/common/vi_db.c:1.4 Wed Nov 27 22:14:28 2013 +++ src/external/bsd/nvi/dist/common/vi_db.c Fri Nov 29 17:56:19 2013 @@ -23,11 +23,14 @@ static const char sccsid[] = "Id: db.c,v #include <limits.h> #include <stdio.h> #include <string.h> +#include <stdlib.h> +#include <unistd.h> #include "common.h" +#include "dbinternal.h" #include "../vi/vi.h" -static int append __P((SCR*, db_recno_t, CHAR_T*, size_t, lnop_t, int)); +static int append __P((SCR*, db_recno_t, const CHAR_T*, size_t, lnop_t, int)); /* * db_eget -- @@ -87,7 +90,7 @@ db_get(SCR *sp, db_recno_t lno, u_int32_ EXF *ep; TEXT *tp; db_recno_t l1, l2; - CHAR_T *wp; + const CHAR_T *wp; size_t wlen; size_t nlen; @@ -275,12 +278,12 @@ db_delete(SCR *sp, db_recno_t lno) * line */ static int -append(SCR *sp, db_recno_t lno, CHAR_T *p, size_t len, lnop_t op, int update) +append(SCR *sp, db_recno_t lno, const CHAR_T *p, size_t len, lnop_t op, int update) { DBT data, key; DBC *dbcp_put; EXF *ep; - char *fp; + const char *fp; size_t flen; int rval; @@ -312,7 +315,7 @@ append(SCR *sp, db_recno_t lno, CHAR_T * if ((sp->db_error = dbcp_put->c_get(dbcp_put, &key, &data, DB_SET)) != 0) goto err2; - data.data = fp; + data.data = __UNCONST(fp); data.size = flen; if ((sp->db_error = dbcp_put->c_put(dbcp_put, &key, &data, DB_AFTER)) != 0) { err2: @@ -329,7 +332,7 @@ err2: if (sp->db_error != DB_NOTFOUND) goto err2; - data.data = fp; + data.data = __UNCONST(fp); data.size = flen; if ((sp->db_error = ep->db->put(ep->db, NULL, &key, &data, DB_APPEND)) != 0) { goto err2; @@ -337,7 +340,7 @@ err2: } else { key.data = &lno; key.size = sizeof(lno); - data.data = fp; + data.data = __UNCONST(fp); data.size = flen; if ((sp->db_error = dbcp_put->c_put(dbcp_put, &key, &data, DB_BEFORE)) != 0) { goto err2; @@ -419,7 +422,7 @@ db_set(SCR *sp, db_recno_t lno, CHAR_T * { DBT data, key; EXF *ep; - char *fp; + const char *fp; size_t flen; #if defined(DEBUG) && 0 @@ -446,7 +449,7 @@ db_set(SCR *sp, db_recno_t lno, CHAR_T * key.data = &lno; key.size = sizeof(lno); memset(&data, 0, sizeof(data)); - data.data = fp; + data.data = __UNCONST(fp); data.size = flen; if ((sp->db_error = ep->db->put(ep->db, NULL, &key, &data, 0)) != 0) { msgq(sp, M_DBERR, "006|unable to store line %lu", (u_long)lno); @@ -514,7 +517,7 @@ db_last(SCR *sp, db_recno_t *lnop) DBC *dbcp; EXF *ep; db_recno_t lno; - CHAR_T *wp; + const CHAR_T *wp; size_t wlen; /* Check for no underlying file. */ @@ -530,8 +533,8 @@ db_last(SCR *sp, db_recno_t *lnop) if (ep->c_nlines != OOBLNO) { *lnop = ep->c_nlines; if (F_ISSET(sp, SC_TINPUT)) - *lnop += TAILQ_LAST&sp->tiq, _texth)->lno - - TAILQ_FIRST&sp->tiq)->lno; + *lnop += TAILQ_LAST(&sp->tiq, _texth)->lno - + TAILQ_FIRST(&sp->tiq)->lno; return (0); } @@ -648,6 +651,8 @@ update_cache(SCR *sp, lnop_t op, db_recn if (lno == scrp->c_lno) scrp->c_lno = OOBLNO; break; + case LINE_APPEND: + break; } if (ep->c_nlines != OOBLNO) @@ -658,6 +663,9 @@ update_cache(SCR *sp, lnop_t op, db_recn case LINE_DELETE: --ep->c_nlines; break; + case LINE_APPEND: + case LINE_RESET: + break; } } Index: src/external/bsd/nvi/dist/common/vi_db.h diff -u src/external/bsd/nvi/dist/common/vi_db.h:1.2 src/external/bsd/nvi/dist/common/vi_db.h:1.3 --- src/external/bsd/nvi/dist/common/vi_db.h:1.2 Fri Nov 22 10:52:05 2013 +++ src/external/bsd/nvi/dist/common/vi_db.h Fri Nov 29 17:56:19 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: vi_db.h,v 1.2 2013/11/22 15:52:05 christos Exp $ */ +/* $NetBSD: vi_db.h,v 1.3 2013/11/29 22:56:19 christos Exp $ */ #include <db.h> @@ -27,7 +27,7 @@ typedef recno_t db_recno_t; #else -#if DB_VERSION_MAJOR >= 3 && DB_VERSION_MINOR >= 1 +#if USE_DB1 || (DB_VERSION_MAJOR >= 3 && DB_VERSION_MINOR >= 1) #define db_env_open(env,path,flags,mode) \ (env)->open(env, path, flags, mode) #define db_env_remove(env,path,flags) \ @@ -65,3 +65,112 @@ extern int (*nvi_db_create) __P((DB ** extern int (*nvi_db_env_create) __P((DB_ENV **, u_int32_t)); extern char *(*nvi_db_strerror) __P((int)); #endif + +#ifdef USE_DB1 + +#define DB_AFTER 1 +#define DB_APPEND 2 +#define DB_BEFORE 3 +#define DB_FIRST 7 +#define DB_LAST 15 +#define DB_SET 25 + +#define DB_NOTFOUND (-30989) + +/* DBT emulation */ +typedef DBT DBT_v1; +#undef DBT +#define DBT DBT_new + +typedef struct { + void *data; + size_t size; + + u_int32_t ulen; + +#define DB_DBT_USERMEM 0x040 + u_int32_t flags; +} DBT; + +/* DB_ENV emulation */ +struct __db_env_new; +typedef struct __db_env_new DB_ENV; + +struct __db_env_new { + int (*close)(DB_ENV *, u_int32_t); + int (*open)(DB_ENV *, char *, u_int32_t, int); +#define DB_INIT_MPOOL 0x004000 +#define DB_PRIVATE 0x200000 + int (*remove)(DB_ENV *, char *, u_int32_t); + + char *base_path; + int mode; +}; + +/* DBC emulation */ + +struct __dbc_new; +typedef struct __dbc_new DBC; + +typedef recno_t db_recno_t; +#define DB_MAX_RECORDS MAX_REC_NUMBER + +#define DB_UNKNOWN (-1) + +/* DB emulation */ +typedef DB DB_old; +#undef DB +#define DB DB_new +typedef struct __db_new DB; + +#undef DB_TXN +typedef void DB_TXN; + +#undef DB_LSN +typedef struct { + int dummy; +} DB_LSN; + +struct __db_new { + DB_old *actual_db; + + int type; + + int (*close)(DB *, u_int32_t); +#define DB_NOSYNC 26 /* close() */ + + int (*open)(DB *, const char *, const char *, DBTYPE, u_int32_t, int); +#define DB_CREATE 0x000001 /* Create file as necessary. */ +#define DB_TRUNCATE 0x004000 /* Discard existing DB (O_TRUNC) */ + + int (*sync)(DB *, u_int32_t); + int (*get)(DB *, DB_TXN *, DBT *, DBT *, u_int32_t); + int (*put)(DB *, DB_TXN *, DBT *, DBT *, u_int32_t); + int (*del)(DB *, DB_TXN *, DBT *, u_int32_t); + + int (*cursor)(DB *, DB_TXN *, DBC **, u_int32_t); + + int (*set_flags)(DB *, u_int32_t); +#define DB_RENUMBER 0x0008 /* Recno: renumber on insert/delete. */ +#define DB_SNAPSHOT 0x0020 /* Recno: snapshot the input. */ + + int (*set_pagesize)(DB *, u_int32_t); + + int (*set_re_delim)(DB *, int); + int (*set_re_source)(DB *, const char *); + + RECNOINFO _recno_info; + u_int32_t _pagesize; + u_int32_t _flags; +}; + +struct __dbc_new { + DB *db; + db_recno_t pos; + DBT_v1 pos_key; + int (*c_close)(DBC *); + int (*c_get)(DBC *, DBT *, DBT *, u_int32_t); + int (*c_put)(DBC *, DBT *, DBT *, u_int32_t); +}; + +#endif /* USE_DB1 */ Index: src/external/bsd/nvi/usr.bin/nvi/Makefile diff -u src/external/bsd/nvi/usr.bin/nvi/Makefile:1.2 src/external/bsd/nvi/usr.bin/nvi/Makefile:1.3 --- src/external/bsd/nvi/usr.bin/nvi/Makefile:1.2 Fri Nov 29 11:37:35 2013 +++ src/external/bsd/nvi/usr.bin/nvi/Makefile Fri Nov 29 17:56:19 2013 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.2 2013/11/29 16:37:35 christos Exp $ +# $NetBSD: Makefile,v 1.3 2013/11/29 22:56:19 christos Exp $ .include <bsd.own.mk> @@ -6,9 +6,10 @@ USE_WIDECHAR?=yes CWARNFLAGS.clang+= -Wno-uninitialized -Wno-format-security -CPPFLAGS+=-I${DIST}/include -I${.CURDIR} -I. -DGTAGS -DUSE_BUNDLED_DB +CPPFLAGS+=-I${DIST}/include -I${.CURDIR} -I. -DGTAGS #DBG=-g #CPPFLAGS+=-DLOGDEBUG -DTRACE +#CPPFLAGS+=-DDBDEBUG -DTRACE #CWARNFLAGS+=-Wno-parentheses -Wno-unused -Wno-missing-prototypes #.if defined(HAVE_GCC) @@ -31,14 +32,14 @@ SRCS= api.c cl_bsd.c cl_funcs.c cl_main. ex_write.c ex_yank.c ex_z.c exf.c getc.c gs.c \ ip_funcs.c ip_read.c ip_screen.c ip_term.c \ ip_run.c ip_send.c ip_trans.c ipc_cmd.c ipc_method.c \ - key.c log1.c trace.c \ + key.c trace.c \ main.c mark.c msg.c nothread.c options.c options_f.c put.c recover.c \ screen.c search.c seq.c util.c v_at.c v_ch.c v_cmd.c v_delete.c \ v_event.c v_ex.c v_increment.c v_init.c v_itxt.c v_left.c v_mark.c \ v_match.c v_paragraph.c v_put.c v_redraw.c v_replace.c v_right.c \ v_screen.c v_scroll.c v_search.c v_section.c v_sentence.c v_status.c \ v_txt.c v_ulcase.c v_undo.c v_util.c v_word.c v_xchar.c v_yank.c \ - v_z.c v_zexit.c vi.c vi_db1.c vs_line.c vs_msg.c vs_refresh.c \ + v_z.c v_zexit.c vi.c vs_line.c vs_msg.c vs_refresh.c \ vs_relative.c vs_smap.c vs_split.c # For wide char support @@ -47,6 +48,14 @@ SRCS+= regcomp.c regerror.c regexec.c re CPPFLAGS+=-I${DIST}/regex -D__REGEX_PRIVATE -DUSE_WIDECHAR .endif +# For db3 db1 emulation +#SRCS+=db1.c log.c vi_db.c +#CPPFLAGS+=-DUSE_DB1 + +# For built-in db1 emulation +SRCS+=vi_db1.c log1.c +CPPFLAGS+=-DUSE_BUNDLED_DB + LINKS= ${BINDIR}/vi ${BINDIR}/ex ${BINDIR}/vi ${BINDIR}/view MLINKS= vi.1 ex.1 vi.1 view.1 Index: src/external/bsd/nvi/usr.bin/nvi/config.h diff -u src/external/bsd/nvi/usr.bin/nvi/config.h:1.2 src/external/bsd/nvi/usr.bin/nvi/config.h:1.3 --- src/external/bsd/nvi/usr.bin/nvi/config.h:1.2 Mon Nov 25 18:04:39 2013 +++ src/external/bsd/nvi/usr.bin/nvi/config.h Fri Nov 29 17:56:19 2013 @@ -231,9 +231,6 @@ /* Define to 1 if your <sys/time.h> declares `struct tm'. */ /* #undef TM_IN_SYS_TIME */ -/* Define when using bundled db. */ -#define USE_BUNDLED_DB 1 - /* Define when using db4 logging. */ /* #undef USE_DB4_LOGGING */ Index: src/external/bsd/nvi/usr.bin/nvi/port.h diff -u src/external/bsd/nvi/usr.bin/nvi/port.h:1.1 src/external/bsd/nvi/usr.bin/nvi/port.h:1.2 --- src/external/bsd/nvi/usr.bin/nvi/port.h:1.1 Fri Nov 22 11:00:45 2013 +++ src/external/bsd/nvi/usr.bin/nvi/port.h Fri Nov 29 17:56:19 2013 @@ -1,4 +1,4 @@ -/* $Id: port.h,v 1.1 2013/11/22 16:00:45 christos Exp $ (Berkeley) $Date: 2013/11/22 16:00:45 $ */ +/* $Id: port.h,v 1.2 2013/11/29 22:56:19 christos Exp $ (Berkeley) $Date: 2013/11/29 22:56:19 $ */ /* * Declare the basic types, if they aren't already declared. Named and @@ -121,6 +121,7 @@ #define MIN(_a,_b) ((_a)<(_b)?(_a):(_b)) #endif +#ifndef USE_DB1 /* * XXX * "DB" isn't always portable, and we want the private information. @@ -128,6 +129,7 @@ #define DB L__DB #undef pgno_t /* IRIX has its own version. */ #define pgno_t L__db_pgno_t +#endif /* * XXX Added files: Index: src/external/bsd/nvi/dist/common/db1.c diff -u /dev/null src/external/bsd/nvi/dist/common/db1.c:1.1 --- /dev/null Fri Nov 29 17:56:19 2013 +++ src/external/bsd/nvi/dist/common/db1.c Fri Nov 29 17:56:19 2013 @@ -0,0 +1,360 @@ +/* + * DB1->3 compatibility layer + */ + +#include "config.h" + +#include <assert.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +#include <fcntl.h> + +#include "../common/vi_db.h" +#include "../common/dbinternal.h" + +/* + * DB_ENV emulation + */ + +static int db1_dbenv_close(DB_ENV *, u_int32_t); +static int db1_dbenv_open(DB_ENV *, char *, u_int32_t, int); +static int db1_dbenv_remove(DB_ENV *, char *, u_int32_t); + +int +db_env_create(DB_ENV **dbenvp, u_int32_t flags) { + DB_ENV *dbenv; + + assert(flags == 0); + + dbenv = malloc(sizeof *dbenv); + if (dbenv == NULL) + return -1; + + dbenv->close = db1_dbenv_close; + dbenv->open = db1_dbenv_open; + dbenv->remove = db1_dbenv_remove; + + dbenv->base_path = NULL; + dbenv->mode = 0; + + *dbenvp = dbenv; + return 0; +} + +static int +db1_dbenv_close(DB_ENV *dbenv, u_int32_t flags) { + assert(flags == 0); + + if (dbenv->base_path != NULL) + free(dbenv->base_path); + + free(dbenv); + return 0; +} + +static int +db1_dbenv_open(DB_ENV *dbenv, char *base_path, u_int32_t flags, int mode) { + + /* We ignore flags on purpose */ + + dbenv->base_path = strdup(base_path); + if (dbenv->base_path == NULL) + return ENOSPC; + + dbenv->mode = mode != 0? mode : 0660; + return 0; +} + +static int +db1_dbenv_remove(DB_ENV *dbenv_fake, char *base_path, u_int32_t flags) { + /* dbenv_fake is not a useful environment */ + /* XXX check if we have to remove files here */ + + return 0; +} + +/* + * DB emulation + */ +static int db1_db_close(DB *, u_int32_t); +static int db1_db_open(DB *, const char *, const char *, DBTYPE, u_int32_t, int); +static int db1_db_sync(DB *, u_int32_t); +static int db1_db_get(DB *, DB_TXN *, DBT *, DBT *, u_int32_t); +static int db1_db_put(DB *, DB_TXN *, DBT *, DBT *, u_int32_t); +static int db1_db_del(DB *, DB_TXN *, DBT *, u_int32_t); +static int db1_db_set_flags(DB *, u_int32_t); +static int db1_db_set_pagesize(DB *, u_int32_t); +static int db1_db_set_re_delim(DB *, int); +static int db1_db_set_re_source(DB *, const char *); +static int db1_db_cursor(DB *, DB_TXN *, DBC **, u_int32_t); + +int +db_create(DB **dbp, DB_ENV *dbenv, u_int32_t flags) { + assert(flags == 0); + + *dbp = malloc(sizeof **dbp); + if (*dbp == NULL) + return -1; + + (*dbp)->type = DB_UNKNOWN; + (*dbp)->actual_db = NULL; + (*dbp)->_pagesize = 0; + (*dbp)->_flags = 0; + memset(&(*dbp)->_recno_info, 0, sizeof (RECNOINFO)); + + (*dbp)->close = db1_db_close; + (*dbp)->open = db1_db_open; + (*dbp)->sync = db1_db_sync; + (*dbp)->get = db1_db_get; + (*dbp)->put = db1_db_put; + (*dbp)->del = db1_db_del; + (*dbp)->set_flags = db1_db_set_flags; + (*dbp)->set_pagesize = db1_db_set_pagesize; + (*dbp)->set_re_delim = db1_db_set_re_delim; + (*dbp)->set_re_source = db1_db_set_re_source; + (*dbp)->cursor = db1_db_cursor; + + return 0; +} + +const char * +db_strerror(int error) { + return error > 0? strerror(error) : "record not found"; +} + +static int +db1_db_close(DB *db, u_int32_t flags) { + if (flags & DB_NOSYNC) { + /* XXX warn user? */ + } + db->actual_db->close(db->actual_db); + + db->type = DB_UNKNOWN; + db->actual_db = NULL; + db->_pagesize = 0; + db->_flags = 0; + memset(&db->_recno_info, 0, sizeof (RECNOINFO)); + + return 0; +} + +static int +db1_db_open(DB *db, const char *file, const char *database, DBTYPE type, + u_int32_t flags, int mode) { + int oldflags = 0; + + assert(database == NULL && !(flags & ~(DB_CREATE | DB_TRUNCATE))); + + db->type = type; + + if (flags & DB_CREATE) + oldflags |= O_CREAT; + if (flags & DB_TRUNCATE) + oldflags |= O_TRUNC; + + if (type == DB_RECNO) { + const char *tmp = file; + + /* The interface is reversed in DB3 */ + file = db->_recno_info.bfname; + db->_recno_info.bfname = __UNCONST(tmp); + + /* ... and so, we should avoid to truncate the main file! */ + oldflags &= ~O_TRUNC; + + db->_recno_info.flags = + db->_flags & DB_SNAPSHOT? R_SNAPSHOT : 0; + db->_recno_info.psize = db->_pagesize; + } + + db->actual_db = dbopen(file, oldflags, mode, type, + type == DB_RECNO? &db->_recno_info : NULL); + + return db->actual_db == NULL? errno : 0; +} + +static int +db1_db_sync(DB *db, u_int32_t flags) { + assert(flags == 0); + + return db->actual_db->sync(db->actual_db, db->type == DB_UNKNOWN? + R_RECNOSYNC : 0) == 0? 0 : errno; +} + +static int +db1_db_get(DB *db, DB_TXN *txnid, DBT *key, DBT *data, u_int32_t flags) { + int err; + DBT_v1 data1; + + assert(flags == 0 && txnid == NULL); + + err = db->actual_db->get(db->actual_db, (DBT_v1 *) key, &data1, flags); + if (err == 1) + return DB_NOTFOUND; + else if (err == -1) + return errno; + + if (data->flags & DB_DBT_USERMEM) { + data->size = data1.size; + if (data1.size > data->ulen) + return DB_BUFFER_SMALL; + + memcpy(data->data, data1.data, data1.size); + } + + return 0; +} + +static int +db1_db_put(DB *db, DB_TXN *txnid, DBT *key, DBT *data, u_int32_t flags) { + int err; + DB_old *db_v1 = db->actual_db; + DBT data1; + DBT key1; + recno_t recno = 1; + + assert((flags & ~DB_APPEND) == 0 && txnid == NULL); + + key1 = *key; + + if (flags & DB_APPEND) { + if (db_v1->seq(db_v1, (DBT_v1 *)(void *)key, + (DBT_v1 *)(void *)&data1, R_LAST) == 1) { + key1.data = &recno; + key1.size = sizeof recno; + } + } + err = db_v1->put(db_v1, (DBT_v1 *)(void *)&key1, (DBT_v1 *)(void *)data, + 0); + + return err == -1? errno : err; +} + +static int +db1_db_del(DB *db, DB_TXN *txnid, DBT *key, u_int32_t flags) { + int err; + DB_old *db_v1 = db->actual_db; + + assert(txnid == NULL && flags == 0); + + err = db_v1->del(db_v1, (DBT_v1 *) key, 0); + return err == -1? errno : err; +} + +static int +db1_db_set_flags(DB *db, u_int32_t flags) { + assert((flags & ~(DB_RENUMBER | DB_SNAPSHOT)) == 0); + + /* Can't prevent renumbering from happening with DB1 */ + assert((flags | db->_flags) & DB_RENUMBER); + + + db->_flags |= flags; + + return 0; +} + +static int +db1_db_set_pagesize(DB *db, u_int32_t pagesize) { + db->_pagesize = pagesize; + + return 0; +} + +static int +db1_db_set_re_delim(DB *db, int re_delim) { + db->_recno_info.bval = re_delim; + + return 0; +} + +static int +db1_db_set_re_source(DB *db, const char *re_source) { + db->_recno_info.bfname = __UNCONST(re_source); + + return 0; +} + +/* DBC emulation. Very basic, only one cursor at a time, enough for vi */ + +static int db1_dbc_close(DBC *); +static int db1_dbc_get(DBC *, DBT *, DBT *, u_int32_t); +static int db1_dbc_put(DBC *, DBT *, DBT *, u_int32_t); + +static int +db1_db_cursor(DB *db, DB_TXN *txn, DBC **cursorp, u_int32_t flags) { + DBC *cursor; + + assert(txn == NULL && flags == 0); + + cursor = malloc(sizeof *cursor); + if (cursor == NULL) + return -1; + + cursor->db = db; + cursor->pos_key.data = &cursor->pos; + cursor->pos_key.size = sizeof cursor->pos; + cursor->c_close = db1_dbc_close; + cursor->c_get = db1_dbc_get; + cursor->c_put = db1_dbc_put; + + *cursorp = cursor; + + return 0; +} + +static int +db1_dbc_close(DBC *cursor) { + free(cursor); + return 0; +} + +static int +db1_dbc_get(DBC *cursor, DBT *key, DBT *data, u_int32_t flags) { + DB *db = cursor->db; + DB_old *db_v1 = db->actual_db; + int ret = 0; + + + switch(flags) { + case DB_SET: + ret = db_v1->seq(db_v1, (DBT_v1 *) key, (DBT_v1 *) data, + R_CURSOR); + cursor->pos = * (db_recno_t *) key->data; + break; + case DB_FIRST: + ret = db_v1->seq(db_v1, (DBT_v1 *) key, (DBT_v1 *) data, + R_FIRST); + if (ret == 1) + ret = DB_NOTFOUND; + cursor->pos = * (db_recno_t *) key->data; + break; + case DB_LAST: + ret = db_v1->seq(db_v1, (DBT_v1 *) key, (DBT_v1 *) data, + R_LAST); + if (ret == 1) + ret = DB_NOTFOUND; + cursor->pos = * (db_recno_t *) key->data; + break; + default: + abort(); + } + + return ret; +} + +static int +db1_dbc_put(DBC *cursor, DBT *key, DBT *data, u_int32_t flags) { + DB *db = cursor->db; + DB_old *db_v1 = db->actual_db; + int ret = 0; + + assert((flags & ~(DB_BEFORE | DB_AFTER)) == 0); + + ret = db_v1->put(db_v1, &cursor->pos_key, (DBT_v1 *) data, + flags == DB_BEFORE? R_IBEFORE : R_IAFTER); + + return ret == -1? errno : ret; +}