1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-30 20:47:46 +00:00

Build changes after merge with uutils main

This commit is contained in:
Tyler 2021-07-02 10:53:15 -07:00
parent 92281585a7
commit 8334d9f574
6 changed files with 258 additions and 267 deletions

2
Cargo.lock generated
View file

@ -1928,9 +1928,9 @@ name = "uu_dd"
version = "0.0.4"
dependencies = [
"byte-unit",
"clap",
"debug_print",
"gcd",
"getopts",
"libc",
"rand 0.8.4",
"signal-hook",

View file

@ -16,9 +16,8 @@ path = "src/dd.rs"
[dependencies]
byte-unit = "4.0"
clap = "2.33.3"
debug_print = "1.0"
# Probably best to keep the getopts version identical to the version of getopts in the uucore crate
getopts = "<= 0.2.21"
gcd = "2.0"
libc = "0.2"
signal-hook = "0.3.9"

View file

@ -1,4 +1,3 @@
// Conversion tables are just lookup tables.
// eg. The ASCII->EBCDIC table stores the EBCDIC code at the index
// obtained by treating the ASCII representation as a number.

View file

@ -0,0 +1,178 @@
use crate::conversion_tables::*;
use std::error::Error;
use std::time;
pub struct ProgUpdate
{
pub reads_complete: u64,
pub reads_partial: u64,
pub writes_complete: u64,
pub writes_partial: u64,
pub bytes_total: u128,
pub records_truncated: u32,
pub duration: time::Duration,
}
pub struct ReadStat
{
pub reads_complete: u64,
pub reads_partial: u64,
pub records_truncated: u32,
}
impl std::ops::AddAssign for ReadStat
{
fn add_assign(&mut self, other: Self)
{
*self = Self {
reads_complete: self.reads_complete + other.reads_complete,
reads_partial: self.reads_partial + other.reads_partial,
records_truncated: self.records_truncated + other.records_truncated,
}
}
}
pub struct WriteStat
{
pub writes_complete: u64,
pub writes_partial: u64,
pub bytes_total: u128,
}
impl std::ops::AddAssign for WriteStat
{
fn add_assign(&mut self, other: Self)
{
*self = Self {
writes_complete: self.writes_complete + other.writes_complete,
writes_partial: self.writes_partial + other.writes_partial,
bytes_total: self.bytes_total + other.bytes_total,
}
}
}
type Cbs = usize;
/// Stores all Conv Flags that apply to the input
pub struct IConvFlags
{
pub ctable: Option<&'static ConversionTable>,
pub block: Option<Cbs>,
pub unblock: Option<Cbs>,
pub swab: bool,
pub sync: Option<u8>,
pub noerror: bool,
}
/// Stores all Conv Flags that apply to the output
#[derive(Debug, PartialEq)]
pub struct OConvFlags
{
pub sparse: bool,
pub excl: bool,
pub nocreat: bool,
pub notrunc: bool,
pub fdatasync: bool,
pub fsync: bool,
}
/// Stores all Flags that apply to the input
pub struct IFlags
{
pub cio: bool,
pub direct: bool,
pub directory: bool,
pub dsync: bool,
pub sync: bool,
pub nocache: bool,
pub nonblock: bool,
pub noatime: bool,
pub noctty: bool,
pub nofollow: bool,
pub nolinks: bool,
pub binary: bool,
pub text: bool,
pub fullblock: bool,
pub count_bytes: bool,
pub skip_bytes: bool,
}
/// Stores all Flags that apply to the output
pub struct OFlags
{
pub append: bool,
pub cio: bool,
pub direct: bool,
pub directory: bool,
pub dsync: bool,
pub sync: bool,
pub nocache: bool,
pub nonblock: bool,
pub noatime: bool,
pub noctty: bool,
pub nofollow: bool,
pub nolinks: bool,
pub binary: bool,
pub text: bool,
pub seek_bytes: bool,
}
/// The value of the status cl-option.
/// Controls printing of transfer stats
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum StatusLevel
{
Progress,
Noxfer,
None,
}
/// The value of count=N
/// Defaults to Reads(N)
/// if iflag=count_bytes
/// then becomes Bytes(N)
pub enum CountType
{
Reads(usize),
Bytes(usize),
}
#[derive(Debug)]
pub enum InternalError
{
WrongInputType,
WrongOutputType,
InvalidConvBlockUnblockCase,
}
impl std::fmt::Display for InternalError
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self
{
Self::WrongInputType |
Self::WrongOutputType =>
write!(f, "Internal dd error: Wrong Input/Output data type"),
Self::InvalidConvBlockUnblockCase =>
write!(f, "Internal dd error: Invalid Conversion, Block, or Unblock data"),
}
}
}
impl Error for InternalError {}
pub mod options
{
pub const INFILE: &'static str = "if";
pub const OUTFILE: &'static str = "of";
pub const IBS: &'static str = "ibs";
pub const OBS: &'static str = "obs";
pub const BS: &'static str = "bs";
pub const CBS: &'static str = "cbs";
pub const COUNT: &'static str = "count";
pub const SKIP: &'static str = "skip";
pub const SEEK: &'static str = "seek";
pub const STATUS: &'static str = "status";
pub const CONV: &'static str = "conv";
pub const IFLAG: &'static str = "iflag";
pub const OFLAG: &'static str = "oflag";
}

