From fc1da5a691dd0257a70ef17b799a432c33eda99d Mon Sep 17 00:00:00 2001 From: Nick Juszczak Date: Fri, 3 Jan 2014 17:32:39 -0600 Subject: [PATCH] remove cat warning, update makefile --- Makefile | 1 + cat/cat.rs | 1 + mkdir/mkdir.rs | 120 ++++++++++++++++++++++++++++++++++++++++--------- mkdir/test.rs | 3 ++ 4 files changed, 105 insertions(+), 20 deletions(-) create mode 100644 mkdir/test.rs diff --git a/Makefile b/Makefile index b0368d529..d6ddf8589 100644 --- a/Makefile +++ b/Makefile @@ -31,6 +31,7 @@ EXES := \ # Programs with usable tests TEST_PROGS := \ cat \ + mkdir \ TEST ?= $(TEST_PROGS) diff --git a/cat/cat.rs b/cat/cat.rs index 1a20937a0..170f16ce2 100644 --- a/cat/cat.rs +++ b/cat/cat.rs @@ -86,6 +86,7 @@ pub enum NumberingMode { } static TAB: u8 = '\t' as u8; +#[allow(dead_code)] static CR: u8 = '\r' as u8; static LF: u8 = '\n' as u8; diff --git a/mkdir/mkdir.rs b/mkdir/mkdir.rs index da5e3f1a8..e0f0476ab 100644 --- a/mkdir/mkdir.rs +++ b/mkdir/mkdir.rs @@ -1,6 +1,6 @@ #[crate_id(name="mkdir", vers="1.0.0", author="Nicholas Juszczak")]; -/* +/** * This file is part of the uutils coreutils package. * * (c) Nicholas Juszczak @@ -12,26 +12,29 @@ extern mod extra; use std::os; -use std::io::stderr; +use std::io::{fs, result, stderr}; +use std::num::strconv; use extra::getopts::groups; -use std::io::fs; static VERSION: &'static str = "1.0.0"; +/** + * Handles option parsing + */ fn main() { let args: ~[~str] = os::args(); let opts: ~[groups::OptGroup] = ~[ - // Linux-specific options - // groups::optflag("m", "mode", "set file mode"), + // Linux-specific options, not implemented // groups::optflag("Z", "context", "set SELinux secutiry context" + // " of each created directory to CTX"), + groups::optopt("m", "mode", "set file mode", "755"), groups::optflag("p", "parents", "make parent directories as needed"), groups::optflag("v", "verbose", "print a message for each printed directory"), groups::optflag("", "help", "display this help"), groups::optflag("", "version", "display this version") - ]; + ]; let matches = match groups::getopts(args.tail(), opts) { Ok(m) => m, @@ -43,7 +46,7 @@ fn main() { } }; - if matches.opt_present("help") { + if args.len() == 1 || matches.opt_present("help") { print_help(opts); return; } @@ -51,10 +54,35 @@ fn main() { println("mkdir v" + VERSION); return; } + let mut verbose_flag: bool = false; + if matches.opt_present("verbose") { + verbose_flag = true; + } let mk_parents: bool = matches.opt_present("parents"); + + // Translate a ~str in octal form to u32, default to 755 + // Not tested on Windows + let mode_match = matches.opts_str(&[~"mode"]); + let mode: u32 = if mode_match.is_some() { + let m: ~str = mode_match.unwrap(); + let res = strconv::from_str_common(m, 8, false, false, false, + strconv::ExpNone, + false, false); + if res.is_some() { + res.unwrap() + } else { + writeln!(&mut stderr() as &mut Writer, + "Error: no mode given"); + os::set_exit_status(1); + return; + } + } else { + 0o755 + }; + let dirs: ~[~str] = matches.free; - mkdir(dirs, mk_parents); + exec(dirs, mk_parents, mode, verbose_flag); } fn print_help(opts: &[groups::OptGroup]) { @@ -65,27 +93,79 @@ fn print_help(opts: &[groups::OptGroup]) { " if they do not exist", opts)); } -/* std::libc currently does not provide bindings for any bits -besides user bits, so might as well use octal for now. -See 'std::io::FilePermission', -'std::libc::consts::os::posix88' for future updates */ -fn mkdir(dirs: ~[~str], mk_parents: bool) { - let default: u32 = 0o755; - +/** + * Create the list of new directories + */ +fn exec(dirs: ~[~str], mk_parents: bool, mode: u32, verbose: bool) { + let mut parent_dirs: ~[~str] = ~[]; for dir in dirs.iter() { let path = Path::new((*dir).clone()); - // Recursively create parent dirs as needed + // Build list of parent dirs which need to be created if mk_parents { match path.dirname_str() { Some(p) => if p != "." { - mkdir(~[p.into_owned()], mk_parents) + parent_dirs.push(p.into_owned()) }, None => () } } - if !path.exists() { - println(*dir); - fs::mkdir(&path, default); + } + // Recursively build parent dirs that are needed + if !parent_dirs.is_empty() { + exec(parent_dirs, mk_parents, mode, verbose); + } + + for dir in dirs.iter() { + let path = Path::new((*dir).clone()); + // Determine if parent directory to the one to + // be created exists + let parent: &str = match path.dirname_str() { + Some(p) => p, + None => "" + }; + let parent_exists:bool = Path::new(parent).exists(); + if parent_exists && !path.exists() { + // if mkdir failed return + if !mkdir(&path, mode) {return;} + if verbose {println(*dir);} + } else { + let mut error_msg: ~str = ~""; + if !parent_exists { + error_msg.push_str("Error: parent directory '"); + error_msg.push_str(parent); + error_msg.push_str("' does not exist"); + } else { + error_msg.push_str("Error: directory '"); + error_msg.push_str(*dir); + error_msg.push_str("' already exists"); + } + writeln!(&mut stderr() as &mut Writer, + "{}", error_msg); } } } + +/** + * Wrapper to catch errors, return false if failed + */ +fn mkdir(path: &Path, mode: u32) -> bool { + match result(|| fs::mkdir(path, mode)) { + Ok(_) => true, + Err(e) => { + writeln!(&mut stderr() as &mut Writer, + "mkdir: test {}", e.to_str()); + os::set_exit_status(1); + false + } + } +} + +// #[test] +// fn create_dir() { +// let test_dir = "mkdir_test_dir"; +// let path: Path = Path::new(test_dir); +// let mode: u32 = 0x755; +// let result = mkdir(&path, mode); +// fs::rmdir(&path); +// assert_eq!(true, result); +// } diff --git a/mkdir/test.rs b/mkdir/test.rs new file mode 100644 index 000000000..58dfaaa8a --- /dev/null +++ b/mkdir/test.rs @@ -0,0 +1,3 @@ +fn main() { + +}