diff --git a/Cargo.lock b/Cargo.lock index 55121ae..999754c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -65,18 +65,72 @@ version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +[[package]] +name = "bindgen" +version = "0.59.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bd2a9a458e8f4304c52c43ebb0cfbd520289f8379a52e329a38afda99bf8eb8" +dependencies = [ + "bitflags 1.3.2", + "cexpr", + "clang-sys", + "lazy_static", + "lazycell", + "peeking_take_while", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "bitflags" version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "clang-sys" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f" +dependencies = [ + "glob", + "libc", + "libloading", +] + [[package]] name = "clap" version = "4.4.7" @@ -118,7 +172,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn", + "syn 2.0.39", ] [[package]] @@ -146,6 +200,40 @@ dependencies = [ "windows-sys 0.45.0", ] +[[package]] +name = "dialoguer" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "658bce805d770f407bc62102fca7c2c64ceef2fbcb2b8bd19d2765ce093980de" +dependencies = [ + "console", + "shell-words", + "tempfile", + "thiserror", + "zeroize", +] + +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + [[package]] name = "encode_unicode" version = "0.3.6" @@ -165,6 +253,17 @@ dependencies = [ "termcolor", ] +[[package]] +name = "errno" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" +dependencies = [ + "errno-dragonfly", + "libc", + "winapi", +] + [[package]] name = "errno" version = "0.3.7" @@ -175,6 +274,39 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "fastrand" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" + +[[package]] +name = "getrandom" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + [[package]] name = "heck" version = "0.4.1" @@ -206,11 +338,15 @@ dependencies = [ "anyhow", "clap", "clap-verbosity-flag", + "dialoguer", + "dirs", "env_logger", "hound", "hydrophonitor-lib", "indicatif", + "lazy_static", "log", + "sys-mount", "walkdir", ] @@ -219,9 +355,12 @@ name = "hydrophonitor-lib" version = "0.1.0" dependencies = [ "anyhow", + "dirs", "hound", "indicatif", + "lazy_static", "log", + "sys-mount", "walkdir", ] @@ -264,12 +403,39 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "libc" version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + +[[package]] +name = "libredox" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +dependencies = [ + "bitflags 2.4.1", + "libc", + "redox_syscall", +] + [[package]] name = "linux-raw-sys" version = "0.4.11" @@ -282,18 +448,69 @@ version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +[[package]] +name = "loopdev" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bfa0855b04611e38acaff718542e9e809cddfc16535d39f9d9c694ab19f7388" +dependencies = [ + "bindgen", + "errno 0.2.8", + "libc", +] + [[package]] name = "memchr" version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "number_prefix" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + [[package]] name = "portable-atomic" version = "1.5.1" @@ -318,6 +535,26 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_users" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + [[package]] name = "regex" version = "1.10.2" @@ -347,14 +584,20 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustix" version = "0.38.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e" dependencies = [ - "bitflags", - "errno", + "bitflags 2.4.1", + "errno 0.3.7", "libc", "linux-raw-sys", "windows-sys 0.48.0", @@ -369,12 +612,46 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "shell-words" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" + +[[package]] +name = "shlex" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" + +[[package]] +name = "smart-default" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "133659a15339456eeeb07572eb02a91c91e9815e9cbc89566944d2c8d3efdbf6" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "strsim" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "syn" version = "2.0.39" @@ -386,6 +663,33 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sys-mount" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab6b8b397ed1fa2364625189a004d532b5d58f772943c57aa144feb1966142bd" +dependencies = [ + "bitflags 1.3.2", + "libc", + "loopdev", + "smart-default", + "thiserror", + "tracing", +] + +[[package]] +name = "tempfile" +version = "3.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" +dependencies = [ + "cfg-if", + "fastrand", + "redox_syscall", + "rustix", + "windows-sys 0.48.0", +] + [[package]] name = "termcolor" version = "1.4.0" @@ -395,6 +699,57 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "thiserror" +version = "1.0.51" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f11c217e1416d6f036b870f14e0413d480dbf28edbee1f877abaf0206af43bb7" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.51" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01742297787513b79cf8e29d1056ede1313e2420b7b3b15d0a768b4921f549df" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + [[package]] name = "unicode-ident" version = "1.0.12" @@ -423,6 +778,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + [[package]] name = "winapi" version = "0.3.9" @@ -651,3 +1012,9 @@ name = "windows_x86_64_msvc" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + +[[package]] +name = "zeroize" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" diff --git a/Cargo.toml b/Cargo.toml index bbb92a0..3e2b941 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,8 +9,12 @@ members = [ anyhow = "1.0.70" clap = { version = "4.1.11", features = ["derive"] } clap-verbosity-flag = "2.1.0" +dialoguer = "0.11.0" +dirs = "5.0.1" env_logger = "0.10.1" hound = "3.5.0" indicatif = "0.17.3" +lazy_static = "1.4.0" log = "0.4" +sys-mount = "2.1.0" walkdir = "2.3.3" diff --git a/cli/Cargo.toml b/cli/Cargo.toml index aad367b..40acf0a 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -10,8 +10,12 @@ hydrophonitor-lib = { path = "../lib" } anyhow.workspace = true clap.workspace = true clap-verbosity-flag.workspace = true +dialoguer.workspace = true +dirs.workspace = true env_logger.workspace = true hound.workspace = true indicatif.workspace = true +lazy_static.workspace = true log.workspace = true +sys-mount.workspace = true walkdir.workspace = true diff --git a/cli/src/clean.rs b/cli/src/clean.rs index eb3ef5a..d38c381 100644 --- a/cli/src/clean.rs +++ b/cli/src/clean.rs @@ -1,18 +1,64 @@ use std::path::PathBuf; +use anyhow::{anyhow, Context, Result}; use clap::Parser; +use dialoguer::Confirm; use log::info; +use hydrophonitor_lib::{clean as clean_lib, connect}; + +use crate::connect::connect; + #[derive(Parser, Debug)] #[clap(about = "This command removes all deployment data from the given device's /output path")] pub struct Clean { ///Path to USB mass storage or SD card where data will be deleted from. - #[clap(short, long, required = true)] - pub device: PathBuf, + #[clap(short, long)] + device: Option, } impl Clean { - pub fn clean(&self) { - info!("Cleaning device at {:?}", self.device); + pub fn clean(&mut self) -> Result<()> { + //create path to output folder + let _mount; + let mut output_dir: PathBuf; + match &self.device { + Some(device) => output_dir = device.clone(), + None => { + _mount = connect().with_context(|| "connecting to device failed:")?; + output_dir = connect::MOUNT_PATH.clone(); + } + } + output_dir.push("output"); + + // Show deployments and ask for confirmation + match clean_lib::get_deployments_of_device(&output_dir) { + Some(deployments) => { + info!("Cleaning device at {:?}", self.device); + + if !deployments.is_empty() { + dbg!(deployments); + + if !Confirm::new() + .with_prompt("Do you really want to delete these deployments? (y/n)") + .default(true) + .interact()? { + println!("Aborting!"); + return Ok(()); + } + } else { + println!("The directory is already empty!"); + return Ok(()); + } + } + None => { + return Err(anyhow!("{output_dir:?} is not a valid device! please select a hydrophonitor device with output folder!")); + } + } + + // Clean device + clean_lib::clear_directory(&output_dir).with_context(|| "Error cleaning directory")?; + println!("Successfully cleaned directory!"); + Ok(()) } } diff --git a/cli/src/connect.rs b/cli/src/connect.rs new file mode 100644 index 0000000..77d7def --- /dev/null +++ b/cli/src/connect.rs @@ -0,0 +1,41 @@ +use anyhow::{Context, Result}; +use dialoguer::{Confirm, Select}; +use sys_mount::{Mount, UnmountDrop}; + +use hydrophonitor_lib::connect as connect_lib; + +//Runs the connect wizard to select and mount the hydrophonitor device. It returns a mount object that defines the lifetime of the mount. +pub fn connect() -> Result> { + let devices = connect_lib::get_device_list().with_context(|| "Failed to get device list")?; + let suitable_device = connect_lib::find_suitable_device(&devices).with_context(|| "Getting device failed")?; + let selected_device = match suitable_device { + Some(dev) => { + let connect_to_device = Confirm::new() + .with_prompt(format!("Found potential Hydrophonitor device '{dev}'. Do you want to connect to this device?")) + .default(true) + .interact()?; + if connect_to_device { + dev + } else { + manual_connect(&devices) + } + } + None => { + println!("No device found matching the Hydrophonitor disk."); + manual_connect(&devices) + } + }; + + let mount = connect_lib::mount_device(selected_device).with_context(|| "Mounting device failed")?; + println!("successfully connected to device {selected_device}!"); + Ok(mount) +} + +fn manual_connect(devices: &[String]) -> &String { + let selection = Select::new() + .with_prompt("Please choose a device from the list:") + .items(devices) + .default(0) + .interact(); + &devices[selection.unwrap_or_default()] +} \ No newline at end of file diff --git a/cli/src/import.rs b/cli/src/import.rs index f70a245..27acd8f 100644 --- a/cli/src/import.rs +++ b/cli/src/import.rs @@ -1,5 +1,6 @@ use std::path::PathBuf; +use anyhow::Result; use clap::Parser; use hydrophonitor_lib::import::import; @@ -28,7 +29,8 @@ pub struct Import { impl Import { //TODO old logic; has to be changed to match new commands - pub fn import(&mut self) { - import(&mut self.device, self.output.clone()) + pub fn import(&mut self) -> Result<()> { + import(&mut self.device, self.output.clone()); + Ok(()) } } diff --git a/cli/src/main.rs b/cli/src/main.rs index 5d6c07f..2ce777b 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -6,6 +6,7 @@ use crate::import::Import; mod import; mod clean; +mod connect; #[derive(Subcommand)] #[clap(about = "A tool to record audio on Linux using the command line.")] @@ -32,9 +33,13 @@ fn main() { env_logger::builder().filter_level(verbose.log_level_filter()).init(); - match commands { + let result = match commands { Commands::Import(mut import) => import.import(), Commands::Clean(mut clean) => clean.clean(), + }; + + if let Err(err) = result { + println!("{err:?}") } } diff --git a/lib/Cargo.toml b/lib/Cargo.toml index 56ecca9..2d25496 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -7,7 +7,10 @@ edition = "2021" [dependencies] anyhow.workspace = true +dirs.workspace = true hound.workspace = true indicatif.workspace = true +lazy_static.workspace = true log.workspace = true +sys-mount.wokspace = true walkdir.workspace = true diff --git a/lib/src/clean.rs b/lib/src/clean.rs new file mode 100644 index 0000000..d385388 --- /dev/null +++ b/lib/src/clean.rs @@ -0,0 +1,28 @@ +use std::fs; +use std::path::PathBuf; + +use anyhow::{Context, Error}; +use log::warn; + +pub fn get_deployments_of_device(output_dir: &PathBuf) -> Option> { + match fs::read_dir(output_dir) { + Ok(dir) => { + let mut entries = Vec::new(); + // Iterate over the entries in the directory + for entry in dir { + entries.push(entry.unwrap().file_name().into_string().unwrap()); + } + Some(entries) + } + Err(e) => { + warn!("Error opening the directory {:?}: {}", output_dir, e); + None + } + } +} + +pub fn clear_directory(output_dir: &PathBuf) -> Result<(), Error> { + fs::remove_dir_all(output_dir).with_context(|| format!("Removing everything in directory {:?} failed", &output_dir))?; + fs::create_dir(output_dir).with_context(|| format!("Creating new empty output directory in {:?} failed", &output_dir))?; + Ok(()) +} diff --git a/lib/src/connect.rs b/lib/src/connect.rs new file mode 100644 index 0000000..2a03e38 --- /dev/null +++ b/lib/src/connect.rs @@ -0,0 +1,78 @@ +use std::fs; +use std::io::ErrorKind; +use std::path::PathBuf; +use std::process::Command; + +use anyhow::{anyhow, Context, Result}; +use lazy_static::lazy_static; +use log::debug; +use sys_mount::{Mount, unmount, UnmountDrop, UnmountFlags}; + +lazy_static! { +pub static ref MOUNT_PATH: PathBuf = PathBuf::from("/var/lib/hydrophonitor/device"); +static ref TEMP_MOUNT_PATH: PathBuf = PathBuf::from("/var/lib/hydrophonitor/temp_device"); +} + +//gets all available devices with lsblk +pub fn get_device_list() -> Result> { + let output = Command::new("lsblk").arg("-l").output().with_context(|| "Failed to run lsblk!")?; + let output = String::from_utf8_lossy(&output.stdout); + let devices: Vec<&str> = output.lines().collect(); + let mut devices_cropped: Vec = Vec::new(); + for device in devices.iter() { + let mut device_columns = device.split_whitespace(); + let cropped_device = device_columns.next().unwrap_or_default().to_string(); + let device_type = device_columns.nth(4); + if device_type.unwrap_or_default() == "part" { + devices_cropped.push(cropped_device); + } + } + Ok(devices_cropped) +} + +pub fn find_suitable_device(devices: &[String]) -> Result> { + create_dir_if_not_existing(&TEMP_MOUNT_PATH).with_context(|| format!("Failed to create dir {:?}", &*TEMP_MOUNT_PATH))?; + + //Checking all devices for an output directory + for device in devices.iter() { + let device_path = format!("/dev/{device}"); + match Mount::builder() + .mount_autodrop(&device_path, &*TEMP_MOUNT_PATH, UnmountFlags::DETACH) { + Ok(_) => + { + let read_dir_result = fs::read_dir(format!("{}/output", TEMP_MOUNT_PATH.to_str().unwrap())); + if read_dir_result.is_ok() { + return Ok(Some(device)); + } + } + Err(e) => { + if e.kind() == ErrorKind::PermissionDenied { + return Err(anyhow!("Please execute the command with sudo rights or specify a device path with access rights!")); + } + debug!("Mount of device {device_path} failed: {e}") + } + } + } + Ok(None) +} + +pub fn mount_device(device: &String) -> Result> { + if unmount(&*MOUNT_PATH, UnmountFlags::empty()).is_ok() { debug!("unmounting previously mounted device at {:?}", &*MOUNT_PATH) } + create_dir_if_not_existing(&MOUNT_PATH).with_context(|| format!("Failed to create dir {:?}", &*MOUNT_PATH))?; + + let device_path = format!("/dev/{device}"); + Mount::builder().mount_autodrop(device_path, &*MOUNT_PATH, UnmountFlags::DETACH).with_context(|| "Mount failed") +} + +fn create_dir_if_not_existing(dir_path: &PathBuf) -> Result<()> { + match fs::create_dir_all(dir_path) { + Ok(_) => Ok(()), + Err(e) => { + if e.kind() != ErrorKind::PermissionDenied { + Err(anyhow!("Please execute the command with sudo rights or specify a device path with access rights!")) + } else { + Err(anyhow!(e)) + } + } + } +} \ No newline at end of file diff --git a/lib/src/lib.rs b/lib/src/lib.rs index 07fecca..36e298a 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -1 +1,3 @@ pub mod import; +pub mod clean; +pub mod connect; \ No newline at end of file