Alien-libmaxminddb
view release on metacpan or search on metacpan
maxminddb/src/maxminddb.c view on Meta::CPAN
}
if (file_size.QuadPart < 0 || file_size.QuadPart > SSIZE_MAX) {
status = MMDB_IO_ERROR;
goto cleanup;
}
size = (ssize_t)file_size.QuadPart;
mmh = CreateFileMapping(fd, NULL, PAGE_READONLY, 0, 0, NULL);
/* Microsoft documentation for CreateFileMapping indicates this returns
NULL not INVALID_HANDLE_VALUE on error */
if (NULL == mmh) {
status = MMDB_IO_ERROR;
goto cleanup;
}
uint8_t *file_content =
(uint8_t *)MapViewOfFile(mmh, FILE_MAP_READ, 0, 0, 0);
if (file_content == NULL) {
status = MMDB_IO_ERROR;
goto cleanup;
}
mmdb->file_size = size;
mmdb->file_content = file_content;
cleanup:;
int saved_errno = errno;
if (INVALID_HANDLE_VALUE != fd) {
CloseHandle(fd);
}
if (NULL != mmh) {
CloseHandle(mmh);
}
errno = saved_errno;
free(utf16_filename);
return status;
}
#else // _WIN32
static int map_file(MMDB_s *const mmdb) {
int status = MMDB_SUCCESS;
int o_flags = O_RDONLY;
#ifdef O_CLOEXEC
o_flags |= O_CLOEXEC;
#endif
int fd = open(mmdb->filename, o_flags);
if (fd < 0) {
status = MMDB_FILE_OPEN_ERROR;
goto cleanup;
}
#if defined(FD_CLOEXEC) && !defined(O_CLOEXEC)
int fd_flags = fcntl(fd, F_GETFD);
if (fd_flags >= 0) {
fcntl(fd, F_SETFD, fd_flags | FD_CLOEXEC);
}
#endif
struct stat s;
if (fstat(fd, &s)) {
status = MMDB_FILE_OPEN_ERROR;
goto cleanup;
}
off_t size = s.st_size;
if (size < 0 || size > SSIZE_MAX) {
status = MMDB_OUT_OF_MEMORY_ERROR;
goto cleanup;
}
uint8_t *file_content =
(uint8_t *)mmap(NULL, (size_t)size, PROT_READ, MAP_SHARED, fd, 0);
if (MAP_FAILED == file_content) {
if (ENOMEM == errno) {
status = MMDB_OUT_OF_MEMORY_ERROR;
} else {
status = MMDB_IO_ERROR;
}
goto cleanup;
}
mmdb->file_size = (ssize_t)size;
mmdb->file_content = file_content;
cleanup:;
int saved_errno = errno;
if (fd >= 0) {
close(fd);
}
errno = saved_errno;
return status;
}
#endif // _WIN32
static const uint8_t *find_metadata(const uint8_t *file_content,
ssize_t file_size,
uint32_t *metadata_size) {
const ssize_t marker_len = sizeof(METADATA_MARKER) - 1;
ssize_t max_size = file_size > METADATA_BLOCK_MAX_SIZE
? METADATA_BLOCK_MAX_SIZE
: file_size;
if (max_size < 0) {
return NULL;
}
uint8_t const *search_area = (file_content + (file_size - max_size));
uint8_t const *start = search_area;
uint8_t const *tmp;
do {
tmp = mmdb_memmem(
search_area, (size_t)max_size, METADATA_MARKER, marker_len);
if (NULL != tmp) {
max_size -= tmp - search_area;
search_area = tmp;
/* Continue searching just after the marker we just read, in case
* there are multiple markers in the same file. This would be odd
( run in 0.311 second using v1.01-cache-2.11-cpan-8644d7adfcd )