X-Git-Url: http://www.git.stargrave.org/?a=blobdiff_plain;f=cmd%2Fmeta4ra%2Fcheck.go;fp=cmd%2Fmeta4-check%2Fmain.go;h=c030f8b8417ec376d2008ab8aed377efa43ac15e;hb=be69a4fc0c240c2772a0f0bf0955b39783e4c48a;hp=b807a26993c8b945b477ab63c72ea3ca8b9461ae;hpb=ce902a58a32f42801603475c67dd75da86d4502a;p=meta4ra.git diff --git a/cmd/meta4-check/main.go b/cmd/meta4ra/check.go similarity index 59% rename from cmd/meta4-check/main.go rename to cmd/meta4ra/check.go index b807a26..c030f8b 100644 --- a/cmd/meta4-check/main.go +++ b/cmd/meta4ra/check.go @@ -13,7 +13,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -// Metalink 4.0 checker package main import ( @@ -28,12 +27,14 @@ import ( "path" "strings" - "go.stargrave.org/meta4ra" + meta4ra "go.stargrave.org/meta4ra/internal" ) -func main() { - hashes := flag.String("hashes", - strings.Join(meta4ra.HashesDefault, ","), "hash-name:command-s") +func runCheck() { + stdin := flag.Bool("stdin", false, "Compare data of single file taken from stdin") + allHashes := flag.Bool("all-hashes", false, "Check all hashes, not the first common one") + hashes := flag.String("hashes", meta4ra.HashesDefault, + "hash-name:commandline[,...]") extractSig := flag.Bool("extract-sig", false, "Extract signature files") metaPath := flag.String("meta4", "file.meta4", "Metalink file") flag.Usage = func() { @@ -44,11 +45,10 @@ func main() { If no FILEs are specified, then all s from metalink are searched and verified if they exist. Otherwise only specified FILEs are checked. If you want to skip any verification (for example only to validate the format -and -extract-sig, then you can just specify empty ("") FILE. +and -extract-sig, then you can just specify an empty ("") FILE. `) } flag.Parse() - log.SetFlags(log.Lshortfile) data, err := os.ReadFile(*metaPath) if err != nil { @@ -64,6 +64,9 @@ and -extract-sig, then you can just specify empty ("") FILE. for _, fn := range flag.Args() { toCheck[path.Base(fn)] = fn } + if *stdin && len(toCheck) != 1 { + log.Fatalln("exactly single FILE must be specified when using -stdin") + } bad := false for _, f := range meta.Files { @@ -92,28 +95,39 @@ and -extract-sig, then you can just specify empty ("") FILE. } fullPath := toCheck[f.Name] + delete(toCheck, f.Name) if !(len(toCheck) == 0 || fullPath != "") { continue } if fullPath == "" { fullPath = f.Name } - s, err := os.Stat(fullPath) - if err != nil { - fmt.Println(err) - bad = true - continue + if !*stdin { + s, err := os.Stat(fullPath) + if err != nil { + fmt.Println(err) + bad = true + continue + } + if uint64(s.Size()) != f.Size { + fmt.Println("size mismatch", + f.Name, "our:", s.Size(), "their:", f.Size) + bad = true + continue + } } - if uint64(s.Size()) != f.Size { - fmt.Println("size mismatch", - f.Name, "our:", s.Size(), "their:", f.Size) + + hasher, err := meta4ra.NewHasher(*hashes) + if err != nil { + fmt.Println(f.Name, err) bad = true continue } - - hasher := meta4ra.NewHasher(*hashes) var hashTheir string var hashName string + if *allHashes { + goto HashFound + } for i, name := range hasher.Names { for _, h := range f.Hashes { if h.Type == name { @@ -130,35 +144,80 @@ and -extract-sig, then you can just specify empty ("") FILE. fmt.Println("no common hashes found for:", f.Name) bad = true continue - HashFound: - fd, err := os.Open(fullPath) + + fd := os.Stdin + if !*stdin { + fd, err = os.Open(fullPath) + if err != nil { + fmt.Println("Error:", f.Name, err) + bad = true + continue + } + } + err = hasher.Start() if err != nil { + if !*stdin { + fd.Close() + } + hasher.Stop() fmt.Println("Error:", f.Name, err) bad = true continue } - hasher.Start() - _, err = io.Copy(hasher, bufio.NewReaderSize(fd, 1<<20)) - fd.Close() - sums := hasher.Sums() + _, err = io.Copy(hasher, bufio.NewReaderSize(fd, meta4ra.BufLen)) + if !*stdin { + fd.Close() + } if err != nil { + hasher.Stop() fmt.Println("Error:", f.Name, err) bad = true continue } - hashOur := sums[0].Hash - if hashOur == hashTheir { - fmt.Println(f.Name, hashName, "good") - } else { - fmt.Println( - "hash mismatch:", f.Name, hashName, - "our:", hashOur, - "their:", hashTheir, - ) + sums, err := hasher.Sums() + if err != nil { + hasher.Stop() + fmt.Println("Error:", f.Name, err) bad = true continue } + if *allHashes { + hashesOur := make(map[string]string, len(sums)) + for _, h := range sums { + hashesOur[h.Type] = h.Hash + } + for _, h := range f.Hashes { + hashOur := hashesOur[h.Type] + if h.Hash == hashOur { + fmt.Println(f.Name, h.Type, "good") + } else { + fmt.Println( + "hash mismatch:", f.Name, h.Type, + "our:", hashOur, + "their:", h.Hash, + ) + bad = true + } + } + } else { + hashOur := sums[0].Hash + if hashOur == hashTheir { + fmt.Println(f.Name, hashName, "good") + } else { + fmt.Println( + "hash mismatch:", f.Name, hashName, + "our:", hashOur, + "their:", hashTheir, + ) + bad = true + continue + } + } + } + if len(toCheck) != 0 { + fmt.Println("not all FILEs met") + bad = true } if bad { os.Exit(1)