/* $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); }