Use +force in dependency list of installation targets.
[kopensolaris-gnu/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 }