#define _FILE_OFFSET_BITS 64 #include #include #include #include "mstorage.h" #ifdef UNITTEST #include int failafter=0; void* my_mmap(void* addr, size_t len, int prot, int flags, int fd, off_t ofs) { if (--failafter == 0) { errno=EINVAL; return MAP_FAILED; } return mmap(addr,len,prot,flags,fd,ofs); } #define mmap my_mmap #endif int mstorage_init_persistent(mstorage_t* p,int fd) { off_t o; p->fd=fd; p->mapped=p->used=0; p->root=NULL; o=lseek(fd,0,SEEK_END); if (o==-1) return -1; if (o==0) { if (ftruncate(fd,4096)==-1) return -1; o=4096; } p->root=mmap(0,o,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0); if (p->root==MAP_FAILED) { p->root=NULL; return -1; } p->mapped=p->used=o; return 0; } #ifdef UNITTEST #include #include #include #include int main() { mstorage_t m; char filename[]="/tmp/fooXXXXXX"; int fd; assert((fd=mkstemp(filename)) != -1); assert(unlink(filename) == 0); // success case assert(mstorage_init_persistent(&m, fd) == 0); assert(munmap(m.root, m.mapped) == 0); assert(close(fd) == 0); // make lseek fail int pipes[2]; assert(pipe(pipes) == 0); assert(mstorage_init_persistent(&m, pipes[0]) == -1); close(pipes[0]); close(pipes[1]); // make ftruncate fail assert((fd=open(filename, O_RDWR|O_CREAT|O_EXCL, 0600)) != -1); assert(close(fd) == 0); assert((fd=open(filename, O_RDONLY)) != -1); assert(unlink(filename) == 0); // fd is now a read-only handle to a 0 byte file assert(mstorage_init_persistent(&m, fd) == -1); assert(m.root == NULL && m.mapped == 0); assert(close(fd) == 0); // make mmap fail failafter=1; assert((fd=open(filename, O_RDWR|O_CREAT|O_EXCL, 0600)) != -1); assert(unlink(filename) == 0); assert(mstorage_init_persistent(&m, fd) == -1); assert(m.root == NULL && m.mapped == 0); assert(close(fd) == 0); return 0; } #endif