diff --git a/coreutils/src/commands/ln.rs b/coreutils/src/commands/ln.rs new file mode 100644 index 0000000..272e1ff --- /dev/null +++ b/coreutils/src/commands/ln.rs @@ -0,0 +1,114 @@ +use boxutils::args::ArgParser; +use boxutils::commands::Command; +use std::env; +use std::ops::Not; +use std::process::exit; + +pub struct Ln; + +impl Command for Ln { + fn execute(&self) { + let mut to_be_linked = String::from(""); + let mut destination = String::from(""); + let family = env::consts::FAMILY; + let args = ArgParser::builder() + .add_flag("-s") + .add_flag("-f") + .add_flag("-n") + .add_flag("-b") + .add_flag("-v") + .add_option("-S") + .parse_args("ln"); + fn help() { + println!("Lorem ipsum dolor sit amet."); + exit(1) + } + if args.get_normal_args().len() != 2 { + help(); + } else { + to_be_linked = args.get_normal_args()[0].clone(); + destination = args.get_normal_args()[1].clone(); + } + if ((family == "unix") || (family == "windows")).not() { + eprintln!("OS family is unknown: {}. Aborting.", family); + exit(1); + } + + #[cfg(unix)] + fn main(args: ArgParser, to_be_linked: String, destination: String) { + use std::os::unix; + use std::fs; + + if args.get_flag("-v"){ + println!("'{}' -> '{}'", to_be_linked, destination) + } + if args.get_flag("-f") { + if fs::metadata(String::from(&destination)).is_ok() { + if fs::metadata(String::from(&destination)).unwrap().is_dir() { + fs::remove_dir_all(String::from(&destination)).unwrap() + } else { + fs::remove_file(String::from(&destination)).unwrap() + } + } + } + + if args.get_flag("-b") { + let suffix = args.get_option("-S").unwrap_or("~"); + let new_filename = format!("{}{}", destination, suffix); + let _ = fs::rename(&destination, new_filename); + } + if args.get_flag("-s") { + if args.get_flag("-n") { + let _ = unix::fs::symlink(String::from(&to_be_linked), String::from(&destination)).unwrap(); + } else { + let mut metadata = fs::metadata(&to_be_linked).unwrap(); + let file = &to_be_linked; + 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() + } + let _ = unix::fs::symlink(String::from(new_file), String::from(&destination)).unwrap(); + } + exit(0) + } else { + if args.get_flag("-n") { + let _ = fs::hard_link(String::from(&to_be_linked), String::from(&destination)).unwrap(); + } else { + let mut metadata = fs::metadata(&to_be_linked).unwrap(); + let file = &to_be_linked; + 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() + } + let _ = fs::hard_link(String::from(&new_file), String::from(&destination)).unwrap(); + } + } + } + + #[cfg(windows)] + fn main(args: ArgParser, to_be_linked: String, destination: String) { + use std::os::windows; + use std::fs; + // TODO: basic code at line 77 + } + + let _ = main(args, to_be_linked, destination); + +// #[cfg(windows)] +// fn windows(to_be_linked: String, destination: String) { +// use std::os::windows; +// use std::fs; +// let attr = fs::metadata(args.get_normal_args()[0].clone()).unwrap(); +// if attr.is_dir() { +// let _ = windows::fs::symlink_dir(args.get_normal_args()[0].clone(), args.get_normal_args()[1].clone()); +// } else { +// let _ = windows::fs::symlink_file(args.get_normal_args()[0].clone(), args.get_normal_args()[1].clone()); +// } +// } +// #[cfg(windows)] +// windows(to_be_linked, destination); +// } + } +} diff --git a/coreutils/src/commands/mod.rs b/coreutils/src/commands/mod.rs index 9345846..ec0abcb 100644 --- a/coreutils/src/commands/mod.rs +++ b/coreutils/src/commands/mod.rs @@ -23,4 +23,5 @@ command!(tee::Tee); command!(base64::Base64); command!(base32::Base32); command!(seq::Seq); -command!(env::Env); \ No newline at end of file +command!(env::Env); +command!(ln::Ln); diff --git a/src/registry.rs b/src/registry.rs index 80bac2f..e7535a6 100644 --- a/src/registry.rs +++ b/src/registry.rs @@ -34,6 +34,7 @@ pub fn get_registry() -> CommandRegistry { "base32" => coreutils::commands::Base32, "seq" => coreutils::commands::Seq, "env" => coreutils::commands::Env, + "ln" => coreutils::commands::Ln, "box" => Boxcmd });