Mirror of :pserver:cvs@cvs.fefe.de:/cvs libowfat https://www.fefe.de/libowfat/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

153 lines
3.1 KiB

  1. #define _FILE_OFFSET_BITS 64
  2. #include <sys/types.h>
  3. #include <sys/stat.h>
  4. #include <unistd.h>
  5. #include <errno.h>
  6. #include "byte.h"
  7. #include "cdb.h"
  8. #ifdef __MINGW32__
  9. #include "windows.h"
  10. #else
  11. #include <sys/mman.h>
  12. #endif
  13. void cdb_free(struct cdb *c) {
  14. if (c->map) {
  15. #ifdef __MINGW32__
  16. UnmapViewOfFile(c->map);
  17. #else
  18. munmap(c->map,c->size);
  19. #endif
  20. c->map = 0;
  21. }
  22. }
  23. void cdb_findstart(struct cdb *c) {
  24. c->loop = 0;
  25. }
  26. void cdb_init(struct cdb *c,int64 fd) {
  27. #ifndef __MINGW32__
  28. struct stat st;
  29. char *x;
  30. #endif
  31. cdb_free(c);
  32. cdb_findstart(c);
  33. c->fd = fd;
  34. #ifdef __MINGW32__
  35. {
  36. HANDLE m=CreateFileMapping((HANDLE)(uintptr_t)fd,0,PAGE_READONLY,0,0,NULL);
  37. if (m)
  38. if ((c->map=MapViewOfFile(m,FILE_MAP_READ,0,0,0)))
  39. c->size=GetFileSize((HANDLE)(uintptr_t)fd,NULL);
  40. CloseHandle(m);
  41. }
  42. #else
  43. if (fstat(fd,&st) == 0)
  44. if (st.st_size <= 0xffffffff) {
  45. x = mmap(0,st.st_size,PROT_READ,MAP_SHARED,fd,0);
  46. if (x != MAP_FAILED) {
  47. c->size = st.st_size;
  48. c->map = x;
  49. }
  50. }
  51. #endif
  52. }
  53. int cdb_read(struct cdb *c,unsigned char *buf,unsigned long len,uint32 pos) {
  54. if (c->map) {
  55. if ((pos > c->size) || (c->size - pos < len)) goto FORMAT;
  56. byte_copy(buf,len,c->map + pos);
  57. }
  58. else {
  59. if (lseek(c->fd,pos,SEEK_SET) == -1) return -1;
  60. while (len > 0) {
  61. int r;
  62. do
  63. r = read(c->fd,buf,len);
  64. while ((r == -1) && (errno == EINTR));
  65. if (r == -1) return -1;
  66. if (r == 0) goto FORMAT;
  67. buf += r;
  68. len -= r;
  69. }
  70. }
  71. return 0;
  72. FORMAT:
  73. #ifdef EPROTO
  74. errno = EPROTO;
  75. #else
  76. errno = EINVAL;
  77. #endif
  78. return -1;
  79. }
  80. static int match(struct cdb *c,const unsigned char *key,unsigned long int len,uint32 pos) {
  81. unsigned char buf[32];
  82. unsigned long n;
  83. while (len > 0) {
  84. n = sizeof buf;
  85. if (n > len) n = len;
  86. if (cdb_read(c,buf,n,pos) == -1) return -1;
  87. if (byte_diff(buf,n,key)) return 0;
  88. pos += n;
  89. key += n;
  90. len -= n;
  91. }
  92. return 1;
  93. }
  94. int cdb_findnext(struct cdb *c,const unsigned char *key,unsigned long int len) {
  95. unsigned char buf[8];
  96. uint32 pos;
  97. uint32 u;
  98. if (!c->loop) {
  99. u = cdb_hash(key,len);
  100. if (cdb_read(c,buf,8,(u << 3) & 2047) == -1) return -1;
  101. uint32_unpack((char*)buf + 4,&c->hslots);
  102. if (!c->hslots) return 0;
  103. uint32_unpack((char*)buf,&c->hpos);
  104. c->khash = u;
  105. u >>= 8;
  106. u %= c->hslots;
  107. u <<= 3;
  108. c->kpos = c->hpos + u;
  109. }
  110. while (c->loop < c->hslots) {
  111. if (cdb_read(c,buf,8,c->kpos) == -1) return -1;
  112. uint32_unpack((char*)buf + 4,&pos);
  113. if (!pos) return 0;
  114. c->loop += 1;
  115. c->kpos += 8;
  116. if (c->kpos == c->hpos + (c->hslots << 3)) c->kpos = c->hpos;
  117. uint32_unpack((char*)buf,&u);
  118. if (u == c->khash) {
  119. if (cdb_read(c,buf,8,pos) == -1) return -1;
  120. uint32_unpack((char*)buf,&u);
  121. if (u == len)
  122. switch(match(c,key,len,pos + 8)) {
  123. case -1:
  124. return -1;
  125. case 1:
  126. uint32_unpack((char*)buf + 4,&c->dlen);
  127. c->dpos = pos + 8 + len;
  128. return 1;
  129. }
  130. }
  131. }
  132. return 0;
  133. }
  134. int cdb_find(struct cdb *c,const unsigned char *key,unsigned long int len) {
  135. cdb_findstart(c);
  136. return cdb_findnext(c,key,len);
  137. }