#include #include #include #include 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; } }