1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-31 04:57:45 +00:00

Merge branch 'main' into cp-lb

This commit is contained in:
Sylvestre Ledru 2022-03-04 20:39:23 +01:00 committed by GitHub
commit 8df4f0bb4d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 74 additions and 15 deletions

View file

@ -495,10 +495,15 @@ jobs:
# - { os: ubuntu-latest , target: x86_64-unknown-linux-gnu , features: feat_selinux , use-cross: use-cross } # - { os: ubuntu-latest , target: x86_64-unknown-linux-gnu , features: feat_selinux , use-cross: use-cross }
# - { os: ubuntu-18.04 , target: i586-unknown-linux-gnu , features: feat_os_unix , use-cross: use-cross } ## note: older windows platform; not required, dev-FYI only # - { os: ubuntu-18.04 , target: i586-unknown-linux-gnu , features: feat_os_unix , use-cross: use-cross } ## note: older windows platform; not required, dev-FYI only
# - { os: ubuntu-18.04 , target: i586-unknown-linux-gnu , features: feat_os_unix , use-cross: use-cross } ## note: older windows platform; not required, dev-FYI only # - { os: ubuntu-18.04 , target: i586-unknown-linux-gnu , features: feat_os_unix , use-cross: use-cross } ## note: older windows platform; not required, dev-FYI only
- { os: ubuntu-18.04 , target: i686-unknown-linux-gnu , features: feat_os_unix , use-cross: use-cross } - { os: ubuntu-latest , target: i686-unknown-linux-gnu , features: feat_os_unix , use-cross: use-cross }
- { os: ubuntu-18.04 , target: i686-unknown-linux-musl , features: feat_os_unix_musl , use-cross: use-cross } - { os: ubuntu-latest , target: i686-unknown-linux-musl , features: feat_os_unix_musl , use-cross: use-cross }
- { os: ubuntu-18.04 , target: x86_64-unknown-linux-gnu , features: feat_os_unix , use-cross: use-cross } - { os: ubuntu-latest , target: x86_64-unknown-linux-gnu , features: feat_os_unix , use-cross: use-cross }
- { os: ubuntu-18.04 , target: x86_64-unknown-linux-musl , features: feat_os_unix_musl , use-cross: use-cross } - { os: ubuntu-latest , target: x86_64-unknown-linux-musl , features: feat_os_unix_musl , use-cross: use-cross }
# Commented until https://github.com/uutils/coreutils/issues/3210 is fixed
#- { os: ubuntu-18.04 , target: i686-unknown-linux-gnu , features: feat_os_unix , use-cross: use-cross }
#- { os: ubuntu-18.04 , target: i686-unknown-linux-musl , features: feat_os_unix_musl , use-cross: use-cross }
#- { os: ubuntu-18.04 , target: x86_64-unknown-linux-gnu , features: feat_os_unix , use-cross: use-cross }
#- { os: ubuntu-18.04 , target: x86_64-unknown-linux-musl , features: feat_os_unix_musl , use-cross: use-cross }
- { os: macos-latest , target: x86_64-apple-darwin , features: feat_os_macos } - { os: macos-latest , target: x86_64-apple-darwin , features: feat_os_macos }
- { os: windows-latest , target: i686-pc-windows-gnu , features: feat_os_windows } - { os: windows-latest , target: i686-pc-windows-gnu , features: feat_os_windows }
- { os: windows-latest , target: i686-pc-windows-msvc , features: feat_os_windows } - { os: windows-latest , target: i686-pc-windows-msvc , features: feat_os_windows }

View file

