1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 19:47:45 +00:00

mkdir: adapt to standardized error handling

This commit is contained in:
Terts Diepraam 2021-06-28 13:45:04 +02:00
parent e4eac825fb
commit 8c5052fcb7

View file

@ -8,25 +8,26 @@
#[macro_use]
extern crate uucore;
use clap::OsValues;
use clap::{crate_version, App, Arg};
use std::fs;
use std::path::Path;
use uucore::error::{FromIo, UResult, USimpleError};
static ABOUT: &str = "Create the given DIRECTORY(ies) if they do not exist";
static OPT_MODE: &str = "mode";
static OPT_PARENTS: &str = "parents";
static OPT_VERBOSE: &str = "verbose";
static ARG_DIRS: &str = "dirs";
mod options {
pub const MODE: &str = "mode";
pub const PARENTS: &str = "parents";
pub const VERBOSE: &str = "verbose";
pub const DIRS: &str = "dirs";
}
fn get_usage() -> String {
format!("{0} [OPTION]... [USER]", executable!())
}
/**
* Handles option parsing
*/
pub fn uumain(args: impl uucore::Args) -> i32 {
#[uucore_procs::gen_uumain]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let usage = get_usage();
// Linux-specific options, not implemented
@ -34,26 +35,16 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
// " of each created directory to CTX"),
let matches = uu_app().usage(&usage[..]).get_matches_from(args);
let dirs: Vec<String> = matches
.values_of(ARG_DIRS)
.map(|v| v.map(ToString::to_string).collect())
.unwrap_or_default();
let verbose = matches.is_present(OPT_VERBOSE);
let recursive = matches.is_present(OPT_PARENTS);
let dirs = matches.values_of_os(options::DIRS).unwrap_or_default();
let verbose = matches.is_present(options::VERBOSE);
let recursive = matches.is_present(options::PARENTS);
// Translate a ~str in octal form to u16, default to 755
// Not tested on Windows
let mode_match = matches.value_of(OPT_MODE);
let mode: u16 = match mode_match {
Some(m) => {
let res: Option<u16> = u16::from_str_radix(m, 8).ok();
match res {
Some(r) => r,
_ => crash!(1, "no mode given"),
}
}
_ => 0o755_u16,
let mode: u16 = match matches.value_of(options::MODE) {
Some(m) => u16::from_str_radix(m, 8)
.map_err(|_| USimpleError::new(1, format!("invalid mode '{}'", m)))?,
None => 0o755_u16,
};
exec(dirs, recursive, mode, verbose)
@ -64,27 +55,27 @@ pub fn uu_app() -> App<'static, 'static> {
.version(crate_version!())
.about(ABOUT)
.arg(
Arg::with_name(OPT_MODE)
Arg::with_name(options::MODE)
.short("m")
.long(OPT_MODE)
.long(options::MODE)
.help("set file mode (not implemented on windows)")
.default_value("755"),
)
.arg(
Arg::with_name(OPT_PARENTS)
Arg::with_name(options::PARENTS)
.short("p")
.long(OPT_PARENTS)
.long(options::PARENTS)
.alias("parent")
.help("make parent directories as needed"),
)
.arg(
Arg::with_name(OPT_VERBOSE)
Arg::with_name(options::VERBOSE)
.short("v")
.long(OPT_VERBOSE)
.long(options::VERBOSE)
.help("print a message for each printed directory"),
)
.arg(
Arg::with_name(ARG_DIRS)
Arg::with_name(options::DIRS)
.multiple(true)
.takes_value(true)
.min_values(1),
@ -94,64 +85,43 @@ pub fn uu_app() -> App<'static, 'static> {
/**
* Create the list of new directories
*/
fn exec(dirs: Vec<String>, recursive: bool, mode: u16, verbose: bool) -> i32 {
let mut status = 0;
let empty = Path::new("");
for dir in &dirs {
fn exec(dirs: OsValues, recursive: bool, mode: u16, verbose: bool) -> UResult<()> {
for dir in dirs {
let path = Path::new(dir);
if !recursive {
if let Some(parent) = path.parent() {
if parent != empty && !parent.exists() {
show_error!(
"cannot create directory '{}': No such file or directory",
path.display()
);
status = 1;
continue;
}
}
}
status |= mkdir(path, recursive, mode, verbose);
show_if_err!(mkdir(path, recursive, mode, verbose));
}
status
Ok(())
}
/**
* Wrapper to catch errors, return 1 if failed
*/
fn mkdir(path: &Path, recursive: bool, mode: u16, verbose: bool) -> i32 {
fn mkdir(path: &Path, recursive: bool, mode: u16, verbose: bool) -> UResult<()> {
let create_dir = if recursive {
fs::create_dir_all
} else {
fs::create_dir
};
if let Err(e) = create_dir(path) {
show_error!("{}: {}", path.display(), e.to_string());
return 1;
}
create_dir(path).map_err_context(|| format!("cannot create directory '{}'", path.display()))?;
if verbose {
println!("{}: created directory '{}'", executable!(), path.display());
}
#[cfg(any(unix, target_os = "redox"))]
fn chmod(path: &Path, mode: u16) -> i32 {
use std::fs::{set_permissions, Permissions};
use std::os::unix::fs::PermissionsExt;
let mode = Permissions::from_mode(u32::from(mode));
if let Err(err) = set_permissions(path, mode) {
show_error!("{}: {}", path.display(), err);
return 1;
}
0
}
#[cfg(windows)]
#[allow(unused_variables)]
fn chmod(path: &Path, mode: u16) -> i32 {
// chmod on Windows only sets the readonly flag, which isn't even honored on directories
0
}
chmod(path, mode)
}
#[cfg(any(unix, target_os = "redox"))]
fn chmod(path: &Path, mode: u16) -> UResult<()> {
use std::fs::{set_permissions, Permissions};
use std::os::unix::fs::PermissionsExt;
let mode = Permissions::from_mode(u32::from(mode));
set_permissions(path, mode)
.map_err_context(|| format!("cannot set permissions '{}'", path.display()))
}
#[cfg(windows)]
fn chmod(_path: &Path, _mode: u16) -> UResult<()> {
// chmod on Windows only sets the readonly flag, which isn't even honored on directories
Ok(())
}