/* i ib_rw.c */ #include "copyright.h" #include "config.h" #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <dirent.h> #include <sys/time.h> #include <sys/stat.h> #include <sys/types.h> #include <fcntl.h> #include <sys/mman.h> #include <errno.h> #include <event.h> #include <string.h> #include <sys/file.h> #include <stdint.h> #include "debug.h" struct mmdb_t { void *base; void *ppos; void *end; int length; int fd; }; struct mmdb_t *mmdb_open_read(char *filename) { struct stat statbuf; struct mmdb_t *mmdb; int fd, length; if(stat(filename, &statbuf) < 0) { return NULL; } mmdb = malloc(sizeof(struct mmdb_t)); if(!mmdb) return NULL; fd = open(filename, O_RDONLY); if(!fd) { free(mmdb); return NULL; } mmdb->fd = fd; mmdb->length = (statbuf.st_size + 0x3FF) & ~(0x3FF); mmdb->base = mmap(NULL, mmdb->length, PROT_READ, MAP_SHARED, mmdb->fd, 0); if(!mmdb->base) { close(mmdb->fd); free(mmdb); return NULL; } mmdb->end = mmdb->base + mmdb->length; mmdb->ppos = mmdb->base; return mmdb; } struct mmdb_t *mmdb_open_write(char *filename) { struct stat statbuf; struct mmdb_t *mmdb; int fd, length; mmdb = malloc(sizeof(struct mmdb_t)); dperror((fd = open(filename, O_RDWR | O_CREAT, 0644)) < 0); mmdb->fd = fd; mmdb->length = 0x400 * 16; mmdb->base = NULL; mmdb->ppos = NULL; dprintk("mmdb->length %d", mmdb->length); ftruncate(mmdb->fd, mmdb->length); fsync(mmdb->fd); mmdb->base = mmap(NULL, mmdb->length, PROT_READ | PROT_WRITE, MAP_SHARED, mmdb->fd, 0); dperror(mmdb->base == MAP_FAILED); mmdb->end = mmdb->base + mmdb->length; mmdb->ppos = mmdb->base; return mmdb; } void mmdb_resize(struct mmdb_t *mmdb, int length) { int offset = 0; if(mmdb->base) { offset = mmdb->ppos - mmdb->base; msync(mmdb->base, mmdb->length, MS_ASYNC); munmap(mmdb->base, mmdb->length); mmdb->base = NULL; mmdb->ppos = NULL; } mmdb->length = (length + 0x3FF) & ~(0x3FF); ftruncate(mmdb->fd, mmdb->length); mmdb->base = mmap(NULL, mmdb->length, PROT_READ | PROT_WRITE, MAP_SHARED, mmdb->fd, 0); dperror(mmdb->base == NULL); mmdb->end = mmdb->base + mmdb->length; mmdb->ppos = mmdb->base + offset; } void mmdb_close(struct mmdb_t *mmdb) { msync(mmdb->base, mmdb->length, MS_SYNC); munmap(mmdb->base, mmdb->length); ftruncate(mmdb->fd, mmdb->ppos - mmdb->base); dprintk("truncating to %d bytes.", mmdb->ppos - mmdb->base); close(mmdb->fd); mmdb->fd = 0; memset(mmdb, 0, sizeof(struct mmdb_t)); free(mmdb); } void mmdb_write(struct mmdb_t *mmdb, void *data, int length) { if(mmdb->end - mmdb->ppos < length) { mmdb_resize(mmdb, mmdb->length + length); } memcpy(mmdb->ppos, data, length); mmdb->ppos += length; } void mmdb_write_uint32(struct mmdb_t *mmdb, uint32_t data) { data = htonl(data); mmdb_write(mmdb, &data, sizeof(uint32_t)); } uint32_t mmdb_read_uint32(struct mmdb_t *mmdb) { uint32_t data = *((uint32_t *) (mmdb->ppos)); mmdb->ppos += sizeof(uint32_t); return ntohl(data); } unsigned int mmdb_read_uint(struct mmdb_t *mmdb) { printk("This function is deprecated, please use mmdb_read_uint32 instead.\n"); return (unsigned int)mmdb_read_uint32(mmdb); } void mmdb_write_uint(struct mmdb_t *mmdb, unsigned int val) { printk("This function is deprecated, please use mmdb_write_uint32 instead.\n"); mmdb_write_uint32(mmdb, (uint32_t)val); return; } void mmdb_write_uint64(struct mmdb_t *mmdb, uint64_t data) { dprintk("technically, this is not 64 bit safe yet."); data = htonl(data); mmdb_write(mmdb, &data, sizeof(uint64_t)); } uint64_t mmdb_read_uint64(struct mmdb_t *mmdb) { dprintk("technically, this is not 64 bit safe yet."); uint64_t data = *((uint64_t *) (mmdb->ppos)); mmdb->ppos += sizeof(uint64_t); return ntohl(data); } void mmdb_write_single(struct mmdb_t *mmdb, float data) { data = htonl(data); mmdb_write(mmdb, &data, sizeof(float)); } float mmdb_read_single(struct mmdb_t *mmdb) { float data = *((float *) (mmdb->ppos)); mmdb->ppos += sizeof(float); return ntohl(data); } void mmdb_write_double(struct mmdb_t *mmdb, double data) { data = htonl(data); mmdb_write(mmdb, &data, sizeof(double)); } double mmdb_read_double(struct mmdb_t *mmdb) { double data = *((double *) (mmdb->ppos)); mmdb->ppos += sizeof(double); return ntohl(data); } void *mmdb_read(struct mmdb_t *mmdb, void *dest, int length) { if((mmdb->end - mmdb->ppos) < length) return NULL; memcpy(dest, mmdb->ppos, length); mmdb->ppos += length; if(length & 3) mmdb->ppos += 4 - (length & 3); return dest; } void mmdb_write_opaque(struct mmdb_t *mmdb, void *data, int length) { unsigned char *pad = (unsigned char *)"\x00\x00\x00\x00"; mmdb_write_uint32(mmdb, length); mmdb_write(mmdb, data, length); if((length & 3) > 0) mmdb_write(mmdb, pad, 4 - (length & 3)); } void mmdb_write_string(struct mmdb_t *mmdb, void *data) { if(data == NULL) { mmdb_write_uint32(mmdb, 0); } else { mmdb_write_opaque(mmdb, data, strlen(data)+1); } } char *mmdb_read_string(struct mmdb_t *mmdb) { char *tmp; int length; length = mmdb_read_uint32(mmdb); if(length == 0) return NULL; tmp = malloc(length); mmdb_read(mmdb, tmp, length); return tmp; } char mmdb_read_opaque(struct mmdb_t *mmdb, void *dest, int maxlength) { int length = mmdb_read_uint32(mmdb); if((mmdb->end - mmdb->ppos) < length) return NULL; if(length > maxlength) { memcpy(dest, mmdb->ppos, maxlength); } else { memcpy(dest, mmdb->ppos, length); } mmdb->ppos += length; if(length & 3) mmdb->ppos += 4 - (length & 3); return dest; }