@ -223,15 +223,17 @@ pub fn normalize_path(path: &Path) -> PathBuf {
ret ret
} }
fn resolve<P: AsRef<Path>>(original: P) -> Result<PathBuf, (PathBuf, IOError)> { fn resolve<P: AsRef<Path>>(original: P) -> Result<PathBuf, (bool, PathBuf, IOError)> {
const MAX_LINKS_FOLLOWED: u32 = 255; const MAX_LINKS_FOLLOWED: u32 = 255;
let mut followed = 0; let mut followed = 0;
let mut result = original.as_ref().to_path_buf(); let mut result = original.as_ref().to_path_buf();
let mut symlink_is_absolute = false;
let mut first_resolution = None; let mut first_resolution = None;
loop { loop {
if followed == MAX_LINKS_FOLLOWED { if followed == MAX_LINKS_FOLLOWED {
return Err(( return Err((
symlink_is_absolute,
// When we hit MAX_LINKS_FOLLOWED we should return the first resolution (that's what GNU does - for whatever reason) // When we hit MAX_LINKS_FOLLOWED we should return the first resolution (that's what GNU does - for whatever reason)
first_resolution.unwrap(), first_resolution.unwrap(),
Error::new(ErrorKind::InvalidInput, "maximum links followed"), Error::new(ErrorKind::InvalidInput, "maximum links followed"),
@ -244,16 +246,17 @@ fn resolve<P: AsRef<Path>>(original: P) -> Result<PathBuf, (PathBuf, IOError)> {
break; break;
} }
} }
Err(e) => return Err((result, e)), Err(e) => return Err((symlink_is_absolute, result, e)),
} }
followed += 1; followed += 1;
match fs::read_link(&result) { match fs::read_link(&result) {
Ok(path) => { Ok(path) => {
result.pop(); result.pop();
symlink_is_absolute = path.is_absolute();
result.push(path); result.push(path);
} }
Err(e) => return Err((result, e)), Err(e) => return Err((symlink_is_absolute, result, e)),
} }
if first_resolution.is_none() { if first_resolution.is_none() {
@ -343,8 +346,13 @@ pub fn canonicalize<P: AsRef<Path>>(
} }
match resolve(&result) { match resolve(&result) {
Err((path, _)) if miss_mode == MissingHandling::Missing => result = path, Err((_, path, e)) => {
Err((_, e)) => return Err(e), if miss_mode == MissingHandling::Missing {
result = path;
} else {
return Err(e);
}
}
Ok(path) => { Ok(path) => {
result = path; result = path;
} }
@ -358,10 +366,20 @@ pub fn canonicalize<P: AsRef<Path>>(
} }
match resolve(&result) { match resolve(&result) {
Err((_, e)) if miss_mode == MissingHandling::Existing => { Err((is_absolute, path, err)) => {
return Err(e); // If the resolved symlink is an absolute path and non-existent,
// `realpath` throws no such file error.
if miss_mode == MissingHandling::Existing
|| (err.kind() == ErrorKind::NotFound
&& is_absolute
&& miss_mode == MissingHandling::Normal)
{
return Err(err);
} else {
result = path;
}
} }
Ok(path) | Err((path, _)) => { Ok(path) => {
result = path; result = path;
} }
} }

View file

@ -149,8 +149,8 @@ fn test_realpath_dangling() {
let (at, mut ucmd) = at_and_ucmd!(); let (at, mut ucmd) = at_and_ucmd!();
at.symlink_file("nonexistent-file", "link"); at.symlink_file("nonexistent-file", "link");
ucmd.arg("link") ucmd.arg("link")
.succeeds() .fails()
.stdout_only(at.plus_as_string("nonexistent-file\n")); .stderr_contains("realpath: link: No such file or directory");
} }
#[test] #[test]
@ -202,3 +202,34 @@ fn test_realpath_missing() {
.succeeds() .succeeds()
.stdout_only(expect); .stdout_only(expect);
} }
#[test]
fn test_realpath_when_symlink_is_absolute_and_enoent() {
let (at, mut ucmd) = at_and_ucmd!();
at.mkdir("dir2");
at.touch("dir2/bar");
at.mkdir("dir1");
at.symlink_file("dir2/bar", "dir1/foo1");
at.symlink_file("/dir2/bar", "dir1/foo2");
at.relative_symlink_file("dir2/baz", at.plus("dir1/foo3").to_str().unwrap());
#[cfg(unix)]
ucmd.arg("dir1/foo1")
.arg("dir1/foo2")
.arg("dir1/foo3")
.run()
.stdout_contains("/dir2/bar\n")
.stdout_contains("/dir2/baz\n")
.stderr_is("realpath: dir1/foo2: No such file or directory");
#[cfg(windows)]
ucmd.arg("dir1/foo1")
.arg("dir1/foo2")
.arg("dir1/foo3")
.run()
.stdout_contains("\\dir2\\bar\n")
.stdout_contains("\\dir2\\baz\n")
.stderr_is("realpath: dir1/foo2: No such file or directory");
}

View file

@ -701,6 +701,11 @@ impl AtPath {
symlink_file(&self.plus(original), &self.plus(link)).unwrap(); symlink_file(&self.plus(original), &self.plus(link)).unwrap();
} }
pub fn relative_symlink_file(&self, original: &str, link: &str) {
log_info("symlink", &format!("{},{}", original, link));
symlink_file(original, link).unwrap();
}
pub fn symlink_dir(&self, original: &str, link: &str) { pub fn symlink_dir(&self, original: &str, link: &str) {
log_info( log_info(
"symlink", "symlink",