Data-Pool-Shared
view release on metacpan or search on metacpan
/* Fixed element width for the typed variants; 0 for RAW/STR (caller-chosen).
* A crafted file could pair a typed variant_id with a wrong elem_size and drive
* the typed accessors past a slot or into a misaligned atomic; pin it here. */
static inline uint32_t pool_variant_elem_size(uint32_t variant_id) {
switch (variant_id) {
case POOL_VAR_I64: case POOL_VAR_F64: return 8;
case POOL_VAR_I32: return 4;
default: return 0;
}
}
/* Validate header: magic, version, variant, sizes, AND layout offsets. */
static inline int pool_validate_header(const PoolHeader *hdr, uint64_t file_size,
uint32_t expected_variant) {
if (hdr->magic != POOL_MAGIC) return 0;
if (hdr->version != POOL_VERSION) return 0;
if (hdr->variant_id != expected_variant) return 0;
{ uint32_t w = pool_variant_elem_size(hdr->variant_id);
if (w && hdr->elem_size != w) return 0; } /* typed variant: elem_size must match its fixed width */
if (hdr->capacity == 0 || hdr->capacity > POOL_MAX_CAPACITY) return 0;
if (hdr->elem_size == 0) return 0;
if (hdr->capacity > (UINT64_MAX - sizeof(PoolHeader)) / hdr->elem_size) return 0;
if (hdr->total_size != file_size) return 0;
uint64_t bm_off, own_off, dat_off, total;
pool_calc_layout(hdr->capacity, hdr->elem_size, &bm_off, &own_off, &dat_off, &total);
if (hdr->bitmap_off != bm_off) return 0;
if (hdr->owners_off != own_off) return 0;
if (hdr->data_off != dat_off) return 0;
if (hdr->total_size != total) return 0;
return 1;
}
static inline PoolHandle *pool_setup_handle(void *base, size_t map_size,
const char *path, int backing_fd) {
PoolHeader *hdr = (PoolHeader *)base;
PoolHandle *h = (PoolHandle *)calloc(1, sizeof(PoolHandle));
if (!h) { munmap(base, map_size); return NULL; }
h->hdr = hdr;
h->bitmap = (uint64_t *)((uint8_t *)base + hdr->bitmap_off);
h->owners = (uint32_t *)((uint8_t *)base + hdr->owners_off);
h->data = (uint8_t *)base + hdr->data_off;
h->mmap_size = map_size;
h->bitmap_words = (uint32_t)((hdr->capacity + 63) / 64);
h->path = path ? strdup(path) : NULL;
h->notify_fd = -1;
h->backing_fd = backing_fd;
h->scan_hint = (uint32_t)getpid() % h->bitmap_words;
return h;
}
/* Securely obtain a fd: create exclusively (O_CREAT|O_EXCL|O_NOFOLLOW at mode,
* default 0600), or attach an existing file (O_RDWR|O_NOFOLLOW, no O_CREAT). */
static int pool_secure_open(const char *path, mode_t mode, char *errbuf) {
for (int attempt = 0; attempt < 100; attempt++) {
int fd = open(path, O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_CLOEXEC, mode);
if (fd >= 0) { (void)fchmod(fd, mode); return fd; } /* exact mode: umask narrowed the O_EXCL create */
if (errno != EEXIST) { POOL_ERR("create %s: %s", path, strerror(errno)); return -1; }
fd = open(path, O_RDWR|O_NOFOLLOW|O_CLOEXEC);
if (fd >= 0) return fd;
if (errno == ENOENT) continue; /* creator unlinked between our two opens; retry */
POOL_ERR("open %s: %s", path, strerror(errno)); /* ELOOP => symlink rejected */
return -1;
}
POOL_ERR("open %s: create/attach kept racing", path);
return -1;
}
static PoolHandle *pool_create(const char *path, uint64_t capacity,
uint32_t elem_size, uint32_t variant_id,
mode_t mode, char *errbuf) {
if (errbuf) errbuf[0] = '\0';
if (capacity == 0) { POOL_ERR("capacity must be > 0"); return NULL; }
if (elem_size == 0) { POOL_ERR("elem_size must be > 0"); return NULL; }
if (capacity > POOL_MAX_CAPACITY) { POOL_ERR("capacity too large"); return NULL; }
if (capacity > (UINT64_MAX - sizeof(PoolHeader)) / elem_size) {
POOL_ERR("capacity * elem_size overflow"); return NULL;
}
uint64_t bm_off, own_off, dat_off, total;
pool_calc_layout(capacity, elem_size, &bm_off, &own_off, &dat_off, &total);
int fd = -1;
int anonymous = (path == NULL);
size_t map_size;
void *base;
if (anonymous) {
map_size = (size_t)total;
base = mmap(NULL, map_size, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
if (base == MAP_FAILED) {
POOL_ERR("mmap(anonymous): %s", strerror(errno));
return NULL;
}
} else {
fd = pool_secure_open(path, mode, errbuf);
if (fd < 0) return NULL;
if (flock(fd, LOCK_EX) < 0) {
POOL_ERR("flock(%s): %s", path, strerror(errno));
close(fd); return NULL;
}
struct stat st;
if (fstat(fd, &st) < 0) {
POOL_ERR("fstat(%s): %s", path, strerror(errno));
flock(fd, LOCK_UN); close(fd); return NULL;
}
int is_new = (st.st_size == 0);
if (!is_new && (uint64_t)st.st_size < sizeof(PoolHeader)) {
POOL_ERR("%s: file too small (%lld)", path, (long long)st.st_size);
flock(fd, LOCK_UN); close(fd); return NULL;
}
( run in 2.189 seconds using v1.01-cache-2.11-cpan-600a1bdf6e4 )