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.

cdb_init.c 3.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /* $Id: cdb_init.c,v 1.12 2008-11-06 18:07:04 mjt Exp $
  2. * cdb_init, cdb_free and cdb_read routines
  3. *
  4. * This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru.
  5. * Public domain.
  6. */
  7. #include "cdb.h"
  8. unsigned
  9. cdb_hash(const void *buf, unsigned len)
  10. {
  11. register const unsigned char *p = (const unsigned char *) buf;
  12. register const unsigned char *end = p + len;
  13. register unsigned hash = 5381; /* start value */
  14. while (p < end)
  15. hash = (hash + (hash << 5)) ^ *p++;
  16. return hash;
  17. }
  18. int
  19. cdb_init(struct cdb *cdbp, int fd)
  20. {
  21. struct stat st;
  22. unsigned char *mem;
  23. unsigned fsize, dend;
  24. #ifdef _WIN32
  25. HANDLE hFile, hMapping;
  26. #endif
  27. /* get file size */
  28. if (fstat (fd, &st) < 0)
  29. return -1;
  30. /* trivial sanity check: at least toc should be here */
  31. if (st.st_size < 2048)
  32. return errno = EPROTO, -1;
  33. fsize = (unsigned) (st.st_size & 0xffffffffu);
  34. /* memory-map file */
  35. #ifdef _WIN32
  36. hFile = (HANDLE) _get_osfhandle(fd);
  37. if (hFile == (HANDLE) -1)
  38. return -1;
  39. hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
  40. if (!hMapping)
  41. return -1;
  42. mem = (unsigned char *)MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
  43. CloseHandle(hMapping);
  44. if (!mem)
  45. return -1;
  46. #else
  47. mem = (unsigned char*) mmap (NULL, fsize, PROT_READ, MAP_SHARED, fd, 0);
  48. if (mem == MAP_FAILED)
  49. return -1;
  50. #endif /* _WIN32 */
  51. cdbp->cdb_fd = fd;
  52. cdbp->cdb_fsize = fsize;
  53. cdbp->cdb_mem = mem;
  54. cdbp->mtime = st.st_mtime;
  55. cdbp->cdb_vpos = cdbp->cdb_vlen = 0;
  56. cdbp->cdb_kpos = cdbp->cdb_klen = 0;
  57. dend = cdb_unpack (mem);
  58. if (dend < 2048)
  59. dend = 2048;
  60. else if (dend >= fsize)
  61. dend = fsize;
  62. cdbp->cdb_dend = dend;
  63. return 0;
  64. }
  65. void
  66. cdb_free(struct cdb *cdbp)
  67. {
  68. if (cdbp->cdb_mem) {
  69. #ifdef _WIN32
  70. UnmapViewOfFile((void*) cdbp->cdb_mem);
  71. #else
  72. munmap ((void*) cdbp->cdb_mem, cdbp->cdb_fsize);
  73. #endif /* _WIN32 */
  74. cdbp->cdb_mem = NULL;
  75. }
  76. cdbp->cdb_fsize = 0;
  77. if (cdbp->check_timer_ev) {
  78. evtimer_del (cdbp->check_timer_ev);
  79. g_free (cdbp->check_timer_ev);
  80. g_free (cdbp->check_timer_tv);
  81. }
  82. }
  83. const void *
  84. cdb_get(const struct cdb *cdbp, unsigned len, unsigned pos)
  85. {
  86. if (pos > cdbp->cdb_fsize || cdbp->cdb_fsize - pos < len) {
  87. errno = EPROTO;
  88. return NULL;
  89. }
  90. return cdbp->cdb_mem + pos;
  91. }
  92. int
  93. cdb_read(const struct cdb *cdbp, void *buf, unsigned len, unsigned pos)
  94. {
  95. const void *data = cdb_get (cdbp, len, pos);
  96. if (!data)
  97. return -1;
  98. memcpy (buf, data, len);
  99. return 0;
  100. }
  101. static void
  102. cdb_timer_callback (int fd, short what, gpointer ud)
  103. {
  104. struct cdb *cdbp = ud;
  105. gint nfd;
  106. struct stat st;
  107. /* Check cdb file for modifications */
  108. if (stat (cdbp->filename, &st) != -1) {
  109. if (st.st_mtime > cdbp->mtime) {
  110. if ((nfd = open (cdbp->filename, O_RDONLY)) != -1) {
  111. if (cdbp->cdb_mem) {
  112. #ifdef _WIN32
  113. UnmapViewOfFile((void*) cdbp->cdb_mem);
  114. #else
  115. munmap ((void*) cdbp->cdb_mem, cdbp->cdb_fsize);
  116. #endif /* _WIN32 */
  117. cdbp->cdb_mem = NULL;
  118. }
  119. (void)close (cdbp->cdb_fd);
  120. cdbp->cdb_fsize = 0;
  121. (void)cdb_init (cdbp, nfd);
  122. }
  123. }
  124. }
  125. evtimer_add (cdbp->check_timer_ev, cdbp->check_timer_tv);
  126. }
  127. void
  128. cdb_add_timer(struct cdb *cdbp, unsigned seconds)
  129. {
  130. cdbp->check_timer_ev = g_malloc (sizeof (struct event));
  131. cdbp->check_timer_tv = g_malloc (sizeof (struct timeval));
  132. cdbp->check_timer_tv->tv_sec = seconds;
  133. cdbp->check_timer_tv->tv_usec = 0;
  134. evtimer_set (cdbp->check_timer_ev, cdb_timer_callback, cdbp);
  135. evtimer_add (cdbp->check_timer_ev, cdbp->check_timer_tv);
  136. }