use linux_unsafe::args::AsRawV;
use linux_unsafe::int;
pub const F_DUPFD: DirectFcntlCmd<int, super::File> = unsafe { fcntl_cmd(0) };
pub const F_GETFD: DirectFcntlCmd<(), int> = unsafe { fcntl_cmd(1) };
pub const F_SETFD: DirectFcntlCmd<int, ()> = unsafe { fcntl_cmd(2) };
pub const F_GETFL: DirectFcntlCmd<(), int> = unsafe { fcntl_cmd(3) };
pub const F_SETFL: DirectFcntlCmd<int, ()> = unsafe { fcntl_cmd(4) };
pub const F_GETLK: MutPtrFcntlCmd<linux_unsafe::flock, ()> = unsafe { fcntl_cmd_mut_ptr(5) };
pub const F_SETLK: MutPtrFcntlCmd<linux_unsafe::flock, ()> = unsafe { fcntl_cmd_mut_ptr(6) };
pub const F_SETLKW: MutPtrFcntlCmd<linux_unsafe::flock, ()> = unsafe { fcntl_cmd_mut_ptr(7) };
pub const F_OFD_GETLK: MutPtrFcntlCmd<linux_unsafe::flock, ()> = unsafe { fcntl_cmd_mut_ptr(36) };
pub const F_OFD_SETLK: MutPtrFcntlCmd<linux_unsafe::flock, ()> = unsafe { fcntl_cmd_mut_ptr(37) };
pub const F_OFD_SETLKW: MutPtrFcntlCmd<linux_unsafe::flock, ()> = unsafe { fcntl_cmd_mut_ptr(38) };
const F_LINUX_SPECIFIC_BASE: int = 1024;
pub const F_DUPFD_CLOEXEC: DirectFcntlCmd<int, int> =
unsafe { fcntl_cmd(F_LINUX_SPECIFIC_BASE + 6) };
pub unsafe trait FcntlCmd<'a> {
type ExtArg
where
Self: 'a;
type RawArg: AsRawV;
type Result;
fn prepare_fcntl_args(&self, arg: Self::ExtArg) -> (int, Self::RawArg);
fn prepare_fcntl_result(&self, raw: int) -> Self::Result;
}
pub const unsafe fn fcntl_cmd<Arg, Result>(cmd: int) -> DirectFcntlCmd<Arg, Result>
where
Arg: AsRawV,
Result: FromFcntlResult,
{
DirectFcntlCmd::<Arg, Result> {
cmd,
_phantom: core::marker::PhantomData,
}
}
pub const unsafe fn fcntl_cmd_const_ptr<Arg, Result>(cmd: int) -> ConstPtrFcntlCmd<Arg, Result>
where
*const Arg: AsRawV,
Result: FromFcntlResult,
{
ConstPtrFcntlCmd::<Arg, Result> {
cmd,
_phantom: core::marker::PhantomData,
}
}
pub const unsafe fn fcntl_cmd_mut_ptr<Arg, Result>(cmd: int) -> MutPtrFcntlCmd<Arg, Result>
where
*mut Arg: AsRawV,
Result: FromFcntlResult,
{
MutPtrFcntlCmd::<Arg, Result> {
cmd,
_phantom: core::marker::PhantomData,
}
}
#[repr(transparent)]
pub struct DirectFcntlCmd<Arg: AsRawV, Result: FromFcntlResult> {
cmd: int,
_phantom: core::marker::PhantomData<(Arg, Result)>,
}
unsafe impl<'a, Arg: AsRawV, Result: FromFcntlResult> FcntlCmd<'a> for DirectFcntlCmd<Arg, Result> {
type ExtArg = Arg where Self: 'a;
type RawArg = Arg;
fn prepare_fcntl_args(&self, arg: Arg) -> (int, Self::RawArg) {
(self.cmd, arg)
}
type Result = Result;
fn prepare_fcntl_result(&self, raw: int) -> Self::Result {
unsafe { Self::Result::prepare_result(raw) }
}
}
#[repr(transparent)]
pub struct ConstPtrFcntlCmd<Arg, Result: FromFcntlResult> {
cmd: int,
_phantom: core::marker::PhantomData<(Arg, Result)>,
}
unsafe impl<'a, Arg, Result: FromFcntlResult> FcntlCmd<'a> for ConstPtrFcntlCmd<Arg, Result> {
type ExtArg = &'a Arg where Self: 'a;
type RawArg = *const Arg;
fn prepare_fcntl_args(&self, arg: &'a Arg) -> (int, Self::RawArg) {
(self.cmd, arg as *const Arg)
}
type Result = Result;
fn prepare_fcntl_result(&self, raw: int) -> Self::Result {
unsafe { Self::Result::prepare_result(raw) }
}
}
#[repr(transparent)]
pub struct MutPtrFcntlCmd<Arg, Result: FromFcntlResult> {
cmd: int,
_phantom: core::marker::PhantomData<(Arg, Result)>,
}
unsafe impl<'a, Arg, Result: FromFcntlResult> FcntlCmd<'a> for MutPtrFcntlCmd<Arg, Result> {
type ExtArg = &'a mut Arg where Self: 'a;
type RawArg = *mut Arg;
fn prepare_fcntl_args(&self, arg: &'a mut Arg) -> (int, Self::RawArg) {
(self.cmd, arg as *mut Arg)
}
type Result = Result;
fn prepare_fcntl_result(&self, raw: int) -> Self::Result {
unsafe { Self::Result::prepare_result(raw) }
}
}
pub trait FromFcntlResult {
unsafe fn prepare_result(raw: int) -> Self;
}
impl FromFcntlResult for int {
#[inline(always)]
unsafe fn prepare_result(raw: int) -> Self {
raw
}
}
impl FromFcntlResult for () {
#[inline(always)]
unsafe fn prepare_result(_: int) -> () {
()
}
}
impl FromFcntlResult for super::File {
#[inline(always)]
unsafe fn prepare_result(raw: int) -> Self {
super::File::from_raw_fd(raw)
}
}