Skip to content

Commit

Permalink
Replace nix with rustix
Browse files Browse the repository at this point in the history
  • Loading branch information
YaLTeR committed Mar 7, 2024
1 parent 7e4f56d commit e81562a
Show file tree
Hide file tree
Showing 8 changed files with 88 additions and 93 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
- **Breaking** Removed `utils::copy_data`. It forked into a `/usr/bin/env cat`
for copying. All internal uses of the function have been changed to simply
use `std::io::copy` instead.
- Replaced `nix` with `rustix`, following `wayland-rs`.

## v0.8.1 (7th Mar 2024)

Expand Down
22 changes: 2 additions & 20 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ keywords = ["wayland", "clipboard"]
[workspace.dependencies]
libc = "0.2.153"
log = "0.4.21"
nix = "0.28.0"
rustix = "0.38.31"

[package]
name = "wl-clipboard-rs"
Expand All @@ -32,8 +32,8 @@ categories = ["os"]
derive-new = "0.6.0"
libc.workspace = true
log.workspace = true
nix = { workspace = true, features = ["fs", "process", "event"] }
os_pipe = { version = "1.1.5", features = ["io_safety"] }
rustix = { workspace = true, features = ["fs", "event"] }
tempfile = "3.10.1"
thiserror = "1"
tree_magic_mini = "3.0.3"
Expand Down
75 changes: 41 additions & 34 deletions src/tests/mod.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use std::ffi::OsStr;
use std::os::fd::OwnedFd;
use std::sync::atomic::AtomicU8;
use std::sync::atomic::Ordering::SeqCst;
use std::sync::{Arc, Mutex};
use std::thread;

use nix::sys::epoll::{Epoll, EpollCreateFlags, EpollEvent, EpollFlags, EpollTimeout};
use rustix::event::epoll;
use wayland_backend::server::ClientData;
use wayland_server::{Display, ListeningSocket};

Expand All @@ -16,7 +17,7 @@ mod utils;
pub struct TestServer<S: 'static> {
pub display: Display<S>,
pub socket: ListeningSocket,
pub epoll: Epoll,
pub epoll: OwnedFd,
}

struct ClientCounter(AtomicU8);
Expand All @@ -36,17 +37,22 @@ impl<S: Send + 'static> TestServer<S> {
let mut display = Display::new().unwrap();
let socket = ListeningSocket::bind_auto("wl-clipboard-rs-test", 0..).unwrap();

let epoll = Epoll::new(EpollCreateFlags::EPOLL_CLOEXEC).unwrap();

epoll
.add(&socket, EpollEvent::new(EpollFlags::EPOLLIN, 0))
.unwrap();
epoll
.add(
display.backend().poll_fd(),
EpollEvent::new(EpollFlags::EPOLLIN, 1),
)
.unwrap();
let epoll = epoll::create(epoll::CreateFlags::CLOEXEC).unwrap();

epoll::add(
&epoll,
&socket,
epoll::EventData::new_u64(0),
epoll::EventFlags::IN,
)
.unwrap();
epoll::add(
&epoll,
display.backend().poll_fd(),
epoll::EventData::new_u64(1),
epoll::EventFlags::IN,
)
.unwrap();

