rspamd/contrib/cdb/cdb_init.c
2015-02-21 18:35:54 +00:00

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);
}