realpath: use uucore::fs::canonicalize()
Use the `uucore::fs::canonicalize()` function to simplify the
implementation of `realpath`.
extern crate uucore;
use clap::{App, Arg};
-use std::fs;
use std::path::{Path, PathBuf};
use uucore::fs::{canonicalize, CanonicalizeMode};
@@ -75,64 +74,35 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
let quiet = matches.is_present(OPT_QUIET);
let mut retcode = 0;
for path in &paths {
- if !resolve_path(path, strip, zero, quiet) {
+ if let Err(e) = resolve_path(path, strip, zero) {
+ if !quiet {
+ show_error!("{}: {}", e, path.display());
+ }
retcode = 1
};
}
retcode
}
-fn resolve_path(p: &Path, strip: bool, zero: bool, quiet: bool) -> bool {
- let abs = canonicalize(p, CanonicalizeMode::Normal).unwrap();
-
- if strip {
- if zero {
- print!("{}\0", p.display());
+/// Resolve a path to an absolute form and print it.
+///
+/// If `strip` is `true`, then this function does not attempt to resolve
+/// symbolic links in the path. If `zero` is `true`, then this function
+/// prints the path followed by the null byte (`'\0'`) instead of a
+/// newline character (`'\n'`).
+///
+/// # Errors
+///
+/// This function returns an error if there is a problem resolving
+/// symbolic links.
+fn resolve_path(p: &Path, strip: bool, zero: bool) -> std::io::Result<()> {
+ let mode = if strip {
+ CanonicalizeMode::None
} else {
- println!("{}", p.display())
- }
- return true;
- }
-
- let mut result = PathBuf::new();
- let mut links_left = 256;
-
- for part in abs.components() {
- result.push(part.as_os_str());
- loop {
- if links_left == 0 {
- if !quiet {
- show_error!("Too many symbolic links: {}", p.display())
- };
- return false;
- }
- match fs::metadata(result.as_path()) {
- Err(_) => break,
- Ok(ref m) if !m.file_type().is_symlink() => break,
- Ok(_) => {
- links_left -= 1;
- match fs::read_link(result.as_path()) {
- Ok(x) => {
- result.pop();
- result.push(x.as_path());
- }
- _ => {
- if !quiet {
- show_error!("Invalid path: {}", p.display())
+ CanonicalizeMode::Normal
};
- return false;
- }
- }
- }
- }
- }
- }
-
- if zero {
- print!("{}\0", result.display());
- } else {
- println!("{}", result.display());
- }
-
- true
+ let abs = canonicalize(p, mode)?;
+ let line_ending = if zero { '\0' } else { '\n' };
+ print!("{}{}", abs.display(), line_ending);
+ Ok(())
}
