4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright (c) 2016 by Delphix. All rights reserved.
28 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
29 /* All Rights Reserved */
32 * University Copyright- Copyright (c) 1982, 1986, 1988
33 * The Regents of the University of California
36 * University Acknowledgment- Portions of this document are derived from
37 * software developed by the University of California, Berkeley, and its
41 #pragma ident "%Z%%M% %I% %E% SMI"
44 #include <sys/types.h>
56 /* add support for batched writing for NIS */
58 #define _DBM_DEFWRITE 0x4
59 #define _DBM_DIRTY 0x8
60 #define _DBM_DIRDIRTY 0x10
61 #define dbm_dirty(db) ((db)->dbm_flags & _DBM_DIRTY)
62 #define dbm_dirdirty(db) ((db)->dbm_flags & _DBM_DIRDIRTY)
63 #define dbm_defwrite(db) ((db)->dbm_flags & _DBM_DEFWRITE)
64 #define dbm_setdirty(db) (db)->dbm_flags |= _DBM_DIRTY
65 #define dbm_clrdirty(db) (db)->dbm_flags &= ~_DBM_DIRTY
66 #define dbm_setdirdirty(db) (db)->dbm_flags |= _DBM_DIRDIRTY
67 #define dbm_clrdirdirty(db) (db)->dbm_flags &= ~_DBM_DIRDIRTY
70 * forward declarations
72 static datum
makdatum(char *, int);
73 static unsigned long dcalchash(datum
);
74 static void dbm_access(DBM
*, unsigned long);
75 static int finddatum(char *, datum
);
76 static int delitem(char *, int);
77 static int additem(char *, datum
, datum
);
78 static int cmpdatum(datum
, datum
);
79 static int setbit(DBM
*);
80 static int getbit(DBM
*);
81 static int dbm_flushdir(DBM
*);
82 static int dbm_flushpag(DBM
*db
);
84 /* the following three are required by mapfile-vers */
85 datum
dbm_do_nextkey(DBM
*, datum
);
86 int dbm_close_status(DBM
*);
88 /* used to make a dbm file all at once instead of incrementally */
90 dbm_setdefwrite(DBM
*db
)
92 db
->dbm_flags
|= _DBM_DEFWRITE
;
100 return (db
->dbm_flags
& _DBM_IOERR
);
106 dbm_clearerr(DBM
*db
)
108 return (db
->dbm_flags
&= ~_DBM_IOERR
);
115 if (dbm_flushpag(db
) < 0)
117 if (dbm_flushdir(db
) < 0)
123 dbm_flushpag(DBM
*db
)
128 if (dbm_dirty(db
)) { /* must page out the page */
129 where
= (((off64_t
)db
->dbm_pagbno
) * PBLKSIZ
);
130 if ((lseek64(db
->dbm_pagf
, where
, L_SET
) != where
) ||
131 (write(db
->dbm_pagf
, db
->dbm_pagbuf
, PBLKSIZ
) != PBLKSIZ
)) {
132 db
->dbm_flags
|= _DBM_IOERR
;
141 dbm_flushdir(DBM
*db
)
145 if (dbm_dirdirty(db
)) { /* must page out the dir */
146 where
= (((off64_t
)db
->dbm_dirbno
) * DBLKSIZ
);
147 if ((lseek64(db
->dbm_dirf
, where
, L_SET
) != where
) ||
148 (write(db
->dbm_dirf
, db
->dbm_dirbuf
, DBLKSIZ
) != DBLKSIZ
)) {
160 dbm_open(const char *file
, int flags
, mode_t mode
)
166 if ((db
= (DBM
*)malloc(sizeof (*db
))) == 0) {
170 db
->dbm_flags
= (flags
& 03) == O_RDONLY
? _DBM_RDONLY
: 0;
171 if ((flags
& 03) == O_WRONLY
)
172 flags
= (flags
& ~03) | O_RDWR
;
173 if (strlcpy(db
->dbm_pagbuf
, file
, sizeof (db
->dbm_pagbuf
)) >=
174 sizeof (db
->dbm_pagbuf
) ||
175 strlcat(db
->dbm_pagbuf
, ".pag", sizeof (db
->dbm_pagbuf
)) >=
176 sizeof (db
->dbm_pagbuf
)) {
178 * file.pag does not fit into dbm_pagbuf.
179 * fail with ENAMETOOLONG.
181 serrno
= ENAMETOOLONG
;
184 db
->dbm_pagf
= open64(db
->dbm_pagbuf
, flags
, mode
);
185 if (db
->dbm_pagf
< 0) {
190 * We know this won't overflow so it is safe to ignore the
191 * return value; we use strl* to prevent false hits in
194 (void) strlcpy(db
->dbm_pagbuf
, file
, sizeof (db
->dbm_pagbuf
));
195 (void) strlcat(db
->dbm_pagbuf
, ".dir", sizeof (db
->dbm_pagbuf
));
196 db
->dbm_dirf
= open64(db
->dbm_pagbuf
, flags
, mode
);
197 if (db
->dbm_dirf
< 0) {
201 (void) fstat64(db
->dbm_dirf
, &statb
);
202 db
->dbm_maxbno
= statb
.st_size
* BYTESIZ
-1;
203 db
->dbm_pagbno
= db
->dbm_dirbno
= -1;
206 (void) close(db
->dbm_pagf
);
216 (void) dbm_close_status(db
);
219 /* close with return code */
221 dbm_close_status(DBM
*db
)
226 if (dbm_flush(db
) < 0)
228 if (close(db
->dbm_dirf
) < 0)
230 if (close(db
->dbm_pagf
) < 0)
237 dbm_forder(DBM
*db
, datum key
)
241 hash
= dcalchash(key
);
242 for (db
->dbm_hmask
= 0; ; db
->dbm_hmask
= (db
->dbm_hmask
<<1)+1) {
243 db
->dbm_blkno
= hash
& db
->dbm_hmask
;
244 db
->dbm_bitno
= db
->dbm_blkno
+ db
->dbm_hmask
;
248 return (db
->dbm_blkno
);
252 dbm_fetch(DBM
*db
, datum key
)
259 dbm_access(db
, dcalchash(key
));
260 if ((i
= finddatum(db
->dbm_pagbuf
, key
)) >= 0) {
261 item
= makdatum(db
->dbm_pagbuf
, i
+1);
262 if (item
.dptr
!= NULL
)
272 dbm_delete(DBM
*db
, datum key
)
279 if (dbm_rdonly(db
)) {
283 dbm_access(db
, dcalchash(key
));
284 if ((i
= finddatum(db
->dbm_pagbuf
, key
)) < 0)
286 if (!delitem(db
->dbm_pagbuf
, i
))
288 db
->dbm_pagbno
= db
->dbm_blkno
;
289 if (dbm_defwrite(db
)) {
292 where
= (((off64_t
)db
->dbm_blkno
) * PBLKSIZ
);
293 if ((lseek64(db
->dbm_pagf
, where
, L_SET
) != where
) ||
294 (write(db
->dbm_pagf
, db
->dbm_pagbuf
, PBLKSIZ
) != PBLKSIZ
)) {
296 db
->dbm_flags
|= _DBM_IOERR
;
304 dbm_store(DBM
*db
, datum key
, datum dat
, int replace
)
308 char ovfbuf
[PBLKSIZ
];
309 unsigned long hashdiff
, key_hash
, item_hash
;
314 if (dbm_rdonly(db
)) {
319 key_hash
= dcalchash(key
);
320 dbm_access(db
, key_hash
);
321 if ((i
= finddatum(db
->dbm_pagbuf
, key
)) >= 0) {
324 if (!delitem(db
->dbm_pagbuf
, i
)) {
325 db
->dbm_flags
|= _DBM_IOERR
;
329 if (!additem(db
->dbm_pagbuf
, key
, dat
))
331 db
->dbm_pagbno
= db
->dbm_blkno
;
332 if (dbm_defwrite(db
)) {
335 where
= (((off64_t
)db
->dbm_blkno
) * PBLKSIZ
);
336 if ((lseek64(db
->dbm_pagf
, where
, L_SET
) != where
) ||
337 (write(db
->dbm_pagf
, db
->dbm_pagbuf
, PBLKSIZ
) != PBLKSIZ
)) {
338 db
->dbm_flags
|= _DBM_IOERR
;
345 if (key
.dsize
+ dat
.dsize
+ 3 * (int)sizeof (short) >= PBLKSIZ
) {
346 db
->dbm_flags
|= _DBM_IOERR
;
350 (void) memset(ovfbuf
, 0, PBLKSIZ
);
352 item
= makdatum(db
->dbm_pagbuf
, i
);
353 if (item
.dptr
== NULL
)
355 item_hash
= dcalchash(item
);
356 if (item_hash
!= key_hash
) {
360 if (item_hash
& (db
->dbm_hmask
+1)) {
361 item1
= makdatum(db
->dbm_pagbuf
, i
+1);
362 if (item1
.dptr
== NULL
) {
363 /* (void) fprintf(stderr, "ndbm: */
364 /* split not paired\n"); */
365 db
->dbm_flags
|= _DBM_IOERR
;
368 if (!additem(ovfbuf
, item
, item1
) ||
369 !delitem(db
->dbm_pagbuf
, i
)) {
370 db
->dbm_flags
|= _DBM_IOERR
;
377 db
->dbm_pagbno
= db
->dbm_blkno
;
378 where
= (((off64_t
)db
->dbm_blkno
) * PBLKSIZ
);
379 if ((lseek64(db
->dbm_pagf
, where
, L_SET
) != where
) ||
380 (write(db
->dbm_pagf
, db
->dbm_pagbuf
, PBLKSIZ
) != PBLKSIZ
)) {
381 db
->dbm_flags
|= _DBM_IOERR
;
384 dbm_clrdirty(db
); /* clear dirty */
385 where
= (((off64_t
)db
->dbm_blkno
+ db
->dbm_hmask
+ 1) * PBLKSIZ
);
386 if ((lseek64(db
->dbm_pagf
, where
, L_SET
) != where
) ||
387 (write(db
->dbm_pagf
, ovfbuf
, PBLKSIZ
) != PBLKSIZ
)) {
388 db
->dbm_flags
|= _DBM_IOERR
;
391 if (setbit(db
) < 0) {
392 db
->dbm_flags
|= _DBM_IOERR
;
396 db
->dbm_flags
|= _DBM_IOERR
;
403 dbm_hashinc(DBM
*db
, unsigned long hash
)
407 hash
&= db
->dbm_hmask
;
408 bit
= db
->dbm_hmask
+1;
421 static datum nullkey
= {NULL
, 0};
424 dbm_firsthash(DBM
*db
, unsigned long hash
)
430 dbm_access(db
, hash
);
432 bitem
= makdatum(db
->dbm_pagbuf
, 0);
433 for (i
= 2; ; i
+= 2) {
434 item
= makdatum(db
->dbm_pagbuf
, i
);
435 if (item
.dptr
== NULL
)
437 if (cmpdatum(bitem
, item
) < 0) {
442 if (bitem
.dptr
!= NULL
) {
443 db
->dbm_keyptr
= j
+ 2;
444 db
->dbm_blkptr
= db
->dbm_blkno
;
447 hash
= dbm_hashinc(db
, hash
);
449 return (item
); /* null item */
455 dbm_firstkey(DBM
*db
)
458 * For some reason, the Posix specification (SUSv3)
459 * says that dbm_firstkey() is not a cancellation point.
460 * It really should be, but in order to pass the SUSv3
461 * test suite we make it not a cancellation point.
462 * XXX: fix me when the SUSv3 specification gets fixed.
469 (void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE
, &cancel_state
);
470 rval
= dbm_firsthash(db
, 0L);
471 (void) pthread_setcancelstate(cancel_state
, NULL
);
479 return (dbm_do_nextkey(db
, nullkey
));
483 * this is used if keyptr-2, blocknum doesn't point to the previous
484 * specific key allowing the fast hash order search --
485 * its use indicates user tampering with our state variables,
486 * which some evil users might do to search from some specific place.
487 * It finds the first key at or after blkptr, keyptr in block seq order
488 * this requires looking at all sorts of emtpy blocks in many cases
493 dbm_slow_nextkey(DBM
*db
)
500 if (dbm_error(db
) || fstat64(db
->dbm_pagf
, &statb
) < 0)
502 statb
.st_size
/= PBLKSIZ
;
505 if (db
->dbm_blkptr
!= db
->dbm_pagbno
) {
507 if (dbm_dirty(db
)) (void) dbm_flushpag(db
);
509 db
->dbm_pagbno
= db
->dbm_blkptr
;
510 where
= (((off64_t
)db
->dbm_blkptr
) * PBLKSIZ
);
511 if ((lseek64(db
->dbm_pagf
, where
, L_SET
) != where
) ||
512 (read(db
->dbm_pagf
, db
->dbm_pagbuf
, PBLKSIZ
) !=
514 (void) memset(db
->dbm_pagbuf
, 0, PBLKSIZ
);
516 else if (chkblk(db
->dbm_pagbuf
) < 0)
517 db
->dbm_flags
|= _DBM_IOERR
;
520 /* Am I an empty block? */
521 if (((short *)(uintptr_t)db
->dbm_pagbuf
)[0] != 0) {
522 item
= makdatum(db
->dbm_pagbuf
, db
->dbm_keyptr
);
523 if (item
.dptr
!= NULL
) {
529 /* go to next sequential block */
530 if (++db
->dbm_blkptr
>= statb
.st_size
)
542 dbm_do_nextkey(DBM
*db
, datum inkey
)
561 /* user has supplied lastkey */
563 if (inkey
.dptr
!= NULL
) {
564 dbm_access(db
, (hash
= dcalchash(inkey
)));
565 if ((i
= finddatum(db
->dbm_pagbuf
, inkey
)) >= 0) {
566 db
->dbm_keyptr
= i
+ 2;
567 db
->dbm_blkptr
= db
->dbm_blkno
;
571 /* is this a manual firstkey request? */
573 if (db
->dbm_blkptr
== 0L &&
575 return (dbm_firsthash(db
, 0L));
577 /* no -- get lastkey this is like dbm_access by blkptr */
579 if (db
->dbm_blkptr
!= db
->dbm_pagbno
) {
581 if (dbm_dirty(db
)) (void) dbm_flushpag(db
);
582 db
->dbm_pagbno
= db
->dbm_blkptr
;
583 where
= (((off64_t
)db
->dbm_blkptr
) * PBLKSIZ
);
584 if ((lseek64(db
->dbm_pagf
, where
, L_SET
) != where
) ||
585 (read(db
->dbm_pagf
, db
->dbm_pagbuf
, PBLKSIZ
) !=
587 (void) memset(db
->dbm_pagbuf
, 0, PBLKSIZ
);
589 else if (chkblk(db
->dbm_pagbuf
) < 0)
590 db
->dbm_flags
|= _DBM_IOERR
;
593 /* now just make up last key datum */
594 if (db
->dbm_keyptr
>= 2)
595 key
= makdatum(db
->dbm_pagbuf
, (db
->dbm_keyptr
-2));
599 * the keyptr pagbuf have failed us, the user must
600 * be an extra clever moron who depends on
601 * these variables and their former meaning.
602 * If we set the variables this would have got
603 * us the key for sure! So give it the old algorithm.
605 if (key
.dptr
== NULL
)
606 return (dbm_slow_nextkey(db
));
610 * at this point the last key is paged in and
611 * we can proceed as in old dbm -- like Ken did his.
616 sp
= (short *)(uintptr_t)db
->dbm_pagbuf
;
618 for (i
= 0; ; i
+= 2) {
620 /* begin put makdatum inline */
622 if ((unsigned)i
>= sp
[0]) {
625 break; /* from below */
627 if (i
> 0) item
.dsize
= sp
[i
] - sp
[i
+ 1];
628 else item
.dsize
= PBLKSIZ
- sp
[i
+ 1];
629 item
.dptr
= db
->dbm_pagbuf
+sp
[i
+ 1];
632 /* item = makdatum(db->dbm_pagbuf, i); */
633 /* end put makdatum inline */
635 if (item
.dptr
== NULL
)
637 /* inline cmpdatum */
641 if (n
!= item
.dsize
) {
642 if ((n
- item
.dsize
) <= 0)
645 if (n
== 0) continue;
650 if ((*--p1
- *--p2
) > 0)
659 /* end inline cmpdatum */
661 * if (cmpdatum(key, item) <= 0)
671 /* if (cmpdatum(bitem, item) < 0) */
674 if (n
!= item
.dsize
) {
675 if ((n
- item
.dsize
) < 0) {
684 if (*p1
++ != *p2
++) {
685 if ((*--p1
- *--p2
) < 0) {
697 db
->dbm_keyptr
= j
+ 2;
698 db
->dbm_blkptr
= db
->dbm_blkno
;
702 /* really need hash at this point */
703 /* if it gave us a key we have already calculated the hash */
704 /* if not get the hash */
705 if (inkey
.dptr
== NULL
)
706 hash
= dcalchash(key
);
707 hash
= dbm_hashinc(db
, hash
);
710 return (item
); /* null */
711 /* get first item on next page in hash table order */
712 return (dbm_firsthash(db
, hash
));
718 dbm_access(DBM
*db
, unsigned long hash
)
725 int j
= (sizeof (my_hmask
)) * 8;
728 for (my_hmask
= 0; j
-- > 0; my_hmask
= (my_hmask
<<1) + 1) {
729 my_blkno
= hash
& my_hmask
;
730 my_bitno
= my_blkno
+ my_hmask
;
732 if (my_bitno
> db
->dbm_maxbno
) break;
733 n
= my_bitno
% BYTESIZ
;
734 bn
= my_bitno
/ BYTESIZ
;
737 if (b
!= db
->dbm_dirbno
) {
738 if (dbm_dirdirty(db
))
739 (void) dbm_flushdir(db
); /* must flush */
741 where
= (((off64_t
)b
) * DBLKSIZ
);
742 if ((lseek64(db
->dbm_dirf
, where
, L_SET
) != where
) ||
743 (read(db
->dbm_dirf
, db
->dbm_dirbuf
, DBLKSIZ
) !=
745 (void) memset(db
->dbm_dirbuf
, 0, DBLKSIZ
);
747 if ((db
->dbm_dirbuf
[i
] & (1<<n
)) == 0) break;
750 * if (getbit(db) == 0)
755 db
->dbm_blkno
= my_blkno
;
756 db
->dbm_bitno
= my_bitno
;
757 db
->dbm_hmask
= my_hmask
;
759 if (my_blkno
!= db
->dbm_pagbno
) {
760 if (dbm_dirty(db
)) { /* must page out the page */
761 where
= (((off64_t
)db
->dbm_pagbno
) * PBLKSIZ
);
762 if ((lseek64(db
->dbm_pagf
, where
, L_SET
) != where
) ||
763 (write(db
->dbm_pagf
, db
->dbm_pagbuf
, PBLKSIZ
) !=
765 db
->dbm_flags
|= _DBM_IOERR
;
770 db
->dbm_pagbno
= my_blkno
;
771 where
= (((off64_t
)my_blkno
) * PBLKSIZ
);
772 if ((lseek64(db
->dbm_pagf
, where
, L_SET
) != where
) ||
773 (read(db
->dbm_pagf
, db
->dbm_pagbuf
, PBLKSIZ
) != PBLKSIZ
))
774 (void) memset(db
->dbm_pagbuf
, 0, PBLKSIZ
);
776 else if (chkblk(db
->dbm_pagbuf
) < 0)
777 db
->dbm_flags
|= _DBM_IOERR
;
789 if (db
->dbm_bitno
> db
->dbm_maxbno
)
791 n
= db
->dbm_bitno
% BYTESIZ
;
792 bn
= db
->dbm_bitno
/ BYTESIZ
;
795 if (b
!= db
->dbm_dirbno
) {
796 if (dbm_dirdirty(db
))
797 (void) dbm_flushdir(db
); /* must flush */
799 where
= (((off64_t
)b
) * DBLKSIZ
);
800 if ((lseek64(db
->dbm_dirf
, where
, L_SET
) != where
) ||
801 (read(db
->dbm_dirf
, db
->dbm_dirbuf
, DBLKSIZ
) != DBLKSIZ
))
802 (void) memset(db
->dbm_dirbuf
, 0, DBLKSIZ
);
804 return (db
->dbm_dirbuf
[i
] & (1<<n
));
814 if (db
->dbm_bitno
> db
->dbm_maxbno
)
815 db
->dbm_maxbno
= db
->dbm_bitno
;
816 n
= db
->dbm_bitno
% BYTESIZ
;
817 bn
= db
->dbm_bitno
/ BYTESIZ
;
820 if (b
!= db
->dbm_dirbno
) {
821 if (dbm_dirdirty(db
))
822 (void) dbm_flushdir(db
);
824 where
= (((off64_t
)b
) * DBLKSIZ
);
825 if ((lseek64(db
->dbm_dirf
, where
, L_SET
) != where
) ||
826 (read(db
->dbm_dirf
, db
->dbm_dirbuf
, DBLKSIZ
) != DBLKSIZ
))
827 (void) memset(db
->dbm_dirbuf
, 0, DBLKSIZ
);
829 db
->dbm_dirbuf
[i
] |= 1<<n
;
831 if (dbm_defwrite(db
)) {
834 where
= (((off64_t
)b
) * DBLKSIZ
);
835 if ((lseek64(db
->dbm_dirf
, where
, L_SET
) != where
) ||
836 (write(db
->dbm_dirf
, db
->dbm_dirbuf
, DBLKSIZ
) != DBLKSIZ
)) {
844 makdatum(char buf
[PBLKSIZ
], int n
)
850 sp
= (short *)(uintptr_t)buf
;
851 if ((unsigned)n
>= sp
[0]) {
859 item
.dptr
= buf
+ sp
[n
+ 1];
860 item
.dsize
= t
- sp
[n
+ 1];
865 cmpdatum(datum d1
, datum d2
)
872 return ((int)(n
- d2
.dsize
));
889 finddatum(char buf
[PBLKSIZ
], datum item
)
894 sp
= (short *)(uintptr_t)buf
;
896 for (i
= 0, j
= sp
[0]; i
< j
; i
+= 2, n
= sp
[i
]) {
900 if (n
== 0 || memcmp(&buf
[sp
[i
+1]], item
.dptr
, n
) == 0)
906 static const int hitab
[16]
910 * 055, 043, 036, 054, 063, 014, 004, 005,
911 * 010, 064, 077, 000, 035, 027, 025, 071,
914 = { 61, 57, 53, 49, 45, 41, 37, 33,
915 29, 25, 21, 17, 13, 9, 5, 1,
918 /* could consider to make it 32-bit int table to minimize memory usage */
919 static const long hltab
[64]
921 06100151277L, 06106161736L, 06452611562L, 05001724107L,
922 02614772546L, 04120731531L, 04665262210L, 07347467531L,
923 06735253126L, 06042345173L, 03072226605L, 01464164730L,
924 03247435524L, 07652510057L, 01546775256L, 05714532133L,
925 06173260402L, 07517101630L, 02431460343L, 01743245566L,
926 00261675137L, 02433103631L, 03421772437L, 04447707466L,
927 04435620103L, 03757017115L, 03641531772L, 06767633246L,
928 02673230344L, 00260612216L, 04133454451L, 00615531516L,
929 06137717526L, 02574116560L, 02304023373L, 07061702261L,
930 05153031405L, 05322056705L, 07401116734L, 06552375715L,
931 06165233473L, 05311063631L, 01212221723L, 01052267235L,
932 06000615237L, 01075222665L, 06330216006L, 04402355630L,
933 01451177262L, 02000133436L, 06025467062L, 07121076461L,
934 03123433522L, 01010635225L, 01716177066L, 05161746527L,
935 01736635071L, 06243505026L, 03637211610L, 01756474365L,
936 04723077174L, 03642763134L, 05750130273L, 03655541561L,
940 dcalchash(datum item
)
950 for (cp
= item
.dptr
, s
= item
.dsize
; --s
>= 0; ) {
952 for (j
= 0; j
< BYTESIZ
; j
+= 4) {
953 hashi
+= hitab
[c
&017];
954 hashl
+= hltab
[hashi
&63];
962 * Delete pairs of items (n & n+1).
965 delitem(char buf
[PBLKSIZ
], int n
)
970 sp
= (short *)(uintptr_t)buf
;
972 if ((unsigned)n
>= i2
|| (n
& 1))
984 (void) memmove(&buf
[i2
+ i1
], &buf
[i2
], sp
[n
+2] - i2
);
987 for (sp1
= sp
+ sp
[0], sp
+= n
+1; sp
<= sp1
; sp
++)
993 * Add pairs of items (item & item1).
996 additem(char buf
[PBLKSIZ
], datum item
, datum item1
)
1001 sp
= (short *)(uintptr_t)buf
;
1006 i1
-= item
.dsize
+ item1
.dsize
;
1007 if (i1
<= (i2
+3) * (int)sizeof (short))
1010 sp
[++i2
] = (short)(i1
+ item1
.dsize
);
1011 (void) memmove(&buf
[i1
+ item1
.dsize
], item
.dptr
, item
.dsize
);
1013 (void) memmove(&buf
[i1
], item1
.dptr
, item1
.dsize
);
1019 chkblk(char buf
[PBLKSIZ
])
1026 for (i
= 0; i
< sp
[0]; i
++) {
1031 if (t
< (sp
[0] + 1) * sizeof (short))