mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-08-02 14:07: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"]
|
#![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.
|
* This file is part of the uutils coreutils package.
|
||||||
|
@ -13,7 +13,10 @@
|
||||||
extern crate getopts;
|
extern crate getopts;
|
||||||
extern crate libc;
|
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;
|
#[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"),
|
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,
|
Ok(m) => m,
|
||||||
Err(f) => {
|
Err(f) => {
|
||||||
show_error!("{}", f);
|
show_error!("{}", f);
|
||||||
show_usage(program.as_slice(), &options);
|
show_usage(program, &options);
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if opts.opt_present("V") { version(); return 0 }
|
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 {
|
if opts.free.len() == 0 {
|
||||||
show_error!("Missing operand: FILENAME, at least one is required");
|
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
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +56,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
||||||
let quiet = opts.opt_present("q");
|
let quiet = opts.opt_present("q");
|
||||||
let mut retcode = 0;
|
let mut retcode = 0;
|
||||||
for path in opts.free.iter() {
|
for path in opts.free.iter() {
|
||||||
if !resolve_path(path.as_slice(), strip, zero, quiet) {
|
if !resolve_path(path, strip, zero, quiet) {
|
||||||
retcode = 1
|
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 {
|
fn resolve_path(path: &str, strip: bool, zero: bool, quiet: bool) -> bool {
|
||||||
let p = Path::new(path);
|
let p = Path::new(path).to_path_buf();
|
||||||
let abs = std::os::make_absolute(&p).unwrap();
|
let abs = p.canonicalize().unwrap();
|
||||||
|
|
||||||
if strip {
|
if strip {
|
||||||
if zero {
|
if zero {
|
||||||
|
@ -73,29 +76,25 @@ fn resolve_path(path: &str, strip: bool, zero: bool, quiet: bool) -> bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut result = match abs.root_path() {
|
let mut result = PathBuf::new();
|
||||||
None => crash!(2, "Broken path parse! Report to developers: {}", path),
|
let mut links_left = 256;
|
||||||
Some(x) => x,
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut links_left = 256isize;
|
|
||||||
|
|
||||||
for part in abs.components() {
|
for part in abs.components() {
|
||||||
result.push(part);
|
result.push(part.as_ref());
|
||||||
loop {
|
loop {
|
||||||
if links_left == 0 {
|
if links_left == 0 {
|
||||||
if !quiet { show_error!("Too many symbolic links: {}", path) };
|
if !quiet { show_error!("Too many symbolic links: {}", path) };
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
match std::old_io::fs::lstat(&result) {
|
match result.as_path().metadata() {
|
||||||
Err(_) => break,
|
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(_) => {
|
Ok(_) => {
|
||||||
links_left -= 1;
|
links_left -= 1;
|
||||||
match std::old_io::fs::readlink(&result) {
|
match result.as_path().read_link() {
|
||||||
Ok(x) => {
|
Ok(x) => {
|
||||||
result.pop();
|
result.pop();
|
||||||
result.push(x);
|
result.push(x.as_path());
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
if !quiet {
|
if !quiet {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#![crate_name = "relpath"]
|
#![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.
|
* This file is part of the uutils coreutils package.
|
||||||
|
@ -13,7 +13,11 @@
|
||||||
extern crate getopts;
|
extern crate getopts;
|
||||||
extern crate libc;
|
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;
|
#[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"),
|
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,
|
Ok(m) => m,
|
||||||
Err(f) => {
|
Err(f) => {
|
||||||
show_error!("{}", f);
|
show_error!("{}", f);
|
||||||
show_usage(program.as_slice(), &options);
|
show_usage(program, &options);
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if opts.opt_present("V") { version(); return 0 }
|
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 {
|
if opts.free.len() == 0 {
|
||||||
show_error!("Missing operand: TO");
|
show_error!("Missing operand: TO");
|
||||||
println!("Try `{} --help` for more information.", program.as_slice());
|
println!("Try `{} --help` for more information.", program);
|
||||||
return 1
|
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 {
|
let from = if opts.free.len() > 1 {
|
||||||
Path::new(opts.free[1].as_slice())
|
Path::new(&opts.free[1]).to_path_buf()
|
||||||
} else {
|
} else {
|
||||||
std::os::getcwd().unwrap()
|
env::current_dir().unwrap()
|
||||||
};
|
};
|
||||||
let absto = std::os::make_absolute(&to).unwrap();
|
let absto = to.canonicalize().unwrap();
|
||||||
let absfrom = std::os::make_absolute(&from).unwrap();
|
let absfrom = from.canonicalize().unwrap();
|
||||||
|
|
||||||
if opts.opt_present("d") {
|
if opts.opt_present("d") {
|
||||||
let base = Path::new(opts.opt_str("d").unwrap());
|
let base = Path::new(&opts.opt_str("d").unwrap()).to_path_buf();
|
||||||
let absbase = std::os::make_absolute(&base).unwrap();
|
let absbase = base.canonicalize().unwrap();
|
||||||
if !absbase.is_ancestor_of(&absto) || !absbase.is_ancestor_of(&absfrom) {
|
if !absto.as_path().starts_with(absbase.as_path()) || !absfrom.as_path().starts_with(absbase.as_path()) {
|
||||||
println!("{}", absto.display());
|
println!("{}", absto.display());
|
||||||
return 0
|
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();
|
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());
|
println!("{}", result.display());
|
||||||
0
|
0
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue