mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-08-01 21:47:46 +00:00
Merge pull request #572 from jbcrail/fix-realpath-relpath
Fix realpath and relpath.
This commit is contained in:
commit
b8232eccab
2 changed files with 39 additions and 36 deletions
|
@ -1,5 +1,5 @@
|
|||
#![crate_name= "realpath"]
|
||||
#![feature(collections, core, old_io, os, old_path, rustc_private)]
|
||||
#![feature(file_type, path_ext, rustc_private)]
|
||||
|
||||
/*
|
||||
* This file is part of the uutils coreutils package.
|
||||
|
@ -13,7 +13,10 @@
|
|||
extern crate getopts;
|
||||
extern crate libc;
|
||||
|
||||
use getopts::{optflag, getopts, usage};
|
||||
use getopts::{getopts, optflag, usage};
|
||||
use std::fs::PathExt;
|
||||
use std::io::Write;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
#[path = "../common/util.rs"] #[macro_use] mod util;
|
||||
|
||||
|
@ -30,21 +33,21 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
optflag("q", "quiet", "Do not print warnings for invalid paths"),
|
||||
];
|
||||
|
||||
let opts = match getopts(args.tail(), &options) {
|
||||
let opts = match getopts(&args[1..], &options) {
|
||||
Ok(m) => m,
|
||||
Err(f) => {
|
||||
show_error!("{}", f);
|
||||
show_usage(program.as_slice(), &options);
|
||||
show_usage(program, &options);
|
||||
return 1
|
||||
}
|
||||
};
|
||||
|
||||
if opts.opt_present("V") { version(); return 0 }
|
||||
if opts.opt_present("h") { show_usage(program.as_slice(), &options); return 0 }
|
||||
if opts.opt_present("h") { show_usage(program, &options); return 0 }
|
||||
|
||||
if opts.free.len() == 0 {
|
||||
show_error!("Missing operand: FILENAME, at least one is required");
|
||||
println!("Try `{} --help` for more information.", program.as_slice());
|
||||
println!("Try `{} --help` for more information.", program);
|
||||
return 1
|
||||
}
|
||||
|
||||
|
@ -53,7 +56,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
let quiet = opts.opt_present("q");
|
||||
let mut retcode = 0;
|
||||
for path in opts.free.iter() {
|
||||
if !resolve_path(path.as_slice(), strip, zero, quiet) {
|
||||
if !resolve_path(path, strip, zero, quiet) {
|
||||
retcode = 1
|
||||
};
|
||||
}
|
||||
|
@ -61,8 +64,8 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
}
|
||||
|
||||
fn resolve_path(path: &str, strip: bool, zero: bool, quiet: bool) -> bool {
|
||||
let p = Path::new(path);
|
||||
let abs = std::os::make_absolute(&p).unwrap();
|
||||
let p = Path::new(path).to_path_buf();
|
||||
let abs = p.canonicalize().unwrap();
|
||||
|
||||
if strip {
|
||||
if zero {
|
||||
|
@ -73,29 +76,25 @@ fn resolve_path(path: &str, strip: bool, zero: bool, quiet: bool) -> bool {
|
|||
return true
|
||||
}
|
||||
|
||||
let mut result = match abs.root_path() {
|
||||
None => crash!(2, "Broken path parse! Report to developers: {}", path),
|
||||
Some(x) => x,
|
||||
};
|
||||
|
||||
let mut links_left = 256isize;
|
||||
let mut result = PathBuf::new();
|
||||
let mut links_left = 256;
|
||||
|
||||
for part in abs.components() {
|
||||
result.push(part);
|
||||
result.push(part.as_ref());
|
||||
loop {
|
||||
if links_left == 0 {
|
||||
if !quiet { show_error!("Too many symbolic links: {}", path) };
|
||||
return false
|
||||
}
|
||||
match std::old_io::fs::lstat(&result) {
|
||||
match result.as_path().metadata() {
|
||||
Err(_) => break,
|
||||
Ok(ref s) if s.kind != std::old_io::FileType::Symlink => break,
|
||||
Ok(ref m) if !m.file_type().is_symlink() => break,
|
||||
Ok(_) => {
|
||||
links_left -= 1;
|
||||
match std::old_io::fs::readlink(&result) {
|
||||
match result.as_path().read_link() {
|
||||
Ok(x) => {
|
||||
result.pop();
|
||||
result.push(x);
|
||||
result.push(x.as_path());
|
||||
},
|
||||
_ => {
|
||||
if !quiet {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#![crate_name = "relpath"]
|
||||
#![feature(collections, core, os, old_path, rustc_private)]
|
||||
#![feature(path_ext, rustc_private)]
|
||||
|
||||
/*
|
||||
* This file is part of the uutils coreutils package.
|
||||
|
@ -13,7 +13,11 @@
|
|||
extern crate getopts;
|
||||
extern crate libc;
|
||||
|
||||
use getopts::{optflag, optopt, getopts, usage};
|
||||
use getopts::{getopts, optflag, optopt, usage};
|
||||
use std::env;
|
||||
use std::fs::PathExt;
|
||||
use std::io::Write;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
#[path = "../common/util.rs"] #[macro_use] mod util;
|
||||
|
||||
|
@ -28,37 +32,37 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
optopt("d", "", "If any of FROM and TO is not subpath of DIR, output absolute path instead of relative", "DIR"),
|
||||
];
|
||||
|
||||
let opts = match getopts(args.tail(), &options) {
|
||||
let opts = match getopts(&args[1..], &options) {
|
||||
Ok(m) => m,
|
||||
Err(f) => {
|
||||
show_error!("{}", f);
|
||||
show_usage(program.as_slice(), &options);
|
||||
show_usage(program, &options);
|
||||
return 1
|
||||
}
|
||||
};
|
||||
|
||||
if opts.opt_present("V") { version(); return 0 }
|
||||
if opts.opt_present("h") { show_usage(program.as_slice(), &options); return 0 }
|
||||
if opts.opt_present("h") { show_usage(program, &options); return 0 }
|
||||
|
||||
if opts.free.len() == 0 {
|
||||
show_error!("Missing operand: TO");
|
||||
println!("Try `{} --help` for more information.", program.as_slice());
|
||||
println!("Try `{} --help` for more information.", program);
|
||||
return 1
|
||||
}
|
||||
|
||||
let to = Path::new(opts.free[0].as_slice());
|
||||
let to = Path::new(&opts.free[0]);
|
||||
let from = if opts.free.len() > 1 {
|
||||
Path::new(opts.free[1].as_slice())
|
||||
Path::new(&opts.free[1]).to_path_buf()
|
||||
} else {
|
||||
std::os::getcwd().unwrap()
|
||||
env::current_dir().unwrap()
|
||||
};
|
||||
let absto = std::os::make_absolute(&to).unwrap();
|
||||
let absfrom = std::os::make_absolute(&from).unwrap();
|
||||
let absto = to.canonicalize().unwrap();
|
||||
let absfrom = from.canonicalize().unwrap();
|
||||
|
||||
if opts.opt_present("d") {
|
||||
let base = Path::new(opts.opt_str("d").unwrap());
|
||||
let absbase = std::os::make_absolute(&base).unwrap();
|
||||
if !absbase.is_ancestor_of(&absto) || !absbase.is_ancestor_of(&absfrom) {
|
||||
let base = Path::new(&opts.opt_str("d").unwrap()).to_path_buf();
|
||||
let absbase = base.canonicalize().unwrap();
|
||||
if !absto.as_path().starts_with(absbase.as_path()) || !absfrom.as_path().starts_with(absbase.as_path()) {
|
||||
println!("{}", absto.display());
|
||||
return 0
|
||||
}
|
||||
|
@ -73,9 +77,9 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
}
|
||||
}
|
||||
|
||||
let mut result = Path::new("");
|
||||
let mut result = PathBuf::new();
|
||||
absfrom.components().skip(suffix_pos).map(|_| result.push("..")).last();
|
||||
absto.components().skip(suffix_pos).map(|x| result.push(x)).last();
|
||||
absto.components().skip(suffix_pos).map(|x| result.push(x.as_ref())).last();
|
||||
|
||||
println!("{}", result.display());
|
||||
0
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue