Update.
[glibc.git] / db2 / db185 / db185.c
blob893dfa3c7f2d775fa0fbfc9e48c3d763391e5189
1 /*-
2 * See the file LICENSE for redistribution information.
4 * Copyright (c) 1996, 1997, 1998
5 * Sleepycat Software. All rights reserved.
6 */
8 #include "config.h"
10 #ifndef lint
11 static const char copyright[] =
12 "@(#) Copyright (c) 1996, 1997, 1998\n\
13 Sleepycat Software Inc. All rights reserved.\n";
14 static const char sccsid[] = "@(#)db185.c 8.17 (Sleepycat) 5/7/98";
15 #endif
17 #ifndef NO_SYSTEM_INCLUDES
18 #include <sys/types.h>
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25 #endif
27 #include "db_int.h"
28 #include "db185_int.h"
29 #include "common_ext.h"
31 static int db185_close __P((DB185 *));
32 static int db185_del __P((const DB185 *, const DBT185 *, u_int));
33 static int db185_fd __P((const DB185 *));
34 static int db185_get __P((const DB185 *, const DBT185 *, DBT185 *, u_int));
35 static int db185_put __P((const DB185 *, DBT185 *, const DBT185 *, u_int));
36 static int db185_seq __P((const DB185 *, DBT185 *, DBT185 *, u_int));
37 static int db185_sync __P((const DB185 *, u_int));
39 DB185 *
40 __dbopen(file, oflags, mode, type, openinfo)
41 const char *file;
42 int oflags, mode;
43 DBTYPE type;
44 const void *openinfo;
46 const BTREEINFO *bi;
47 const HASHINFO *hi;
48 const RECNOINFO *ri;
49 DB *dbp;
50 DB185 *db185p;
51 DB_INFO dbinfo, *dbinfop;
52 int s_errno;
54 if ((db185p = (DB185 *)__db_calloc(1, sizeof(DB185))) == NULL)
55 return (NULL);
56 dbinfop = NULL;
57 memset(&dbinfo, 0, sizeof(dbinfo));
60 * !!!
61 * The DBTYPE enum wasn't initialized in DB 185, so it's off-by-one
62 * from DB 2.0.
64 switch (type) {
65 case 0: /* DB_BTREE */
66 type = DB_BTREE;
67 if ((bi = openinfo) != NULL) {
68 dbinfop = &dbinfo;
69 if (bi->flags & ~R_DUP)
70 goto einval;
71 if (bi->flags & R_DUP)
72 dbinfop->flags |= DB_DUP;
73 dbinfop->db_cachesize = bi->cachesize;
74 dbinfop->bt_maxkey = bi->maxkeypage;
75 dbinfop->bt_minkey = bi->minkeypage;
76 dbinfop->db_pagesize = bi->psize;
78 * !!!
79 * Comparisons and prefix calls work because the DBT
80 * structures in 1.85 and 2.0 have the same initial
81 * fields.
83 dbinfop->bt_compare = bi->compare;
84 dbinfop->bt_prefix = bi->prefix;
85 dbinfop->db_lorder = bi->lorder;
87 break;
88 case 1: /* DB_HASH */
89 type = DB_HASH;
90 if ((hi = openinfo) != NULL) {
91 dbinfop = &dbinfo;
92 dbinfop->db_pagesize = hi->bsize;
93 dbinfop->h_ffactor = hi->ffactor;
94 dbinfop->h_nelem = hi->nelem;
95 dbinfop->db_cachesize = hi->cachesize;
96 dbinfop->h_hash = hi->hash;
97 dbinfop->db_lorder = hi->lorder;
100 break;
101 case 2: /* DB_RECNO */
102 type = DB_RECNO;
103 dbinfop = &dbinfo;
105 /* DB 1.85 did renumbering by default. */
106 dbinfop->flags |= DB_RENUMBER;
109 * !!!
110 * The file name given to DB 1.85 recno is the name of the DB
111 * 2.0 backing file. If the file doesn't exist, create it if
112 * the user has the O_CREAT flag set, DB 1.85 did it for you,
113 * and DB 2.0 doesn't.
115 * !!!
116 * Setting the file name to NULL specifies that we're creating
117 * a temporary backing file, in DB 2.X. If we're opening the
118 * DB file read-only, change the flags to read-write, because
119 * temporary backing files cannot be opened read-only, and DB
120 * 2.X will return an error. We are cheating here -- if the
121 * application does a put on the database, it will succeed --
122 * although that would be a stupid thing for the application
123 * to do.
125 * !!!
126 * Note, the file name in DB 1.85 was a const -- we don't do
127 * that in DB 2.0, so do that cast.
129 if (file != NULL) {
130 if (oflags & O_CREAT && __db_exists(file, NULL) != 0)
131 (void)__os_close(__os_open(file, oflags, mode));
132 dbinfop->re_source = (char *)file;
133 file = NULL;
135 if (O_RDONLY)
136 oflags &= ~O_RDONLY;
137 oflags |= O_RDWR;
140 if ((ri = openinfo) != NULL) {
142 * !!!
143 * We can't support the bfname field.
145 #define BFMSG "DB: DB 1.85's recno bfname field is not supported.\n"
146 if (ri->bfname != NULL) {
147 (void)__os_write(2, BFMSG, sizeof(BFMSG) - 1);
148 goto einval;
151 if (ri->flags & ~(R_FIXEDLEN | R_NOKEY | R_SNAPSHOT))
152 goto einval;
153 if (ri->flags & R_FIXEDLEN) {
154 dbinfop->flags |= DB_FIXEDLEN;
155 if (ri->bval != 0) {
156 dbinfop->flags |= DB_PAD;
157 dbinfop->re_pad = ri->bval;
159 } else
160 if (ri->bval != 0) {
161 dbinfop->flags |= DB_DELIMITER;
162 dbinfop->re_delim = ri->bval;
166 * !!!
167 * We ignore the R_NOKEY flag, but that's okay, it was
168 * only an optimization that was never implemented.
171 if (ri->flags & R_SNAPSHOT)
172 dbinfop->flags |= DB_SNAPSHOT;
174 dbinfop->db_cachesize = ri->cachesize;
175 dbinfop->db_pagesize = ri->psize;
176 dbinfop->db_lorder = ri->lorder;
177 dbinfop->re_len = ri->reclen;
179 break;
180 default:
181 goto einval;
184 db185p->close = db185_close;
185 db185p->del = db185_del;
186 db185p->fd = db185_fd;
187 db185p->get = db185_get;
188 db185p->put = db185_put;
189 db185p->seq = db185_seq;
190 db185p->sync = db185_sync;
193 * !!!
194 * Store the returned pointer to the real DB 2.0 structure in the
195 * internal pointer. Ugly, but we're not going for pretty, here.
197 if ((errno = db_open(file,
198 type, __db_oflags(oflags), mode, NULL, dbinfop, &dbp)) != 0) {
199 __db_free(db185p);
200 return (NULL);
203 /* Create the cursor used for sequential ops. */
204 if ((errno = dbp->cursor(dbp, NULL, &((DB185 *)db185p)->dbc)) != 0) {
205 s_errno = errno;
206 (void)dbp->close(dbp, 0);
207 __db_free(db185p);
208 __set_errno(s_errno);
209 return (NULL);
212 db185p->internal = dbp;
213 return (db185p);
215 einval: __db_free(db185p);
216 __set_errno(EINVAL);
217 return (NULL);
219 weak_alias (__dbopen, dbopen)
221 static int
222 db185_close(db185p)
223 DB185 *db185p;
225 DB *dbp;
227 dbp = (DB *)db185p->internal;
229 __set_errno(dbp->close(dbp, 0));
231 __db_free(db185p);
233 return (errno == 0 ? 0 : -1);
236 static int
237 db185_del(db185p, key185, flags)
238 const DB185 *db185p;
239 const DBT185 *key185;
240 u_int flags;
242 DB *dbp;
243 DBT key;
245 dbp = (DB *)db185p->internal;
247 memset(&key, 0, sizeof(key));
248 key.data = key185->data;
249 key.size = key185->size;
251 if (flags & ~R_CURSOR)
252 goto einval;
253 if (flags & R_CURSOR)
254 __set_errno(db185p->dbc->c_del(db185p->dbc, 0));
255 else
256 __set_errno(dbp->del(dbp, NULL, &key, 0));
258 switch (errno) {
259 case 0:
260 return (0);
261 case DB_NOTFOUND:
262 return (1);
264 return (-1);
266 einval: __set_errno(EINVAL);
267 return (-1);
270 static int
271 db185_fd(db185p)
272 const DB185 *db185p;
274 DB *dbp;
275 int fd;
277 dbp = (DB *)db185p->internal;
279 return ((__set_errno(dbp->fd(dbp, &fd))) == 0 ? fd : -1);
282 static int
283 db185_get(db185p, key185, data185, flags)
284 const DB185 *db185p;
285 const DBT185 *key185;
286 DBT185 *data185;
287 u_int flags;
289 DB *dbp;
290 DBT key, data;
292 dbp = (DB *)db185p->internal;
294 memset(&key, 0, sizeof(key));
295 key.data = key185->data;
296 key.size = key185->size;
297 memset(&data, 0, sizeof(data));
298 data.data = data185->data;
299 data.size = data185->size;
301 if (flags)
302 goto einval;
304 switch (__set_errno(dbp->get(dbp, NULL, &key, &data, 0))) {
305 case 0:
306 data185->data = data.data;
307 data185->size = data.size;
308 return (0);
309 case DB_NOTFOUND:
310 return (1);
312 return (-1);
314 einval: __set_errno(EINVAL);
315 return (-1);
318 static int
319 db185_put(db185p, key185, data185, flags)
320 const DB185 *db185p;
321 DBT185 *key185;
322 const DBT185 *data185;
323 u_int flags;
325 DB *dbp;
326 DBC *dbcp_put;
327 DBT key, data;
328 int s_errno;
330 dbp = (DB *)db185p->internal;
332 memset(&key, 0, sizeof(key));
333 key.data = key185->data;
334 key.size = key185->size;
335 memset(&data, 0, sizeof(data));
336 data.data = data185->data;
337 data.size = data185->size;
339 switch (flags) {
340 case 0:
341 __set_errno(dbp->put(dbp, NULL, &key, &data, 0));
342 break;
343 case R_CURSOR:
344 __set_errno(
345 db185p->dbc->c_put(db185p->dbc, &key, &data, DB_CURRENT));
346 break;
347 case R_IAFTER:
348 case R_IBEFORE:
349 if (dbp->type != DB_RECNO)
350 goto einval;
352 if ((__set_errno(dbp->cursor(dbp, NULL, &dbcp_put))) != 0)
353 return (-1);
354 if ((__set_errno(
355 dbcp_put->c_get(dbcp_put, &key, &data, DB_SET))) != 0) {
356 s_errno = errno;
357 (void)dbcp_put->c_close(dbcp_put);
358 __set_errno(s_errno);
359 return (-1);
361 memset(&data, 0, sizeof(data));
362 data.data = data185->data;
363 data.size = data185->size;
364 __set_errno(dbcp_put->c_put(dbcp_put,
365 &key, &data, flags == R_IAFTER ? DB_AFTER : DB_BEFORE));
366 s_errno = errno;
367 (void)dbcp_put->c_close(dbcp_put);
368 __set_errno(s_errno);
369 break;
370 case R_NOOVERWRITE:
371 __set_errno(dbp->put(dbp, NULL, &key, &data, DB_NOOVERWRITE));
372 break;
373 case R_SETCURSOR:
374 if (dbp->type != DB_BTREE && dbp->type != DB_RECNO)
375 goto einval;
377 if ((__set_errno(dbp->put(dbp, NULL, &key, &data, 0))) != 0)
378 break;
379 __set_errno(db185p->dbc->c_get(db185p->dbc,
380 &key, &data, DB_SET_RANGE));
381 break;
382 default:
383 goto einval;
386 switch (errno) {
387 case 0:
388 key185->data = key.data;
389 key185->size = key.size;
390 return (0);
391 case DB_KEYEXIST:
392 return (1);
394 return (-1);
396 einval: __set_errno(EINVAL);
397 return (-1);
400 static int
401 db185_seq(db185p, key185, data185, flags)
402 const DB185 *db185p;
403 DBT185 *key185, *data185;
404 u_int flags;
406 DB *dbp;
407 DBT key, data;
409 dbp = (DB *)db185p->internal;
411 memset(&key, 0, sizeof(key));
412 key.data = key185->data;
413 key.size = key185->size;
414 memset(&data, 0, sizeof(data));
415 data.data = data185->data;
416 data.size = data185->size;
418 switch (flags) {
419 case R_CURSOR:
420 flags = DB_SET_RANGE;
421 break;
422 case R_FIRST:
423 flags = DB_FIRST;
424 break;
425 case R_LAST:
426 if (dbp->type != DB_BTREE && dbp->type != DB_RECNO)
427 goto einval;
428 flags = DB_LAST;
429 break;
430 case R_NEXT:
431 flags = DB_NEXT;
432 break;
433 case R_PREV:
434 if (dbp->type != DB_BTREE && dbp->type != DB_RECNO)
435 goto einval;
436 flags = DB_PREV;
437 break;
438 default:
439 goto einval;
441 switch (__set_errno(db185p->dbc->c_get(db185p->dbc,
442 &key, &data, flags))) {
443 case 0:
444 key185->data = key.data;
445 key185->size = key.size;
446 data185->data = data.data;
447 data185->size = data.size;
448 return (0);
449 case DB_NOTFOUND:
450 return (1);
452 return (-1);
454 einval: __set_errno(EINVAL);
455 return (-1);
458 static int
459 db185_sync(db185p, flags)
460 const DB185 *db185p;
461 u_int flags;
463 DB *dbp;
465 dbp = (DB *)db185p->internal;
467 switch (flags) {
468 case 0:
469 break;
470 case R_RECNOSYNC:
472 * !!!
473 * We can't support the R_RECNOSYNC flag.
475 #define RSMSG "DB: DB 1.85's R_RECNOSYNC sync flag is not supported.\n"
476 (void)__os_write(2, RSMSG, sizeof(RSMSG) - 1);
477 goto einval;
478 default:
479 goto einval;
482 return ((__set_errno(dbp->sync(dbp, 0))) == 0 ? 0 : -1);
484 einval: __set_errno(EINVAL);
485 return (-1);