Skip to content

Commit

Permalink
Use rustix instead of nix
Browse files Browse the repository at this point in the history
This is cleaner than `nix` due to the use of `OwnedFd`/`BorrowedFd`.

`calloop` is already using `rustix`.
  • Loading branch information
ids1024 committed Sep 28, 2023
1 parent 08f6081 commit 2f442a2
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 74 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ cursor-icon = "1.0.0"
dlib = "0.5"
log = "0.4"
memmap2 = "0.7.0"
nix = { version = "0.26.1", default-features = false, features = ["fs", "mman"] }
# rustix = { version = "0.38.14", features = ["fs", "pipe"] }
rustix = { git = "https://github.com/ids1024/rustix", branch = "shm_open", features = ["fs", "pipe", "shm"] }
thiserror = "1.0.30"
wayland-backend = "0.3.0"
wayland-client = "0.31.1"
Expand Down
21 changes: 5 additions & 16 deletions src/data_device_manager/data_offer.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{
ops::{Deref, DerefMut},
os::unix::prelude::{AsFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd},
os::unix::prelude::{AsFd, OwnedFd},
sync::{Arc, Mutex},
};

Expand Down Expand Up @@ -402,18 +402,13 @@ impl PartialEq for UndeterminedOffer {
/// Fails if too many file descriptors were already open and a pipe
/// could not be created.
pub fn receive(offer: &WlDataOffer, mime_type: String) -> std::io::Result<ReadPipe> {
use nix::fcntl::OFlag;
use nix::unistd::{close, pipe2};
use rustix::pipe::{pipe_with, PipeFlags};
// create a pipe
let (readfd, writefd) = pipe2(OFlag::O_CLOEXEC)?;
let (readfd, writefd) = pipe_with(PipeFlags::CLOEXEC)?;

offer.receive(mime_type, unsafe { BorrowedFd::borrow_raw(writefd) });
receive_to_fd(offer, mime_type, writefd);

if let Err(err) = close(writefd) {
log::warn!("Failed to close write pipe: {}", err);
}

Ok(unsafe { FromRawFd::from_raw_fd(readfd) })
Ok(ReadPipe::from(readfd))
}

/// Receive data to the write end of a raw file descriptor. If you have the read end, you can read from it.
Expand All @@ -430,11 +425,5 @@ pub fn receive(offer: &WlDataOffer, mime_type: String) -> std::io::Result<ReadPi
/// The provided file destructor must be a valid FD for writing, and will be closed
/// once the contents are written.
pub fn receive_to_fd(offer: &WlDataOffer, mime_type: String, writefd: OwnedFd) {
use nix::unistd::close;

offer.receive(mime_type, writefd.as_fd());

if let Err(err) = close(writefd.into_raw_fd()) {
log::warn!("Failed to close write pipe: {}", err);
}
}
21 changes: 5 additions & 16 deletions src/primary_selection/offer.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::{
os::unix::io::{AsFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd},
os::unix::io::{AsFd, OwnedFd},
sync::Mutex,
};

Expand Down Expand Up @@ -36,32 +36,21 @@ impl PrimarySelectionOffer {
/// Fails if too many file descriptors were already open and a pipe
/// could not be created.
pub fn receive(&self, mime_type: String) -> std::io::Result<ReadPipe> {
use nix::fcntl::OFlag;
use nix::unistd::{close, pipe2};
use rustix::pipe::{pipe_with, PipeFlags};
// create a pipe
let (readfd, writefd) = pipe2(OFlag::O_CLOEXEC)?;
let (readfd, writefd) = pipe_with(PipeFlags::CLOEXEC)?;

self.offer.receive(mime_type, unsafe { BorrowedFd::borrow_raw(writefd) });
self.receive_to_fd(mime_type, writefd);

if let Err(err) = close(writefd) {
log::warn!("Failed to close write pipe: {}", err);
}

Ok(unsafe { FromRawFd::from_raw_fd(readfd) })
Ok(ReadPipe::from(readfd))
}

/// Request to receive the data of a given mime type, writen to `writefd`.
///
/// The provided file destructor must be a valid FD for writing, and will be closed
/// once the contents are written.
pub fn receive_to_fd(&self, mime_type: String, writefd: OwnedFd) {
use nix::unistd::close;

self.offer.receive(mime_type, writefd.as_fd());

if let Err(err) = close(writefd.into_raw_fd()) {
log::warn!("Failed to close write pipe: {}", err);
}
}
}

Expand Down
7 changes: 0 additions & 7 deletions src/shm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ pub mod slot;

use std::io;

use nix::errno::Errno;
use wayland_client::{
globals::{BindError, GlobalList},
protocol::wl_shm,
Expand Down Expand Up @@ -70,12 +69,6 @@ pub enum CreatePoolError {
Create(#[from] io::Error),
}

impl From<Errno> for CreatePoolError {
fn from(errno: Errno) -> Self {
Into::<io::Error>::into(errno).into()
}
}

/// Delegates the handling of [`wl_shm`] to some [`Shm`].
///
/// This macro requires two things, the type that will delegate to [`Shm`] and a closure specifying how
Expand Down
54 changes: 20 additions & 34 deletions src/shm/raw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,19 @@
//! This is intended as a safe building block for higher level shared memory pool abstractions and is not
//! encouraged for most library users.
use rustix::{
io::Errno,
shm::{Mode, ShmOFlags},
};
use std::{
fs::File,
io,
os::unix::prelude::{AsFd, FromRawFd, OwnedFd, RawFd},
os::unix::prelude::{AsFd, OwnedFd},
sync::Arc,
time::{SystemTime, UNIX_EPOCH},
};

use memmap2::MmapMut;
use nix::{
errno::Errno,
fcntl,
sys::{mman, stat},
unistd,
};
use wayland_client::{
backend::ObjectData,
protocol::{wl_buffer, wl_shm, wl_shm_pool},
Expand Down Expand Up @@ -48,7 +46,7 @@ impl RawPool {
) -> Result<RawPool, CreatePoolError> {
let shm = shm.bound_global()?;
let shm_fd = RawPool::create_shm_fd()?;
let mem_file = unsafe { File::from_raw_fd(shm_fd) };
let mem_file = File::from(shm_fd);
mem_file.set_len(len as u64)?;

let pool = shm
Expand Down Expand Up @@ -170,14 +168,14 @@ impl io::Seek for RawPool {
}

impl RawPool {
fn create_shm_fd() -> io::Result<RawFd> {
fn create_shm_fd() -> io::Result<OwnedFd> {
#[cfg(target_os = "linux")]
{
match RawPool::create_memfd() {
Ok(fd) => return Ok(fd),

// Not supported, use fallback.
Err(Errno::ENOSYS) => (),
Err(Errno::NOSYS) => (),

Err(err) => return Err(Into::<io::Error>::into(err)),
};
Expand All @@ -190,25 +188,20 @@ impl RawPool {
);

loop {
let flags = fcntl::OFlag::O_CREAT
| fcntl::OFlag::O_EXCL
| fcntl::OFlag::O_RDWR
| fcntl::OFlag::O_CLOEXEC;
let flags = ShmOFlags::CREATE | ShmOFlags::EXCL | ShmOFlags::RDWR;

let mode = stat::Mode::S_IRUSR | stat::Mode::S_IWUSR;
let mode = Mode::RUSR | Mode::WUSR;

match mman::shm_open(mem_file_handle.as_str(), flags, mode) {
Ok(fd) => match mman::shm_unlink(mem_file_handle.as_str()) {
match rustix::shm::shm_open(mem_file_handle.as_str(), flags, mode) {
Ok(fd) => match rustix::shm::shm_unlink(mem_file_handle.as_str()) {
Ok(_) => return Ok(fd),

Err(errno) => {
unistd::close(fd)?;

return Err(errno.into());
}
},

Err(Errno::EEXIST) => {
Err(Errno::EXIST) => {
// Change the handle if we happen to be duplicate.
let time = SystemTime::now();

Expand All @@ -220,38 +213,31 @@ impl RawPool {
continue;
}

Err(Errno::EINTR) => continue,
Err(Errno::INTR) => continue,

Err(err) => return Err(err.into()),
}
}
}

#[cfg(target_os = "linux")]
fn create_memfd() -> nix::Result<RawFd> {
fn create_memfd() -> rustix::io::Result<OwnedFd> {
use std::ffi::CStr;

use nix::{
fcntl::{FcntlArg, SealFlag},
sys::memfd::{self, MemFdCreateFlag},
};
use rustix::fs::{MemfdFlags, SealFlags};

loop {
let name = CStr::from_bytes_with_nul(b"smithay-client-toolkit\0").unwrap();
let flags = MemFdCreateFlag::MFD_ALLOW_SEALING | MemFdCreateFlag::MFD_CLOEXEC;
let flags = MemfdFlags::ALLOW_SEALING | MemfdFlags::CLOEXEC;

match memfd::memfd_create(name, flags) {
match rustix::fs::memfd_create(name, flags) {
Ok(fd) => {
let arg =
FcntlArg::F_ADD_SEALS(SealFlag::F_SEAL_SHRINK | SealFlag::F_SEAL_SEAL);

// We only need to seal for the purposes of optimization, ignore the errors.
let _ = fcntl::fcntl(fd, arg);

let _ = rustix::fs::fcntl_add_seals(&fd, SealFlags::SHRINK | SealFlags::SEAL);
return Ok(fd);
}

Err(Errno::EINTR) => continue,
Err(Errno::INTR) => continue,

Err(err) => return Err(err),
}
Expand Down

0 comments on commit 2f442a2

Please sign in to comment.