blob: 9082394079f6c4d98a37b8d68eb6242b30abf418 [file] [log] [blame]
// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use std::mem;
use std::ops::Drop;
use std::os::unix::io::{AsRawFd, RawFd};
use crate::{errno_result, Result};
pub type RawDescriptor = RawFd;
/// Trait for forfeiting ownership of the current raw descriptor, and returning the raw descriptor
pub trait IntoRawDescriptor {
fn into_raw_descriptor(self) -> RawDescriptor;
}
/// Trait for returning the underlying raw descriptor, without giving up ownership of the
/// descriptor.
pub trait AsRawDescriptor {
fn as_raw_descriptor(&self) -> RawDescriptor;
}
pub trait FromRawDescriptor {
/// # Safety
/// Safe only if the caller ensures nothing has access to the descriptor after passing it to
/// `from_raw_descriptor`
unsafe fn from_raw_descriptor(descriptor: RawDescriptor) -> Self;
}
/// Wraps a RawDescriptor and safely closes it when self falls out of scope.
#[derive(Debug, PartialEq)]
pub struct SafeDescriptor {
descriptor: RawDescriptor,
}
impl Drop for SafeDescriptor {
fn drop(&mut self) {
let _ = unsafe { libc::close(self.descriptor) };
}
}
impl AsRawDescriptor for SafeDescriptor {
fn as_raw_descriptor(&self) -> RawDescriptor {
self.descriptor
}
}
impl IntoRawDescriptor for SafeDescriptor {
fn into_raw_descriptor(self) -> RawDescriptor {
let descriptor = self.descriptor;
mem::forget(self);
descriptor
}
}
impl FromRawDescriptor for SafeDescriptor {
unsafe fn from_raw_descriptor(descriptor: RawDescriptor) -> Self {
SafeDescriptor { descriptor }
}
}
impl AsRawFd for SafeDescriptor {
fn as_raw_fd(&self) -> RawFd {
self.as_raw_descriptor()
}
}
impl SafeDescriptor {
/// Clones this descriptor, internally creating a new descriptor. The new SafeDescriptor will
/// share the same underlying count within the kernel.
pub fn try_clone(&self) -> Result<SafeDescriptor> {
// Safe because self.as_raw_descriptor() returns a valid value
let copy_fd = unsafe { libc::dup(self.as_raw_descriptor()) };
if copy_fd < 0 {
return errno_result();
}
// Safe becuase we just successfully duplicated and this object will uniquely
// own the raw descriptor.
Ok(unsafe { SafeDescriptor::from_raw_descriptor(copy_fd) })
}
}
/// For use cases where a simple wrapper around a RawDescriptor is needed.
/// This is a simply a wrapper and does not manage the lifetime of the descriptor.
/// Most usages should prefer SafeDescriptor or using a RawDescriptor directly
#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[repr(transparent)]
pub struct Descriptor(pub RawDescriptor);
impl AsRawDescriptor for Descriptor {
fn as_raw_descriptor(&self) -> RawDescriptor {
self.0
}
}