mirror of
https://github.com/uutils/coreutils.git
synced 2026-06-10 15:48:22 -07:00
Merge pull request #2563 from koutheir/master
chcon: reduce the number of unsafe blocks.
This commit is contained in:
Generated
+5
-5
@@ -713,9 +713,9 @@ checksum = "31a7a908b8f32538a2143e59a6e4e2508988832d5d4d6f7c156b3cbc762643a5"
|
||||
|
||||
[[package]]
|
||||
name = "filetime"
|
||||
version = "0.2.14"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d34cfa13a63ae058bfa601fe9e313bbdb3746427c1459185464ce0fcf62e1e8"
|
||||
checksum = "975ccf83d8d9d0d84682850a38c8169027be83368805971cc4f238c2b245bc98"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
@@ -1631,9 +1631,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "selinux"
|
||||
version = "0.1.3"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd525eeb189eb26c8471463186bba87644e3d8a9c7ae392adaf9ec45ede574bc"
|
||||
checksum = "1aa2f705dd871c2eb90888bb2d44b13218b34f5c7318c3971df62f799d0143eb"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"libc",
|
||||
@@ -2033,7 +2033,7 @@ dependencies = [
|
||||
"clap",
|
||||
"fts-sys",
|
||||
"libc",
|
||||
"selinux-sys",
|
||||
"selinux",
|
||||
"thiserror",
|
||||
"uucore",
|
||||
"uucore_procs",
|
||||
|
||||
+1
-1
@@ -241,7 +241,7 @@ clap = { version = "2.33", features = ["wrap_help"] }
|
||||
lazy_static = { version="1.3" }
|
||||
textwrap = { version="=0.11.0", features=["term_size"] } # !maint: [2020-05-10; rivy] unstable crate using undocumented features; pinned currently, will review
|
||||
uucore = { version=">=0.0.9", package="uucore", path="src/uucore" }
|
||||
selinux = { version="0.1.3", optional = true }
|
||||
selinux = { version="0.2.1", optional = true }
|
||||
# * uutils
|
||||
uu_test = { optional=true, version="0.0.7", package="uu_test", path="src/uu/test" }
|
||||
#
|
||||
|
||||
@@ -17,7 +17,7 @@ path = "src/chcon.rs"
|
||||
clap = { version = "2.33", features = ["wrap_help"] }
|
||||
uucore = { version = ">=0.0.9", package="uucore", path="../../uucore", features=["entries", "fs", "perms"] }
|
||||
uucore_procs = { version = ">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
||||
selinux-sys = { version = "0.5" }
|
||||
selinux = { version = "0.2" }
|
||||
fts-sys = { version = "0.2" }
|
||||
thiserror = { version = "1.0" }
|
||||
libc = { version = "0.2" }
|
||||
|
||||
+134
-563
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,71 @@
|
||||
use std::ffi::OsString;
|
||||
use std::fmt::Write;
|
||||
use std::io;
|
||||
|
||||
pub(crate) type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub(crate) enum Error {
|
||||
#[error("No context is specified")]
|
||||
MissingContext,
|
||||
|
||||
#[error("No files are specified")]
|
||||
MissingFiles,
|
||||
|
||||
#[error("{0}")]
|
||||
ArgumentsMismatch(String),
|
||||
|
||||
#[error(transparent)]
|
||||
CommandLine(#[from] clap::Error),
|
||||
|
||||
#[error("{operation} failed")]
|
||||
SELinux {
|
||||
operation: &'static str,
|
||||
source: selinux::errors::Error,
|
||||
},
|
||||
|
||||
#[error("{operation} failed")]
|
||||
Io {
|
||||
operation: &'static str,
|
||||
source: io::Error,
|
||||
},
|
||||
|
||||
#[error("{operation} failed on '{}'", .operand1.to_string_lossy())]
|
||||
Io1 {
|
||||
operation: &'static str,
|
||||
operand1: OsString,
|
||||
source: io::Error,
|
||||
},
|
||||
}
|
||||
|
||||
impl Error {
|
||||
pub(crate) fn from_io(operation: &'static str, source: io::Error) -> Self {
|
||||
Self::Io { operation, source }
|
||||
}
|
||||
|
||||
pub(crate) fn from_io1(
|
||||
operation: &'static str,
|
||||
operand1: impl Into<OsString>,
|
||||
source: io::Error,
|
||||
) -> Self {
|
||||
Self::Io1 {
|
||||
operation,
|
||||
operand1: operand1.into(),
|
||||
source,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn from_selinux(operation: &'static str, source: selinux::errors::Error) -> Self {
|
||||
Self::SELinux { operation, source }
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn report_full_error(mut err: &dyn std::error::Error) -> String {
|
||||
let mut desc = String::with_capacity(256);
|
||||
write!(&mut desc, "{}", err).unwrap();
|
||||
while let Some(source) = err.source() {
|
||||
err = source;
|
||||
write!(&mut desc, ". {}", err).unwrap();
|
||||
}
|
||||
desc
|
||||
}
|
||||
@@ -0,0 +1,193 @@
|
||||
use std::ffi::{CStr, CString, OsStr};
|
||||
use std::marker::PhantomData;
|
||||
use std::os::raw::{c_int, c_long, c_short};
|
||||
use std::path::Path;
|
||||
use std::ptr::NonNull;
|
||||
use std::{io, iter, ptr, slice};
|
||||
|
||||
use crate::errors::{Error, Result};
|
||||
use crate::os_str_to_c_string;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct FTS {
|
||||
fts: ptr::NonNull<fts_sys::FTS>,
|
||||
|
||||
entry: Option<ptr::NonNull<fts_sys::FTSENT>>,
|
||||
_phantom_data: PhantomData<fts_sys::FTSENT>,
|
||||
}
|
||||
|
||||
impl FTS {
|
||||
pub(crate) fn new<I>(paths: I, options: c_int) -> Result<Self>
|
||||
where
|
||||
I: IntoIterator,
|
||||
I::Item: AsRef<OsStr>,
|
||||
{
|
||||
let files_paths: Vec<CString> = paths
|
||||
.into_iter()
|
||||
.map(|s| os_str_to_c_string(s.as_ref()))
|
||||
.collect::<Result<_>>()?;
|
||||
|
||||
if files_paths.is_empty() {
|
||||
return Err(Error::from_io(
|
||||
"FTS::new()",
|
||||
io::ErrorKind::InvalidInput.into(),
|
||||
));
|
||||
}
|
||||
|
||||
let path_argv: Vec<_> = files_paths
|
||||
.iter()
|
||||
.map(CString::as_ref)
|
||||
.map(CStr::as_ptr)
|
||||
.chain(iter::once(ptr::null()))
|
||||
.collect();
|
||||
|
||||
// SAFETY: We assume calling fts_open() is safe:
|
||||
// - `path_argv` is an array holding at least one path, and null-terminated.
|
||||
// - `compar` is None.
|
||||
let fts = unsafe { fts_sys::fts_open(path_argv.as_ptr().cast(), options, None) };
|
||||
|
||||
let fts = ptr::NonNull::new(fts)
|
||||
.ok_or_else(|| Error::from_io("fts_open()", io::Error::last_os_error()))?;
|
||||
|
||||
Ok(Self {
|
||||
fts,
|
||||
entry: None,
|
||||
_phantom_data: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn last_entry_ref(&mut self) -> Option<EntryRef> {
|
||||
self.entry.map(move |entry| EntryRef::new(self, entry))
|
||||
}
|
||||
|
||||
pub(crate) fn read_next_entry(&mut self) -> Result<bool> {
|
||||
// SAFETY: We assume calling fts_read() is safe with a non-null `fts`
|
||||
// pointer assumed to be valid.
|
||||
let new_entry = unsafe { fts_sys::fts_read(self.fts.as_ptr()) };
|
||||
|
||||
self.entry = NonNull::new(new_entry);
|
||||
if self.entry.is_none() {
|
||||
let r = io::Error::last_os_error();
|
||||
if let Some(0) = r.raw_os_error() {
|
||||
Ok(false)
|
||||
} else {
|
||||
Err(Error::from_io("fts_read()", r))
|
||||
}
|
||||
} else {
|
||||
Ok(true)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn set(&mut self, instr: c_int) -> Result<()> {
|
||||
let fts = self.fts.as_ptr();
|
||||
let entry = self
|
||||
.entry
|
||||
.ok_or_else(|| Error::from_io("FTS::set()", io::ErrorKind::UnexpectedEof.into()))?;
|
||||
|
||||
// SAFETY: We assume calling fts_set() is safe with non-null `fts`
|
||||
// and `entry` pointers assumed to be valid.
|
||||
if unsafe { fts_sys::fts_set(fts, entry.as_ptr(), instr) } == -1 {
|
||||
Err(Error::from_io("fts_set()", io::Error::last_os_error()))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for FTS {
|
||||
fn drop(&mut self) {
|
||||
// SAFETY: We assume calling fts_close() is safe with a non-null `fts`
|
||||
// pointer assumed to be valid.
|
||||
unsafe { fts_sys::fts_close(self.fts.as_ptr()) };
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct EntryRef<'fts> {
|
||||
pub(crate) pointer: ptr::NonNull<fts_sys::FTSENT>,
|
||||
|
||||
_fts: PhantomData<&'fts FTS>,
|
||||
_phantom_data: PhantomData<fts_sys::FTSENT>,
|
||||
}
|
||||
|
||||
impl<'fts> EntryRef<'fts> {
|
||||
fn new(_fts: &'fts FTS, entry: ptr::NonNull<fts_sys::FTSENT>) -> Self {
|
||||
Self {
|
||||
pointer: entry,
|
||||
_fts: PhantomData,
|
||||
_phantom_data: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
fn as_ref(&self) -> &fts_sys::FTSENT {
|
||||
// SAFETY: `self.pointer` is a non-null pointer that is assumed to be valid.
|
||||
unsafe { self.pointer.as_ref() }
|
||||
}
|
||||
|
||||
fn as_mut(&mut self) -> &mut fts_sys::FTSENT {
|
||||
// SAFETY: `self.pointer` is a non-null pointer that is assumed to be valid.
|
||||
unsafe { self.pointer.as_mut() }
|
||||
}
|
||||
|
||||
pub(crate) fn flags(&self) -> c_int {
|
||||
c_int::from(self.as_ref().fts_info)
|
||||
}
|
||||
|
||||
pub(crate) fn errno(&self) -> c_int {
|
||||
self.as_ref().fts_errno
|
||||
}
|
||||
|
||||
pub(crate) fn level(&self) -> c_short {
|
||||
self.as_ref().fts_level
|
||||
}
|
||||
|
||||
pub(crate) fn number(&self) -> c_long {
|
||||
self.as_ref().fts_number
|
||||
}
|
||||
|
||||
pub(crate) fn set_number(&mut self, new_number: c_long) {
|
||||
self.as_mut().fts_number = new_number;
|
||||
}
|
||||
|
||||
pub(crate) fn path(&self) -> Option<&Path> {
|
||||
let entry = self.as_ref();
|
||||
if entry.fts_pathlen == 0 {
|
||||
return None;
|
||||
}
|
||||
|
||||
NonNull::new(entry.fts_path)
|
||||
.map(|path_ptr| {
|
||||
let path_size = usize::from(entry.fts_pathlen).saturating_add(1);
|
||||
|
||||
// SAFETY: `entry.fts_path` is a non-null pointer that is assumed to be valid.
|
||||
unsafe { slice::from_raw_parts(path_ptr.as_ptr().cast(), path_size) }
|
||||
})
|
||||
.and_then(|bytes| CStr::from_bytes_with_nul(bytes).ok())
|
||||
.map(c_str_to_os_str)
|
||||
.map(Path::new)
|
||||
}
|
||||
|
||||
pub(crate) fn access_path(&self) -> Option<&Path> {
|
||||
ptr::NonNull::new(self.as_ref().fts_accpath)
|
||||
.map(|path_ptr| {
|
||||
// SAFETY: `entry.fts_accpath` is a non-null pointer that is assumed to be valid.
|
||||
unsafe { CStr::from_ptr(path_ptr.as_ptr()) }
|
||||
})
|
||||
.map(c_str_to_os_str)
|
||||
.map(Path::new)
|
||||
}
|
||||
|
||||
pub(crate) fn stat(&self) -> Option<&libc::stat> {
|
||||
ptr::NonNull::new(self.as_ref().fts_statp).map(|stat_ptr| {
|
||||
// SAFETY: `entry.fts_statp` is a non-null pointer that is assumed to be valid.
|
||||
unsafe { stat_ptr.as_ref() }
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn c_str_to_os_str(s: &CStr) -> &OsStr {
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
|
||||
OsStr::from_bytes(s.to_bytes())
|
||||
}
|
||||
@@ -18,7 +18,7 @@ path = "src/id.rs"
|
||||
clap = { version = "2.33", features = ["wrap_help"] }
|
||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore", features=["entries", "process"] }
|
||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
||||
selinux = { version="0.1.3", optional = true }
|
||||
selinux = { version="0.2.1", optional = true }
|
||||
|
||||
[[bin]]
|
||||
name = "id"
|
||||
|
||||
@@ -40,8 +40,6 @@
|
||||
extern crate uucore;
|
||||
|
||||
use clap::{crate_version, App, Arg};
|
||||
#[cfg(all(target_os = "linux", feature = "selinux"))]
|
||||
use selinux;
|
||||
use std::ffi::CStr;
|
||||
use uucore::entries::{self, Group, Locate, Passwd};
|
||||
use uucore::error::UResult;
|
||||
|
||||
Reference in New Issue
Block a user