Cache-FastMmap
view release on metacpan or search on metacpan
the previous value instead of silently losing it.
- _mmc_set_error (unix.c, win32.c): use snprintf into the
remaining buffer space instead of strncat with the wrong
size argument, which could overflow errbuf on long error
messages.
- mmc_lock: fix off-by-one allowing page == c_num_pages
(one past the last valid page).
- mmc_lock: replace hardcoded num_slots >= 89 sanity check
with cache->start_slots, so caches built with custom
start_slots values lock correctly.
- mmc_check_fh: check fstat() return value before trusting
statbuf.st_ino, restoring the safety net the function
was added for.
- mmc_iterate_next: end iteration cleanly if mmc_lock fails
instead of walking stale page state.
- Win32 mmc_unlock_page: split p_offset into Offset and
OffsetHigh and add the missing return, so caches larger
than 4GB unlock at the same offset they locked at.
- Win32 mmc_lock_page: CloseHandle on the event handle on
every exit path; previously every successful lock leaked
one HANDLE.
}
require_ok('Cache::FastMmap');
my $old_umask = umask 0000;
note( 'umask returns undef on this system, test results may not be reliable')
unless defined $old_umask;
my $FC = Cache::FastMmap->new(init_file => 1);
ok( defined $FC );
my (undef, undef, $Mode) = stat($FC->{share_file});
$Mode = $Mode & 0777;
is($Mode, 0640, "default persmissions 0640");
undef $FC;
my $FC = Cache::FastMmap->new(init_file => 1, permissions => 0600);
ok( defined $FC );
my (undef, undef, $Mode) = stat($FC->{share_file});
$Mode = $Mode & 0777;
is($Mode, 0600, "can set to 0600");
undef $FC;
my $FC = Cache::FastMmap->new(init_file => 1, permissions => 0666);
ok( defined $FC );
my (undef, undef, $Mode) = stat($FC->{share_file});
$Mode = $Mode & 0777;
is($Mode, 0666, "can set to 0666");
undef $FC;
{
return def_share_file;
}
int mmc_open_cache_file(mmap_cache* cache, int * do_init) {
int res, i, fh;
void * tmp;
struct stat statbuf;
/* Check if file exists */
res = stat(cache->share_file, &statbuf);
/* Remove if different size or remove requested */
if (!res &&
(cache->init_file || (statbuf.st_size != cache->c_size))) {
res = remove(cache->share_file);
if (res == -1 && errno != ENOENT) {
return _mmc_set_error(cache, errno, "Unlink of existing share file %s failed", cache->share_file);
}
}
/* Create file if it doesn't exist */
res = stat(cache->share_file, &statbuf);
if (res == -1) {
mode_t permissions = (mode_t)cache->permissions;
res = open(cache->share_file, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC | O_APPEND, permissions);
if (res == -1) {
return _mmc_set_error(cache, errno, "Create of share file %s failed", cache->share_file);
}
/* Fill file with 0's */
tmp = calloc(1, cache->c_page_size);
if (!tmp) {
/* Open for reading/writing */
fh = open(cache->share_file, O_RDWR);
if (fh == -1) {
return _mmc_set_error(cache, errno, "Open of share file %s failed", cache->share_file);
}
/* Automatically close cache fd on exec */
fcntl(fh, F_SETFD, FD_CLOEXEC);
fstat(fh, &statbuf);
cache->inode = statbuf.st_ino;
cache->fh = fh;
return 0;
}
/*
* mmc_map_memory(mmap_cache * cache)
}
return res;
}
int mmc_check_fh(mmap_cache* cache) {
struct stat statbuf;
/* fstat must succeed before we can trust statbuf.st_ino. If it fails
* (e.g. fd was closed externally) treat that as the same kind of "fd
* messed with" condition the inode check is here to catch. */
if (fstat(cache->fh, &statbuf) == -1) {
_mmc_set_error(cache, errno, "Underlying cache file fd %d fstat failed, something messed up underlying file descriptors", cache->fh);
return 0;
}
if (cache->inode != statbuf.st_ino) {
_mmc_set_error(cache, 0, "Underlying cache file fd %d was inode %ld but now %ld, something messed up underlying file descriptors", cache->fh, cache->inode, statbuf.st_ino);
return 0;
}
return 1;
}
( run in 0.660 second using v1.01-cache-2.11-cpan-97f6503c9c8 )