mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 03:27:44 +00:00
Merge pull request #2252 from jfinkels/realpath-simplify
realpath: use uucore::fs::canonicalize() to reduce code duplication
This commit is contained in:
commit
73fb426b2b
2 changed files with 54 additions and 54 deletions
|
@ -11,7 +11,6 @@
|
||||||
extern crate uucore;
|
extern crate uucore;
|
||||||
|
|
||||||
use clap::{App, Arg};
|
use clap::{App, Arg};
|
||||||
use std::fs;
|
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use uucore::fs::{canonicalize, CanonicalizeMode};
|
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 quiet = matches.is_present(OPT_QUIET);
|
||||||
let mut retcode = 0;
|
let mut retcode = 0;
|
||||||
for path in &paths {
|
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 = 1
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
retcode
|
retcode
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_path(p: &Path, strip: bool, zero: bool, quiet: bool) -> bool {
|
/// Resolve a path to an absolute form and print it.
|
||||||
let abs = canonicalize(p, CanonicalizeMode::Normal).unwrap();
|
///
|
||||||
|
/// If `strip` is `true`, then this function does not attempt to resolve
|
||||||
if strip {
|
/// symbolic links in the path. If `zero` is `true`, then this function
|
||||||
if zero {
|
/// prints the path followed by the null byte (`'\0'`) instead of a
|
||||||
print!("{}\0", p.display());
|
/// 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 {
|
} else {
|
||||||
println!("{}", p.display())
|
CanonicalizeMode::Normal
|
||||||
}
|
|
||||||
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;
|
let abs = canonicalize(p, mode)?;
|
||||||
}
|
let line_ending = if zero { '\0' } else { '\n' };
|
||||||
match fs::metadata(result.as_path()) {
|
print!("{}{}", abs.display(), line_ending);
|
||||||
Err(_) => break,
|
Ok(())
|
||||||
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())
|
|
||||||
};
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if zero {
|
|
||||||
print!("{}\0", result.display());
|
|
||||||
} else {
|
|
||||||
println!("{}", result.display());
|
|
||||||
}
|
|
||||||
|
|
||||||
true
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,11 +54,19 @@ pub fn resolve_relative_path(path: &Path) -> Cow<Path> {
|
||||||
result.into()
|
result.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Controls how symbolic links should be handled when canonicalizing a path.
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
pub enum CanonicalizeMode {
|
pub enum CanonicalizeMode {
|
||||||
|
/// Do not resolve any symbolic links.
|
||||||
None,
|
None,
|
||||||
|
|
||||||
|
/// Resolve all symbolic links.
|
||||||
Normal,
|
Normal,
|
||||||
|
|
||||||
|
/// Resolve symbolic links, ignoring errors on the final component.
|
||||||
Existing,
|
Existing,
|
||||||
|
|
||||||
|
/// Resolve symbolic links, ignoring errors on the non-final components.
|
||||||
Missing,
|
Missing,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,6 +133,24 @@ fn resolve<P: AsRef<Path>>(original: P) -> IOResult<PathBuf> {
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return the canonical, absolute form of a path.
|
||||||
|
///
|
||||||
|
/// This function is a generalization of [`std::fs::canonicalize`] that
|
||||||
|
/// allows controlling how symbolic links are resolved and how to deal
|
||||||
|
/// with missing components. It returns the canonical, absolute form of
|
||||||
|
/// a path. The `can_mode` parameter controls how symbolic links are
|
||||||
|
/// resolved:
|
||||||
|
///
|
||||||
|
/// * [`CanonicalizeMode::Normal`] makes this function behave like
|
||||||
|
/// [`std::fs::canonicalize`], resolving symbolic links and returning
|
||||||
|
/// an error if the path does not exist.
|
||||||
|
/// * [`CanonicalizeMode::Missing`] makes this function ignore non-final
|
||||||
|
/// components of the path that could not be resolved.
|
||||||
|
/// * [`CanonicalizeMode::Existing`] makes this function return an error
|
||||||
|
/// if the final component of the path does not exist.
|
||||||
|
/// * [`CanonicalizeMode::None`] makes this function not try to resolve
|
||||||
|
/// any symbolic links.
|
||||||
|
///
|
||||||
pub fn canonicalize<P: AsRef<Path>>(original: P, can_mode: CanonicalizeMode) -> IOResult<PathBuf> {
|
pub fn canonicalize<P: AsRef<Path>>(original: P, can_mode: CanonicalizeMode) -> IOResult<PathBuf> {
|
||||||
// Create an absolute path
|
// Create an absolute path
|
||||||
let original = original.as_ref();
|
let original = original.as_ref();
|
||||||
|
@ -180,6 +206,10 @@ pub fn canonicalize<P: AsRef<Path>>(original: P, can_mode: CanonicalizeMode) ->
|
||||||
|
|
||||||
result.push(parts.last().unwrap());
|
result.push(parts.last().unwrap());
|
||||||
|
|
||||||
|
if can_mode == CanonicalizeMode::None {
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
match resolve(&result) {
|
match resolve(&result) {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
if can_mode == CanonicalizeMode::Existing {
|
if can_mode == CanonicalizeMode::Existing {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue