aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib.rs18
-rw-r--r--src/tftpc.rs56
-rw-r--r--src/tftpd.rs66
3 files changed, 49 insertions, 91 deletions
diff --git a/src/lib.rs b/src/lib.rs
index f049d05..64291cb 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -151,7 +151,7 @@ impl Tftp {
/* build string from buffer */
String::from_utf8(buf.iter()
.take_while(|&x| *x != 0)
- .map(|&x| x)
+ .cloned()
.collect()).ok()
}
@@ -372,26 +372,18 @@ impl Tftp {
}
pub fn parse_file_mode_options(&self, buf: &[u8]) -> Result<(PathBuf, String, HashMap<String, String>), io::Error> {
- let dataerr = io::Error::new(io::ErrorKind::InvalidData, "invalid data received");
+ let dataerr = || io::Error::new(io::ErrorKind::InvalidData, "invalid data received");
let mut pos = 0;
- let filename = match self.get_tftp_str(&buf[pos..]) {
- Some(f) => f,
- None => return Err(dataerr),
- };
+ let filename = self.get_tftp_str(&buf[pos..]).ok_or_else(dataerr)?;
pos += filename.len() + 1;
- let filename = Path::new(&filename);
-
- let mode = match self.get_tftp_str(&buf[pos..]) {
- Some(m) => m.to_lowercase(),
- None => return Err(dataerr),
- };
+ let mode = self.get_tftp_str(&buf[pos..]).ok_or_else(dataerr)?.to_lowercase();
pos += mode.len() + 1;
let options = self.parse_options(&buf[pos..]);
- Ok((filename.to_path_buf(), mode, options))
+ Ok((Path::new(&filename).to_path_buf(), mode, options))
}
pub fn send_error(&self, socket: &UdpSocket, code: u16, msg: &str) -> Result<(), io::Error> {
diff --git a/src/tftpc.rs b/src/tftpc.rs
index 240ef2c..a134293 100644
--- a/src/tftpc.rs
+++ b/src/tftpc.rs
@@ -131,8 +131,8 @@ impl Tftpc {
let mut file = File::open(self.conf.filename.as_path())?;
let err_invalidpath = || io::Error::new(io::ErrorKind::InvalidInput, "Invalid path/filename");
- let filename = self.conf.filename.file_name().ok_or(err_invalidpath())?
- .to_str().ok_or(err_invalidpath())?;
+ let filename = self.conf.filename.file_name().ok_or_else(err_invalidpath)?
+ .to_str().ok_or_else(err_invalidpath)?;
let metadata = file.metadata().map_err(|_| err_invalidpath())?;
if !metadata.is_file() {
return Err(err_invalidpath());
@@ -171,10 +171,10 @@ impl Tftpc {
fn handle_rrq(&mut self, sock: &UdpSocket) -> Result<String, io::Error> {
let err_invalidpath = || io::Error::new(io::ErrorKind::InvalidInput, "Invalid path/filename");
- let filename = self.conf.filename.file_name().ok_or(err_invalidpath())?;
+ let filename = self.conf.filename.file_name().ok_or_else(err_invalidpath)?;
let outpath = env::current_dir().expect("Can't get current directory").join(filename);
let mut file = File::create(outpath)?;
- let filename = self.conf.filename.to_str().ok_or(err_invalidpath())?;
+ let filename = self.conf.filename.to_str().ok_or_else(err_invalidpath)?;
let buf = self.init_req(rtftp::Opcode::RRQ, filename, 0);
@@ -226,7 +226,7 @@ impl Tftpc {
}
}
-fn usage(opts: Options, program: String, error: Option<String>) {
+fn usage(opts: &Options, program: &str, error: Option<String>) {
if let Some(err) = error {
println!("{}\n", err);
}
@@ -234,7 +234,7 @@ fn usage(opts: Options, program: String, error: Option<String>) {
println!("{}", opts.usage(format!("RusTFTP {}\n\n{} [options] <remote>[:port]", version, program).as_str()));
}
-fn parse_commandline(args: &[String]) -> Result<Configuration, &str> {
+fn parse_commandline(args: &[String]) -> Option<Configuration> {
let program = args[0].clone();
let mut operation = None;
let mut mode = rtftp::Mode::OCTET;
@@ -247,16 +247,14 @@ fn parse_commandline(args: &[String]) -> Result<Configuration, &str> {
opts.optopt("p", "put", "upload file to remote server", "FILE");
opts.optopt("b", "blksize", format!("negotiate a different block size (default: {})", blksize).as_ref(), "SIZE");
opts.optflag("n", "netascii","use netascii mode (instead of octet)");
- let matches = match opts.parse(&args[1..]) {
- Ok(m) => m,
- Err(err) => {
- usage(opts, program, Some(err.to_string()));
- return Err("Parsing error");
- }
- };
+
+ let getopts_fail = |err: getopts::Fail| { usage(&opts, &program, Some(err.to_string())) };
+ let conv_error = |err: std::num::ParseIntError| { usage(&opts, &program, Some(err.to_string())) };
+
+ let matches = opts.parse(&args[1..]).map_err(getopts_fail).ok()?;
if matches.opt_present("h") || matches.free.len() != 1 {
- usage(opts, program, None);
- return Err("usage");
+ usage(&opts, &program, None);
+ return None;
}
if let Some(f) = matches.opt_str("g") {
@@ -269,8 +267,8 @@ fn parse_commandline(args: &[String]) -> Result<Configuration, &str> {
}
if operation.is_none() || (matches.opt_present("g") && matches.opt_present("p")) {
- usage(opts, program, Some("Exactly one of g (get) and p (put) required".to_string()));
- return Err("get put");
+ usage(&opts, &program, Some("Exactly one of g (get) and p (put) required".to_string()));
+ return None;
}
if matches.opt_present("n") {
@@ -279,25 +277,19 @@ fn parse_commandline(args: &[String]) -> Result<Configuration, &str> {
let remote_in = matches.free[0].as_str();
let remote = match remote_in.to_socket_addrs() {
- Ok(mut i) => i.next(),
+ Ok(i) => i,
Err(_) => match (remote_in, 69).to_socket_addrs() {
- Ok(mut j) => j.next(),
+ Ok(j) => j,
Err(_) => {
- usage(opts, program, Some("Failed to parse and lookup specified remote".to_string()));
- return Err("lookup");
+ usage(&opts, &program, Some("Failed to parse and lookup specified remote".to_string()));
+ return None;
}
},
- };
+ }.next();
- blksize = match matches.opt_get_default::<usize>("b", blksize) {
- Ok(b) => b,
- Err(err) => {
- usage(opts, program, Some(err.to_string()));
- return Err("blksize");
- }
- };
+ blksize = matches.opt_get_default::<usize>("b", blksize).map_err(conv_error).ok()?;
- Ok(Configuration {
+ Some(Configuration {
operation: operation.unwrap(),
mode,
filename: filename.unwrap(),
@@ -309,8 +301,8 @@ fn parse_commandline(args: &[String]) -> Result<Configuration, &str> {
fn main() {
let args: Vec<String> = env::args().collect();
let conf = match parse_commandline(&args) {
- Ok(c) => c,
- Err(_) => return,
+ Some(c) => c,
+ None => return,
};
Tftpc::new(conf).start();
diff --git a/src/tftpd.rs b/src/tftpd.rs
index d10287b..638c5d5 100644
--- a/src/tftpd.rs
+++ b/src/tftpd.rs
@@ -301,7 +301,7 @@ impl Tftpd {
}
}
-fn usage(opts: Options, program: String, error: Option<String>) {
+fn usage(opts: &Options, program: &str, error: Option<String>) {
if let Some(err) = error {
println!("{}\n", err);
}
@@ -309,7 +309,7 @@ fn usage(opts: Options, program: String, error: Option<String>) {
println!("{}", opts.usage(format!("RusTFTP {}\n\n{} [options]", version, program).as_str()));
}
-fn parse_commandline(args: &[String]) -> Result<Configuration, &str> {
+fn parse_commandline(args: &[String]) -> Option<Configuration> {
let program = args[0].clone();
let mut conf: Configuration = Default::default();
let mut opts = Options::new();
@@ -321,70 +321,44 @@ fn parse_commandline(args: &[String]) -> Result<Configuration, &str> {
opts.optflag("r", "read-only", "allow only reading/downloading of files (RRQ)");
opts.optflag("w", "write-only", "allow only writing/uploading of files (WRQ)");
opts.optopt("t", "threads", format!("number of worker threads (default: {})", conf.threads).as_ref(), "N");
- let matches = match opts.parse(&args[1..]) {
- Ok(m) => m,
- Err(err) => {
- usage(opts, program, Some(err.to_string()));
- return Err("Parsing error");
- }
- };
+
+ let getopts_fail = |err: getopts::Fail| { usage(&opts, &program, Some(err.to_string())) };
+ let conv_error = |err: std::num::ParseIntError| { usage(&opts, &program, Some(err.to_string())) };
+
+ let matches = opts.parse(&args[1..]).map_err(getopts_fail).ok()?;
if matches.opt_present("h") {
- usage(opts, program, None);
- return Err("usage");
+ usage(&opts, &program, None);
+ return None;
}
- conf.port = match matches.opt_get_default("p", conf.port) {
- Ok(p) => p,
- Err(err) => {
- usage(opts, program, Some(err.to_string()));
- return Err("port");
- }
- };
- conf.uid = match matches.opt_get_default("u", conf.uid) {
- Ok(u) => u,
- Err(err) => {
- usage(opts, program, Some(err.to_string()));
- return Err("uid");
- }
- };
- conf.gid = match matches.opt_get_default("g", conf.gid) {
- Ok(g) => g,
- Err(err) => {
- usage(opts, program, Some(err.to_string()));
- return Err("gid");
- }
- };
- conf.threads = match matches.opt_get_default("t", conf.threads) {
- Ok(t) => t,
- Err(err) => {
- usage(opts, program, Some(err.to_string()));
- return Err("threads");
- }
- };
+ conf.port = matches.opt_get_default("p", conf.port).map_err(conv_error).ok()?;
+ conf.uid = matches.opt_get_default("u", conf.uid).map_err(conv_error).ok()?;
+ conf.gid = matches.opt_get_default("g", conf.gid).map_err(conv_error).ok()?;
+ conf.threads = matches.opt_get_default("t", conf.threads).map_err(conv_error).ok()?;
conf.ro = matches.opt_present("r");
conf.wo = matches.opt_present("w");
if conf.ro && conf.wo {
- usage(opts, program, Some(String::from("Only one of r (read-only) and w (write-only) allowed")));
- return Err("ro and wo");
+ usage(&opts, &program, Some(String::from("Only one of r (read-only) and w (write-only) allowed")));
+ return None;
}
if matches.opt_present("d") {
conf.dir = match matches.opt_str("d") {
Some(d) => Path::new(&d).to_path_buf(),
None => {
- usage(opts, program, None);
- return Err("directory");
+ usage(&opts, &program, None);
+ return None;
}
};
}
- Ok(conf)
+ Some(conf)
}
fn main() {
let args: Vec<String> = env::args().collect();
let conf = match parse_commandline(&args) {
- Ok(c) => c,
- Err(_) => return,
+ Some(c) => c,
+ None => return,
};
Tftpd::new(conf).start();