From d4cb1d0185b794ad7c79190ee01993bfb5ec8d7a Mon Sep 17 00:00:00 2001 From: Michael Gehring Date: Fri, 16 May 2014 23:01:20 +0200 Subject: [PATCH] add cksum --- Makefile | 1 + README.md | 1 - cksum/cksum.rs | 122 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 cksum/cksum.rs diff --git a/Makefile b/Makefile index a6f5f5833..a578864da 100644 --- a/Makefile +++ b/Makefile @@ -5,6 +5,7 @@ PROGS := \ base64 \ basename \ cat \ + cksum \ comm \ dirname \ echo \ diff --git a/README.md b/README.md index bc0e73135..139ebf94b 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,6 @@ To do - chown-core - chown - chroot -- cksum - copy - cp-hash - cp (some work done in ```dev``` branch) diff --git a/cksum/cksum.rs b/cksum/cksum.rs new file mode 100644 index 000000000..56be7d88f --- /dev/null +++ b/cksum/cksum.rs @@ -0,0 +1,122 @@ +#![crate_id(name="cksum", vers="1.0.0", author="Michael Gehring")] +#![feature(macro_rules)] + +/* + * This file is part of the uutils coreutils package. + * + * (c) Michael Gehring + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +extern crate getopts; + +use std::io::{BufferedReader, EndOfFile, File, IoError, IoResult, print}; +use std::io::stdio::stdin; +use std::os; + +#[path="../common/util.rs"] +mod util; + +static NAME : &'static str = "cksum"; +static VERSION : &'static str = "1.0.0"; + +fn crc_update(mut crc: u32, input: u8) -> u32 { + crc ^= input as u32 << 24; + + for _ in range(0, 8) { + if crc & 0x80000000 != 0 { + crc <<= 1; + crc ^= 0x04c11db7; + } else { + crc <<= 1; + } + } + + crc +} + +fn crc_final(mut crc: u32, mut length: uint) -> u32 { + while length != 0 { + crc = crc_update(crc, length as u8); + length >>= 8; + } + + !crc +} + +fn cksum(fname: &str) -> IoResult<(u32, uint)> { + let mut crc = 0u32; + let mut size = 0u; + + let mut rd = try!(open_file(fname)); + loop { + match rd.read_byte() { + Ok(b) => { + crc = crc_update(crc, b); + size += 1; + } + Err(err) => { + return match err { + IoError{kind: k, ..} if k == EndOfFile => Ok((crc_final(crc, size), size)), + _ => Err(err), + } + } + } + } +} + +fn open_file(name: &str) -> IoResult> { + match name { + "-" => Ok(box stdin() as Box), + _ => { + let f = try!(File::open(&Path::new(name))); + Ok(box BufferedReader::new(f) as Box) + } + } +} + +pub fn main() { + let opts = [ + getopts::optflag("h", "help", "display this help and exit"), + getopts::optflag("V", "version", "output version information and exit"), + ]; + + let matches = match getopts::getopts(os::args().tail(), opts) { + Ok(m) => m, + Err(err) => fail!("{}", err.to_err_msg()), + }; + + if matches.opt_present("help") { + println!("{} {}", NAME, VERSION); + println!(""); + println!("Usage:"); + println!(" {} [OPTIONS] [FILE]...", NAME); + println!(""); + print(getopts::usage("Print CRC and size for each file.", opts.as_slice())); + return; + } + + if matches.opt_present("version") { + println!("{} {}", NAME, VERSION); + return; + } + + let files = matches.free; + + if files.is_empty() { + match cksum("-") { + Ok((crc, size)) => println!("{} {}", crc, size), + Err(err) => show_error!(2, "{}", err), + } + return + } + + for fname in files.iter() { + match cksum(*fname) { + Ok((crc, size)) => println!("{} {} {}", crc, size, fname), + Err(err) => show_error!(2, "'{}' {}", fname, err), + } + } +}