]> Sergey Matveev's repositories - meta4ra.git/commitdiff
Different checking logic
authorSergey Matveev <stargrave@stargrave.org>
Wed, 14 Feb 2024 07:38:29 +0000 (10:38 +0300)
committerSergey Matveev <stargrave@stargrave.org>
Wed, 14 Feb 2024 07:38:29 +0000 (10:38 +0300)
cmd/meta4-check/main.go

index f83d8d3e79598f2fc4da500634a334dbff893e0f..61b50486b1d6795d19920662568a36862aa885de 100644 (file)
@@ -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 <file>s from metalink are searched and
+verified if they exist. Otherwise only specified FILEs are checked. If you
+want to skip any <file> 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)