Skip to content

Commit e08252c

Browse files
committed
Use nix for more things
1 parent 3f1fb9d commit e08252c

File tree

6 files changed

+118
-222
lines changed

6 files changed

+118
-222
lines changed

Cargo.lock

Lines changed: 22 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ insta = "1.14.0"
3737
itertools = "0.10.3"
3838
libc = "0.2.133"
3939
log = "0.4.16"
40-
nix = "0.24"
40+
nix = "0.26"
4141
num-complex = "0.4.0"
4242
num-bigint = "0.4.3"
4343
num-integer = "0.1.44"

stdlib/src/posixsubprocess.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,8 @@ fn exec_inner(args: &ForkExecArgs, procargs: ProcArgs) -> nix::Result<Never> {
177177

178178
let mut first_err = None;
179179
for exec in args.exec_list.as_slice() {
180+
// not using nix's versions of these functions because those allocate the char-ptr array,
181+
// and we can't allocate
180182
if let Some(envp) = procargs.envp {
181183
unsafe { libc::execve(exec.s.as_ptr(), procargs.argv.as_ptr(), envp.as_ptr()) };
182184
} else {
@@ -195,9 +197,8 @@ fn close_fds(above: i32, keep: &[i32]) -> nix::Result<()> {
195197
use nix::{dir::Dir, fcntl::OFlag};
196198
// TODO: close fds by brute force if readdir doesn't work:
197199
// https://github.com/python/cpython/blob/3.8/Modules/_posixsubprocess.c#L220
198-
let path = unsafe { CStr::from_bytes_with_nul_unchecked(FD_DIR_NAME) };
199200
let mut dir = Dir::open(
200-
path,
201+
FD_DIR_NAME,
201202
OFlag::O_RDONLY | OFlag::O_DIRECTORY,
202203
nix::sys::stat::Mode::empty(),
203204
)?;
@@ -219,10 +220,10 @@ fn close_fds(above: i32, keep: &[i32]) -> nix::Result<()> {
219220
target_os = "openbsd",
220221
target_vendor = "apple",
221222
))]
222-
const FD_DIR_NAME: &[u8] = b"/dev/fd\0";
223+
const FD_DIR_NAME: &CStr = unsafe { CStr::from_bytes_with_nul_unchecked(b"/dev/fd\0") };
223224

224225
#[cfg(any(target_os = "linux", target_os = "android"))]
225-
const FD_DIR_NAME: &[u8] = b"/proc/self/fd\0";
226+
const FD_DIR_NAME: &CStr = unsafe { CStr::from_bytes_with_nul_unchecked(b"/proc/self/fd\0") };
226227

227228
#[cfg(not(target_os = "redox"))]
228229
fn pos_int_from_ascii(name: &CStr) -> Option<i32> {

stdlib/src/socket.rs

Lines changed: 26 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -891,53 +891,8 @@ mod _socket {
891891
use std::os::unix::ffi::OsStrExt;
892892
let buf = crate::vm::function::ArgStrOrBytesLike::try_from_object(vm, addr)?;
893893
let path = &*buf.borrow_bytes();
894-
if cfg!(any(target_os = "linux", target_os = "android"))
895-
&& path.first() == Some(&0)
896-
{
897-
use libc::{sa_family_t, socklen_t};
898-
use {socket2::SockAddr, std::ptr};
899-
unsafe {
900-
// based on SockAddr::unix
901-
// TODO: upstream or fix socklen check for SockAddr::unix()?
902-
SockAddr::init(|storage, len| {
903-
// Safety: `SockAddr::init` zeros the address, which is a valid
904-
// representation.
905-
let storage: &mut libc::sockaddr_un = &mut *storage.cast();
906-
let len: &mut socklen_t = &mut *len;
907-
908-
let bytes = path;
909-
if bytes.len() > storage.sun_path.len() {
910-
return Err(io::Error::new(
911-
io::ErrorKind::InvalidInput,
912-
"path must be shorter than SUN_LEN",
913-
));
914-
}
915-
916-
storage.sun_family = libc::AF_UNIX as sa_family_t;
917-
// Safety: `bytes` and `addr.sun_path` are not overlapping and
918-
// both point to valid memory.
919-
// `SockAddr::init` zeroes the memory, so the path is already
920-
// null terminated.
921-
ptr::copy_nonoverlapping(
922-
bytes.as_ptr(),
923-
storage.sun_path.as_mut_ptr() as *mut u8,
924-
bytes.len(),
925-
);
926-
927-
let base = storage as *const _ as usize;
928-
let path = &storage.sun_path as *const _ as usize;
929-
let sun_path_offset = path - base;
930-
let length = sun_path_offset + bytes.len();
931-
*len = length as socklen_t;
932-
933-
Ok(())
934-
})
935-
}
936-
.map(|(_, addr)| addr)
937-
} else {
938-
socket2::SockAddr::unix(ffi::OsStr::from_bytes(path))
939-
}
940-
.map_err(|_| vm.new_os_error("AF_UNIX path too long".to_owned()).into())
894+
socket2::SockAddr::unix(ffi::OsStr::from_bytes(path))
895+
.map_err(|_| vm.new_os_error("AF_UNIX path too long".to_owned()).into())
941896
}
942897
c::AF_INET => {
943898
let tuple: PyTupleRef = addr.downcast().map_err(|obj| {
@@ -1087,20 +1042,7 @@ mod _socket {
10871042
_ => {}
10881043
}
10891044
if socket_kind == -1 {
1090-
// TODO: when socket2 cuts a new release, type will be available on all os
1091-
// socket_kind = sock.r#type().map_err(|e| e.into_pyexception(vm))?.into();
1092-
let res = unsafe {
1093-
c::getsockopt(
1094-
sock_fileno(&sock) as _,
1095-
c::SOL_SOCKET,
1096-
c::SO_TYPE,
1097-
&mut socket_kind as *mut libc::c_int as *mut _,
1098-
&mut (std::mem::size_of::<i32>() as _),
1099-
)
1100-
};
1101-
if res < 0 {
1102-
return Err(crate::common::os::errno().into());
1103-
}
1045+
socket_kind = sock.r#type().map_err(|e| e.into_pyexception(vm))?.into();
11041046
}
11051047
cfg_if::cfg_if! {
11061048
if #[cfg(any(
@@ -1601,30 +1543,23 @@ mod _socket {
16011543
if let Some(addr) = addr.as_socket() {
16021544
return get_ip_addr_tuple(&addr, vm);
16031545
}
1604-
match addr.family() as i32 {
1605-
#[cfg(unix)]
1606-
libc::AF_UNIX => {
1607-
let addr_len = addr.len() as usize;
1608-
let unix_addr = unsafe { &*(addr.as_ptr() as *const libc::sockaddr_un) };
1609-
let path_u8 = unsafe { &*(&unix_addr.sun_path[..] as *const [_] as *const [u8]) };
1610-
let sun_path_offset =
1611-
&unix_addr.sun_path as *const _ as usize - unix_addr as *const _ as usize;
1612-
if cfg!(any(target_os = "linux", target_os = "android"))
1613-
&& addr_len > sun_path_offset
1614-
&& unix_addr.sun_path[0] == 0
1615-
{
1616-
let abstractaddrlen = addr_len - sun_path_offset;
1617-
let abstractpath = &path_u8[..abstractaddrlen];
1618-
vm.ctx.new_bytes(abstractpath.to_vec()).into()
1619-
} else {
1620-
let len = memchr::memchr(b'\0', path_u8).unwrap_or(path_u8.len());
1621-
let path = &path_u8[..len];
1622-
vm.ctx.new_str(String::from_utf8_lossy(path)).into()
1623-
}
1546+
#[cfg(unix)]
1547+
use nix::sys::socket::{SockaddrLike, UnixAddr};
1548+
#[cfg(unix)]
1549+
if let Some(unix_addr) = unsafe { UnixAddr::from_raw(addr.as_ptr(), Some(addr.len())) } {
1550+
use std::os::unix::ffi::OsStrExt;
1551+
#[cfg(any(target_os = "android", target_os = "linux"))]
1552+
if let Some(abstractpath) = unix_addr.as_abstract() {
1553+
return vm.ctx.new_bytes([b"\0", abstractpath].concat()).into();
16241554
}
1625-
// TODO: support more address families
1626-
_ => (String::new(), 0).to_pyobject(vm),
1555+
// necessary on macos
1556+
let path = ffi::OsStr::as_bytes(unix_addr.path().unwrap_or("".as_ref()).as_ref());
1557+
let nul_pos = memchr::memchr(b'\0', path).unwrap_or(path.len());
1558+
let path = ffi::OsStr::from_bytes(&path[..nul_pos]);
1559+
return vm.ctx.new_str(path.to_string_lossy()).into();
16271560
}
1561+
// TODO: support more address families
1562+
(String::new(), 0).to_pyobject(vm)
16281563
}
16291564

16301565
#[pyfunction]
@@ -1764,25 +1699,19 @@ mod _socket {
17641699
let fd = sock_fileno(sock);
17651700
#[cfg(unix)]
17661701
{
1767-
let mut pollfd = libc::pollfd {
1768-
fd,
1769-
events: match kind {
1770-
SelectKind::Read => libc::POLLIN,
1771-
SelectKind::Write => libc::POLLOUT,
1772-
SelectKind::Connect => libc::POLLOUT | libc::POLLERR,
1773-
},
1774-
revents: 0,
1702+
use nix::poll::*;
1703+
let events = match kind {
1704+
SelectKind::Read => PollFlags::POLLIN,
1705+
SelectKind::Write => PollFlags::POLLOUT,
1706+
SelectKind::Connect => PollFlags::POLLOUT | PollFlags::POLLERR,
17751707
};
1708+
let mut pollfd = [PollFd::new(fd, events)];
17761709
let timeout = match interval {
17771710
Some(d) => d.as_millis() as _,
17781711
None => -1,
17791712
};
1780-
let ret = unsafe { libc::poll(&mut pollfd, 1, timeout) };
1781-
if ret < 0 {
1782-
Err(io::Error::last_os_error())
1783-
} else {
1784-
Ok(ret == 0)
1785-
}
1713+
let ret = poll(&mut pollfd, timeout)?;
1714+
Ok(ret == 0)
17861715
}
17871716
#[cfg(windows)]
17881717
{

vm/src/stdlib/posix.rs

Lines changed: 15 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1091,13 +1091,9 @@ pub mod module {
10911091

10921092
#[pyfunction]
10931093
fn ttyname(fd: i32, vm: &VirtualMachine) -> PyResult {
1094-
let name = unsafe { libc::ttyname(fd) };
1095-
if name.is_null() {
1096-
Err(errno_err(vm))
1097-
} else {
1098-
let name = unsafe { CStr::from_ptr(name) }.to_str().unwrap();
1099-
Ok(vm.ctx.new_str(name).into())
1100-
}
1094+
let name = unistd::ttyname(fd).map_err(|e| e.into_pyexception(vm))?;
1095+
let name = name.into_os_string().into_string().unwrap();
1096+
Ok(vm.ctx.new_str(name).into())
11011097
}
11021098

11031099
#[pyfunction]
@@ -1129,30 +1125,24 @@ pub mod module {
11291125
#[cfg(any(target_os = "android", target_os = "linux", target_os = "openbsd"))]
11301126
#[pyfunction]
11311127
fn getresuid(vm: &VirtualMachine) -> PyResult<(u32, u32, u32)> {
1132-
let mut ruid = 0;
1133-
let mut euid = 0;
1134-
let mut suid = 0;
1135-
let ret = unsafe { libc::getresuid(&mut ruid, &mut euid, &mut suid) };
1136-
if ret == 0 {
1137-
Ok((ruid, euid, suid))
1138-
} else {
1139-
Err(errno_err(vm))
1140-
}
1128+
let ret = unistd::getresuid().map_err(|e| e.into_pyexception(vm))?;
1129+
Ok((
1130+
ret.real.as_raw(),
1131+
ret.effective.as_raw(),
1132+
ret.saved.as_raw(),
1133+
))
11411134
}
11421135

11431136
// cfg from nix
11441137
#[cfg(any(target_os = "android", target_os = "linux", target_os = "openbsd"))]
11451138
#[pyfunction]
11461139
fn getresgid(vm: &VirtualMachine) -> PyResult<(u32, u32, u32)> {
1147-
let mut rgid = 0;
1148-
let mut egid = 0;
1149-
let mut sgid = 0;
1150-
let ret = unsafe { libc::getresgid(&mut rgid, &mut egid, &mut sgid) };
1151-
if ret == 0 {
1152-
Ok((rgid, egid, sgid))
1153-
} else {
1154-
Err(errno_err(vm))
1155-
}
1140+
let ret = unistd::getresgid().map_err(|e| e.into_pyexception(vm))?;
1141+
Ok((
1142+
ret.real.as_raw(),
1143+
ret.effective.as_raw(),
1144+
ret.saved.as_raw(),
1145+
))
11561146
}
11571147

11581148
// cfg from nix

0 commit comments

Comments
 (0)