#include #include #include #include #include #include "filterdb.h" #define PAGE_SIZE 4096 #define ALIGN(s,a) (((s) + a - 1) & ~(a - 1)) const char *sqdb_section_names[SQDB_SECTION_MAX] = { [SQDB_SECTION_STRINGS] = "strings", [SQDB_SECTION_CATEGORIES] = "categories", [SQDB_SECTION_INDEX] = "index", [SQDB_SECTION_INDEX_MPH] = "index_mph", [SQDB_SECTION_KEYWORD] = "keyword", [SQDB_SECTION_KEYWORD_MPH] = "keyword_mph", }; static int sqdb_allocate(struct sqdb *db, size_t s, int wr) { size_t old_size, new_size; void *base; int prot = PROT_READ; old_size = db->file_length; new_size = ALIGN(db->file_length + s, PAGE_SIZE); if (new_size == ALIGN(db->file_length, PAGE_SIZE)) { db->file_length += s; return old_size; } if (wr && ftruncate(db->fd, new_size) < 0) return -1; if (db->mmap_base == NULL) { if (wr) prot |= PROT_WRITE; base = mmap(NULL, new_size, prot, MAP_SHARED, db->fd, 0); } else { base = mremap(db->mmap_base, ALIGN(old_size, PAGE_SIZE), new_size, MREMAP_MAYMOVE); } if (base == MAP_FAILED) return -1; db->mmap_base = base; db->file_length += ALIGN(s, 16); return old_size; } int sqdb_open(struct sqdb *db, const char *fn) { struct stat st; db->fd = open(fn, O_RDONLY); if (db->fd < 0) return -1; fstat(db->fd, &st); db->file_length = 0; db->mmap_base = NULL; sqdb_allocate(db, st.st_size, 0); return 0; } int sqdb_create(struct sqdb *db, const char *fn) { struct sqdb_header *hdr; int rc; db->fd = open(fn, O_CREAT | O_TRUNC | O_RDWR, 0666); if (db->fd < 0) return -1; db->file_length = 0; db->mmap_base = NULL; rc = sqdb_allocate(db, sizeof(struct sqdb_header), 1); if (rc < 0) { close(db->fd); return rc; } hdr = db->mmap_base; strcpy(hdr->description, "Squark Filtering Database"); hdr->version = 1; hdr->magic = 0xdbdbdbdb; hdr->num_sections = SQDB_SECTION_MAX; return 0; } int sqdb_open(struct sqdb *db, const char *fn); void sqdb_close(struct sqdb *db) { if (db->mmap_base) munmap(db->mmap_base, ALIGN(db->file_length, PAGE_SIZE)); close(db->fd); } void *sqdb_section_create(struct sqdb *db, int id, uint32_t size) { struct sqdb_header *hdr; size_t pos; hdr = db->mmap_base; if (hdr->section[id].offset || hdr->section[id].length) return NULL; pos = sqdb_allocate(db, size, 1); if (pos < 0) return NULL; /* sqdb_allocate can remap mmap_base */ hdr = db->mmap_base; hdr->section[id].offset = pos; hdr->section[id].length = size; return db->mmap_base + pos; } void *sqdb_section_get(struct sqdb *db, int id, uint32_t *size) { struct sqdb_header *hdr = db->mmap_base; if (hdr->section[id].offset == 0) return NULL; if (size) *size = hdr->section[id].length; return db->mmap_base + hdr->section[id].offset; } blob_t sqdb_get_string_literal(struct sqdb *db, uint32_t encoded_ptr) { uint32_t section_size; unsigned char *ptr; unsigned int len, off; ptr = sqdb_section_get(db, SQDB_SECTION_STRINGS, §ion_size); if (ptr == NULL) return BLOB_NULL; off = encoded_ptr >> SQDB_LENGTH_BITS; len = encoded_ptr & ((1 << SQDB_LENGTH_BITS) - 1); if (off + len >= section_size) return BLOB_NULL; if (len == 0) len = ptr[off++]; if (off + len >= section_size) return BLOB_NULL; return BLOB_PTR_LEN(ptr + off, len); }