10 #include "ruby/config.h"
28 #define SEEK_SET L_SET
29 #define memset(s,c,n) bzero((s), (n))
30 #define memcpy(s1,s2,n) bcopy((s2), (s1), (n))
31 #define memcmp(s1,s2,n) bcmp((s1),(s2),(n))
50 #define debug(x) printf x
56 #define GET_SHORT(p, i) (((unsigned)((unsigned char *)(p))[(i)*2] << 8) + (((unsigned char *)(p))[(i)*2 + 1]))
57 #define PUT_SHORT(p, i, s) (((unsigned char *)(p))[(i)*2] = (unsigned char)((s) >> 8), ((unsigned char *)(p))[(i)*2 + 1] = (unsigned char)(s))
59 #define GET_SHORT(p, i) ((p)[(i)])
60 #define PUT_SHORT(p, i, s) ((p)[(i)] = (s))
80 #include <sys/types.h>
109 #if !defined(__sun) && !defined(_WIN32) && !defined(__CYGWIN__) && !defined(errno)
125 #define bad(x) ((x).dptr == NULL || (x).dsize < 0)
126 #define exhash(item) sdbm_hash((item).dptr, (item).dsize)
127 #define ioerr(db) ((db)->flags |= DBM_IOERR)
129 #define OFF_PAG(off) (long) (off) * PBLKSIZ
130 #define OFF_DIR(off) (long) (off) * DBLKSIZ
133 000000000000L, 000000000001L, 000000000003L,
134 000000000007L, 000000000017L, 000000000037L,
135 000000000077L, 000000000177L, 000000000377L,
136 000000000777L, 000000001777L, 000000003777L,
137 000000007777L, 000000017777L, 000000037777L,
138 000000077777L, 000000177777L, 000000377777L,
139 000000777777L, 000001777777L, 000003777777L,
140 000007777777L, 000017777777L, 000037777777L,
141 000077777777L, 000177777777L, 000377777777L,
142 000777777777L, 001777777777L, 003777777777L,
143 007777777777L, 017777777777L
149 sdbm_open(
register char *file,
register int flags,
register int mode)
152 register char *dirname;
153 register char *pagname;
156 if (file ==
NULL || !*file)
157 return errno = EINVAL, (
DBM *)
NULL;
164 return errno = ENOMEM, (
DBM *)
NULL;
168 dirname = strcat(strcpy(dirname, file),
DIRFEXT);
169 pagname = strcpy(dirname +
strlen(dirname) + 1, file);
170 pagname = strcat(pagname,
PAGFEXT);
172 db =
sdbm_prep(dirname, pagname, flags, mode);
173 free((
char *) dirname);
183 flags =
fcntl(fd, F_GETFD);
188 if (!(flags & FD_CLOEXEC)) {
190 ret =
fcntl(fd, F_SETFD, flags);
201 sdbm_prep(
char *dirname,
char *pagname,
int flags,
int mode)
207 return errno = ENOMEM, (
DBM *)
NULL;
220 if (flags & O_WRONLY)
221 flags = (flags & ~O_WRONLY) | O_RDWR;
222 if (flags & O_RDONLY)
233 if ((db->
pagf = open(pagname, flags, mode)) == -1)
goto err;
235 if ((db->
dirf = open(dirname, flags, mode)) == -1)
goto err;
245 db->
dirbno = (!dstat.st_size) ? 0 : -1;
258 (void) close(db->
pagf);
260 (void) close(db->
dirf);
271 (void) close(db->
dirf);
272 (void) close(db->
pagf);
293 return errno = EINVAL, -1;
295 return errno =
EPERM, -1;
305 return ioerr(db), -1;
310 return ioerr(db), -1;
320 return errno = EINVAL, -1;
322 return errno =
EPERM, -1;
328 if (need < 0 || need >
PAIRMAX)
329 return errno = EINVAL, -1;
347 return ioerr(db), -1;
356 return ioerr(db), -1;
363 return ioerr(db), -1;
376 #if defined _WIN32 && !defined __CYGWIN__
393 debug((
"newp: %ld\n", newp));
403 #if defined _WIN32 && !defined __CYGWIN__
410 while (
OFF_PAG(newp) > oldtail) {
420 if (hash & (db->
hmask + 1)) {
425 (void) memcpy(pag,
new,
PBLKSIZ);
445 ((hash & (db->
hmask + 1)) ? 2 : 1);
458 (void) (write(2,
"sdbm: cannot insert after SPLTMAX attempts.\n", 44) < 0);
507 while (dbit < db->maxbno &&
getdbit(db, dbit))
508 dbit = 2 * dbit + ((hash & ((long) 1 << hbit++)) ? 2 : 1);
510 debug((
"dbit: %d...", dbit));
513 db->
hmask = masks[hbit];
515 pagb = hash & db->
hmask;
535 debug((
"pag read: %d\n", pagb));
555 debug((
"dir read: %d\n", dirb));
576 debug((
"dir read: %d\n", dirb));
639 #define exhash(item) sdbm_hash((item).dptr, (item).dsize)
672 register short *ino = (
short *) pag;
675 free = off - (n + 1) * (
int)
sizeof(short);
676 need += 2 * (int)
sizeof(
short);
678 debug((
"free %d need %d\n", free, need));
688 register short *ino = (
short *) pag;
696 (void) memcpy(pag + off, key.
dptr, key.
dsize);
703 (void) memcpy(pag + off, val.
dptr, val.
dsize);
717 register short *ino = (
short *) pag;
734 register short *ino = (
short *) pag;
745 register short *ino = (
short *) pag;
764 register short *ino = (
short *) pag;
781 register char *src = pag +
GET_SHORT(ino,i + 1);
782 register ptrdiff_t zoo = dst - src;
790 #define MOVB *--dst = *--src
793 register int loop = (m + 8 - 1) >> 3;
795 switch (m & (8 - 1)) {
798 case 6: MOVB;
case 5: MOVB;
799 case 4: MOVB;
case 3: MOVB;
800 case 2: MOVB;
case 1: MOVB;
830 seepair(
char *pag,
register int n,
register char *
key,
register int siz)
834 register short *ino = (
short *) pag;
836 for (i = 1; i < n; i += 2) {
854 register short *ino = (
short *) cur;
856 (void) memcpy(cur, pag,
PBLKSIZ);
857 (void) memset(pag, 0,
PBLKSIZ);
858 (void) memset(
new, 0,
PBLKSIZ);
861 for (ino++; n > 0; ino += 2) {
875 debug((
"%d split %d/%d\n", ((
short *) cur)[0] / 2,
876 ((
short *)
new)[0] / 2,
877 ((
short *) pag)[0] / 2));
891 register short *ino = (
short *) pag;
898 for (ino++; n > 0; ino += 2) {
929 register unsigned long n = 0;
933 #define HASHC n = *str++ + 65599 * n
936 register int loop = (len + 8 - 1) >> 3;
938 switch(len & (8 - 1)) {
940 HASHC;
case 7: HASHC;
941 case 6: HASHC;
case 5: HASHC;
942 case 4: HASHC;
case 3: HASHC;
943 case 2: HASHC;
case 1: HASHC;
950 n = ((*str++) & 255) + 65587L * n;
static int makroom(register DBM *db, long int hash, int need)
long sdbm_hash(register char *str, register int len)
size_t strlen(const char *)
static datum getnext(register DBM *db)
static int chkpage(char *pag)
static int duppair(char *pag, datum key)
static datum getpair(char *pag, datum key)
static int getpage(register DBM *db, register long int hash)
RUBY_EXTERN void * memmove(void *, const void *, size_t)
void sdbm_close(register DBM *db)
DBM * sdbm_open(register char *file, register int flags, register int mode)
static int seepair(char *pag, register int n, register char *key, register int siz)
datum sdbm_firstkey(register DBM *db)
DBM * sdbm_prep(char *dirname, char *pagname, int flags, int mode)
static void putpair(char *pag, datum key, datum val)
int memcmp(const void *s1, const void *s2, size_t len)
static int fitpair(char *pag, int need)
static int delpair(char *pag, datum key)
#define PUT_SHORT(p, i, s)
static int getdbit(register DBM *db, register long int dbit)
int sdbm_store(register DBM *db, datum key, datum val, int flags)
static void splpage(char *pag, char *new, long int sbit)
static unsigned int hash(const char *str, unsigned int len)
datum sdbm_nextkey(register DBM *db)
static int fitpair proto((char *, int))
static datum getnkey(char *pag, int num)
int sdbm_delete(register DBM *db, datum key)
datum sdbm_fetch(register DBM *db, datum key)
static int setdbit(register DBM *db, register long int dbit)
static int fd_set_cloexec(int fd)