mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-29 12:07:46 +00:00
truncate: make better use of UResult
Replace some uses of `crash!()` and move `UError` handling down into the `truncate()` function. This does not change the behavior of the program, just organizes the code to facilitate introducing code to handle other types of errors in the future.
This commit is contained in:
parent
b816e80e2f
commit
1074deeb03
1 changed files with 41 additions and 47 deletions
|
@ -6,17 +6,13 @@
|
||||||
// * file that was distributed with this source code.
|
// * file that was distributed with this source code.
|
||||||
|
|
||||||
// spell-checker:ignore (ToDO) RFILE refsize rfilename fsize tsize
|
// spell-checker:ignore (ToDO) RFILE refsize rfilename fsize tsize
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate uucore;
|
|
||||||
|
|
||||||
use clap::{crate_version, App, Arg};
|
use clap::{crate_version, App, Arg};
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::fs::{metadata, OpenOptions};
|
use std::fs::{metadata, OpenOptions};
|
||||||
use std::io::ErrorKind;
|
use std::io::ErrorKind;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use uucore::display::Quotable;
|
use uucore::display::Quotable;
|
||||||
use uucore::error::{UIoError, UResult, USimpleError, UUsageError};
|
use uucore::error::{FromIo, UResult, USimpleError, UUsageError};
|
||||||
use uucore::parse_size::{parse_size, ParseSizeError};
|
use uucore::parse_size::{parse_size, ParseSizeError};
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
|
@ -113,24 +109,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
let no_create = matches.is_present(options::NO_CREATE);
|
let no_create = matches.is_present(options::NO_CREATE);
|
||||||
let reference = matches.value_of(options::REFERENCE).map(String::from);
|
let reference = matches.value_of(options::REFERENCE).map(String::from);
|
||||||
let size = matches.value_of(options::SIZE).map(String::from);
|
let size = matches.value_of(options::SIZE).map(String::from);
|
||||||
truncate(no_create, io_blocks, reference, size, files).map_err(|e| {
|
truncate(no_create, io_blocks, reference, size, files)
|
||||||
match e.kind() {
|
|
||||||
ErrorKind::NotFound => {
|
|
||||||
// TODO Improve error-handling so that the error
|
|
||||||
// returned by `truncate()` provides the necessary
|
|
||||||
// parameter for formatting the error message.
|
|
||||||
let reference = matches.value_of(options::REFERENCE).map(String::from);
|
|
||||||
USimpleError::new(
|
|
||||||
1,
|
|
||||||
format!(
|
|
||||||
"cannot stat {}: No such file or directory",
|
|
||||||
reference.as_deref().unwrap_or("").quote()
|
|
||||||
),
|
|
||||||
) // TODO: fix '--no-create' see test_reference and test_truncate_bytes_size
|
|
||||||
}
|
|
||||||
_ => uio_error!(e, ""),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,20 +191,31 @@ fn truncate_reference_and_size(
|
||||||
size_string: &str,
|
size_string: &str,
|
||||||
filenames: Vec<String>,
|
filenames: Vec<String>,
|
||||||
create: bool,
|
create: bool,
|
||||||
) -> std::io::Result<()> {
|
) -> UResult<()> {
|
||||||
let mode = match parse_mode_and_size(size_string) {
|
let mode = match parse_mode_and_size(size_string) {
|
||||||
Ok(m) => match m {
|
Err(e) => return Err(USimpleError::new(1, format!("Invalid number: {}", e))),
|
||||||
TruncateMode::Absolute(_) => {
|
Ok(TruncateMode::Absolute(_)) => {
|
||||||
crash!(1, "you must specify a relative '--size' with '--reference'")
|
return Err(USimpleError::new(
|
||||||
|
1,
|
||||||
|
String::from("you must specify a relative '--size' with '--reference'"),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
_ => m,
|
Ok(m) => m,
|
||||||
},
|
|
||||||
Err(e) => crash!(1, "Invalid number: {}", e.to_string()),
|
|
||||||
};
|
};
|
||||||
let fsize = usize::try_from(metadata(rfilename)?.len()).unwrap();
|
let metadata = metadata(rfilename).map_err(|e| match e.kind() {
|
||||||
|
ErrorKind::NotFound => USimpleError::new(
|
||||||
|
1,
|
||||||
|
format!(
|
||||||
|
"cannot stat {}: No such file or directory",
|
||||||
|
rfilename.quote()
|
||||||
|
),
|
||||||
|
),
|
||||||
|
_ => e.map_err_context(String::new),
|
||||||
|
})?;
|
||||||
|
let fsize = metadata.len() as usize;
|
||||||
let tsize = mode.to_size(fsize);
|
let tsize = mode.to_size(fsize);
|
||||||
for filename in &filenames {
|
for filename in &filenames {
|
||||||
file_truncate(filename, create, tsize)?;
|
file_truncate(filename, create, tsize).map_err_context(String::new)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -245,10 +235,20 @@ fn truncate_reference_file_only(
|
||||||
rfilename: &str,
|
rfilename: &str,
|
||||||
filenames: Vec<String>,
|
filenames: Vec<String>,
|
||||||
create: bool,
|
create: bool,
|
||||||
) -> std::io::Result<()> {
|
) -> UResult<()> {
|
||||||
let tsize = usize::try_from(metadata(rfilename)?.len()).unwrap();
|
let metadata = metadata(rfilename).map_err(|e| match e.kind() {
|
||||||
|
ErrorKind::NotFound => USimpleError::new(
|
||||||
|
1,
|
||||||
|
format!(
|
||||||
|
"cannot stat {}: No such file or directory",
|
||||||
|
rfilename.quote()
|
||||||
|
),
|
||||||
|
),
|
||||||
|
_ => e.map_err_context(String::new),
|
||||||
|
})?;
|
||||||
|
let tsize = metadata.len() as usize;
|
||||||
for filename in &filenames {
|
for filename in &filenames {
|
||||||
file_truncate(filename, create, tsize)?;
|
file_truncate(filename, create, tsize).map_err_context(String::new)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -268,15 +268,9 @@ fn truncate_reference_file_only(
|
||||||
///
|
///
|
||||||
/// If the any file could not be opened, or there was a problem setting
|
/// If the any file could not be opened, or there was a problem setting
|
||||||
/// the size of at least one file.
|
/// the size of at least one file.
|
||||||
fn truncate_size_only(
|
fn truncate_size_only(size_string: &str, filenames: Vec<String>, create: bool) -> UResult<()> {
|
||||||
size_string: &str,
|
let mode = parse_mode_and_size(size_string)
|
||||||
filenames: Vec<String>,
|
.map_err(|e| USimpleError::new(1, format!("Invalid number: {}", e)))?;
|
||||||
create: bool,
|
|
||||||
) -> std::io::Result<()> {
|
|
||||||
let mode = match parse_mode_and_size(size_string) {
|
|
||||||
Ok(m) => m,
|
|
||||||
Err(e) => crash!(1, "Invalid number: {}", e.to_string()),
|
|
||||||
};
|
|
||||||
for filename in &filenames {
|
for filename in &filenames {
|
||||||
let fsize = match metadata(filename) {
|
let fsize = match metadata(filename) {
|
||||||
Ok(m) => m.len(),
|
Ok(m) => m.len(),
|
||||||
|
@ -286,7 +280,7 @@ fn truncate_size_only(
|
||||||
match file_truncate(filename, create, tsize) {
|
match file_truncate(filename, create, tsize) {
|
||||||
Ok(_) => continue,
|
Ok(_) => continue,
|
||||||
Err(e) if e.kind() == ErrorKind::NotFound && !create => continue,
|
Err(e) if e.kind() == ErrorKind::NotFound && !create => continue,
|
||||||
Err(e) => return Err(e),
|
Err(e) => return Err(e.map_err_context(String::new)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -298,7 +292,7 @@ fn truncate(
|
||||||
reference: Option<String>,
|
reference: Option<String>,
|
||||||
size: Option<String>,
|
size: Option<String>,
|
||||||
filenames: Vec<String>,
|
filenames: Vec<String>,
|
||||||
) -> std::io::Result<()> {
|
) -> UResult<()> {
|
||||||
let create = !no_create;
|
let create = !no_create;
|
||||||
// There are four possibilities
|
// There are four possibilities
|
||||||
// - reference file given and size given,
|
// - reference file given and size given,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue