1
1
mirror of https://github.com/wez/wezterm.git synced 2024-11-23 15:04:36 +03:00

move filedescriptor to its own crate

This commit is contained in:
Wez Furlong 2019-04-22 21:20:33 -07:00
commit b0d1a56eaa
2 changed files with 126 additions and 0 deletions

11
filedescriptor/Cargo.toml Normal file
View File

@ -0,0 +1,11 @@
[package]
name = "filedescriptor"
version = "0.1.0"
authors = ["Wez Furlong"]
edition = "2018"
[dependencies]
failure = "0.1"
failure_derive = "0.1"
libc = "0.2"

115
filedescriptor/src/lib.rs Normal file
View File

@ -0,0 +1,115 @@
use failure::{bail, Fallible};
use std::os::unix::prelude::*;
pub struct FileDescriptor {
fd: RawFd,
}
impl std::io::Read for FileDescriptor {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, std::io::Error> {
let size = unsafe { libc::read(self.fd, buf.as_mut_ptr() as *mut _, buf.len()) };
if size == -1 {
Err(std::io::Error::last_os_error())
} else {
Ok(size as usize)
}
}
}
impl std::io::Write for FileDescriptor {
fn write(&mut self, buf: &[u8]) -> Result<usize, std::io::Error> {
let size = unsafe { libc::write(self.fd, buf.as_ptr() as *const _, buf.len()) };
if size == -1 {
Err(std::io::Error::last_os_error())
} else {
Ok(size as usize)
}
}
fn flush(&mut self) -> Result<(), std::io::Error> {
Ok(())
}
}
impl Drop for FileDescriptor {
fn drop(&mut self) {
unsafe {
libc::close(self.fd);
}
}
}
impl AsRawFd for FileDescriptor {
fn as_raw_fd(&self) -> RawFd {
self.fd
}
}
fn dup(fd: RawFd) -> Fallible<FileDescriptor> {
let duped = unsafe { libc::dup(fd) };
if duped == -1 {
bail!(
"dup of fd {} failed: {:?}",
fd,
std::io::Error::last_os_error()
)
} else {
let mut owned = FileDescriptor { fd: duped };
owned.cloexec()?;
Ok(owned)
}
}
pub struct Pipes {
pub read: FileDescriptor,
pub write: FileDescriptor,
}
impl FileDescriptor {
pub fn dup<F: AsRawFd>(f: F) -> Fallible<Self> {
dup(f.as_raw_fd())
}
pub fn pipe() -> Fallible<Pipes> {
let mut fds = [-1i32; 2];
let res = unsafe { libc::pipe(fds.as_mut_ptr()) };
if res == -1 {
bail!(
"failed to create a pipe: {:?}",
std::io::Error::last_os_error()
)
} else {
let mut read = FileDescriptor { fd: fds[0] };
let mut write = FileDescriptor { fd: fds[1] };
read.cloexec()?;
write.cloexec()?;
Ok(Pipes { read, write })
}
}
/// Helper function to set the close-on-exec flag for a raw descriptor
fn cloexec(&mut self) -> Fallible<()> {
let flags = unsafe { libc::fcntl(self.fd, libc::F_GETFD) };
if flags == -1 {
bail!(
"fcntl to read flags failed: {:?}",
std::io::Error::last_os_error()
);
}
let result = unsafe { libc::fcntl(self.fd, libc::F_SETFD, flags | libc::FD_CLOEXEC) };
if result == -1 {
bail!(
"fcntl to set CLOEXEC failed: {:?}",
std::io::Error::last_os_error()
);
}
Ok(())
}
pub fn as_stdio(&self) -> Fallible<std::process::Stdio> {
let duped = dup(self.fd)?;
let fd = duped.fd;
let stdio = unsafe { std::process::Stdio::from_raw_fd(fd) };
std::mem::forget(duped); // don't drop; stdio now owns it
Ok(stdio)
}
}