Skip to content

Commit 54177a6

Browse files
author
user0-07161
committed
feat, fix: make -n flag busybox-compatible, add dereferncing of symlinks in cross::fs
1 parent 95a5c3f commit 54177a6

File tree

2 files changed

+47
-18
lines changed

2 files changed

+47
-18
lines changed

coreutils/src/commands/ln.rs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use boxutils::args::ArgParser;
22
use boxutils::commands::Command;
33
use std::fs;
4-
use std::path::Path;
54

65
pub struct Ln;
76

@@ -17,6 +16,7 @@ impl Command for Ln {
1716
.add_option("-S")
1817
.parse_args("ln");
1918

19+
let mut dereference = true;
2020
let help = args.get_normal_args().len() != 2 || args.get_flag("--help");
2121
if help {
2222
println!("Usage: ln [-sfnbtv] [-S SUF] TARGET LINK");
@@ -31,7 +31,7 @@ impl Command for Ln {
3131
}
3232

3333
if args.get_flag("-f") {
34-
if fs::metadata(&destination).is_ok() {
34+
if fs::exists(&destination).unwrap() {
3535
if fs::metadata(&destination).unwrap().is_dir() {
3636
fs::remove_dir_all(&destination).unwrap();
3737
} else {
@@ -41,10 +41,7 @@ impl Command for Ln {
4141
}
4242

4343
if args.get_flag("-n") {
44-
if Path::new(&destination).exists() {
45-
println!("ln: {} exists, stopping...", destination);
46-
return;
47-
}
44+
dereference = false;
4845
}
4946

5047
if args.get_flag("-b") {
@@ -54,13 +51,13 @@ impl Command for Ln {
5451
}
5552

5653
if args.get_flag("-s") {
57-
let symlink_result = boxutils::cross::fs::symlink(to_be_linked, destination);
54+
let symlink_result = boxutils::cross::fs::symlink(to_be_linked, destination, dereference);
5855

5956
if let Err(e) = symlink_result {
6057
eprintln!("ln: failed to create symlink: {}", e);
6158
}
6259
} else {
63-
if let Err(e) = boxutils::cross::fs::hard_link(to_be_linked, destination) {
60+
if let Err(e) = boxutils::cross::fs::hard_link(to_be_linked, destination, dereference) {
6461
eprintln!("ln: failed to create hard link: {}", e);
6562
}
6663
}

utils/src/cross/fs.rs

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,56 @@ use std::os::unix::fs::symlink as unix_symlink;
55
#[cfg(windows)]
66
use std::os::windows::fs::{symlink_dir, symlink_file};
77

8+
fn deref(to_be_dereferenced: String) -> String {
9+
let mut metadata = fs::metadata(&to_be_dereferenced).unwrap();
10+
let file = &to_be_dereferenced;
11+
let mut new_file = file.clone();
12+
while metadata.is_symlink() {
13+
new_file = String::from(fs::read_link(new_file.to_string()).unwrap().into_os_string().into_string().unwrap());
14+
metadata = fs::metadata(&new_file).unwrap()
15+
}
16+
17+
new_file
18+
}
19+
820
#[cfg(windows)]
9-
pub fn symlink(to_be_linked: String, destination: String) -> std::io::Result<()> {
10-
let target_metadata = fs::metadata(&to_be_linked)?;
11-
if target_metadata.is_dir() {
12-
symlink_dir(&to_be_linked, &destination)
21+
pub fn symlink(to_be_linked: String, destination: String, dereference: bool) -> std::io::Result<()> {
22+
if !dereference {
23+
let target_metadata = fs::metadata(&to_be_linked)?;
24+
if target_metadata.is_dir() {
25+
symlink_dir(&to_be_linked, &destination)
26+
} else {
27+
symlink_file(&to_be_linked, &destination)
28+
}?;
1329
} else {
14-
symlink_file(&to_be_linked, &destination)
15-
}?;
30+
let dereferenced = deref(to_be_linked);
31+
let deref_metadata = fs::metadata(&to_be_linked)?;
32+
if deref_metadata.is_dir() {
33+
symlink_dir(&dereferenced, &destination)
34+
} else {
35+
symlink_file(&dereferenced, &destination)
36+
}?;
37+
}
1638
Ok(())
1739
}
1840

1941
#[cfg(unix)]
20-
pub fn symlink(to_be_linked: String, destination: String) -> std::io::Result<()> {
21-
unix_symlink(to_be_linked, destination)?;
42+
pub fn symlink(to_be_linked: String, destination: String, dereference: bool) -> std::io::Result<()> {
43+
if !dereference {
44+
unix_symlink(to_be_linked, destination)?;
45+
} else {
46+
let dereferenced = deref(to_be_linked);
47+
unix_symlink(dereferenced, destination)?;
48+
}
2249
Ok(())
2350
}
2451

25-
pub fn hard_link(to_be_linked: String, destination: String) -> std::io::Result<()> {
26-
fs::hard_link(to_be_linked, destination)?;
52+
pub fn hard_link(to_be_linked: String, destination: String, dereference: bool) -> std::io::Result<()> {
53+
if !dereference {
54+
fs::hard_link(to_be_linked, destination)?;
55+
} else {
56+
let dereferenced = deref(to_be_linked);
57+
fs::hard_link(dereferenced, destination)?;
58+
}
2759
Ok(())
2860
}

0 commit comments

Comments
 (0)