/*
meta4a -- Metalink 4.0 checker
-Copyright (C) 2021-2022 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2021-2023 Sergey Matveev <stargrave@stargrave.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
import (
"bufio"
- "crypto/sha256"
- "crypto/sha512"
- "encoding/hex"
"encoding/xml"
"flag"
"fmt"
- "hash"
"io"
"io/fs"
"log"
"os"
+ "strings"
"go.stargrave.org/meta4ra"
)
func main() {
+ hashes := flag.String("hashes", strings.Join(meta4ra.HashesDefault, ","), "hash-name:command-s")
extractSig := flag.Bool("extract-sig", false, "Extract signature files")
log.SetFlags(log.Lshortfile)
flag.Parse()
- sha256Hasher := sha256.New()
- sha512Hasher := sha512.New()
bad := false
for _, metaPath := range flag.Args() {
data, err := os.ReadFile(metaPath)
bad = true
}
}
- var sha256Digest string
- var sha512Digest string
- fd, err := os.Open(f.Name)
- if err != nil {
- continue
- }
- for _, h := range f.Hashes {
- switch h.Type {
- case meta4ra.HashSHA256:
- sha256Digest = h.Hash
- case meta4ra.HashSHA512:
- sha512Digest = h.Hash
+ hasher := meta4ra.NewHasher(*hashes)
+ var hashTheir string
+ var hashName string
+ for i, name := range hasher.Names {
+ for _, h := range f.Hashes {
+ if h.Type == name {
+ hasher.Names = []string{name}
+ hasher.Cmds = append(hasher.Cmds[:0], hasher.Cmds[i])
+ hasher.Ins = append(hasher.Ins[:0], hasher.Ins[i])
+ hasher.Outs = append(hasher.Outs[:0], hasher.Outs[i])
+ hashName = name
+ hashTheir = h.Hash
+ goto HashFound
+ }
}
}
- var digestTheir string
- var digestName string
- var hasher hash.Hash
- if sha512Digest != "" {
- digestName = meta4ra.HashSHA512
- digestTheir = sha512Digest
- hasher = sha512Hasher
- } else if sha256Digest != "" {
- digestName = meta4ra.HashSHA256
- digestTheir = sha256Digest
- hasher = sha256Hasher
- } else {
- fd.Close()
- fmt.Println("Error:", f.Name, "no satisfiable hash algorithm found")
- bad = true
+ log.Fatalln("no common hashes found for:", f.Name)
+ HashFound:
+ fd, err := os.Open(f.Name)
+ if err != nil {
continue
}
- hasher.Reset()
- _, err = io.Copy(hasher, bufio.NewReader(fd))
+ hasher.Start()
+ _, err = io.Copy(hasher, bufio.NewReaderSize(fd, 1<<20))
fd.Close()
+ sums := hasher.Sums()
if err != nil {
fmt.Println("Error:", f.Name, err)
bad = true
continue
}
- digestOur := hex.EncodeToString(hasher.Sum(nil))
- if digestOur == digestTheir {
- fmt.Println(f.Name, digestName, "good")
+ hashOur := sums[0].Hash
+ if hashOur == hashTheir {
+ fmt.Println(f.Name, hashName, "good")
} else {
fmt.Println(
- "Hash does not match:", f.Name, digestName,
- "our:", digestOur,
- "their:", digestTheir,
+ "Hash does not match:", f.Name, hashName,
+ "our:", hashOur,
+ "their:", hashTheir,
)
bad = true
continue