From: Sergey Matveev Date: Wed, 14 Feb 2024 07:38:29 +0000 (+0300) Subject: Different checking logic X-Git-Tag: v0.5.0~1 X-Git-Url: http://www.git.stargrave.org/?p=meta4ra.git;a=commitdiff_plain;h=a593d8a9fcd8bf82fcad3735fa2052379faea295 Different checking logic --- diff --git a/cmd/meta4-check/main.go b/cmd/meta4-check/main.go index f83d8d3..61b5048 100644 --- a/cmd/meta4-check/main.go +++ b/cmd/meta4-check/main.go @@ -25,95 +25,123 @@ import ( "io/fs" "log" "os" + "path" "strings" "go.stargrave.org/meta4ra" ) func main() { - hashes := flag.String("hashes", strings.Join(meta4ra.HashesDefault, ","), "hash-name:command-s") + 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) + metaPath := flag.String("meta4", "file.meta4", "Metalink file") + flag.Usage = func() { + fmt.Fprintf(flag.CommandLine.Output(), + "Usage: %s [options] [FILE ...]\n", os.Args[0]) + flag.PrintDefaults() + fmt.Fprint(flag.CommandLine.Output(), ` +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. +`) + } flag.Parse() + log.SetFlags(log.Lshortfile) + + data, err := os.ReadFile(*metaPath) + if err != nil { + log.Fatalln(err) + } + var meta meta4ra.Metalink + err = xml.Unmarshal(data, &meta) + if err != nil { + log.Fatalln(err) + } + + toCheck := make(map[string]string) + for _, fn := range flag.Args() { + toCheck[path.Base(fn)] = fn + } + bad := false - for _, metaPath := range flag.Args() { - data, err := os.ReadFile(metaPath) - if err != nil { - log.Fatalln(err) - } - var meta meta4ra.Metalink - err = xml.Unmarshal(data, &meta) - if err != nil { - log.Fatalln(err) - } - for _, f := range meta.Files { - for _, sig := range f.Signature { - if !*extractSig { - continue - } - var fn string - switch sig.MediaType { - case meta4ra.SigMediaTypePGP: - fn = f.Name + ".asc" - case meta4ra.SigMediaTypeSSH: - fn = f.Name + ".sig" - } - if fn == "" { - continue - } - if err = os.WriteFile( - fn, - []byte(strings.TrimPrefix(sig.Signature, "\n")), - fs.FileMode(0666), - ); err != nil { - fmt.Println("Error:", f.Name, "can not save signature:", err) - bad = true - } + for _, f := range meta.Files { + for _, sig := range f.Signature { + if !*extractSig { + continue } - 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 fn string + switch sig.MediaType { + case meta4ra.SigMediaTypePGP: + fn = f.Name + ".asc" + case meta4ra.SigMediaTypeSSH: + fn = f.Name + ".sig" } - log.Fatalln("no common hashes found for:", f.Name) - HashFound: - fd, err := os.Open(f.Name) - if err != nil { + if fn == "" { continue } - 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) + if err = os.WriteFile( + fn, + []byte(strings.TrimPrefix(sig.Signature, "\n")), + fs.FileMode(0666), + ); err != nil { + fmt.Println("Error:", f.Name, "can not save signature:", err) bad = true - continue } - hashOur := sums[0].Hash - if hashOur == hashTheir { - fmt.Println(f.Name, hashName, "good") - } else { - fmt.Println( - "Hash does not match:", f.Name, hashName, - "our:", hashOur, - "their:", hashTheir, - ) - bad = true - continue + } + 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 + } } } + log.Fatalln("no common hashes found for:", f.Name) + HashFound: + fullPath := toCheck[f.Name] + if !(len(toCheck) == 0 || fullPath != "") { + continue + } + if fullPath == "" { + fullPath = f.Name + } + fd, err := os.Open(fullPath) + if err != nil { + 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() + if err != nil { + 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 does not match:", f.Name, hashName, + "our:", hashOur, + "their:", hashTheir, + ) + bad = true + continue + } } if bad { os.Exit(1)