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:
parent
e4eac825fb
commit
8c5052fcb7
1 changed files with 48 additions and 78 deletions
|
@ -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(())
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue