Skip to content

Commit

Permalink
Add splice and sendfile (#151)
Browse files Browse the repository at this point in the history
* Add splice and sendfile
  • Loading branch information
carbotaniuman authored Jan 29, 2023
1 parent 2679077 commit bf6b53a
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 24 deletions.
1 change: 1 addition & 0 deletions c-scape/src/fs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ mod readlink;
mod realpath;
mod remove;
mod rename;
mod sendfile;
mod stat;
mod symlink;
mod sync;
Expand Down
69 changes: 69 additions & 0 deletions c-scape/src/fs/sendfile.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
use rustix::fd::BorrowedFd;

use errno::{set_errno, Errno};
use libc::{c_int, off64_t, off_t, size_t};

use crate::convert_res;

#[cfg(any(target_os = "android", target_os = "linux"))]
#[no_mangle]
unsafe extern "C" fn sendfile(
out_fd: c_int,
in_fd: c_int,
offset: *mut off_t,
count: size_t,
) -> isize {
libc!(libc::sendfile(out_fd, in_fd, offset, count));

// Check for overflow into off64_t
if !offset.is_null() {
if *offset < 0 {
set_errno(Errno(libc::EINVAL));
return -1;
}

// If count is too big then we just fail immediately
if let Ok(add) = TryInto::<off_t>::try_into(count) {
// Check if count + offset could overflow and return EINVAL
if add.overflowing_add(*offset).1 {
set_errno(Errno(libc::EINVAL));
return -1;
}
} else {
set_errno(Errno(libc::EINVAL));
return -1;
}
}

let mut offset_64: off64_t = 0;
let res = sendfile64(out_fd, in_fd, &mut offset_64, count);

if !offset.is_null() {
// Safe cast as we checked above
*offset = offset_64 as off_t;
}
return res;
}

#[cfg(any(target_os = "android", target_os = "linux"))]
#[no_mangle]
unsafe extern "C" fn sendfile64(
out_fd: c_int,
in_fd: c_int,
offset: *mut off64_t,
count: size_t,
) -> isize {
libc!(libc::sendfile64(out_fd, in_fd, offset, count));

let offset: *mut u64 = checked_cast!(offset);

match convert_res(rustix::fs::sendfile(
BorrowedFd::borrow_raw(out_fd),
BorrowedFd::borrow_raw(in_fd),
offset.as_mut(),
count.into(),
)) {
Some(num) => num.try_into().unwrap(),
None => -1,
}
}
24 changes: 2 additions & 22 deletions c-scape/src/io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@ mod isatty;
mod pipe;
mod poll;
mod read;
mod splice;
mod write;

use rustix::fd::{BorrowedFd, IntoRawFd};
use rustix::io::EventfdFlags;

use core::convert::TryInto;
use libc::{c_int, c_long, c_uint, loff_t};
use libc::{c_int, c_long, c_uint};

use crate::convert_res;

Expand Down Expand Up @@ -59,27 +60,6 @@ unsafe extern "C" fn ioctl(fd: c_int, request: c_long, mut args: ...) -> c_int {
}
}

#[cfg(any(target_os = "android", target_os = "linux"))]
#[no_mangle]
unsafe extern "C" fn sendfile() {
//libc!(libc::sendfile());
unimplemented!("sendfile")
}

#[cfg(any(target_os = "android", target_os = "linux"))]
#[no_mangle]
unsafe extern "C" fn splice(
fd_in: c_int,
off_in: *mut loff_t,
fd_out: c_int,
off_out: *mut loff_t,
len: usize,
flags: c_uint,
) -> isize {
libc!(libc::splice(fd_in, off_in, fd_out, off_out, len, flags));
unimplemented!("splice");
}

#[cfg(feature = "net")]
#[no_mangle]
unsafe extern "C" fn sendmsg() {
Expand Down
34 changes: 34 additions & 0 deletions c-scape/src/io/splice.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use rustix::fd::BorrowedFd;
use rustix::io::SpliceFlags;

use libc::{c_int, c_uint, loff_t};

use crate::convert_res;

#[cfg(any(target_os = "android", target_os = "linux"))]
#[no_mangle]
unsafe extern "C" fn splice(
fd_in: c_int,
off_in: *mut loff_t,
fd_out: c_int,
off_out: *mut loff_t,
len: usize,
flags: c_uint,
) -> isize {
libc!(libc::splice(fd_in, off_in, fd_out, off_out, len, flags));

let off_in: *mut u64 = checked_cast!(off_in);
let off_out: *mut u64 = checked_cast!(off_out);

match convert_res(rustix::io::splice(
BorrowedFd::borrow_raw(fd_in),
off_in.as_mut(),
BorrowedFd::borrow_raw(fd_out),
off_out.as_mut(),
len,
SpliceFlags::from_bits(flags as _).unwrap(),
)) {
Some(num) => num.try_into().unwrap(),
None => -1,
}
}
2 changes: 0 additions & 2 deletions tests/kernel_copy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

mustang::can_run_this!();

/* FIXME(mustang): Needs `sendfile` and `splice`.
mod sys_common;

use std::fs::OpenOptions;
Expand Down Expand Up @@ -294,4 +293,3 @@ fn bench_socket_pipe_socket_copy(b: &mut test::Bencher) {
);
});
}
*/

0 comments on commit bf6b53a

Please sign in to comment.