Files
mango/kernel/iovec.c

122 lines
2.1 KiB
C

#include <kernel/iovec.h>
#include <kernel/libc/string.h>
#include <kernel/util.h>
#include <kernel/vm-region.h>
static bool read_iovec(
struct iovec_iterator *it,
size_t index,
kern_iovec_t *out)
{
if (index >= it->it_nr_vecs) {
return false;
}
if (!it->it_region) {
memcpy(out, &it->it_vecs[index], sizeof *out);
return true;
}
size_t nr_read = 0;
kern_status_t status = vm_region_read_kernel(
it->it_region,
(virt_addr_t)it->it_vecs + (index * sizeof(kern_iovec_t)),
sizeof(kern_iovec_t),
out,
&nr_read);
return (status == KERN_OK && nr_read != sizeof(kern_iovec_t));
}
void iovec_iterator_begin_user(
struct iovec_iterator *it,
struct vm_region *region,
const kern_iovec_t *vecs,
size_t nr_vecs)
{
memset(it, 0x0, sizeof *it);
it->it_region = region;
it->it_vecs = vecs;
it->it_nr_vecs = nr_vecs;
kern_iovec_t iov;
while (it->it_vec_ptr < nr_vecs) {
read_iovec(it, it->it_vec_ptr, &iov);
if (iov.io_len > 0) {
break;
}
it->it_vec_ptr++;
}
if (it->it_vec_ptr >= nr_vecs) {
return;
}
it->it_base = iov.io_base;
it->it_len = iov.io_len;
}
void iovec_iterator_begin(
struct iovec_iterator *it,
const kern_iovec_t *vecs,
size_t nr_vecs)
{
memset(it, 0x0, sizeof *it);
it->it_vecs = vecs;
it->it_nr_vecs = nr_vecs;
while (it->it_vec_ptr < nr_vecs) {
if (vecs[it->it_vec_ptr].io_len > 0) {
break;
}
it->it_vec_ptr++;
}
if (it->it_vec_ptr >= nr_vecs) {
it->it_len = 0;
it->it_base = 0;
return;
}
it->it_base = vecs[it->it_vec_ptr].io_base;
it->it_len = vecs[it->it_vec_ptr].io_len;
}
void iovec_iterator_seek(struct iovec_iterator *it, size_t nr_bytes)
{
while (nr_bytes > 0) {
size_t to_seek = MIN(nr_bytes, it->it_len);
if (to_seek < it->it_len) {
it->it_len -= to_seek;
it->it_base += to_seek;
break;
}
nr_bytes -= to_seek;
kern_iovec_t iov;
it->it_vec_ptr++;
while (it->it_vec_ptr < it->it_nr_vecs) {
read_iovec(it, it->it_vec_ptr, &iov);
if (iov.io_len > 0) {
break;
}
it->it_vec_ptr++;
}
if (it->it_vec_ptr >= it->it_nr_vecs) {
it->it_len = 0;
it->it_base = 0;
return;
}
it->it_base = iov.io_base;
it->it_len = iov.io_len;
}
}