mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 11:37:44 +00:00
Merge pull request #143 from Arcterus/md5sum
Implement md5sum (closes #47)
This commit is contained in:
commit
2e124cc778
9 changed files with 204 additions and 10 deletions
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
[submodule "md5sum/rust-crypto"]
|
||||||
|
path = md5sum/rust-crypto
|
||||||
|
url = git://github.com/DaGenix/rust-crypto.git
|
19
Makefile
19
Makefile
|
@ -1,10 +1,4 @@
|
||||||
# Binaries
|
include common.mk
|
||||||
RUSTC ?= rustc
|
|
||||||
RM := rm
|
|
||||||
|
|
||||||
# Flags
|
|
||||||
RUSTCFLAGS := --opt-level=3
|
|
||||||
RMFLAGS :=
|
|
||||||
|
|
||||||
# Possible programs
|
# Possible programs
|
||||||
PROGS := \
|
PROGS := \
|
||||||
|
@ -16,6 +10,7 @@ PROGS := \
|
||||||
env \
|
env \
|
||||||
du \
|
du \
|
||||||
false \
|
false \
|
||||||
|
md5sum \
|
||||||
mkdir \
|
mkdir \
|
||||||
paste \
|
paste \
|
||||||
printenv \
|
printenv \
|
||||||
|
@ -70,8 +65,16 @@ command = sh -c '$(1)'
|
||||||
|
|
||||||
# Main exe build rule
|
# Main exe build rule
|
||||||
define EXE_BUILD
|
define EXE_BUILD
|
||||||
|
ifeq ($(wildcard $(1)/Makefile),)
|
||||||
build/$(1): $(1)/$(1).rs
|
build/$(1): $(1)/$(1).rs
|
||||||
$(call command,$(RUSTC) $(RUSTCFLAGS) -o build/$(1) $(1)/$(1).rs)
|
$(call command,$(RUSTC) $(RUSTCFLAGS) -o build/$(1) $(1)/$(1).rs)
|
||||||
|
clean_$(1):
|
||||||
|
else
|
||||||
|
build/$(1): $(1)/$(1).rs
|
||||||
|
cd $(1) && make
|
||||||
|
clean_$(1):
|
||||||
|
cd $(1) && make clean
|
||||||
|
endif
|
||||||
endef
|
endef
|
||||||
|
|
||||||
# Test exe built rules
|
# Test exe built rules
|
||||||
|
@ -89,7 +92,7 @@ all: build $(EXES_PATHS)
|
||||||
test: tmp $(addprefix test_,$(TESTS))
|
test: tmp $(addprefix test_,$(TESTS))
|
||||||
$(RM) -rf tmp
|
$(RM) -rf tmp
|
||||||
|
|
||||||
clean:
|
clean: $(addprefix clean_,$(EXES))
|
||||||
$(RM) -rf build tmp
|
$(RM) -rf build tmp
|
||||||
|
|
||||||
build:
|
build:
|
||||||
|
|
|
@ -108,7 +108,6 @@ To do
|
||||||
- ls-vdir
|
- ls-vdir
|
||||||
- ls
|
- ls
|
||||||
- make-prime-list
|
- make-prime-list
|
||||||
- md5sum
|
|
||||||
- mkfifo
|
- mkfifo
|
||||||
- mknod
|
- mknod
|
||||||
- mktemp
|
- mktemp
|
||||||
|
|
7
common.mk
Normal file
7
common.mk
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
# Binaries
|
||||||
|
RUSTC ?= rustc
|
||||||
|
RM := rm
|
||||||
|
|
||||||
|
# Flags
|
||||||
|
RUSTCFLAGS := --opt-level=3
|
||||||
|
RMFLAGS :=
|
|
@ -18,6 +18,14 @@ macro_rules! show_error(
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! show_warning(
|
||||||
|
($($args:expr),+) => ({
|
||||||
|
safe_write!(&mut ::std::io::stderr(), "{}: warning: ", ::NAME);
|
||||||
|
safe_writeln!(&mut ::std::io::stderr(), $($args),+);
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! crash(
|
macro_rules! crash(
|
||||||
($exitcode:expr, $($args:expr),+) => ({
|
($exitcode:expr, $($args:expr),+) => ({
|
||||||
|
|
15
md5sum/Makefile
Normal file
15
md5sum/Makefile
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
include ../common.mk
|
||||||
|
|
||||||
|
all: ../build/md5sum
|
||||||
|
|
||||||
|
CRYPTO_DIR := rust-crypto
|
||||||
|
CRYPTO_LIB := $(CRYPTO_DIR)/$(shell $(RUSTC) --crate-file-name --crate-type rlib $(CRYPTO_DIR)/src/rust-crypto/lib.rs)
|
||||||
|
|
||||||
|
../build/md5sum: md5sum.rs $(CRYPTO_LIB)
|
||||||
|
$(RUSTC) $(RUSTFLAGS) -L $(CRYPTO_DIR) -o $@ $<
|
||||||
|
|
||||||
|
$(CRYPTO_LIB): $(CRYPTO_DIR)/src/rust-crypto/*.rs
|
||||||
|
cd $(CRYPTO_DIR) && make
|
||||||
|
|
||||||
|
clean:
|
||||||
|
cd $(CRYPTO_DIR) && make clean
|
158
md5sum/md5sum.rs
Normal file
158
md5sum/md5sum.rs
Normal file
|
@ -0,0 +1,158 @@
|
||||||
|
#[crate_id(name = "md5sum", vers = "1.0.0", author = "Arcterus")];
|
||||||
|
|
||||||
|
#[feature(macro_rules)];
|
||||||
|
|
||||||
|
extern crate crypto = "rust-crypto";
|
||||||
|
extern crate getopts;
|
||||||
|
|
||||||
|
use std::io::fs::File;
|
||||||
|
use std::io::BufferedReader;
|
||||||
|
use std::os;
|
||||||
|
use crypto::digest::Digest;
|
||||||
|
|
||||||
|
#[path = "../common/util.rs"]
|
||||||
|
mod util;
|
||||||
|
|
||||||
|
static NAME: &'static str = "md5sum";
|
||||||
|
static VERSION: &'static str = "1.0.0";
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let args = os::args();
|
||||||
|
|
||||||
|
let program = args[0].clone();
|
||||||
|
|
||||||
|
let opts = [
|
||||||
|
getopts::optflag("b", "binary", "read in binary mode"),
|
||||||
|
getopts::optflag("c", "check", "read MD5 sums from the FILEs and check them"),
|
||||||
|
getopts::optflag("", "tag", "create a BSD-style checksum"),
|
||||||
|
getopts::optflag("t", "text", "read in text mode (default)"),
|
||||||
|
getopts::optflag("q", "quiet", "don't print OK for each successfully verified file"),
|
||||||
|
getopts::optflag("s", "status", "don't output anything, status code shows success"),
|
||||||
|
getopts::optflag("", "strict", "exit non-zero for improperly formatted checksum lines"),
|
||||||
|
getopts::optflag("w", "warn", "warn about improperly formatted checksum lines"),
|
||||||
|
getopts::optflag("h", "help", "display this help and exit"),
|
||||||
|
getopts::optflag("V", "version", "output version information and exit")
|
||||||
|
];
|
||||||
|
|
||||||
|
let matches = match getopts::getopts(args.tail(), opts) {
|
||||||
|
Ok(m) => m,
|
||||||
|
Err(f) => crash!(1, "{}", f.to_err_msg())
|
||||||
|
};
|
||||||
|
|
||||||
|
if matches.opt_present("help") {
|
||||||
|
println!("{} v{}", NAME, VERSION);
|
||||||
|
println!("");
|
||||||
|
println!("Usage:");
|
||||||
|
println!(" {} [OPTION]... [FILE]...", program);
|
||||||
|
println!("");
|
||||||
|
print!("{}", getopts::usage("Compute and check MD5 message digests.", opts));
|
||||||
|
} else if matches.opt_present("version") {
|
||||||
|
println!("{} v{}", NAME, VERSION);
|
||||||
|
} else {
|
||||||
|
let binary = matches.opt_present("binary");
|
||||||
|
let check = matches.opt_present("check");
|
||||||
|
let tag = matches.opt_present("tag");
|
||||||
|
let status = matches.opt_present("status");
|
||||||
|
let quiet = matches.opt_present("quiet") || status;
|
||||||
|
let strict = matches.opt_present("strict");
|
||||||
|
let warn = matches.opt_present("warn") && !status;
|
||||||
|
md5sum(matches.free, binary, check, tag, status, quiet, strict, warn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn md5sum(files: Vec<~str>, binary: bool, check: bool, tag: bool, status: bool, quiet: bool, strict: bool, warn: bool) {
|
||||||
|
let mut md5 = crypto::md5::Md5::new();
|
||||||
|
let bytes = md5.output_bits() / 4;
|
||||||
|
let mut bad_format = 0;
|
||||||
|
let mut failed = 0;
|
||||||
|
for filename in files.iter() {
|
||||||
|
let filename: &str = *filename;
|
||||||
|
let mut file = safe_unwrap!(File::open(&Path::new(filename)));
|
||||||
|
if check {
|
||||||
|
let mut buffer = BufferedReader::new(file);
|
||||||
|
for (i, line) in buffer.lines().enumerate() {
|
||||||
|
let line = safe_unwrap!(line);
|
||||||
|
let (ck_filename, sum) = match from_gnu(line, bytes) {
|
||||||
|
Some(m) => m,
|
||||||
|
None => match from_bsd(line, bytes) {
|
||||||
|
Some(m) => m,
|
||||||
|
None => {
|
||||||
|
bad_format += 1;
|
||||||
|
if strict {
|
||||||
|
os::set_exit_status(1);
|
||||||
|
}
|
||||||
|
if warn {
|
||||||
|
show_warning!("{}: {}: improperly formatted MD5 checksum line", filename, i + 1);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let real_sum = calc_sum(&mut md5, &mut safe_unwrap!(File::open(&Path::new(ck_filename))), binary);
|
||||||
|
if sum == real_sum {
|
||||||
|
if !quiet {
|
||||||
|
println!("{}: OK", ck_filename);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if !status {
|
||||||
|
println!("{}: FAILED", ck_filename);
|
||||||
|
}
|
||||||
|
failed += 1;
|
||||||
|
os::set_exit_status(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let sum = calc_sum(&mut md5, &mut file, binary);
|
||||||
|
if tag {
|
||||||
|
println!("MD5 ({}) = {}", filename, sum);
|
||||||
|
} else {
|
||||||
|
println!("{} {}", sum, filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !status {
|
||||||
|
if bad_format == 1 {
|
||||||
|
show_warning!("{} line is improperly formatted", bad_format);
|
||||||
|
} else if bad_format > 1 {
|
||||||
|
show_warning!("{} lines are improperly formatted", bad_format);
|
||||||
|
}
|
||||||
|
if failed > 0 {
|
||||||
|
show_warning!("{} computed checksum did NOT match", failed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn calc_sum(md5: &mut crypto::md5::Md5, file: &mut File, binary: bool) -> ~str {
|
||||||
|
let data =
|
||||||
|
if binary {
|
||||||
|
safe_unwrap!(file.read_to_end())
|
||||||
|
} else {
|
||||||
|
let val = safe_unwrap!(file.read_to_str()).into_bytes(); // XXX: i don't know why the variable is necessary
|
||||||
|
val
|
||||||
|
};
|
||||||
|
md5.reset();
|
||||||
|
md5.input(data);
|
||||||
|
md5.result_str()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_gnu<'a>(line: &'a str, bytes: uint) -> Option<(&'a str, &'a str)> {
|
||||||
|
let sum = line.slice_to(bytes);
|
||||||
|
if sum.len() < bytes || line.slice(bytes, bytes + 2) != " " {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some((line.slice(bytes + 2, line.len() - 1), sum))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_bsd<'a>(line: &'a str, bytes: uint) -> Option<(&'a str, &'a str)> {
|
||||||
|
if line.slice(0, 5) == "MD5 (" {
|
||||||
|
let rparen = match line.find(')') {
|
||||||
|
Some(m) => m,
|
||||||
|
None => return None
|
||||||
|
};
|
||||||
|
if rparen > 5 && line.slice(rparen + 1, rparen + 4) == " = " && line.len() - 1 == rparen + 4 + bytes {
|
||||||
|
return Some((line.slice(5, rparen), line.slice(rparen + 4, line.len() - 1)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
1
md5sum/rust-crypto
Submodule
1
md5sum/rust-crypto
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit fd168c53c00475c4fae3efc329301e80451bd967
|
|
@ -176,7 +176,7 @@ fn parse_size(size: ~str) -> (u64, TruncateMode) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
slice
|
slice
|
||||||
}.bytes().to_owned_vec();
|
}.to_owned().into_bytes();
|
||||||
let mut number = match u64::parse_bytes(bytes, 10) {
|
let mut number = match u64::parse_bytes(bytes, 10) {
|
||||||
Some(num) => num,
|
Some(num) => num,
|
||||||
None => {
|
None => {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue