From 0893fd1b8b61618be3c7e0eb26641f0597827afb Mon Sep 17 00:00:00 2001 From: David Carlier Date: Fri, 24 Nov 2023 21:12:59 +0000 Subject: [PATCH] sys::sendfile adding solaris' sendfilev wrapper proposal. --- src/sys/sendfile.rs | 68 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/src/sys/sendfile.rs b/src/sys/sendfile.rs index 6e2e0ace90..735fc7a109 100644 --- a/src/sys/sendfile.rs +++ b/src/sys/sendfile.rs @@ -120,6 +120,49 @@ cfg_if! { ) } } + } else if #[cfg(any(target_os = "solaris", target_os = "illumos"))] { + #[derive(Clone, Debug, Copy)] + /// Mapping of the raw C sendfilevec_t struct + /// no need to bother with `sfv_flag` since it needs to be always 0. + pub struct SendfileVec { + /// input file descriptor + pub fd: i32, + /// offset to read from + pub off: isize, + /// size of the data to read + pub len: usize, + } + + const SFV_FD_SELF: i32 = -2; + + impl SendfileVec { + /// initialises SendfileVec to send data directly from the process's address space + /// same in C with sfv_fd set to SFV_FD_SELF. + pub fn newself( + off: isize, + len: usize + ) -> SendfileVec { + SendfileVec{fd: SFV_FD_SELF, off: off, len: len} + } + + /// initialises SendfileVec to send data from `fd`. + pub fn new( + fd: i32, + off: isize, + len: usize + ) -> SendfileVec { + SendfileVec{fd: fd, off: off, len: len} + } + + fn tosendfilevec(&self) -> libc::sendfilevec_t { + libc::sendfilevec_t{ + sfv_fd: self.fd, + sfv_flag: 0, + sfv_off: self.off as off_t, + sfv_len: self.len + } + } + } } } @@ -287,5 +330,30 @@ cfg_if! { }; (Errno::result(return_code).and(Ok(())), len) } + } else if #[cfg(any(target_os = "solaris", target_os = "illumos"))] { + /// Write data from the vec arrays to `out_sock` and returns a `Result` and a + /// count of bytes written. + /// + /// Each `SendfileVec` set needs to be instantiated either with `SendfileVec::new` or + /// `SendfileVec::newself`. + /// + /// The former allows to send data from a file descriptor through `fd`, + /// from an offset `off` and for a given amount of data `len`. + /// + /// The latter allows to send data from the process' address space, from an offset `off` + /// and for a given amount of data `len`. + /// + /// For more information, see + /// [the sendfilev{3) man page.](https://docs.oracle.com/cd/E86824_01/html/E54768/sendfilev-3ext.html) + pub fn sendfilev( + out_sock: F2, + vec: Vec + ) -> Result { + let rawvec: Vec = vec.iter().map(|&v| v.tosendfilevec()).collect(); + let ret = unsafe { + libc::sendfilev(out_sock.as_fd().as_raw_fd(), rawvec.as_ptr(), rawvec.len() as i32, ptr::null_mut()) + }; + Errno::result(ret).map(|r| r as usize) + } } }