Make pointers NonNull after error check

This commit is contained in:
topjohnwu 2025-04-14 13:31:52 -07:00 committed by John Wu
parent f063fa5054
commit 30e79310ab
3 changed files with 39 additions and 28 deletions

View File

@ -178,9 +178,7 @@ impl Directory {
pub fn open(path: &Utf8CStr) -> OsResult<Directory> { pub fn open(path: &Utf8CStr) -> OsResult<Directory> {
let dirp = unsafe { libc::opendir(path.as_ptr()) }; let dirp = unsafe { libc::opendir(path.as_ptr()) };
let dirp = dirp.as_os_result("opendir", Some(path), None)?; let dirp = dirp.as_os_result("opendir", Some(path), None)?;
Ok(Directory { Ok(Directory { inner: dirp })
inner: unsafe { NonNull::new_unchecked(dirp) },
})
} }
pub fn read(&mut self) -> OsResult<'static, Option<DirEntry>> { pub fn read(&mut self) -> OsResult<'static, Option<DirEntry>> {
@ -424,9 +422,7 @@ impl TryFrom<OwnedFd> for Directory {
fn try_from(fd: OwnedFd) -> OsResult<'static, Self> { fn try_from(fd: OwnedFd) -> OsResult<'static, Self> {
let dirp = unsafe { libc::fdopendir(fd.into_raw_fd()) }; let dirp = unsafe { libc::fdopendir(fd.into_raw_fd()) };
let dirp = dirp.as_os_result("fdopendir", None, None)?; let dirp = dirp.as_os_result("fdopendir", None, None)?;
Ok(Directory { Ok(Directory { inner: dirp })
inner: unsafe { NonNull::new_unchecked(dirp) },
})
} }
} }

View File

