Skip to content

Commit 5c97c1c

Browse files
authored
Merge pull request #2678 from blyxxyz/io-error-detect-os
Do not discard non-OS error messages
2 parents 1cfed70 + 1edd2bf commit 5c97c1c

File tree

4 files changed

+64
-35
lines changed

4 files changed

+64
-35
lines changed

.vscode/cspell.dictionaries/jargon.wordlist.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ gibi
4343
gibibytes
4444
glob
4545
globbing
46+
hardcode
47+
hardcoded
48+
hardcoding
4649
hardfloat
4750
hardlink
4851
hardlinks

src/uu/install/src/install.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -490,11 +490,10 @@ fn copy_files_into_dir(files: &[PathBuf], target_dir: &Path, b: &Behavior) -> UR
490490
return Err(InstallError::TargetDirIsntDir(target_dir.to_path_buf()).into());
491491
}
492492
for sourcepath in files.iter() {
493-
if !sourcepath.exists() {
494-
let err = UIoError::new(
495-
std::io::ErrorKind::NotFound,
496-
format!("cannot stat {}", sourcepath.quote()),
497-
);
493+
if let Err(err) = sourcepath
494+
.metadata()
495+
.map_err_context(|| format!("cannot stat {}", sourcepath.quote()))
496+
{
498497
show!(err);
499498
continue;
500499
}

src/uu/ls/src/ls.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ use std::{
4242
use term_grid::{Cell, Direction, Filling, Grid, GridOptions};
4343
use uucore::{
4444
display::Quotable,
45-
error::{set_exit_code, FromIo, UError, UResult},
45+
error::{set_exit_code, UError, UResult},
4646
};
4747

4848
use unicode_width::UnicodeWidthStr;
@@ -1257,8 +1257,13 @@ fn list(locs: Vec<&Path>, config: Config) -> UResult<()> {
12571257
let path_data = PathData::new(p, None, None, &config, true);
12581258

12591259
if path_data.md().is_none() {
1260-
show!(std::io::ErrorKind::NotFound
1261-
.map_err_context(|| format!("cannot access {}", path_data.p_buf.quote())));
1260+
// FIXME: Would be nice to use the actual error instead of hardcoding it
1261+
// Presumably other errors can happen too?
1262+
show_error!(
1263+
"cannot access {}: No such file or directory",
1264+
path_data.p_buf.quote()
1265+
);
1266+
set_exit_code(1);
12621267
// We found an error, no need to continue the execution
12631268
continue;
12641269
}

src/uucore/src/lib/mods/error.rs

Lines changed: 49 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -393,42 +393,64 @@ impl Display for UIoError {
393393
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
394394
use std::io::ErrorKind::*;
395395

396-
let message;
397-
let message = match self.inner.kind() {
398-
NotFound => "No such file or directory",
399-
PermissionDenied => "Permission denied",
400-
ConnectionRefused => "Connection refused",
401-
ConnectionReset => "Connection reset",
402-
ConnectionAborted => "Connection aborted",
403-
NotConnected => "Not connected",
404-
AddrInUse => "Address in use",
405-
AddrNotAvailable => "Address not available",
406-
BrokenPipe => "Broken pipe",
407-
AlreadyExists => "Already exists",
408-
WouldBlock => "Would block",
409-
InvalidInput => "Invalid input",
410-
InvalidData => "Invalid data",
411-
TimedOut => "Timed out",
412-
WriteZero => "Write zero",
413-
Interrupted => "Interrupted",
414-
UnexpectedEof => "Unexpected end of file",
415-
_ => {
416-
// TODO: using `strip_errno()` causes the error message
417-
// to not be capitalized. When the new error variants (https://github.com/rust-lang/rust/issues/86442)
418-
// are stabilized, we should add them to the match statement.
419-
message = strip_errno(&self.inner);
420-
&message
396+
let mut message;
397+
let message = if self.inner.raw_os_error().is_some() {
398+
// These are errors that come directly from the OS.
399+
// We want to normalize their messages across systems,
400+
// and we want to strip the "(os error X)" suffix.
401+
match self.inner.kind() {
402+
NotFound => "No such file or directory",
403+
PermissionDenied => "Permission denied",
404+
ConnectionRefused => "Connection refused",
405+
ConnectionReset => "Connection reset",
406+
ConnectionAborted => "Connection aborted",
407+
NotConnected => "Not connected",
408+
AddrInUse => "Address in use",
409+
AddrNotAvailable => "Address not available",
410+
BrokenPipe => "Broken pipe",
411+
AlreadyExists => "Already exists",
412+
WouldBlock => "Would block",
413+
InvalidInput => "Invalid input",
414+
InvalidData => "Invalid data",
415+
TimedOut => "Timed out",
416+
WriteZero => "Write zero",
417+
Interrupted => "Interrupted",
418+
UnexpectedEof => "Unexpected end of file",
419+
_ => {
420+
// TODO: When the new error variants
421+
// (https://github.com/rust-lang/rust/issues/86442)
422+
// are stabilized, we should add them to the match statement.
423+
message = strip_errno(&self.inner);
424+
capitalize(&mut message);
425+
&message
426+
}
421427
}
428+
} else {
429+
// These messages don't need as much normalization, and the above
430+
// messages wouldn't always be a good substitute.
431+
// For example, ErrorKind::NotFound doesn't necessarily mean it was
432+
// a file that was not found.
433+
// There are also errors with entirely custom messages.
434+
message = self.inner.to_string();
435+
capitalize(&mut message);
436+
&message
422437
};
423-
write!(f, "{}: {}", self.context, message,)
438+
write!(f, "{}: {}", self.context, message)
439+
}
440+
}
441+
442+
/// Capitalize the first character of an ASCII string.
443+
fn capitalize(text: &mut str) {
444+
if let Some(first) = text.get_mut(..1) {
445+
first.make_ascii_uppercase();
424446
}
425447
}
426448

427449
/// Strip the trailing " (os error XX)" from io error strings.
428450
pub fn strip_errno(err: &std::io::Error) -> String {
429451
let mut msg = err.to_string();
430452
if let Some(pos) = msg.find(" (os error ") {
431-
msg.drain(pos..);
453+
msg.truncate(pos);
432454
}
433455
msg
434456
}

0 commit comments

Comments
 (0)