in src/couch/priv/couch_cfile/couch_cfile.c [360:419]
static ERL_NIF_TERM pread_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
#ifdef COUCH_CFILE_SUPPORTED
handle_t* hdl;
long offset, block_size, bytes_read;
SysIOVec io_vec[1];
posix_errno_t res_errno = 0;
ErlNifBinary result;
if (argc != 3
|| !get_handle(env, argv[0], &hdl)
|| !enif_is_number(env, argv[1])
|| !enif_is_number(env, argv[2])
) {
return badarg(env);
}
if (!enif_get_int64(env, argv[1], &offset)
|| !enif_get_int64(env, argv[2], &block_size)
|| offset < 0
|| block_size < 0
) {
return err_tup(env, EINVAL);
}
if (!enif_alloc_binary((size_t) block_size, &result)) {
return err_tup(env, ENOMEM);
}
io_vec[0].iov_base = (char *)result.data;
io_vec[0].iov_len = result.size;
// ------ Critical section start ------
READ_LOCK;
if (hdl->fd < 0) {
READ_UNLOCK;
enif_release_binary(&result);
return err_tup(env, EINVAL);
}
bytes_read = efile_preadv(hdl->fd, offset, io_vec, 1, &res_errno);
READ_UNLOCK;
// ------ Critical section end ------
if (bytes_read < 0) {
enif_release_binary(&result);
return err_tup(env, res_errno);
}
if (bytes_read == 0) {
enif_release_binary(&result);
return ATOM_EOF;
}
if (bytes_read < block_size && !enif_realloc_binary(&result, bytes_read)) {
enif_release_binary(&result);
return err_tup(env, ENOMEM);
}
return ok_tup(env, enif_make_binary(env, &result));
#else
return err_tup(env, EINVAL);
#endif
}