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