dd_lib/lib.rs
1//! # dd: convert and copy a file
2//!
3//! ## SYNOPSIS
4//! dd \[OPERAND\]...
5//! dd OPTION
6//! ## DESCRIPTION
7//! Copy a file converting and formatting according to the operands.
8//!
9//! ## [`opts`]
10//! Note: the parsing of numeric arguments is a little unusual and allows for
11//! numeric suffixes. See the documentation of [opts::number] and
12//! [opts::number::units];
13//!
14//! - **bs**=BYTES: read and write up to BYTES bytes at a time (default: 512).
15//! - **overrides ibs and obs**
16//!
17//! - **cbs**=BYTES: convert BYTES bytes at a time
18//!
19//! - **conv**=[`CONVS`][opts::Conv]: convert the file as per the coma
20//! separated symbol list
21//!
22//! - **count**=N: copy only N input blocks
23//!
24//! - **ibs**=BYTES: read up to BYTES bytes at a time (default: 512)
25//!
26//! - **if**=FILE: read from FILE instead of stdin
27//!
28//! - **iflag**=[`FLAGS`][opts::In]: read as per the comma separated symbol
29//! list
30//!
31//! - **obs**=BYTES: write BYTES bytes at a time (default: 512)
32//!
33//! - **of**=FILE: write to FILE instead of stdout
34//!
35//! - **oflag**=[`FLAGS`][opts::Out]: write as per the comma separated symbol
36//! list
37//!
38//! - **seek**=N: skip N obs-sized blocks at start of output
39//!
40//! - **skip**=N: skip N ibs-sized blocks at start of input
41//!
42//! - **status=[LEVEL][opts::StatusLevel]**: the level of information to print
43//! to stderr
44//!
45//! none: suppresses everything but error messages,
46//! progress //! - **shows** periodic transfer statistics
47//! noxfer: suppresses the final transfer statistics,
48//!
49//!
50//! ### [Units][opts::number::units]:
51
52//! ### [`CONV`][opts::Conv]
53//! Each CONV symbol may be:
54
55//!
56//! - **ascii** from EBCDIC to ASCII
57
58//!
59//! - **ebcdic** from ASCII to EBCDIC
60
61//!
62//! - **ibm** from ASCII to alternate EBCDIC
63
64//!
65//! - **block** pad newline-terminated records with spaces to cbs-size
66
67//!
68//! - **unblock** replace trailing spaces in cbs-size records with newline
69
70//!
71//! - **lcase** change upper case to lower case
72
73//!
74//! - **ucase** change lower case to upper case
75
76//!
77//! - **sparse** try to seek rather than write the output for NUL input blocks
78
79//!
80//! - **swab** swap every pair of input bytes
81
82//!
83//! - **sync** pad every input block with NULs to ibs-size; when used with
84//! block or unblock, pad with spaces rather than NULs
85
86//!
87//! - **excl** fail if the output file already exists
88
89//!
90//! - **nocreat** do not create the output file
91
92//!
93//! - **notrunc** do not truncate the output file
94
95//!
96//! - **noerror** continue after read errors
97
98//!
99//! - **fdatasync**
100//! physically write output file data before finishing
101//! - **fsync** likewise, but also write metadata
102
103//! ### SIGNALS
104//! Sending a USR1 signal to a running 'dd' process makes it print I/O
105//! statistics to standard error and then resume copying.
106//!
107//!
108//! ### OPTIONS
109//! --help display this help and exit
110//! --version
111//! output version information and exit
112//! ### AUTHOR
113//! Originally Written by Paul Rubin, David MacKenzie, and Stuart Kemp.
114//! Clone written _only_ by looking at man page by Efron Licht
115//! input, output, and encoding
116
117pub mod io;
118pub mod opts;
119pub mod units;
120use io::{Converter, ErrHandler, Reader, Writer};
121pub use results::{Result, Success};
122
123mod results;
124
125#[cfg(test)]
126extern crate tempfile;
127#[macro_use]
128extern crate bitflags;
129extern crate encoding8;
130
131#[cfg(test)]
132mod tests;
133
134/// The dd utility copies the standard input to the standard output. Input data
135/// is read and written in n-byte blocks (default `512`). If input reads are
136/// short, input from multiple reads are aggregated to form the output block.
137/// When finished, dd displays the number of complete and partial input and
138/// output blocks and truncated input records to the standard error output.
139pub fn dd(o: &opts::Opts) -> Result<Success> {
140 let stderr = std::io::stderr();
141 let lock = stderr.lock();
142 dd_pipe_err(o, lock)
143}
144
145/// dd, piping standard error to E
146pub fn dd_pipe_err<E>(o: &opts::Opts, err: E) -> Result<Success>
147where
148 E: std::io::Write, // in practice, this is always stderr
149{
150 let (stdin, stdout) = (std::io::stdin(), std::io::stdout());
151 let r = Reader::new(&stdin, o)?;
152 let mut w = Writer::new(&stdout, o)?;
153 let c = Converter::new(o)?;
154 let e = ErrHandler::new(err, o);
155 match o.mode {
156 opts::Mode::Block(n) => io::copy::block(r, &mut w, c, e, n),
157 opts::Mode::Unblock(n) => io::copy::unblock(r, &mut w, c, e, n),
158 opts::Mode::Standard => io::copy::standard(r, &mut w, c, e),
159 }
160}