mirror of
https://github.com/wez/wezterm.git
synced 2024-11-27 02:25:28 +03:00
make filedescriptor crate compile on windows
This commit is contained in:
parent
8a38ab6cb1
commit
9271c130c5
@ -9,3 +9,10 @@ failure = "0.1"
|
||||
failure_derive = "0.1"
|
||||
libc = "0.2"
|
||||
|
||||
[target."cfg(windows)".dependencies]
|
||||
winapi = { version = "0.3", features = [
|
||||
"winuser",
|
||||
"handleapi",
|
||||
"fileapi",
|
||||
"namedpipeapi",
|
||||
]}
|
||||
|
@ -1,143 +1,14 @@
|
||||
use failure::{bail, Fallible};
|
||||
use std::os::unix::prelude::*;
|
||||
|
||||
#[cfg(unix)]
|
||||
pub trait AsRawFileDescriptor: AsRawFd {}
|
||||
|
||||
mod unix;
|
||||
#[cfg(unix)]
|
||||
impl<T: AsRawFd> AsRawFileDescriptor for T {}
|
||||
pub use crate::unix::*;
|
||||
|
||||
#[cfg(windows)]
|
||||
pub trait AsRawFileDescriptor: AsRawHandle {}
|
||||
|
||||
mod windows;
|
||||
#[cfg(windows)]
|
||||
impl<T: AsRawHandle> AsRawFileDescriptor for T {}
|
||||
|
||||
#[derive(Debug)]
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for &FileDescriptor {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.fd
|
||||
}
|
||||
}
|
||||
|
||||
fn dup_fd(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 use crate::windows::*;
|
||||
|
||||
pub struct Pipes {
|
||||
pub read: FileDescriptor,
|
||||
pub write: FileDescriptor,
|
||||
}
|
||||
|
||||
pub fn dup<F: AsRawFileDescriptor>(f: F) -> Fallible<FileDescriptor> {
|
||||
#[cfg(unix)]
|
||||
dup_fd(f.as_raw_fd())
|
||||
}
|
||||
|
||||
impl FileDescriptor {
|
||||
pub fn dup<F: AsRawFileDescriptor>(f: F) -> Fallible<Self> {
|
||||
dup(f)
|
||||
}
|
||||
|
||||
pub fn clone(&self) -> Fallible<FileDescriptor> {
|
||||
dup(self)
|
||||
}
|
||||
|
||||
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_fd(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)
|
||||
}
|
||||
}
|
||||
|
130
filedescriptor/src/unix.rs
Normal file
130
filedescriptor/src/unix.rs
Normal file
@ -0,0 +1,130 @@
|
||||
use crate::Pipes;
|
||||
use failure::{bail, Fallible};
|
||||
use std::os::unix::prelude::*;
|
||||
|
||||
pub trait AsRawFileDescriptor: AsRawFd {}
|
||||
|
||||
impl<T: AsRawFd> AsRawFileDescriptor for T {}
|
||||
|
||||
#[derive(Debug)]
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for &FileDescriptor {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.fd
|
||||
}
|
||||
}
|
||||
|
||||
fn dup_fd(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 fn dup<F: AsRawFileDescriptor>(f: F) -> Fallible<FileDescriptor> {
|
||||
dup_fd(f.as_raw_fd())
|
||||
}
|
||||
|
||||
impl FileDescriptor {
|
||||
pub fn dup<F: AsRawFileDescriptor>(f: F) -> Fallible<Self> {
|
||||
dup(f)
|
||||
}
|
||||
|
||||
pub fn try_clone(&self) -> Fallible<Self> {
|
||||
dup(self)
|
||||
}
|
||||
|
||||
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_fd(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)
|
||||
}
|
||||
}
|
134
filedescriptor/src/windows.rs
Normal file
134
filedescriptor/src/windows.rs
Normal file
@ -0,0 +1,134 @@
|
||||
use crate::Pipes;
|
||||
use failure::{bail, Fallible};
|
||||
use std::io::{self, Error as IoError};
|
||||
use std::os::windows::prelude::*;
|
||||
use std::os::windows::raw::HANDLE;
|
||||
use std::ptr;
|
||||
use winapi::um::fileapi::*;
|
||||
use winapi::um::handleapi::*;
|
||||
use winapi::um::namedpipeapi::CreatePipe;
|
||||
use winapi::um::processthreadsapi::*;
|
||||
|
||||
pub trait AsRawFileDescriptor: AsRawHandle {}
|
||||
|
||||
impl<T: AsRawHandle> AsRawFileDescriptor for T {}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FileDescriptor {
|
||||
pub handle: HANDLE,
|
||||
}
|
||||
|
||||
unsafe impl Send for FileDescriptor {}
|
||||
|
||||
impl Drop for FileDescriptor {
|
||||
fn drop(&mut self) {
|
||||
if self.handle != INVALID_HANDLE_VALUE && !self.handle.is_null() {
|
||||
unsafe { CloseHandle(self.handle) };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn dup_handle(handle: HANDLE) -> Fallible<FileDescriptor> {
|
||||
if handle == INVALID_HANDLE_VALUE || handle.is_null() {
|
||||
return Ok(FileDescriptor { handle: handle });
|
||||
}
|
||||
|
||||
let proc = unsafe { GetCurrentProcess() };
|
||||
let mut duped = INVALID_HANDLE_VALUE;
|
||||
let ok = unsafe {
|
||||
DuplicateHandle(
|
||||
proc,
|
||||
handle as *mut _,
|
||||
proc,
|
||||
&mut duped,
|
||||
0,
|
||||
0,
|
||||
winapi::um::winnt::DUPLICATE_SAME_ACCESS,
|
||||
)
|
||||
};
|
||||
if ok == 0 {
|
||||
Err(IoError::last_os_error().into())
|
||||
} else {
|
||||
Ok(FileDescriptor {
|
||||
handle: duped as *mut _,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dup<F: AsRawFileDescriptor>(f: F) -> Fallible<FileDescriptor> {
|
||||
dup_handle(f.as_raw_handle())
|
||||
}
|
||||
|
||||
impl FileDescriptor {
|
||||
pub fn new(handle: HANDLE) -> Self {
|
||||
Self { handle }
|
||||
}
|
||||
|
||||
pub fn try_clone(&self) -> Fallible<Self> {
|
||||
dup_handle(self.handle)
|
||||
}
|
||||
pub fn as_stdio(&self) -> Fallible<std::process::Stdio> {
|
||||
let duped = dup_handle(self.handle)?;
|
||||
let handle = duped.handle;
|
||||
let stdio = unsafe { std::process::Stdio::from_raw_handle(handle) };
|
||||
std::mem::forget(duped); // don't drop; stdio now owns it
|
||||
Ok(stdio)
|
||||
}
|
||||
pub fn pipe() -> Fallible<Pipes> {
|
||||
let mut read: HANDLE = INVALID_HANDLE_VALUE;
|
||||
let mut write: HANDLE = INVALID_HANDLE_VALUE;
|
||||
if unsafe { CreatePipe(&mut read, &mut write, ptr::null_mut(), 0) } == 0 {
|
||||
bail!("CreatePipe failed: {}", IoError::last_os_error());
|
||||
}
|
||||
Ok(Pipes {
|
||||
read: FileDescriptor { handle: read },
|
||||
write: FileDescriptor { handle: write },
|
||||
})
|
||||
}
|
||||
pub fn dup<F: AsRawFileDescriptor>(f: F) -> Fallible<Self> {
|
||||
dup(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl io::Read for FileDescriptor {
|
||||
fn read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error> {
|
||||
let mut num_read = 0;
|
||||
let ok = unsafe {
|
||||
ReadFile(
|
||||
self.handle as *mut _,
|
||||
buf.as_mut_ptr() as *mut _,
|
||||
buf.len() as u32,
|
||||
&mut num_read,
|
||||
ptr::null_mut(),
|
||||
)
|
||||
};
|
||||
if ok == 0 {
|
||||
Err(IoError::last_os_error())
|
||||
} else {
|
||||
Ok(num_read as usize)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl io::Write for FileDescriptor {
|
||||
fn write(&mut self, buf: &[u8]) -> Result<usize, io::Error> {
|
||||
let mut num_wrote = 0;
|
||||
let ok = unsafe {
|
||||
WriteFile(
|
||||
self.handle as *mut _,
|
||||
buf.as_ptr() as *const _,
|
||||
buf.len() as u32,
|
||||
&mut num_wrote,
|
||||
ptr::null_mut(),
|
||||
)
|
||||
};
|
||||
if ok == 0 {
|
||||
Err(IoError::last_os_error())
|
||||
} else {
|
||||
Ok(num_wrote as usize)
|
||||
}
|
||||
}
|
||||
fn flush(&mut self) -> Result<(), io::Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user