mirror of
https://github.com/rspamd/rspamd.git
synced 2024-07-28 20:17:53 +02:00
154 lines
3.4 KiB
C
154 lines
3.4 KiB
C
/* $Id: cdb_init.c,v 1.12 2008-11-06 18:07:04 mjt Exp $
|
|
* cdb_init, cdb_free and cdb_read routines
|
|
*
|
|
* This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru.
|
|
* Public domain.
|
|
*/
|
|
|
|
#include "cdb.h"
|
|
|
|
unsigned
|
|
cdb_hash(const void *buf, unsigned len)
|
|
{
|
|
register const unsigned char *p = (const unsigned char *) buf;
|
|
register const unsigned char *end = p + len;
|
|
register unsigned hash = 5381; /* start value */
|
|
while (p < end)
|
|
hash = (hash + (hash << 5)) ^ *p++;
|
|
return hash;
|
|
}
|
|
|
|
int
|
|
cdb_init(struct cdb *cdbp, int fd)
|
|
{
|
|
struct stat st;
|
|
unsigned char *mem;
|
|
unsigned fsize, dend;
|
|
#ifdef _WIN32
|
|
HANDLE hFile, hMapping;
|
|
#endif
|
|
|
|
/* get file size */
|
|
if (fstat (fd, &st) < 0)
|
|
return -1;
|
|
/* trivial sanity check: at least toc should be here */
|
|
if (st.st_size < 2048)
|
|
return errno = EPROTO, -1;
|
|
fsize = (unsigned) (st.st_size & 0xffffffffu);
|
|
/* memory-map file */
|
|
#ifdef _WIN32
|
|
hFile = (HANDLE) _get_osfhandle(fd);
|
|
if (hFile == (HANDLE) -1)
|
|
return -1;
|
|
hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
|
|
if (!hMapping)
|
|
return -1;
|
|
mem = (unsigned char *)MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
|
|
CloseHandle(hMapping);
|
|
if (!mem)
|
|
return -1;
|
|
#else
|
|
mem = (unsigned char*) mmap (NULL, fsize, PROT_READ, MAP_SHARED, fd, 0);
|
|
if (mem == MAP_FAILED)
|
|
return -1;
|
|
#endif /* _WIN32 */
|
|
|
|
cdbp->cdb_fd = fd;
|
|
cdbp->cdb_fsize = fsize;
|
|
cdbp->cdb_mem = mem;
|
|
cdbp->mtime = st.st_mtime;
|
|
|
|
cdbp->cdb_vpos = cdbp->cdb_vlen = 0;
|
|
cdbp->cdb_kpos = cdbp->cdb_klen = 0;
|
|
dend = cdb_unpack (mem);
|
|
if (dend < 2048)
|
|
dend = 2048;
|
|
else if (dend >= fsize)
|
|
dend = fsize;
|
|
cdbp->cdb_dend = dend;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
cdb_free(struct cdb *cdbp)
|
|
{
|
|
if (cdbp->cdb_mem) {
|
|
#ifdef _WIN32
|
|
UnmapViewOfFile((void*) cdbp->cdb_mem);
|
|
#else
|
|
munmap ((void*) cdbp->cdb_mem, cdbp->cdb_fsize);
|
|
#endif /* _WIN32 */
|
|
cdbp->cdb_mem = NULL;
|
|
}
|
|
cdbp->cdb_fsize = 0;
|
|
|
|
if (cdbp->check_timer_ev) {
|
|
evtimer_del (cdbp->check_timer_ev);
|
|
g_free (cdbp->check_timer_ev);
|
|
g_free (cdbp->check_timer_tv);
|
|
}
|
|
}
|
|
|
|
const void *
|
|
cdb_get(const struct cdb *cdbp, unsigned len, unsigned pos)
|
|
{
|
|
if (pos > cdbp->cdb_fsize || cdbp->cdb_fsize - pos < len) {
|
|
errno = EPROTO;
|
|
return NULL;
|
|
}
|
|
return cdbp->cdb_mem + pos;
|
|
}
|
|
|
|
int
|
|
cdb_read(const struct cdb *cdbp, void *buf, unsigned len, unsigned pos)
|
|
{
|
|
const void *data = cdb_get (cdbp, len, pos);
|
|
if (!data)
|
|
return -1;
|
|
memcpy (buf, data, len);
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
cdb_timer_callback (int fd, short what, gpointer ud)
|
|
{
|
|
struct cdb *cdbp = ud;
|
|
gint nfd;
|
|
struct stat st;
|
|
|
|
/* Check cdb file for modifications */
|
|
if (stat (cdbp->filename, &st) != -1) {
|
|
if (st.st_mtime > cdbp->mtime) {
|
|
if ((nfd = open (cdbp->filename, O_RDONLY)) != -1) {
|
|
if (cdbp->cdb_mem) {
|
|
#ifdef _WIN32
|
|
UnmapViewOfFile((void*) cdbp->cdb_mem);
|
|
#else
|
|
munmap ((void*) cdbp->cdb_mem, cdbp->cdb_fsize);
|
|
#endif /* _WIN32 */
|
|
cdbp->cdb_mem = NULL;
|
|
}
|
|
(void)close (cdbp->cdb_fd);
|
|
cdbp->cdb_fsize = 0;
|
|
(void)cdb_init (cdbp, nfd);
|
|
}
|
|
}
|
|
}
|
|
|
|
evtimer_add (cdbp->check_timer_ev, cdbp->check_timer_tv);
|
|
}
|
|
|
|
void
|
|
cdb_add_timer(struct cdb *cdbp, unsigned seconds)
|
|
{
|
|
cdbp->check_timer_ev = g_malloc (sizeof (struct event));
|
|
cdbp->check_timer_tv = g_malloc (sizeof (struct timeval));
|
|
|
|
cdbp->check_timer_tv->tv_sec = seconds;
|
|
cdbp->check_timer_tv->tv_usec = 0;
|
|
|
|
evtimer_set (cdbp->check_timer_ev, cdb_timer_callback, cdbp);
|
|
evtimer_add (cdbp->check_timer_ev, cdbp->check_timer_tv);
|
|
}
|