Sum
March 25, 2011
Today’s exercise implements the old Unix Sys V R4 sum
command. The original sum calculated a checksum as the sum of the bytes in the file, modulo 216−1, as well as the number of 512-byte blocks the file occupied on disk. Called with no arguments, sum
read standard input and wrote the checksum and file blocks to standard output; called with one or more filename arguments, sum
read each file and wrote for each a line containing the checksum, file blocks, and filename. The GNU version of the program, which implements an additional version of the checksum that was part of BSD Unix, is available at ftp://alpha.gnu.org/gnu/coreutils/textutils-2.0.22.tar.gz in file sum.c; if you run it, be sure to give the −s
argument to get the original Unix Sys V R4 version of the checksum.
Your task is to write a program that implements the original Unix Sys V R4 sum
command. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.
I’m not sure that this is quite in the spirit of the site but:
My Haskell solution (see http://bonsaicode.wordpress.com/2011/03/25/programming-praxis-sum/ for a version with comments):
[…] today’s Programming Praxis exercise, our goal is to implement a unix checksum utility. Let’s get […]
I implemented a version in Factor (the short version is below):
The full version is here:
http://re-factor.blogspot.com/2011/03/sum.html
Whoops, mis-understood the requirements – this is a fixed version for Factor:
Here’s a go in Common Lisp using LOOP, also had a bit of fun on tweaking the reading of the file and inlining the calculation:
(defun sv4r-sum (file)
"Calculate a Unix SV4R-style file checksum"
(with-open-file (stream file :direction :input :element-type 'unsigned-byte)
(loop :with buffer = (make-array 512 :element-type 'unsigned-byte)
:and csum = 0
:for pos = (read-sequence buffer stream)
:while (plusp pos)
:do (loop :for b :from 0 :to (1- pos)
:do (setf csum (mod (+ csum (svref buffer b)) 65535)))
:counting buffer :into c
:finally (return (values csum c)))))
You can never have to many Scheme solutions ;)