From 3f388676088388c00a405ee46b427dbaf65eb1ee Mon Sep 17 00:00:00 2001 From: geno Date: Sun, 21 Nov 2021 20:26:18 -0500 Subject: [PATCH] Add remote file location set --- Cargo.lock | 2 +- Cargo.toml | 2 +- README.md | 12 +++++++++- src/client.rs | 58 ++++++++++++++++++++++++++++++++++++++++++++++--- src/teleport.rs | 2 ++ 5 files changed, 70 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 717f370..dd97cf5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -429,7 +429,7 @@ dependencies = [ [[package]] name = "teleporter" -version = "0.6.0" +version = "0.6.1" dependencies = [ "aes-gcm", "blake3", diff --git a/Cargo.toml b/Cargo.toml index 8fb3887..3c56e8d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "teleporter" -version = "0.6.0" +version = "0.6.1" authors = ["geno nullfree "] license = "BSD-3-Clause" description = "A small utility to send files quickly from point A to point B" diff --git a/README.md b/README.md index 172c446..a81c253 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,17 @@ To start a teleporter in client (sending) mode, run: ./teleporter -d -i [[file2] [file3] ...] ``` -Teleporter will transfer files with their name information as well as their file permissions. Any file path information will be lost. All the received files will be written out in the CWD where the server side was started. +Teleporter will transfer files with their name information as well as their file permissions. Any file path information will be lost unless the `-k` option is enabled. All the received files will be written out in the CWD where the server side was started unless the server was started with the `--allow-dangerous-filepath` option. + +## Rename / Copy-To + +Teleporter can now set remote file locations, or file renaming, via the `:` operator. Similar to how `Docker` allows quick mounting of directory locations, Teleporter will first attempt to open a file by the full given path, if that file does not exist, it will see if there are any colons (`:`) in the filename. If present, it will split the filepath and attempt to open on the first portion of the name. If that succeeds, Teleporter assumes this is a file rename / copy-to. Teleporter will also need the `-k` option, to keep filepath information. Otherwise only the file name will be changed. + +For example, given the following command: +```bash +./teleporter -i ~/Downloads/ubuntu-20.04.3-live-server-arm64.iso:/tmp/ubuntu.iso -k +``` +(and assuming the server was started with `--allow-dangerous-filepath`), Teleporter will first attempt to open `~/Downloads/ubuntu-20.04.3-live-server-arm64.iso:/tmp/ubuntu.iso`, if that fails, it will attempt to split the path on `:` and open `~/Downloads/ubuntu-20.04.3-live-server-arm64.iso`. If that succeeds, then it knows it is a rename / copy-to operation and will set the destination filepath to be the second part of the string: `/tmp/ubuntu.iso`. On the server, it will only receive the file for `/tmp/ubuntu.iso`. If the `-k` argument was ommitted, the server would just receive the original file renamed as `ubuntu.iso`. # Installation diff --git a/src/client.rs b/src/client.rs index 35cc13e..50a360c 100644 --- a/src/client.rs +++ b/src/client.rs @@ -5,6 +5,12 @@ use crate::utils::print_updates; use crate::*; use std::path::Path; +#[derive(Debug)] +struct Replace { + orig: Vec, + new: Vec, +} + fn get_file_list(opt: &Opt) -> Vec { let mut files = Vec::::new(); @@ -18,7 +24,7 @@ fn get_file_list(opt: &Opt) -> Vec { } }; files.append(&mut tmp); - } else if item.is_file() { + } else if item.exists() && item.is_file() { files.push(item.to_str().unwrap().to_string()); } } @@ -52,10 +58,51 @@ fn scope_dir(dir: &Path) -> Result, Error> { Ok(files) } +fn find_replacements(opt: &mut Opt) -> Replace { + let mut rep = Replace { + orig: Vec::::new(), + new: Vec::::new(), + }; + + let mut orig: String; + let mut new: String; + let mut poppers = Vec::::new(); + + for (idx, item) in opt.input.iter().enumerate() { + if File::open(&item).is_ok() { + continue; + } + + let path = item.to_str().unwrap(); + if path.contains(&":") { + let mut split = path.split(':'); + orig = split.next().unwrap().to_string(); + new = split.next().unwrap().to_string(); + + if File::open(&orig).is_ok() { + rep.orig.push(orig.clone()); + rep.new.push(new.clone()); + poppers.push(idx); + } + } + } + + while !poppers.is_empty() { + let idx = poppers.pop().unwrap(); + opt.input.remove(idx); + opt.input + .insert(idx, PathBuf::from(&rep.orig[poppers.len()])); + } + + rep +} + /// Client function sends filename and file data for each filepath -pub fn run(opt: Opt) -> Result<(), Error> { +pub fn run(mut opt: Opt) -> Result<(), Error> { println!("Teleporter Client {}", VERSION); + let rep = find_replacements(&mut opt); + let files = get_file_list(&opt); if files.is_empty() { @@ -71,6 +118,11 @@ pub fn run(opt: Opt) -> Result<(), Error> { let filepath = item; let mut filename = filepath.clone().to_string(); + for (idx, item) in rep.orig.iter().enumerate() { + if item.contains(&filepath.to_string()) { + filename = rep.new[idx].clone(); + } + } // Validate file let file = match File::open(&filepath) { @@ -91,7 +143,7 @@ pub fn run(opt: Opt) -> Result<(), Error> { // Remove all path info if !opt.keep_path if !opt.keep_path { - filename = Path::new(item) + filename = Path::new(&filename) .file_name() .unwrap() .to_str() diff --git a/src/teleport.rs b/src/teleport.rs index fab3467..fe8baa7 100644 --- a/src/teleport.rs +++ b/src/teleport.rs @@ -694,6 +694,7 @@ mod tests { let mut test = TeleportInitAck::new(TeleportStatus::Proceed); let feat = TeleportFeatures::NewFile as u32 | TeleportFeatures::Overwrite as u32; test.features = Some(feat); + test.version = [0, 6, 0]; let out = test.serialize(); assert_eq!(out, TESTINITACK); @@ -704,6 +705,7 @@ mod tests { let mut test = TeleportInitAck::new(TeleportStatus::Proceed); let feat = TeleportFeatures::NewFile as u32 | TeleportFeatures::Overwrite as u32; test.features = Some(feat); + test.version = [0, 6, 0]; let mut t = TeleportInitAck::new(TeleportStatus::Proceed); t.deserialize(TESTINITACK).unwrap();