Expand PMF_FN_* macros.
[netbsd-mini2440.git] / dist / nvi / common / db1.c
blob082e8bee117b981a5e1982751c1f4de4f1c19ad6
1 /*
2 * DB1->3 compatibility layer
3 */
5 #include "config.h"
7 #include <assert.h>
8 #include <errno.h>
9 #include <stdlib.h>
10 #include <string.h>
12 #include <fcntl.h>
14 #include "../common/db.h"
15 #include "../common/dbinternal.h"
18 * DB_ENV emulation
21 static int db1_dbenv_close(DB_ENV *, u_int32_t);
22 static int db1_dbenv_open(DB_ENV *, char *, u_int32_t, int);
23 static int db1_dbenv_remove(DB_ENV *, char *, u_int32_t);
25 int
26 db_env_create(DB_ENV **dbenvp, u_int32_t flags) {
27 DB_ENV *dbenv;
29 assert(flags == 0);
31 dbenv = malloc(sizeof *dbenv);
32 if (dbenv == NULL)
33 return -1;
35 dbenv->close = db1_dbenv_close;
36 dbenv->open = db1_dbenv_open;
37 dbenv->remove = db1_dbenv_remove;
39 dbenv->base_path = NULL;
40 dbenv->mode = 0;
42 *dbenvp = dbenv;
43 return 0;
46 static int
47 db1_dbenv_close(DB_ENV *dbenv, u_int32_t flags) {
48 assert(flags == 0);
50 if (dbenv->base_path != NULL)
51 free(dbenv->base_path);
53 free(dbenv);
54 return 0;
57 static int
58 db1_dbenv_open(DB_ENV *dbenv, char *base_path, u_int32_t flags, int mode) {
60 /* We ignore flags on purpose */
62 dbenv->base_path = strdup(base_path);
63 if (dbenv->base_path == NULL)
64 return ENOSPC;
66 dbenv->mode = mode != 0? mode : 0660;
67 return 0;
70 static int
71 db1_dbenv_remove(DB_ENV *dbenv_fake, char *base_path, u_int32_t flags) {
72 /* dbenv_fake is not a useful environment */
73 /* XXX check if we have to remove files here */
75 return 0;
79 * DB emulation
81 static int db1_db_close(DB *, u_int32_t);
82 static int db1_db_open(DB *, const char *, const char *, DBTYPE, u_int32_t, int);
83 static int db1_db_sync(DB *, u_int32_t);
84 static int db1_db_get(DB *, DB_TXN *, DBT *, DBT *, u_int32_t);
85 static int db1_db_put(DB *, DB_TXN *, DBT *, DBT *, u_int32_t);
86 static int db1_db_del(DB *, DB_TXN *, DBT *, u_int32_t);
87 static int db1_db_set_flags(DB *, u_int32_t);
88 static int db1_db_set_pagesize(DB *, u_int32_t);
89 static int db1_db_set_re_delim(DB *, int);
90 static int db1_db_set_re_source(DB *, const char *);
91 static int db1_db_cursor(DB *, DB_TXN *, DBC **, u_int32_t);
93 int
94 db_create(DB **dbp, DB_ENV *dbenv, u_int32_t flags) {
95 assert(flags == 0);
97 *dbp = malloc(sizeof **dbp);
98 if (*dbp == NULL)
99 return -1;
101 (*dbp)->type = DB_UNKNOWN;
102 (*dbp)->actual_db = NULL;
103 (*dbp)->_pagesize = 0;
104 (*dbp)->_flags = 0;
105 memset(&(*dbp)->_recno_info, 0, sizeof (RECNOINFO));
107 (*dbp)->close = db1_db_close;
108 (*dbp)->open = db1_db_open;
109 (*dbp)->sync = db1_db_sync;
110 (*dbp)->get = db1_db_get;
111 (*dbp)->put = db1_db_put;
112 (*dbp)->del = db1_db_del;
113 (*dbp)->set_flags = db1_db_set_flags;
114 (*dbp)->set_pagesize = db1_db_set_pagesize;
115 (*dbp)->set_re_delim = db1_db_set_re_delim;
116 (*dbp)->set_re_source = db1_db_set_re_source;
117 (*dbp)->cursor = db1_db_cursor;
119 return 0;
122 const char *
123 db_strerror(int error) {
124 return error > 0? strerror(error) : "record not found";
127 static int
128 db1_db_close(DB *db, u_int32_t flags) {
129 if (flags & DB_NOSYNC) {
130 /* XXX warn user? */
132 db->actual_db->close(db->actual_db);
134 db->type = DB_UNKNOWN;
135 db->actual_db = NULL;
136 db->_pagesize = 0;
137 db->_flags = 0;
138 memset(&db->_recno_info, 0, sizeof (RECNOINFO));
140 return 0;
143 static int
144 db1_db_open(DB *db, const char *file, const char *database, DBTYPE type,
145 u_int32_t flags, int mode) {
146 int oldflags = 0;
148 assert(database == NULL && !(flags & ~(DB_CREATE | DB_TRUNCATE)));
150 db->type = type;
152 if (flags & DB_CREATE)
153 oldflags |= O_CREAT;
154 if (flags & DB_TRUNCATE)
155 oldflags |= O_TRUNC;
157 if (type == DB_RECNO) {
158 const char *tmp = file;
160 /* The interface is reversed in DB3 */
161 file = db->_recno_info.bfname;
162 db->_recno_info.bfname = __UNCONST(tmp);
164 /* ... and so, we should avoid to truncate the main file! */
165 oldflags &= ~O_TRUNC;
167 db->_recno_info.flags =
168 db->_flags & DB_SNAPSHOT? R_SNAPSHOT : 0;
169 db->_recno_info.psize = db->_pagesize;
172 db->actual_db = dbopen(file, oldflags, mode, type,
173 type == DB_RECNO? &db->_recno_info : NULL);
175 return db->actual_db == NULL? errno : 0;
178 static int
179 db1_db_sync(DB *db, u_int32_t flags) {
180 assert(flags == 0);
182 return db->actual_db->sync(db->actual_db, db->type == DB_UNKNOWN?
183 R_RECNOSYNC : 0) == 0? 0 : errno;
186 static int
187 db1_db_get(DB *db, DB_TXN *txnid, DBT *key, DBT *data, u_int32_t flags) {
188 int err;
189 DBT_v1 data1;
191 assert(flags == 0 && txnid == NULL);
193 err = db->actual_db->get(db->actual_db, (DBT_v1 *) key, &data1, flags);
194 if (err == 1)
195 return DB_NOTFOUND;
196 else if (err == -1)
197 return errno;
199 if (data->flags & DB_DBT_USERMEM) {
200 data->size = data1.size;
201 if (data1.size > data->ulen)
202 return DB_BUFFER_SMALL;
204 memcpy(data->data, data1.data, data1.size);
207 return 0;
210 static int
211 db1_db_put(DB *db, DB_TXN *txnid, DBT *key, DBT *data, u_int32_t flags) {
212 int err;
213 DB_old *db_v1 = db->actual_db;
214 DBT data1;
215 DBT key1;
216 recno_t recno = 1;
218 assert((flags & ~DB_APPEND) == 0 && txnid == NULL);
220 key1 = *key;
222 if (flags & DB_APPEND) {
223 if (db_v1->seq(db_v1, (DBT_v1 *)(void *)key,
224 (DBT_v1 *)(void *)&data1, R_LAST) == 1) {
225 key1.data = &recno;
226 key1.size = sizeof recno;
229 err = db_v1->put(db_v1, (DBT_v1 *)(void *)&key1, (DBT_v1 *)(void *)data,
232 return err == -1? errno : err;
235 static int
236 db1_db_del(DB *db, DB_TXN *txnid, DBT *key, u_int32_t flags) {
237 int err;
238 DB_old *db_v1 = db->actual_db;
240 assert(txnid == NULL && flags == 0);
242 err = db_v1->del(db_v1, (DBT_v1 *) key, 0);
243 return err == -1? errno : err;
246 static int
247 db1_db_set_flags(DB *db, u_int32_t flags) {
248 assert((flags & ~(DB_RENUMBER | DB_SNAPSHOT)) == 0);
250 /* Can't prevent renumbering from happening with DB1 */
251 assert((flags | db->_flags) & DB_RENUMBER);
254 db->_flags |= flags;
256 return 0;
259 static int
260 db1_db_set_pagesize(DB *db, u_int32_t pagesize) {
261 db->_pagesize = pagesize;
263 return 0;
266 static int
267 db1_db_set_re_delim(DB *db, int re_delim) {
268 db->_recno_info.bval = re_delim;
270 return 0;
273 static int
274 db1_db_set_re_source(DB *db, const char *re_source) {
275 db->_recno_info.bfname = __UNCONST(re_source);
277 return 0;
280 /* DBC emulation. Very basic, only one cursor at a time, enough for vi */
282 static int db1_dbc_close(DBC *);
283 static int db1_dbc_get(DBC *, DBT *, DBT *, u_int32_t);
284 static int db1_dbc_put(DBC *, DBT *, DBT *, u_int32_t);
286 static int
287 db1_db_cursor(DB *db, DB_TXN *txn, DBC **cursorp, u_int32_t flags) {
288 DBC *cursor;
290 assert(txn == NULL && flags == 0);
292 cursor = malloc(sizeof *cursor);
293 if (cursor == NULL)
294 return -1;
296 cursor->db = db;
297 cursor->pos_key.data = &cursor->pos;
298 cursor->pos_key.size = sizeof cursor->pos;
299 cursor->c_close = db1_dbc_close;
300 cursor->c_get = db1_dbc_get;
301 cursor->c_put = db1_dbc_put;
303 *cursorp = cursor;
305 return 0;
308 static int
309 db1_dbc_close(DBC *cursor) {
310 free(cursor);
311 return 0;
314 static int
315 db1_dbc_get(DBC *cursor, DBT *key, DBT *data, u_int32_t flags) {
316 DB *db = cursor->db;
317 DB_old *db_v1 = db->actual_db;
318 int ret = 0;
321 switch(flags) {
322 case DB_SET:
323 ret = db_v1->seq(db_v1, (DBT_v1 *) key, (DBT_v1 *) data,
324 R_CURSOR);
325 cursor->pos = * (db_recno_t *) key->data;
326 break;
327 case DB_FIRST:
328 ret = db_v1->seq(db_v1, (DBT_v1 *) key, (DBT_v1 *) data,
329 R_FIRST);
330 if (ret == 1)
331 ret = DB_NOTFOUND;
332 cursor->pos = * (db_recno_t *) key->data;
333 break;
334 case DB_LAST:
335 ret = db_v1->seq(db_v1, (DBT_v1 *) key, (DBT_v1 *) data,
336 R_LAST);
337 if (ret == 1)
338 ret = DB_NOTFOUND;
339 cursor->pos = * (db_recno_t *) key->data;
340 break;
341 default:
342 abort();
345 return ret;
348 static int
349 db1_dbc_put(DBC *cursor, DBT *key, DBT *data, u_int32_t flags) {
350 DB *db = cursor->db;
351 DB_old *db_v1 = db->actual_db;
352 int ret = 0;
354 assert((flags & ~(DB_BEFORE | DB_AFTER)) == 0);
356 ret = db_v1->put(db_v1, &cursor->pos_key, (DBT_v1 *) data,
357 flags == DB_BEFORE? R_IBEFORE : R_IAFTER);
359 return ret == -1? errno : ret;