pub trait FileDescriptor: Sized + Debug + AsRawFd + FromRawFd + IntoRawFd
{
#[inline(always)]
fn copy(&self) -> FileDescriptorCopy<Self>
{
FileDescriptorCopy::new(self.as_raw_fd())
}
#[inline(always)]
fn duplicate_with_close_on_exec_non_blocking(&self) -> Result<Option<Self>, CreationError>
{
let result = unsafe { fcntl(self.as_raw_fd(), F_DUPFD_CLOEXEC, 0) };
if likely!(result >= 0)
{
Ok(Some(unsafe { Self::from_raw_fd(result) }))
}
else if likely!(result == -1)
{
use self::CreationError::*;
match errno().0
{
EBUSY | EINTR | EAGAIN => Ok(None),
EMFILE => Err(PerProcessLimitOnNumberOfFileDescriptorsWouldBeExceeded),
ENFILE => Err(SystemWideLimitOnTotalNumberOfFileDescriptorsWouldBeExceeded),
ENOMEM | ENOSPC => Err(KernelWouldBeOutOfMemory),
EBADF => panic!("oldfd isn't an open file descriptor"),
unexpected @ _ => panic!("Unexpected error {} from fcntl()", unexpected),
}
}
else
{
unreachable_code(format_args!("Unexpected result {} from fcntl()", result))
}
}
#[inline(always)]
fn remove_close_on_exec(&self)
{
let flags = self.get_file_descriptor_flags();
let flags_without_close_on_exec = flags & !FD_CLOEXEC;
let result = unsafe { fcntl (self.as_raw_fd(), F_SETFD, flags_without_close_on_exec) };
if likely!(result == 0)
{
return
}
else if likely!(result == -1)
{
panic!("Error `{}` from fcntl()", errno())
}
else
{
unreachable_code(format_args!("Unexpected result {} from fcntl()", result))
}
}
#[inline(always)]
fn make_blocking(&self)
{
let flags = self.get_o_flags();
let flags_without_non_block = flags & !O_NONBLOCK;
let result = unsafe { fcntl(self.as_raw_fd(), F_SETFL, flags_without_non_block) };
if likely!(result == 0)
{
()
}
else if likely!(result == -1)
{
panic!("Error from fcntl F_SETFL with `{}`", errno())
}
else
{
panic!("Unexpected result from fcntl F_SETFL of `{}`", result)
}
}
#[inline(always)]
fn is_blocking(&self) -> bool
{
self.get_o_flags() & O_NONBLOCK == 0
}
#[inline(always)]
fn is_non_blocking(&self) -> bool
{
self.get_o_flags() & O_NONBLOCK != 0
}
#[doc(hidden)]
#[inline(always)]
fn get_o_flags(&self) -> i32
{
Self::get_o_flags_raw_fd(self.as_raw_fd())
}
#[doc(hidden)]
#[inline(always)]
fn get_o_flags_raw_fd(raw_fd: RawFd) -> i32
{
let result = unsafe { fcntl(raw_fd, F_GETFL) };
if likely!(result >= 0)
{
result
}
else if likely!(result == -1)
{
panic!("Error from fcntl F_GETFL with `{}`", errno())
}
else
{
panic!("Unexpected result from fcntl F_GETFL of `{}`", result)
}
}
#[doc(hidden)]
#[inline(always)]
fn get_file_descriptor_flags(&self) -> i32
{
let file_descriptor_flags = unsafe { fcntl (self.as_raw_fd(), F_GETFD) };
if unlikely!(file_descriptor_flags < 0)
{
panic!("Error getting file descriptor flags `{}`", errno())
}
file_descriptor_flags
}
}