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