Add `md5sum` applet

This commit is contained in:
Nathan Fisher 2023-02-03 19:12:40 -05:00
parent bcb5725a5c
commit 8df1f99f70
5 changed files with 169 additions and 1 deletions

61
Cargo.lock generated
View File

@ -19,6 +19,15 @@ version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "block-buffer"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e"
dependencies = [
"generic-array",
]
[[package]]
name = "cc"
version = "1.0.78"
@ -76,12 +85,32 @@ dependencies = [
"roff",
]
[[package]]
name = "crypto-common"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array",
"typenum",
]
[[package]]
name = "data-encoding"
version = "2.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23d8666cb01533c39dde32bcbab8e227b4ed6679b2c925eba05feabea39508fb"
[[package]]
name = "digest"
version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f"
dependencies = [
"block-buffer",
"crypto-common",
]
[[package]]
name = "errno"
version = "0.2.8"
@ -103,6 +132,16 @@ dependencies = [
"libc",
]
[[package]]
name = "generic-array"
version = "0.14.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "hermit-abi"
version = "0.1.19"
@ -155,6 +194,15 @@ version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
[[package]]
name = "md-5"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6365506850d44bff6e2fbcb5176cf63650e48bd45ef2fe2665ae1570e0f4b9ca"
dependencies = [
"digest",
]
[[package]]
name = "os_str_bytes"
version = "6.4.1"
@ -207,6 +255,7 @@ dependencies = [
"clap_mangen",
"data-encoding",
"libc",
"md-5",
"sc",
"termcolor",
"textwrap",
@ -243,6 +292,18 @@ dependencies = [
"smawk",
]
[[package]]
name = "typenum"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "walkdir"
version = "2.3.2"

View File

@ -13,6 +13,7 @@ clap_complete_nushell = "0.1"
clap_mangen = "0.2"
data-encoding = "2.3"
libc = "0.2"
md-5 = "0.10.5"
sc = "0.2"
termcolor = "1.1"
textwrap = { version = "0.16", default-features = false, features = ["smawk"] }

View File

@ -38,6 +38,7 @@ code between applets, making for an overall smaller binary.
- hostname
- link
- logname
- md5sum
- mkfifo
- mknod
- mountpoint

102
src/cmd/md5sum/mod.rs Normal file
View File

@ -0,0 +1,102 @@
use super::Cmd;
use clap::{Arg, ArgAction, Command};
use md5::{Digest, Md5};
use std::{
fmt::Write,
fs::File,
io::{self, BufRead, BufReader, Read},
process, error::Error,
};
#[derive(Debug, Default)]
pub struct Md5sum;
impl Cmd for Md5sum {
fn cli(&self) -> clap::Command {
Command::new("md5sum")
.about("compute and check MD5 message digest")
.author("Nathan Fisher")
.version(env!("CARGO_PKG_VERSION"))
.args([
Arg::new("check")
.help("read checksums from the FILEs and check them")
.short('c')
.long("check")
.action(ArgAction::SetTrue),
Arg::new("file")
.value_name("FILE")
.num_args(1..)
.default_value("-"),
])
}
fn run(&self, matches: Option<&clap::ArgMatches>) -> Result<(), Box<dyn std::error::Error>> {
let Some(matches) = matches else {
return Err(io::Error::new(io::ErrorKind::Other, "no input").into());
};
if let Some(files) = matches.get_many::<String>("file") {
let mut erred = 0;
for f in files {
if matches.get_flag("check") {
if f == "-" {
return Err(
io::Error::new(io::ErrorKind::Other, "no file specified").into()
);
}
let fd = File::open(f)?;
let reader = BufReader::new(fd);
for line in reader.lines() {
let line = line?;
let mut split = line.split_whitespace();
let sum = split.next().ok_or::<Box<dyn Error>>(
io::Error::new(io::ErrorKind::Other, "invalid checksum file").into(),
)?;
let file = split.next().ok_or::<Box<dyn Error>>(
io::Error::new(io::ErrorKind::Other, "invalid checksum file").into(),
)?;
let mut hasher = Md5::new();
let mut buf = vec![];
let mut fd = File::open(file)?;
let _s = fd.read_to_end(&mut buf)?;
hasher.update(&buf);
let res = hasher.finalize();
let mut s = String::new();
for c in res {
write!(s, "{c:x}")?;
}
if s.as_str() == sum {
println!("{file}: OK");
} else {
println!("{file}: FAILED");
erred += 1;
}
}
} else {
let mut hasher = Md5::new();
let mut buf = vec![];
if f == "-" {
let _s = io::stdin().read_to_end(&mut buf)?;
} else {
let mut fd = File::open(f)?;
let _s = fd.read_to_end(&mut buf)?;
}
hasher.update(&buf);
let res = hasher.finalize();
for c in res {
print!("{c:x}");
}
println!(" {f}");
}
}
if erred > 0 {
println!("md5sum: WARNING: {erred} computed checksum did NOT match");
process::exit(1);
}
}
Ok(())
}
fn path(&self) -> Option<crate::Path> {
Some(crate::Path::UsrBin)
}
}

View File

@ -29,6 +29,7 @@ mod link;
mod ln;
mod logname;
mod ls;
mod md5sum;
mod mkfifo;
mod mknod;
mod mktemp;
@ -93,6 +94,7 @@ pub fn get(name: &str) -> Option<Box<dyn Cmd>> {
"hostname" => Some(Box::new(hostname::Hostname::default())),
"link" => Some(Box::new(link::Link::default())),
"logname" => Some(Box::new(logname::Logname::default())),
"md5sum" => Some(Box::new(md5sum::Md5sum::default())),
"mkfifo" => Some(Box::new(mkfifo::MkFifo::default())),
"mknod" => Some(Box::new(mknod::MkNod::default())),
"mktemp" => Some(Box::new(mktemp::MkTemp::default())),
@ -119,7 +121,7 @@ pub fn get(name: &str) -> Option<Box<dyn Cmd>> {
}
}
pub static COMMANDS: [&str; 43] = [
pub static COMMANDS: [&str; 44] = [
"base32",
"base64",
"basename",
@ -141,6 +143,7 @@ pub static COMMANDS: [&str; 43] = [
"hostname",
"link",
"logname",
"md5sum",
"mkfifo",
"mknod",
"mktemp",