TestServer {
display,
Expand Down Expand Up @@ -76,29 +82,30 @@ impl<S: Send + 'static> TestServer<S> {

while client_counter.0.load(SeqCst) > 0 || waiting_for_first_client {
// Wait for requests from the client.
let mut events = [EpollEvent::empty(); 2];
let nevents = self.epoll.wait(&mut events, EpollTimeout::NONE).unwrap();

let ready_socket = events.iter().take(nevents).any(|event| event.data() == 0);
let ready_clients = events.iter().take(nevents).any(|event| event.data() == 1);

if ready_socket {
// Try to accept a new client.
if let Some(stream) = self.socket.accept().unwrap() {
waiting_for_first_client = false;
client_counter.0.fetch_add(1, SeqCst);
self.display
.handle()
.insert_client(stream, client_counter.clone())
.unwrap();
let mut events = epoll::EventVec::with_capacity(2);
epoll::wait(&self.epoll, &mut events, -1).unwrap();

for event in &events {
match event.data.u64() {
0 => {
// Try to accept a new client.
if let Some(stream) = self.socket.accept().unwrap() {
waiting_for_first_client = false;
client_counter.0.fetch_add(1, SeqCst);
self.display
.handle()
.insert_client(stream, client_counter.clone())
.unwrap();
}
}
1 => {
// Try to dispatch client messages.
self.display.dispatch_clients(state).unwrap();
self.display.flush_clients().unwrap();
}
x => panic!("unexpected epoll event: {x}"),
}
}

if ready_clients {
// Try to dispatch client messages.
self.display.dispatch_clients(state).unwrap();
self.display.flush_clients().unwrap();
}
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/tests/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@
use std::collections::HashMap;
use std::io::Write;
use std::os::fd::{AsFd, AsRawFd};
use std::os::fd::AsFd;
use std::sync::atomic::AtomicU8;
use std::sync::atomic::Ordering::SeqCst;
use std::sync::mpsc::Sender;

use nix::fcntl::{fcntl, FcntlArg, OFlag};
use os_pipe::PipeWriter;
use proptest::prelude::*;
use proptest_derive::Arbitrary;
use rustix::fs::{fcntl_setfl, OFlags};
use wayland_protocols_wlr::data_control::v1::server::zwlr_data_control_device_v1::{
self, ZwlrDataControlDeviceV1,
};
Expand Down Expand Up @@ -261,7 +261,7 @@ impl Dispatch<ZwlrDataControlOfferV1, (String, bool)> for State {
}
OfferInfo::Runtime { source } => {
if state.set_nonblock_on_write_fd {
fcntl(fd.as_raw_fd(), FcntlArg::F_SETFL(OFlag::O_NONBLOCK)).unwrap();
fcntl_setfl(&fd, OFlags::NONBLOCK).unwrap();
}

source.send(mime_type, fd.as_fd())
Expand Down
2 changes: 1 addition & 1 deletion wl-clipboard-rs-tools/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ anyhow = "1.0.80"
libc.workspace = true
log.workspace = true
mime_guess = "2.0.4"
nix.workspace = true
rustix = { workspace = true, features = ["stdio"] }
stderrlog = "0.6.0"
structopt = { version = "0.3.26", features = ["wrap_help"] }
wl-clipboard-rs = { path = "../", version = "0.8.1" }
Expand Down
37 changes: 20 additions & 17 deletions wl-clipboard-rs-tools/src/bin/wl-clip.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
use std::env::args_os;
use std::ffi::OsString;
use std::fs::File;
use std::fs::{File, OpenOptions};
use std::io::{stdout, Read, Write};
use std::process;

use anyhow::{Context, Error};
use libc::{STDIN_FILENO, STDOUT_FILENO};
use nix::fcntl::OFlag;
use nix::unistd::{close, dup2, fork, ForkResult};
use libc::fork;
use rustix::stdio::{dup2_stdin, dup2_stdout};
use wl_clipboard_rs::copy::{self, ServeRequests, Source};
use wl_clipboard_rs::paste::{self, get_contents};
use wl_clipboard_rs::utils::is_text;
Expand Down Expand Up @@ -290,20 +289,24 @@ fn main() -> Result<(), Error> {
} else {
// SAFETY: We don't spawn any threads, so doing things after forking is safe.
// TODO: is there any way to verify that we don't spawn any threads?
if let ForkResult::Child = unsafe { fork() }.unwrap() {
// Replace STDIN and STDOUT with /dev/null. We won't be using them, and keeping them as
// is hangs a potential pipeline (i.e. wl-copy hello | cat). Also, simply closing the
// file descriptors is a bad idea because then they get reused by subsequent temp file
// opens, which breaks the dup2/close logic during data copying.
if let Ok(dev_null) =
nix::fcntl::open("/dev/null", OFlag::O_RDWR, nix::sys::stat::Mode::empty())
{
let _ = dup2(dev_null, STDIN_FILENO);
let _ = dup2(dev_null, STDOUT_FILENO);
let _ = close(dev_null);
}
match unsafe { fork() } {
-1 => panic!("error forking: {:?}", std::io::Error::last_os_error()),
0 => {
// Replace STDIN and STDOUT with /dev/null. We won't be using them, and keeping
// them as is hangs a potential pipeline (i.e. wl-copy hello | cat). Also,
// simply closing the file descriptors is a bad idea because then they get
// reused by subsequent temp file opens, which breaks the dup2/close logic
// during data copying.
if let Ok(dev_null) =
OpenOptions::new().read(true).write(true).open("/dev/null")
{
let _ = dup2_stdin(&dev_null);
let _ = dup2_stdout(&dev_null);
}

drop(prepared_copy.serve());
drop(prepared_copy.serve());
}
_ => (),
}
}
}
Expand Down
34 changes: 18 additions & 16 deletions wl-clipboard-rs-tools/src/bin/wl-copy.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use std::ffi::OsString;
use std::fs::OpenOptions;
use std::os::unix::ffi::OsStringExt;

use libc::{STDIN_FILENO, STDOUT_FILENO};
use nix::fcntl::OFlag;
use nix::unistd::{close, dup2, fork, ForkResult};
use libc::fork;
use rustix::stdio::{dup2_stdin, dup2_stdout};
use structopt::clap::AppSettings;
use structopt::StructOpt;
use wl_clipboard_rs::copy::{self, clear, ClipboardType, MimeType, Seat, ServeRequests, Source};
Expand Down Expand Up @@ -159,20 +159,22 @@ fn main() -> Result<(), anyhow::Error> {
} else {
// SAFETY: We don't spawn any threads, so doing things after forking is safe.
// TODO: is there any way to verify that we don't spawn any threads?
if let ForkResult::Child = unsafe { fork() }.unwrap() {
// Replace STDIN and STDOUT with /dev/null. We won't be using them, and keeping them as
// is hangs a potential pipeline (i.e. wl-copy hello | cat). Also, simply closing the
// file descriptors is a bad idea because then they get reused by subsequent temp file
// opens, which breaks the dup2/close logic during data copying.
if let Ok(dev_null) =
nix::fcntl::open("/dev/null", OFlag::O_RDWR, nix::sys::stat::Mode::empty())
{
let _ = dup2(dev_null, STDIN_FILENO);
let _ = dup2(dev_null, STDOUT_FILENO);
let _ = close(dev_null);
match unsafe { fork() } {
-1 => panic!("error forking: {:?}", std::io::Error::last_os_error()),
0 => {
// Replace STDIN and STDOUT with /dev/null. We won't be using them, and keeping
// them as is hangs a potential pipeline (i.e. wl-copy hello | cat). Also, simply
// closing the file descriptors is a bad idea because then they get reused by
// subsequent temp file opens, which breaks the dup2/close logic during data
// copying.
if let Ok(dev_null) = OpenOptions::new().read(true).write(true).open("/dev/null") {
let _ = dup2_stdin(&dev_null);
let _ = dup2_stdout(&dev_null);
}

drop(prepared_copy.serve());
}

drop(prepared_copy.serve());
_ => (),
}
}

Expand Down

0 comments on commit e81562a

Please sign in to comment.