crc/main.go

73 lines
1.6 KiB
Go

// CRC is a simple command-line utility to compute CRC values for one or more files.
package main
import (
"flag"
"fmt"
"hash"
"hash/crc32"
"hash/crc64"
"encoding/binary"
"io"
"os"
)
func main() {
mode := flag.String("mode", "crc32",
"CRC method to use. Valid values are 'crc32' (IEEE), 'crc64-iso', and 'crc64-ecma'")
flag.Usage = func() {
fmt.Fprintf(os.Stderr, "Usage: %s [-mode=<MODE>] file [file ...]\n", os.Args[0])
flag.PrintDefaults()
}
flag.Parse()
hasher, err := NewHasher(*mode)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
if flag.NArg() == 0 {
fmt.Fprintf(os.Stderr, "Specify one or more filenames to checksum.\n")
os.Exit(2)
}
exitCode := 0
for _, filename := range flag.Args() {
hasher, _ = NewHasher(*mode)
f, err := os.Open(filename)
if err != nil {
exitCode = 3
fmt.Fprintf(os.Stderr, "Cannot open %q: %v\n", filename, err)
continue
}
_, err = io.Copy(hasher, f)
f.Close()
if err != nil {
exitCode = 3
fmt.Fprintf(os.Stderr, "Error reading %q: %v\n", filename, err)
continue
}
if flag.NArg() == 1 {
fmt.Printf("%0*d\n", hasher.Size(), binary.BigEndian.Uint32(hasher.Sum(nil)))
} else {
fmt.Printf("%0*d\t%s\n", hasher.Size(), binary.BigEndian.Uint32(hasher.Sum(nil)), filename)
}
}
os.Exit(exitCode)
}
func NewHasher(mode string) (hash.Hash, error) {
switch mode {
case "crc32", "crc32-ieee":
return crc32.NewIEEE(), nil
case "crc64-iso":
return crc64.New(crc64.MakeTable(crc64.ISO)), nil
case "crc64-ecma":
return crc64.New(crc64.MakeTable(crc64.ECMA)), nil
default:
return nil, fmt.Errorf("ERROR: Invalid mode %q", mode)
}
}