Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion src/uu/chroot/src/chroot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,14 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
.status()
{
Ok(status) => status,
Err(e) => return Err(ChrootError::CommandFailed(command[0].to_string(), e).into()),
Err(e) => {
return Err(if e.kind() == std::io::ErrorKind::NotFound {
ChrootError::CommandNotFound(command[0].to_string(), e)
} else {
ChrootError::CommandFailed(command[0].to_string(), e)
}
.into())
}
};

let code = if pstatus.success() {
Expand Down
12 changes: 9 additions & 3 deletions src/uu/chroot/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ pub enum ChrootError {
/// Failed to execute the specified command.
CommandFailed(String, Error),

/// Failed to find the specified command.
CommandNotFound(String, Error),

/// The given user and group specification was invalid.
InvalidUserspec(String),

Expand All @@ -43,20 +46,23 @@ pub enum ChrootError {
impl std::error::Error for ChrootError {}

impl UError for ChrootError {
// TODO: Exit status:
// 125 if chroot itself fails
// 126 if command is found but cannot be invoked
// 127 if command cannot be found
fn code(&self) -> i32 {
1
match self {
Self::CommandFailed(_, _) => 126,
Self::CommandNotFound(_, _) => 127,
_ => 125,
}
}
}

impl Display for ChrootError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Self::CannotEnter(s, e) => write!(f, "cannot chroot to {}: {}", s.quote(), e,),
Self::CommandFailed(s, e) => {
Self::CommandFailed(s, e) | Self::CommandNotFound(s, e) => {
write!(f, "failed to run command {}: {}", s.to_string().quote(), e,)
}
Self::InvalidUserspec(s) => write!(f, "invalid userspec: {}", s.quote(),),
Expand Down
15 changes: 10 additions & 5 deletions tests/by-util/test_chroot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ fn test_invalid_arg() {

#[test]
fn test_missing_operand() {
let result = new_ucmd!().run();
let result = new_ucmd!().fails();

result.code_is(125);

assert!(result
.stderr_str()
Expand All @@ -27,7 +29,7 @@ fn test_enter_chroot_fails() {
at.mkdir("jail");

let result = ucmd.arg("jail").fails();

result.code_is(125);
assert!(result
.stderr_str()
.starts_with("chroot: cannot chroot to 'jail': Operation not permitted (os error 1)"));
Expand All @@ -41,7 +43,8 @@ fn test_no_such_directory() {

ucmd.arg("a")
.fails()
.stderr_is("chroot: cannot change root directory to 'a': no such directory");
.stderr_is("chroot: cannot change root directory to 'a': no such directory")
.code_is(125);
}

#[test]
Expand All @@ -51,7 +54,7 @@ fn test_invalid_user_spec() {
at.mkdir("a");

let result = ucmd.arg("a").arg("--userspec=ARABA:").fails();

result.code_is(125);
assert!(result.stderr_str().starts_with("chroot: invalid userspec"));
}

Expand Down Expand Up @@ -91,7 +94,9 @@ fn test_preference_of_userspec() {
.arg("-G")
.arg("ABC,DEF")
.arg(format!("--userspec={}:{}", username, group_name))
.run();
.fails();

result.code_is(125);

println!("result.stdout = {}", result.stdout_str());
println!("result.stderr = {}", result.stderr_str());
Expand Down