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 )