@ -2,6 +2,7 @@ use crate::logging::Formatter;
use crate::{LogLevel, errno, log_with_args, log_with_formatter}; use crate::{LogLevel, errno, log_with_args, log_with_formatter};
use std::fmt::Display; use std::fmt::Display;
use std::panic::Location; use std::panic::Location;
use std::ptr::NonNull;
use std::{fmt, io}; use std::{fmt, io};
use thiserror::Error; use thiserror::Error;
@ -206,18 +207,21 @@ pub trait LibcReturn
where where
Self: Copy, Self: Copy,
{ {
type Value;
fn is_error(&self) -> bool; fn is_error(&self) -> bool;
fn map_val(self) -> Self::Value;
fn as_os_result<'a>( fn as_os_result<'a>(
self, self,
name: &'static str, name: &'static str,
arg1: Option<&'a str>, arg1: Option<&'a str>,
arg2: Option<&'a str>, arg2: Option<&'a str>,
) -> OsResult<'a, Self> { ) -> OsResult<'a, Self::Value> {
if self.is_error() { if self.is_error() {
Err(OsError::last_os_error(name, arg1, arg2)) Err(OsError::last_os_error(name, arg1, arg2))
} else { } else {
Ok(self) Ok(self.map_val())
} }
} }
@ -227,8 +231,11 @@ where
arg1: Option<&'a str>, arg1: Option<&'a str>,
arg2: Option<&'a str>, arg2: Option<&'a str>,
) -> OsResult<'a, ()> { ) -> OsResult<'a, ()> {
self.as_os_result(name, arg1, arg2)?; if self.is_error() {
Ok(()) Err(OsError::last_os_error(name, arg1, arg2))
} else {
Ok(())
}
} }
fn check_io_err(self) -> io::Result<()> { fn check_io_err(self) -> io::Result<()> {
@ -243,27 +250,35 @@ where
macro_rules! impl_libc_return { macro_rules! impl_libc_return {
($($t:ty)*) => ($( ($($t:ty)*) => ($(
impl LibcReturn for $t { impl LibcReturn for $t {
#[inline] type Value = Self;
#[inline(always)]
fn is_error(&self) -> bool { fn is_error(&self) -> bool {
*self < 0 *self < 0
} }
#[inline(always)]
fn map_val(self) -> Self::Value {
self
}
} }
)*) )*)
} }
impl_libc_return! { i8 i16 i32 i64 isize } impl_libc_return! { i8 i16 i32 i64 isize }
impl<T> LibcReturn for *const T { impl<T> LibcReturn for *mut T {
#[inline] type Value = NonNull<T>;
#[inline(always)]
fn is_error(&self) -> bool { fn is_error(&self) -> bool {
self.is_null() self.is_null()
} }
}
impl<T> LibcReturn for *mut T { #[inline(always)]
#[inline] fn map_val(self) -> NonNull<T> {
fn is_error(&self) -> bool { // SAFETY: pointer is null checked by is_error
self.is_null() unsafe { NonNull::new_unchecked(self.cast()) }
} }
} }

View File

@ -1,5 +1,10 @@
// Functions in this file are only for exporting to C++, DO NOT USE IN RUST // Functions in this file are only for exporting to C++, DO NOT USE IN RUST
use crate::cxx_extern::readlinkat;
use crate::{
CxxResultExt, Directory, FsPath, LibcReturn, Utf8CStr, cstr_buf, slice_from_ptr,
slice_from_ptr_mut,
};
use libc::{ use libc::{
c_char, c_uint, c_ulong, c_void, dev_t, mode_t, nfds_t, off_t, pollfd, sockaddr, socklen_t, c_char, c_uint, c_ulong, c_void, dev_t, mode_t, nfds_t, off_t, pollfd, sockaddr, socklen_t,
}; };
@ -10,12 +15,7 @@ use std::mem::ManuallyDrop;
use std::os::fd::FromRawFd; use std::os::fd::FromRawFd;
use std::os::unix::io::RawFd; use std::os::unix::io::RawFd;
use std::ptr; use std::ptr;
use std::ptr::NonNull;
use crate::cxx_extern::readlinkat;
use crate::{
CxxResultExt, Directory, FsPath, LibcReturn, Utf8CStr, cstr_buf, slice_from_ptr,
slice_from_ptr_mut,
};
fn ptr_to_str<'a>(ptr: *const c_char) -> Option<&'a str> { fn ptr_to_str<'a>(ptr: *const c_char) -> Option<&'a str> {
if ptr.is_null() { if ptr.is_null() {
@ -78,7 +78,7 @@ unsafe extern "C" fn xfopen(path: *const c_char, mode: *const c_char) -> *mut li
libc::fopen(path, mode) libc::fopen(path, mode)
.as_os_result("fopen", ptr_to_str(path), None) .as_os_result("fopen", ptr_to_str(path), None)
.log_cxx() .log_cxx()
.unwrap_or(ptr::null_mut()) .map_or(ptr::null_mut(), NonNull::as_ptr)
} }
} }
@ -88,7 +88,7 @@ unsafe extern "C" fn xfdopen(fd: RawFd, mode: *const c_char) -> *mut libc::FILE
libc::fdopen(fd, mode) libc::fdopen(fd, mode)
.as_os_result("fdopen", None, None) .as_os_result("fdopen", None, None)
.log_cxx() .log_cxx()
.unwrap_or(ptr::null_mut()) .map_or(ptr::null_mut(), NonNull::as_ptr)
} }
} }
@ -175,7 +175,7 @@ unsafe extern "C" fn xopendir(path: *const c_char) -> *mut libc::DIR {
libc::opendir(path) libc::opendir(path)
.as_os_result("opendir", ptr_to_str(path), None) .as_os_result("opendir", ptr_to_str(path), None)
.log_cxx() .log_cxx()
.unwrap_or(ptr::null_mut()) .map_or(ptr::null_mut(), NonNull::as_ptr)
} }
} }
@ -185,7 +185,7 @@ extern "C" fn xfdopendir(fd: RawFd) -> *mut libc::DIR {
libc::fdopendir(fd) libc::fdopendir(fd)
.as_os_result("fdopendir", None, None) .as_os_result("fdopendir", None, None)
.log_cxx() .log_cxx()
.unwrap_or(ptr::null_mut()) .map_or(ptr::null_mut(), NonNull::as_ptr)
} }
} }