feat, fix: make -n flag busybox-compatible, add dereferncing of symlinks in cross::fs

This commit is contained in:
user0-07161 2025-03-30 11:43:39 +02:00
parent 95a5c3f565
commit 900f84f7ec
2 changed files with 47 additions and 18 deletions

View file

@ -1,7 +1,6 @@
use boxutils::args::ArgParser;
use boxutils::commands::Command;
use std::fs;
use std::path::Path;
pub struct Ln;
@ -17,6 +16,7 @@ impl Command for Ln {
.add_option("-S")
.parse_args("ln");
let mut dereference = true;
let help = args.get_normal_args().len() != 2 || args.get_flag("--help");
if help {
println!("Usage: ln [-sfnbtv] [-S SUF] TARGET LINK");
@ -31,7 +31,7 @@ impl Command for Ln {
}
if args.get_flag("-f") {
if fs::metadata(&destination).is_ok() {
if fs::exists(&destination).unwrap() {
if fs::metadata(&destination).unwrap().is_dir() {
fs::remove_dir_all(&destination).unwrap();
} else {
@ -41,10 +41,7 @@ impl Command for Ln {
}
if args.get_flag("-n") {
if Path::new(&destination).exists() {
println!("ln: {} exists, stopping...", destination);
return;
}
dereference = false;
}
if args.get_flag("-b") {
@ -54,13 +51,13 @@ impl Command for Ln {
}
if args.get_flag("-s") {
let symlink_result = boxutils::cross::fs::symlink(to_be_linked, destination);
let symlink_result = boxutils::cross::fs::symlink(to_be_linked, destination, dereference);
if let Err(e) = symlink_result {
eprintln!("ln: failed to create symlink: {}", e);
}
} else {
if let Err(e) = boxutils::cross::fs::hard_link(to_be_linked, destination) {
if let Err(e) = boxutils::cross::fs::hard_link(to_be_linked, destination, dereference) {
eprintln!("ln: failed to create hard link: {}", e);
}
}

View file

@ -5,24 +5,56 @@ use std::os::unix::fs::symlink as unix_symlink;
#[cfg(windows)]
use std::os::windows::fs::{symlink_dir, symlink_file};
fn deref(to_be_dereferenced: String) -> String {
let mut metadata = fs::metadata(&to_be_dereferenced).unwrap();
let file = &to_be_dereferenced;
let mut new_file = file.clone();
while metadata.is_symlink() {
new_file = String::from(fs::read_link(new_file.to_string()).unwrap().into_os_string().into_string().unwrap());
metadata = fs::metadata(&new_file).unwrap()
}
new_file
}
#[cfg(windows)]
pub fn symlink(to_be_linked: String, destination: String) -> std::io::Result<()> {
pub fn symlink(to_be_linked: String, destination: String, dereference: bool) -> std::io::Result<()> {
if !dereference {
let target_metadata = fs::metadata(&to_be_linked)?;
if target_metadata.is_dir() {
symlink_dir(&to_be_linked, &destination)
} else {
symlink_file(&to_be_linked, &destination)
}?;
} else {
let dereferenced = deref(to_be_linked.clone());
let deref_metadata = fs::metadata(&dereferenced)?;
if deref_metadata.is_dir() {
symlink_dir(&dereferenced, &destination)
} else {
symlink_file(&dereferenced, &destination)
}?;
}
Ok(())
}
#[cfg(unix)]
pub fn symlink(to_be_linked: String, destination: String) -> std::io::Result<()> {
pub fn symlink(to_be_linked: String, destination: String, dereference: bool) -> std::io::Result<()> {
if !dereference {
unix_symlink(to_be_linked, destination)?;
} else {
let dereferenced = deref(to_be_linked);
unix_symlink(dereferenced, destination)?;
}
Ok(())
}
pub fn hard_link(to_be_linked: String, destination: String) -> std::io::Result<()> {
pub fn hard_link(to_be_linked: String, destination: String, dereference: bool) -> std::io::Result<()> {
if !dereference {
fs::hard_link(to_be_linked, destination)?;
} else {
let dereferenced = deref(to_be_linked);
fs::hard_link(dereferenced, destination)?;
}
Ok(())
}