Files
mars-tinyldap/mstorage_init_persistent.c
2024-02-02 14:38:25 +00:00

82 lines
1.9 KiB
C

#define _FILE_OFFSET_BITS 64
#include <sys/types.h>
#include <unistd.h>
#include <sys/mman.h>
#include "mstorage.h"
#ifdef UNITTEST
#include <errno.h>
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 <assert.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/resource.h>
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