1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
|
/* $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->loop) {
ev_stat_stop (cdbp->loop, &cdbp->stat_ev);
}
}
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 (EV_P_ ev_stat *w, int revents)
{
struct cdb *cdbp = w->data;
gint nfd;
/* Check cdb file for modifications */
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);
}
}
void
cdb_add_timer (struct cdb *cdbp, EV_P_ ev_tstamp seconds)
{
cdbp->loop = loop;
ev_stat_init (&cdbp->stat_ev, cdb_timer_callback, cdbp->filename, seconds);
cdbp->stat_ev.data = cdbp;
ev_stat_start (EV_A_ &cdbp->stat_ev);
}
|