4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
24 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
28 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
29 /* All Rights Reserved */
32 * Portions of this source code were derived from Berkeley
33 * under license from the Regents of the University of
37 #pragma ident "%Z%%M% %I% %E% SMI"
40 #include <rpcsvc/dbm.h>
41 #include <sys/types.h>
50 void dbm_access(long);
51 void delitem(char *, int);
53 int additem(char *, datum
);
56 int cmpdatum(datum
, datum
);
64 if (strlcpy(pagbuf
, file
, sizeof (pagbuf
)) >= sizeof (pagbuf
) ||
65 strlcat(pagbuf
, ".pag", sizeof (pagbuf
)) >= sizeof (pagbuf
)) {
67 * file.pag does not fit into pagbuf.
68 * fails with ENAMETOOLONG.
73 pagf
= open(pagbuf
, O_RDWR
);
75 pagf
= open(pagbuf
, O_RDONLY
);
79 * We know this won't overflow so it is safe to ignore the
80 * return value; we use strl* to prevent false hits in
83 (void) strlcpy(pagbuf
, file
, sizeof (pagbuf
));
84 (void) strlcat(pagbuf
, ".dir", sizeof (pagbuf
));
85 dirf
= open(pagbuf
, O_RDWR
);
87 dirf
= open(pagbuf
, O_RDONLY
);
90 if (pagf
< 0 || dirf
< 0)
92 (void) fstat(dirf
, &statb
);
93 maxbno
= statb
.st_size
*BYTESIZ
-1;
97 static long oldb1
= -1;
98 static long oldb2
= -1;
100 /* Avoid using cached data for subsequent accesses. */
109 /* Clean up after ourself. */
129 hash
= calchash(key
);
130 for (hmask
= 0; ; hmask
= (hmask
<<1) + 1) {
131 blkno
= hash
& hmask
;
132 bitno
= blkno
+ hmask
;
145 dbm_access(calchash(key
));
146 for (i
= 0; ; i
+= 2) {
147 item
= makdatum(pagbuf
, i
);
148 if (item
.dptr
== NULL
) {
151 if (cmpdatum(key
, item
) == 0) {
152 item
= makdatum(pagbuf
, i
+1);
153 if (item
.dptr
== NULL
)
154 (void) printf("items not in pairs\n");
168 dbm_access(calchash(key
));
169 for (i
= 0; ; i
+= 2) {
170 item
= makdatum(pagbuf
, i
);
171 if (item
.dptr
== NULL
)
173 if (cmpdatum(key
, item
) == 0) {
179 (void) lseek(pagf
, blkno
*PBLKSIZ
, 0);
180 (void) write(pagf
, pagbuf
, PBLKSIZ
);
185 store(datum key
, datum dat
)
189 char ovfbuf
[PBLKSIZ
];
194 dbm_access(calchash(key
));
195 for (i
= 0; ; i
+= 2) {
196 item
= makdatum(pagbuf
, i
);
197 if (item
.dptr
== NULL
)
199 if (cmpdatum(key
, item
) == 0) {
205 i
= additem(pagbuf
, key
);
208 if (additem(pagbuf
, dat
) < 0) {
212 (void) lseek(pagf
, blkno
*PBLKSIZ
, 0);
213 (void) write(pagf
, pagbuf
, PBLKSIZ
);
217 if (key
.dsize
+ dat
.dsize
+ 3 * sizeof (short) >= PBLKSIZ
) {
218 (void) printf("entry too big\n");
221 (void) memset(&ovfbuf
, 0, PBLKSIZ
);
223 item
= makdatum(pagbuf
, i
);
224 if (item
.dptr
== NULL
)
226 if (calchash(item
) & (hmask
+1)) {
227 (void) additem(ovfbuf
, item
);
229 item
= makdatum(pagbuf
, i
);
230 if (item
.dptr
== NULL
) {
231 (void) printf("split not paired\n");
234 (void) additem(ovfbuf
, item
);
240 (void) lseek(pagf
, blkno
*PBLKSIZ
, 0);
241 if (write(pagf
, pagbuf
, PBLKSIZ
) < 0) {
244 (void) lseek(pagf
, (blkno
+hmask
+1)*PBLKSIZ
, 0);
245 if (write(pagf
, ovfbuf
, PBLKSIZ
) < 0) {
257 return (firsthash(0L));
268 hash
= calchash(key
);
271 for (i
= 0; ; i
+= 2) {
272 item
= makdatum(pagbuf
, i
);
273 if (item
.dptr
== NULL
)
275 if (cmpdatum(key
, item
) <= 0)
277 if (f
|| cmpdatum(bitem
, item
) < 0) {
284 hash
= hashinc(hash
);
287 return (firsthash(hash
));
298 bitem
= makdatum(pagbuf
, 0);
299 for (i
= 2; ; i
+= 2) {
300 item
= makdatum(pagbuf
, i
);
301 if (item
.dptr
== NULL
)
303 if (cmpdatum(bitem
, item
) < 0)
306 if (bitem
.dptr
!= NULL
)
308 hash
= hashinc(hash
);
315 dbm_access(long hash
)
319 for (hmask
= 0; ; hmask
= (hmask
<<1) + 1) {
320 blkno
= hash
& hmask
;
321 bitno
= blkno
+ hmask
;
325 if (blkno
!= oldb1
) {
326 (void) lseek(pagf
, blkno
*PBLKSIZ
, 0);
327 readsize
= read(pagf
, pagbuf
, PBLKSIZ
);
328 if (readsize
!= PBLKSIZ
) {
331 (void) memset((&pagbuf
+readsize
), 0, PBLKSIZ
-readsize
);
348 bn
= bitno
/ BYTESIZ
;
352 (void) lseek(dirf
, (long)b
*DBLKSIZ
, 0);
353 readsize
= read(dirf
, dirbuf
, DBLKSIZ
);
354 if (readsize
!= DBLKSIZ
) {
357 (void) memset(&dirbuf
+readsize
, 0, DBLKSIZ
-readsize
);
361 if (dirbuf
[i
] & (1<<n
))
374 if (bitno
> maxbno
) {
379 bn
= bitno
/ BYTESIZ
;
383 (void) lseek(dirf
, (long)b
*DBLKSIZ
, 0);
384 if (write(dirf
, dirbuf
, DBLKSIZ
) < 0)
390 makdatum(char buf
[PBLKSIZ
], int n
)
396 /* LINTED pointer cast */
398 if (n
< 0 || n
>= sp
[0])
403 item
.dptr
= buf
+sp
[n
+1];
404 item
.dsize
= t
- sp
[n
+1];
414 cmpdatum(datum d1
, datum d2
)
421 return (n
- d2
.dsize
);
428 return (*--p1
- *--p2
);
437 * 055, 043, 036, 054, 063, 014, 004, 005,
438 * 010, 064, 077, 000, 035, 027, 025, 071,
441 = { 61, 57, 53, 49, 45, 41, 37, 33,
442 29, 25, 21, 17, 13, 9, 5, 1,
446 06100151277L, 06106161736L, 06452611562L, 05001724107L,
447 02614772546L, 04120731531L, 04665262210L, 07347467531L,
448 06735253126L, 06042345173L, 03072226605L, 01464164730L,
449 03247435524L, 07652510057L, 01546775256L, 05714532133L,
450 06173260402L, 07517101630L, 02431460343L, 01743245566L,
451 00261675137L, 02433103631L, 03421772437L, 04447707466L,
452 04435620103L, 03757017115L, 03641531772L, 06767633246L,
453 02673230344L, 00260612216L, 04133454451L, 00615531516L,
454 06137717526L, 02574116560L, 02304023373L, 07061702261L,
455 05153031405L, 05322056705L, 07401116734L, 06552375715L,
456 06165233473L, 05311063631L, 01212221723L, 01052267235L,
457 06000615237L, 01075222665L, 06330216006L, 04402355630L,
458 01451177262L, 02000133436L, 06025467062L, 07121076461L,
459 03123433522L, 01010635225L, 01716177066L, 05161746527L,
460 01736635071L, 06243505026L, 03637211610L, 01756474365L,
461 04723077174L, 03642763134L, 05750130273L, 03655541561L,
490 for (i
= 0; i
< item
.dsize
; i
++) {
492 for (j
= 0; j
< BYTESIZ
; j
+= 4) {
493 hashi
+= hitab
[f
&017];
494 hashl
+= hltab
[hashi
&63];
502 delitem(char buf
[PBLKSIZ
], int n
)
507 /* LINTED pointer cast */
509 if (n
< 0 || n
>= sp
[0])
524 for (i1
= n
+ 1; i1
< sp
[0]; i1
++)
525 sp
[i1
+1-1] = sp
[i1
+1] + i2
;
531 (void) printf("bad delitem\n");
536 additem(char buf
[PBLKSIZ
], datum item
)
541 /* LINTED pointer cast */
547 i2
= (sp
[0]+2) * (int)sizeof (short);
550 sp
[sp
[0]+1] = (short)i1
;
551 for (i2
= 0; i2
< item
.dsize
; i2
++) {
552 buf
[i1
] = item
.dptr
[i2
];
560 chkblk(char buf
[PBLKSIZ
])
565 /* LINTED pointer cast */
568 for (i
= 0; i
< sp
[0]; i
++) {
573 if (t
< (sp
[0]+1) * sizeof (short))
578 (void) printf("bad block\n");
580 (void) memset(&buf
, 0, PBLKSIZ
);