|
|
@ -0,0 +1,103 @@ |
|
|
|
package main |
|
|
|
|
|
|
|
import ( |
|
|
|
"bufio" |
|
|
|
"crypto/md5" |
|
|
|
"crypto/sha1" |
|
|
|
"crypto/sha256" |
|
|
|
"crypto/sha512" |
|
|
|
"errors" |
|
|
|
"fmt" |
|
|
|
"hash" |
|
|
|
"io" |
|
|
|
"log" |
|
|
|
"os" |
|
|
|
"strings" |
|
|
|
) |
|
|
|
|
|
|
|
type checksum struct { |
|
|
|
filename string |
|
|
|
hash hash.Hash |
|
|
|
checksum string |
|
|
|
} |
|
|
|
|
|
|
|
func parseCS(line string) (checksum, error) { |
|
|
|
elems := strings.Fields(line) |
|
|
|
if len(elems) != 2 { |
|
|
|
return checksum{}, fmt.Errorf("unexpected content: %d != 2", len(elems)) |
|
|
|
} |
|
|
|
cs, f := elems[0], elems[1] |
|
|
|
var hsh hash.Hash |
|
|
|
switch len(cs) { |
|
|
|
case 32: |
|
|
|
hsh = md5.New() |
|
|
|
case 40: |
|
|
|
hsh = sha1.New() |
|
|
|
case 64: |
|
|
|
hsh = sha256.New() |
|
|
|
case 128: |
|
|
|
hsh = sha512.New() |
|
|
|
default: |
|
|
|
return checksum{}, fmt.Errorf("unknown format: %q", line) |
|
|
|
} |
|
|
|
return checksum{filename: f, hash: hsh, checksum: cs}, nil |
|
|
|
} |
|
|
|
|
|
|
|
func check(files []string) error { |
|
|
|
streams := []io.ReadCloser{} |
|
|
|
defer func() { |
|
|
|
for _, stream := range streams { |
|
|
|
stream.Close() |
|
|
|
} |
|
|
|
}() |
|
|
|
|
|
|
|
for _, name := range files { |
|
|
|
f, err := os.Open(name) |
|
|
|
if err != nil { |
|
|
|
return err |
|
|
|
} |
|
|
|
streams = append(streams, f) |
|
|
|
} |
|
|
|
if len(files) == 0 { |
|
|
|
streams = append(streams, os.Stdin) |
|
|
|
} |
|
|
|
|
|
|
|
jobs := []checksum{} |
|
|
|
for _, stream := range streams { |
|
|
|
s := bufio.NewScanner(stream) |
|
|
|
for s.Scan() { |
|
|
|
cs, err := parseCS(s.Text()) |
|
|
|
if err != nil { |
|
|
|
return err |
|
|
|
} |
|
|
|
jobs = append(jobs, cs) |
|
|
|
} |
|
|
|
if s.Err() != nil { |
|
|
|
return s.Err() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
errs := 0 |
|
|
|
for _, job := range jobs { |
|
|
|
f, err := os.Open(job.filename) |
|
|
|
if err != nil { |
|
|
|
return fmt.Errorf("open: %v", err) |
|
|
|
} |
|
|
|
if _, err := io.Copy(job.hash, f); err != nil { |
|
|
|
log.Printf("%+v", err) |
|
|
|
} |
|
|
|
f.Close() |
|
|
|
if fmt.Sprintf("%x", job.hash.Sum(nil)) == job.checksum { |
|
|
|
fmt.Printf("%s: OK\n", job.filename) |
|
|
|
} else { |
|
|
|
errs++ |
|
|
|
fmt.Fprintf(os.Stderr, "%s: bad\n", job.filename) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
var err error |
|
|
|
if errs != 0 { |
|
|
|
err = errors.New("bad files found") |
|
|
|
} |
|
|
|
return err |
|
|
|
} |