mirror of
https://github.com/uutils/coreutils
synced 2024-07-22 10:24:54 +00:00
commit
496a28a301
2
Makefile
2
Makefile
|
@ -15,6 +15,7 @@ PROGS := \
|
|||
echo \
|
||||
env \
|
||||
false \
|
||||
mkdir \
|
||||
printenv \
|
||||
pwd \
|
||||
rm \
|
||||
|
@ -37,6 +38,7 @@ EXES := \
|
|||
# Programs with usable tests
|
||||
TEST_PROGS := \
|
||||
cat \
|
||||
mkdir \
|
||||
|
||||
TEST ?= $(TEST_PROGS)
|
||||
|
||||
|
|
|
@ -115,7 +115,6 @@ To do
|
|||
- ls
|
||||
- make-prime-list
|
||||
- md5sum
|
||||
- mkdir
|
||||
- mkfifo
|
||||
- mknod
|
||||
- mktemp
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
161
mkdir/mkdir.rs
Normal file
161
mkdir/mkdir.rs
Normal file
|
@ -0,0 +1,161 @@
|
|||
#[crate_id(name="mkdir", vers="1.0.0", author="Nicholas Juszczak")];
|
||||
|
||||
/**
|
||||
* This file is part of the uutils coreutils package.
|
||||
*
|
||||
* (c) Nicholas Juszczak <juszczakn@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
extern mod extra;
|
||||
|
||||
use std::os;
|
||||
use std::io::{fs, result, stderr};
|
||||
use std::num::strconv;
|
||||
use extra::getopts::groups;
|
||||
|
||||
static VERSION: &'static str = "1.0.0";
|
||||
|
||||
/**
|
||||
* Handles option parsing
|
||||
*/
|
||||
fn main() {
|
||||
let args = os::args();
|
||||
|
||||
let opts = ~[
|
||||
// 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("h", "help", "display this help"),
|
||||
groups::optflag("", "version", "display this version")
|
||||
];
|
||||
|
||||
let matches = match groups::getopts(args.tail(), opts) {
|
||||
Ok(m) => m,
|
||||
Err(f) => {
|
||||
writeln!(&mut stderr() as &mut Writer,
|
||||
"Invalid options\n{}", f.to_err_msg());
|
||||
os::set_exit_status(1);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
if args.len() == 1 || matches.opt_present("help") {
|
||||
print_help(opts);
|
||||
return;
|
||||
}
|
||||
if matches.opt_present("version") {
|
||||
println("mkdir v" + VERSION);
|
||||
return;
|
||||
}
|
||||
let verbose_flag = matches.opt_present("verbose");
|
||||
let mk_parents = 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 = 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 = matches.free;
|
||||
exec(dirs, mk_parents, mode, verbose_flag);
|
||||
}
|
||||
|
||||
fn print_help(opts: &[groups::OptGroup]) {
|
||||
println!("mkdir v{} - make a new directory with the given path", VERSION);
|
||||
println("");
|
||||
println("Usage:");
|
||||
print(groups::usage("Create the given DIRECTORY(ies)" +
|
||||
" if they do not exist", opts));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the list of new directories
|
||||
*/
|
||||
fn exec(dirs: ~[~str], mk_parents: bool, mode: u32, verbose: bool) {
|
||||
let mut parent_dirs: ~[~str] = ~[];
|
||||
if mk_parents {
|
||||
for dir in dirs.iter() {
|
||||
let path = Path::new((*dir).clone());
|
||||
// Build list of parent dirs which need to be created
|
||||
let parent = path.dirname_str();
|
||||
match parent {
|
||||
Some(p) => {
|
||||
if !Path::new(p).exists() {
|
||||
parent_dirs.push(p.into_owned())
|
||||
}
|
||||
},
|
||||
None => ()
|
||||
}
|
||||
}
|
||||
}
|
||||
// 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 = match path.dirname_str() {
|
||||
Some(p) => p,
|
||||
None => ""
|
||||
};
|
||||
let parent_exists = 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 = ~"";
|
||||
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);
|
||||
os::set_exit_status(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
}
|
||||
}
|
||||
}
|
68
mkdir/test.rs
Normal file
68
mkdir/test.rs
Normal file
|
@ -0,0 +1,68 @@
|
|||
use std::{run};
|
||||
use std::io::fs::rmdir;
|
||||
|
||||
static exe: &'static str = "build/mkdir";
|
||||
static test_dir1: &'static str = "tmp/mkdir_test1";
|
||||
static test_dir2: &'static str = "tmp/mkdir_test2";
|
||||
static test_dir3: &'static str = "tmp/mkdir_test3";
|
||||
static test_dir4: &'static str = "tmp/mkdir_test4/mkdir_test4_1";
|
||||
static test_dir5: &'static str = "tmp/mkdir_test5/mkdir_test5_1";
|
||||
|
||||
fn cleanup(dir: &'static str) {
|
||||
let d = dir.into_owned();
|
||||
let p = Path::new(d.into_owned());
|
||||
if p.exists() {
|
||||
rmdir(&p);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mkdir_mkdir() {
|
||||
cleanup(test_dir1);
|
||||
let prog = run::process_status(exe.into_owned(), [test_dir1.into_owned()]);
|
||||
let exit_success = prog.unwrap().success();
|
||||
cleanup(test_dir1);
|
||||
assert_eq!(exit_success, true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mkdir_dup_dir() {
|
||||
cleanup(test_dir2);
|
||||
let prog = run::process_status(exe.into_owned(), [test_dir2.into_owned()]);
|
||||
let exit_success = prog.unwrap().success();
|
||||
if !exit_success {
|
||||
cleanup(test_dir2);
|
||||
fail!();
|
||||
}
|
||||
let prog2 = run::process_status(exe.into_owned(), [test_dir2.into_owned()]);
|
||||
let exit_success2 = prog2.unwrap().success();
|
||||
cleanup(test_dir2);
|
||||
assert_eq!(exit_success2, false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mkdir_mode() {
|
||||
cleanup(test_dir3);
|
||||
let prog = run::process_status(exe.into_owned(), [~"-m", ~"755", test_dir3.into_owned()]);
|
||||
let exit_success = prog.unwrap().success();
|
||||
cleanup(test_dir3);
|
||||
assert_eq!(exit_success, true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mkdir_parent() {
|
||||
cleanup(test_dir4);
|
||||
let prog = run::process_status(exe.into_owned(), [~"-p", test_dir4.into_owned()]);
|
||||
let exit_success = prog.unwrap().success();
|
||||
cleanup(test_dir4);
|
||||
assert_eq!(exit_success, true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mkdir_no_parent() {
|
||||
cleanup(test_dir5);
|
||||
let prog = run::process_status(exe.into_owned(), [test_dir5.into_owned()]);
|
||||
let exit_success = prog.unwrap().success();
|
||||
cleanup(test_dir5);
|
||||
assert_eq!(exit_success, false);
|
||||
}
|
Loading…
Reference in a new issue