You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
141 lines
2.3 KiB
141 lines
2.3 KiB
package main |
|
|
|
import ( |
|
"bufio" |
|
"crypto/md5" |
|
"errors" |
|
"fmt" |
|
"hash" |
|
"io" |
|
"os" |
|
"strings" |
|
|
|
"github.com/alexflint/go-arg" |
|
common "source.heropunch.io/tomo/go-coreutils" |
|
) |
|
|
|
var ImproperlyFormattedErr = errors.New("improperly formatted line") |
|
|
|
func printSumForFile(filename string, sumFunc func(io.Reader) (hash.Hash, error)) error { |
|
file, err := os.Open(filename) |
|
if err != nil { |
|
return err |
|
} |
|
defer file.Close() |
|
|
|
h, err := sumFunc(file) |
|
if err != nil { |
|
return err |
|
} |
|
|
|
printHash(h, filename) |
|
return nil |
|
} |
|
|
|
func printSumForStdin(sumFunc func(io.Reader) (hash.Hash, error)) { |
|
h, err := sumFunc(os.Stdin) |
|
if err != nil { |
|
common.PrintToStderr(err) |
|
os.Exit(1) |
|
} |
|
printHash(h, "<stdin>") |
|
os.Exit(0) |
|
} |
|
|
|
func md5sum(r io.Reader) (hash.Hash, error) { |
|
h := md5.New() |
|
if _, err := io.Copy(h, r); err != nil { |
|
return nil, err |
|
} |
|
return h, nil |
|
} |
|
|
|
func printHash(h hash.Hash, filename string) { |
|
fmt.Printf("%x %v\n", h.Sum(nil), filename) |
|
} |
|
|
|
func checkSumForFile(filename string) error { |
|
file, err := os.Open(filename) |
|
if err != nil { |
|
return err |
|
} |
|
defer file.Close() |
|
|
|
return checkSums(file) |
|
} |
|
|
|
func checkSums(r io.Reader) error { |
|
scanner := bufio.NewScanner(r) |
|
|
|
for scanner.Scan() { |
|
err := checkMD5Sum(scanner.Text()) |
|
if err != nil { |
|
return err |
|
} |
|
} |
|
return scanner.Err() |
|
} |
|
|
|
func checkMD5Sum(line string) error { |
|
s := strings.SplitN(line, " ", 2) |
|
hash := s[0] |
|
filename := s[1] |
|
|
|
if filename == "" { |
|
return ImproperlyFormattedErr |
|
} |
|
|
|
file, err := os.Open(filename) |
|
if err != nil { |
|
return err |
|
} |
|
defer file.Close() |
|
|
|
h, err := md5sum(file) |
|
if err != nil { |
|
return err |
|
} |
|
result := "OK" |
|
if fmt.Sprintf("%x", h.Sum(nil)) != hash { |
|
result = "FAILED" |
|
} |
|
fmt.Printf("%s: %s\n", filename, result) |
|
|
|
return nil |
|
} |
|
|
|
func main() { |
|
var args struct { |
|
Check bool `arg:"-c"` |
|
Files []string `arg:"positional"` |
|
} |
|
|
|
arg.MustParse(&args) |
|
|
|
exitCode := 0 |
|
if len(args.Files) == 0 { |
|
if !args.Check { |
|
printSumForStdin(md5sum) |
|
} else { |
|
fmt.Println("Checking from stdin") |
|
} |
|
} |
|
|
|
for _, filename := range args.Files { |
|
if !args.Check { |
|
err := printSumForFile(filename, md5sum) |
|
if err != nil { |
|
common.PrintToStderr(err) |
|
exitCode = 1 |
|
} |
|
} else { |
|
err := checkSumForFile(filename) |
|
if err != nil { |
|
common.PrintToStderr(err) |
|
exitCode = 1 |
|
} |
|
} |
|
} |
|
|
|
os.Exit(exitCode) |
|
}
|
|
|