View file

@ -14,202 +14,40 @@ use uucore::InvalidEncodingHandling;
#[cfg(test)]
mod dd_unit_tests;
mod datastructures;
use datastructures::*;
mod parseargs;
use parseargs::Matches;
mod conversion_tables;
use conversion_tables::*;
use clap::{self, crate_version};
use byte_unit::Byte;
use debug_print::debug_println;
use gcd::Gcd;
use getopts;
use signal_hook::consts::signal;
use std::cmp;
use std::convert::TryInto;
use std::error::Error;
use std::env;
use std::fs::{
File, OpenOptions,
};
use std::io::{
self, Read, Write,
Seek,
};
use std::fs::{File, OpenOptions, };
use std::io::{self, Read, Write, Seek, };
#[cfg(unix)]
use libc;
#[cfg(unix)]
use std::os::unix::fs::OpenOptionsExt;
use std::sync::{
Arc, atomic::AtomicUsize, mpsc, atomic::Ordering,
};
use std::sync::{Arc, atomic::AtomicUsize, mpsc, atomic::Ordering, };
use std::thread;
use std::time;
const SYNTAX: &str = "dd [OPERAND]...\ndd OPTION";
const SUMMARY: &str = "copy, and optionally convert, a file system resource";
const LONG_HELP: &str = "";
const ABOUT: &str = "copy, and optionally convert, a file system resource";
const BUF_INIT_BYTE: u8 = 0xDD;
const RTN_SUCCESS: i32 = 0;
const RTN_FAILURE: i32 = 1;
// ----- Datatypes -----
struct ProgUpdate
{
reads_complete: u64,
reads_partial: u64,
writes_complete: u64,
writes_partial: u64,
bytes_total: u128,
records_truncated: u32,
duration: time::Duration,
}
struct ReadStat
{
reads_complete: u64,
reads_partial: u64,
records_truncated: u32,
}
impl std::ops::AddAssign for ReadStat
{
fn add_assign(&mut self, other: Self)
{
*self = Self {
reads_complete: self.reads_complete + other.reads_complete,
reads_partial: self.reads_partial + other.reads_partial,
records_truncated: self.records_truncated + other.records_truncated,
}
}
}
struct WriteStat
{
writes_complete: u64,
writes_partial: u64,
bytes_total: u128,
}
impl std::ops::AddAssign for WriteStat
{
fn add_assign(&mut self, other: Self)
{
*self = Self {
writes_complete: self.writes_complete + other.writes_complete,
writes_partial: self.writes_partial + other.writes_partial,
bytes_total: self.bytes_total + other.bytes_total,
}
}
}
type Cbs = usize;
/// Stores all Conv Flags that apply to the input
pub struct IConvFlags
{
ctable: Option<&'static ConversionTable>,
block: Option<Cbs>,
unblock: Option<Cbs>,
swab: bool,
sync: Option<u8>,
noerror: bool,
}
/// Stores all Conv Flags that apply to the output
#[derive(Debug, PartialEq)]
pub struct OConvFlags
{
sparse: bool,
excl: bool,
nocreat: bool,
notrunc: bool,
fdatasync: bool,
fsync: bool,
}
/// Stores all Flags that apply to the input
pub struct IFlags
{
cio: bool,
direct: bool,
directory: bool,
dsync: bool,
sync: bool,
nocache: bool,
nonblock: bool,
noatime: bool,
noctty: bool,
nofollow: bool,
nolinks: bool,
binary: bool,
text: bool,
fullblock: bool,
count_bytes: bool,
skip_bytes: bool,
}
/// Stores all Flags that apply to the output
pub struct OFlags
{
append: bool,
cio: bool,
direct: bool,
directory: bool,
dsync: bool,
sync: bool,
nocache: bool,
nonblock: bool,
noatime: bool,
noctty: bool,
nofollow: bool,
nolinks: bool,
binary: bool,
text: bool,
seek_bytes: bool,
}
/// The value of the status cl-option.
/// Controls printing of transfer stats
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum StatusLevel
{
Progress,
Noxfer,
None,
}
/// The value of count=N
/// Defaults to Reads(N)
/// if iflag=count_bytes
/// then becomes Bytes(N)
pub enum CountType
{
Reads(usize),
Bytes(usize),
}
#[derive(Debug)]
enum InternalError
{
WrongInputType,
WrongOutputType,
InvalidConvBlockUnblockCase,
}
impl std::fmt::Display for InternalError
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self
{
Self::WrongInputType |
Self::WrongOutputType =>
write!(f, "Internal dd error: Wrong Input/Output data type"),
Self::InvalidConvBlockUnblockCase =>
write!(f, "Internal dd error: Invalid Conversion, Block, or Unblock data"),
}
}
}
impl Error for InternalError {}
struct Input<R: Read>
{
src: R,
@ -223,7 +61,7 @@ struct Input<R: Read>
impl Input<io::Stdin>
{
fn new(matches: &getopts::Matches) -> Result<Self, Box<dyn Error>>
fn new(matches: &Matches) -> Result<Self, Box<dyn Error>>
{
let ibs = parseargs::parse_ibs(matches)?;
let non_ascii = parseargs::parse_input_non_ascii(matches)?;
@ -303,7 +141,7 @@ fn make_unix_iflags(oflags: &IFlags) -> Option<libc::c_int>
impl Input<File>
{
fn new(matches: &getopts::Matches) -> Result<Self, Box<dyn Error>>
fn new(matches: &Matches) -> Result<Self, Box<dyn Error>>
{
let ibs = parseargs::parse_ibs(matches)?;
let non_ascii = parseargs::parse_input_non_ascii(matches)?;
@ -313,7 +151,7 @@ impl Input<File>
let skip = parseargs::parse_skip_amt(&ibs, &iflags, matches)?;
let count = parseargs::parse_count(&iflags, matches)?;
if let Some(fname) = matches.opt_str("if")
if let Some(fname) = matches.value_of("if")
{
let mut src =
{
@ -359,7 +197,7 @@ impl Input<File>
impl<R: Read> Read for Input<R>
{
fn read(&mut self, mut buf: &mut [u8]) -> io::Result<usize>
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize>
{
let mut base_idx = 0;
let tlen = buf.len();
@ -513,21 +351,16 @@ struct Output<W: Write>
}
impl Output<io::Stdout> {
fn new(matches: &getopts::Matches) -> Result<Self, Box<dyn Error>>
fn new(matches: &Matches) -> Result<Self, Box<dyn Error>>
{
let obs = parseargs::parse_obs(matches)?;
let cflags = parseargs::parse_conv_flag_output(matches)?;
let oflags = parseargs::parse_oflags(matches)?;
let seek = parseargs::parse_seek_amt(&obs, &oflags, matches)?;
if let Some(amt) = seek
{
let amt: u64 = amt.try_into()?;
dst.seek(io::SeekFrom::Start(amt))?;
}
let dst = io::stdout();
Ok(Output {
dst: io::stdout(),
dst,
obs,
cflags,
oflags,
@ -598,14 +431,14 @@ fn make_unix_oflags(oflags: &OFlags) -> Option<libc::c_int>
}
impl Output<File> {
fn new(matches: &getopts::Matches) -> Result<Self, Box<dyn Error>>
fn new(matches: &Matches) -> Result<Self, Box<dyn Error>>
{
let obs = parseargs::parse_obs(matches)?;
let cflags = parseargs::parse_conv_flag_output(matches)?;
let oflags = parseargs::parse_oflags(matches)?;
let seek = parseargs::parse_seek_amt(&obs, &oflags, matches)?;
if let Some(fname) = matches.opt_str("of")
if let Some(fname) = matches.value_of("of")
{
let mut dst = {
let mut opts = OpenOptions::new();
@ -702,37 +535,11 @@ impl Write for Output<File>
}
}
impl Seek for Output<io::Stdout>
{
fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64>
{
self.dst.seek(pos)
}
}
impl Write for Output<io::Stdout>
{
fn write(&mut self, buf: &[u8]) -> io::Result<usize>
{
#[inline]
fn is_sparse(buf: &[u8]) -> bool
{
buf.iter()
.all(|&e| e == 0u8)
}
// -----------------------------
if self.cflags.sparse && is_sparse(buf)
{
let seek_amt: i64 = buf.len()
.try_into()
.expect("Internal dd Error: Seek amount greater than signed 64-bit integer");
self.dst.seek(io::SeekFrom::Current(seek_amt))?;
Ok(buf.len())
}
else
{
self.dst.write(buf)
}
self.dst.write(buf)
}
fn flush(&mut self) -> io::Result<()>
@ -1446,9 +1253,14 @@ pub fn uumain(args: impl uucore::Args) -> i32
.accept_any()
.iter()
.fold(Vec::new(), append_dashes_if_not_present);
let matches = build_app!().parse(dashed_args);
let result = match (matches.opt_present("if"), matches.opt_present("of"))
let matches = build_dd_app!()
// TODO: usage, after_help
//.usage(...)
//.after_help(...)
.get_matches_from(dashed_args);
let result = match (matches.is_present(options::INFILE), matches.is_present(options::OUTFILE))
{
(true, true) =>
{
@ -1489,74 +1301,74 @@ pub fn uumain(args: impl uucore::Args) -> i32
}
}
pub fn uu_app() -> App<'static, 'static>
pub fn uu_app() -> clap::App<'static, 'static>
{
build_app!()
build_dd_app!()
}
#[macro_export]
macro_rules! build_app (
macro_rules! build_dd_app (
() =>
{
App::new(executable!())
clap::App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.arg(
Arg::with_name(options::INFILE)
clap::Arg::with_name(options::INFILE)
.long(options::INFILE)
.takes_value(true)
.help("if=FILE (alternatively --if FILE) specifies the file used for input. When not specified, stdin is used instead")
)
.arg(
Arg::with_name(options::OUTFILE)
clap::Arg::with_name(options::OUTFILE)
.long(options::OUTFILE)
.takes_value(true)
.help("of=FILE (alternatively --of FILE) specifies the file used for output. When not specified, stdout is used instead")
)
.arg(
Arg::with_name(options::IBS)
clap::Arg::with_name(options::IBS)
.long(options::IBS)
.takes_value(true)
.help("ibs=N (alternatively --ibs N) specifies the size of buffer used for reads (default: 512). Multiplier strings permitted.")
)
.arg(
Arg::with_name(options::OBS)
clap::Arg::with_name(options::OBS)
.long(options::OBS)
.takes_value(true)
.help("obs=N (alternatively --obs N) specifies the size of buffer used for writes (default: 512). Multiplier strings permitted.")
)
.arg(
Arg::with_name(options::BS)
clap::Arg::with_name(options::BS)
.long(options::BS)
.takes_value(true)
.help("bs=N (alternatively --bs N) specifies ibs=N and obs=N (default: 512). If ibs or obs are also specified, bs=N takes presedence. Multiplier strings permitted.")
)
.arg(
Arg::with_name(options::CBS)
clap::Arg::with_name(options::CBS)
.long(options::CBS)
.takes_value(true)
.help("cbs=BYTES (alternatively --cbs BYTES) specifies the 'conversion block size' in bytes. Applies to the conv=block, and conv=unblock operations. Multiplier strings permitted.")
)
.arg(
Arg::with_name(options::SKIP)
clap::Arg::with_name(options::SKIP)
.long(options::SKIP)
.takes_value(true)
.help("skip=N (alternatively --skip N) causes N ibs-sized records of input to be skipped before beginning copy/convert operations. See iflag=count_bytes if skipping N bytes is prefered. Multiplier strings permitted.")
)
.arg(
Arg::with_name(options::SEEK)
clap::Arg::with_name(options::SEEK)
.long(options::SEEK)
.takes_value(true)
.help("seek=N (alternatively --seek N) seeks N obs-sized records into output before beginning copy/convert operations. See oflag=seek_bytes if seeking N bytes is prefered. Multiplier strings permitted.")
)
.arg(
Arg::with_name(options::COUNT)
clap::Arg::with_name(options::COUNT)
.long(options::COUNT)
.takes_value(true)
.help("count=N (alternatively --count N) stop reading input after N ibs-sized read operations rather than proceeding until EOF. See iflag=count_bytes if stopping after N bytes is prefered. Multiplier strings permitted.")
)
.arg(
Arg::with_name(options::STATUS)
clap::Arg::with_name(options::STATUS)
.long(options::STATUS)
.takes_value(true)
.help("status=LEVEL (alternatively --status LEVEL) controls whether volume and performace stats are written to stderr.
@ -1577,7 +1389,7 @@ Printing performance stats is also triggered by the INFO signal (where supported
")
)
.arg(
Arg::with_name(options::CONV)
clap::Arg::with_name(options::CONV)
.long(options::CONV)
.takes_value(true)
.help("conv=CONV[,CONV] (alternatively --conv CONV[,CONV]) specifies a comma-separated list of conversion options or (for legacy reasons) file-flags. Conversion options and file flags may be intermixed.
@ -1611,7 +1423,7 @@ Flags:
")
)
.arg(
Arg::with_name(options::IFLAG)
clap::Arg::with_name(options::IFLAG)
.long(options::IFLAG)
.takes_value(true)
.help("iflag=FLAG[,FLAG] (alternatively --iflag FLAG[,FLAG]) a comma separated list of input flags which specify how the input source is treated. FLAG may be any of the input-flags or general-flags specified below.
@ -1638,7 +1450,7 @@ Output-Flags
")
)
.arg(
Arg::with_name(options::OFLAG)
clap::Arg::with_name(options::OFLAG)
.long(options::OFLAG)
.takes_value(true)
.help("oflag=FLAG[,FLAG] (alternatively --oflag FLAG[,FLAG]) a comma separated list of output flags which specify how the output source is treated. FLAG may be any of the output-flags or general-flags specified below.

View file

@ -13,6 +13,8 @@ use crate::{
use std::error::Error;
pub type Matches = clap::ArgMatches<'static>;
/// Parser Errors describe errors with parser input
#[derive(Debug)]
pub enum ParseError
@ -300,21 +302,22 @@ fn parse_multiplier<'a>(s: &'a str) -> Result<usize, ParseError>
// "Y" | "YiB" =>
// Ok(1024*1024*1024*1024*1024*1024*1024*1024),
_ =>
Err(ParseError::NoMatchingMultiplier(String::from(s))),
Err(ParseError::NoMatchingMultiplier(s.to_string())),
}
}
fn parse_bytes_only(s: &str) -> Result<usize, ParseError>
{
let bytes: usize = match s.parse()
match s.parse()
{
Ok(val) => val,
Err(_) => return Err(ParseError::ByteStringContainsNoValue(String::from(s))),
};
Ok(bytes)
Ok(bytes) =>
Ok(bytes),
Err(_) =>
Err(ParseError::ByteStringContainsNoValue(s.to_string())),
}
}
fn parse_bytes_with_opt_multiplier(s: String) -> Result<usize, ParseError>
fn parse_bytes_with_opt_multiplier(s: &str) -> Result<usize, ParseError>
{
match s.find(char::is_alphabetic)
{
@ -329,7 +332,7 @@ fn parse_bytes_with_opt_multiplier(s: String) -> Result<usize, ParseError>
}
else
{
Err(ParseError::MultiplierStringWouldOverflow(s))
Err(ParseError::MultiplierStringWouldOverflow(s.to_string()))
}
}
_ =>
@ -337,13 +340,13 @@ fn parse_bytes_with_opt_multiplier(s: String) -> Result<usize, ParseError>
}
}
pub fn parse_ibs(matches: &getopts::Matches) -> Result<usize, ParseError>
pub fn parse_ibs(matches: &Matches) -> Result<usize, ParseError>
{
if let Some(mixed_str) = matches.opt_str("bs")
if let Some(mixed_str) = matches.value_of("bs")
{
parse_bytes_with_opt_multiplier(mixed_str)
}
else if let Some(mixed_str) = matches.opt_str("ibs")
else if let Some(mixed_str) = matches.value_of("ibs")
{
parse_bytes_with_opt_multiplier(mixed_str)
}
@ -353,9 +356,9 @@ pub fn parse_ibs(matches: &getopts::Matches) -> Result<usize, ParseError>
}
}
fn parse_cbs(matches: &getopts::Matches) -> Result<Option<usize>, ParseError>
fn parse_cbs(matches: &Matches) -> Result<Option<usize>, ParseError>
{
if let Some(s) = matches.opt_str("cbs")
if let Some(s) = matches.value_of("cbs")
{
let bytes = parse_bytes_with_opt_multiplier(s)?;
Ok(Some(bytes))
@ -366,9 +369,9 @@ fn parse_cbs(matches: &getopts::Matches) -> Result<Option<usize>, ParseError>
}
}
pub fn parse_status_level(matches: &getopts::Matches) -> Result<Option<StatusLevel>, ParseError>
pub fn parse_status_level(matches: &Matches) -> Result<Option<StatusLevel>, ParseError>
{
match matches.opt_str("status")
match matches.value_of("status")
{
Some(s) =>
{
@ -380,13 +383,13 @@ pub fn parse_status_level(matches: &getopts::Matches) -> Result<Option<StatusLev
}
}
pub fn parse_obs(matches: &getopts::Matches) -> Result<usize, ParseError>
pub fn parse_obs(matches: &Matches) -> Result<usize, ParseError>
{
if let Some(mixed_str) = matches.opt_str("bs")
if let Some(mixed_str) = matches.value_of("bs")
{
parse_bytes_with_opt_multiplier(mixed_str)
}
else if let Some(mixed_str) = matches.opt_str("obs")
else if let Some(mixed_str) = matches.value_of("obs")
{
parse_bytes_with_opt_multiplier(mixed_str)
}
@ -452,11 +455,11 @@ fn parse_ctable(fmt: Option<ConvFlag>, case: Option<ConvFlag>) -> Option<&'stati
}
}
fn parse_flag_list<T: std::str::FromStr<Err = ParseError>>(tag: &str, matches: &getopts::Matches) -> Result<Vec<T>, ParseError>
fn parse_flag_list<T: std::str::FromStr<Err = ParseError>>(tag: &str, matches: &Matches) -> Result<Vec<T>, ParseError>
{
let mut flags = Vec::new();
if let Some(comma_str) = matches.opt_str(tag)
if let Some(comma_str) = matches.value_of(tag)
{
for s in comma_str.split(",")
{
@ -470,7 +473,7 @@ fn parse_flag_list<T: std::str::FromStr<Err = ParseError>>(tag: &str, matches: &
/// Parse Conversion Options (Input Variety)
/// Construct and validate a IConvFlags
pub fn parse_conv_flag_input(matches: &getopts::Matches) -> Result<IConvFlags, ParseError>
pub fn parse_conv_flag_input(matches: &Matches) -> Result<IConvFlags, ParseError>
{
let flags = parse_flag_list("conv", matches)?;
let cbs = parse_cbs(matches)?;
@ -588,7 +591,7 @@ pub fn parse_conv_flag_input(matches: &getopts::Matches) -> Result<IConvFlags, P
/// Parse Conversion Options (Output Variety)
/// Construct and validate a OConvFlags
pub fn parse_conv_flag_output(matches: &getopts::Matches) -> Result<OConvFlags, ParseError>
pub fn parse_conv_flag_output(matches: &Matches) -> Result<OConvFlags, ParseError>
{
let flags = parse_flag_list("conv", matches)?;
@ -644,7 +647,7 @@ pub fn parse_conv_flag_output(matches: &getopts::Matches) -> Result<OConvFlags,
}
/// Parse IFlags struct from CL-input
pub fn parse_iflags(matches: &getopts::Matches) -> Result<IFlags, ParseError>
pub fn parse_iflags(matches: &Matches) -> Result<IFlags, ParseError>
{
let mut cio = false;
let mut direct = false;
@ -726,7 +729,7 @@ pub fn parse_iflags(matches: &getopts::Matches) -> Result<IFlags, ParseError>
}
/// Parse OFlags struct from CL-input
pub fn parse_oflags(matches: &getopts::Matches) -> Result<OFlags, ParseError>
pub fn parse_oflags(matches: &Matches) -> Result<OFlags, ParseError>
{
let mut append = false;
let mut cio = false;
@ -804,9 +807,9 @@ pub fn parse_oflags(matches: &getopts::Matches) -> Result<OFlags, ParseError>
}
/// Parse the amount of the input file to skip.
pub fn parse_skip_amt(ibs: &usize, iflags: &IFlags, matches: &getopts::Matches) -> Result<Option<usize>, ParseError>
pub fn parse_skip_amt(ibs: &usize, iflags: &IFlags, matches: &Matches) -> Result<Option<usize>, ParseError>
{
if let Some(amt) = matches.opt_str("skip")
if let Some(amt) = matches.value_of("skip")
{
if iflags.skip_bytes
{
@ -826,9 +829,9 @@ pub fn parse_skip_amt(ibs: &usize, iflags: &IFlags, matches: &getopts::Matches)
}
/// Parse the amount of the output file to seek.
pub fn parse_seek_amt(obs: &usize, oflags: &OFlags, matches: &getopts::Matches) -> Result<Option<usize>, ParseError>
pub fn parse_seek_amt(obs: &usize, oflags: &OFlags, matches: &Matches) -> Result<Option<usize>, ParseError>
{
if let Some(amt) = matches.opt_str("seek")
if let Some(amt) = matches.value_of("seek")
{
if oflags.seek_bytes
{
@ -848,9 +851,9 @@ pub fn parse_seek_amt(obs: &usize, oflags: &OFlags, matches: &getopts::Matches)
}
/// Parse the value of count=N and the type of N implied by iflags
pub fn parse_count(iflags: &IFlags, matches: &getopts::Matches) -> Result<Option<CountType>, ParseError>
pub fn parse_count(iflags: &IFlags, matches: &Matches) -> Result<Option<CountType>, ParseError>
{
if let Some(amt) = matches.opt_str("count")
if let Some(amt) = matches.value_of("count")
{
let n = parse_bytes_with_opt_multiplier(amt)?;
if iflags.count_bytes
@ -869,9 +872,9 @@ pub fn parse_count(iflags: &IFlags, matches: &getopts::Matches) -> Result<Optio
}
/// Parse whether the args indicate the input is not ascii
pub fn parse_input_non_ascii(matches: &getopts::Matches) -> Result<bool, ParseError>
pub fn parse_input_non_ascii(matches: &Matches) -> Result<bool, ParseError>
{
if let Some(conv_opts) = matches.opt_str("conv")
if let Some(conv_opts) = matches.value_of("conv")
{
Ok(conv_opts.contains("ascii"))
}