integrity.go | 151 +++++++++++++++++++++++++++++++++-------------------- main.go | 2 +- diff --git a/integrity.go b/integrity.go index 60f64d2b15819d2cad4933b87abebda6552bc13f737090fc40606e12e16fa615..e121d37f381ac0b15d55b91f9bd2193bf198621d5f063a9e97d9fd9c7543b466 100644 --- a/integrity.go +++ b/integrity.go @@ -21,88 +21,123 @@ import ( "bufio" "bytes" "crypto/sha256" + "errors" "fmt" - "hash" "io" + "io/fs" "log" "os" "path/filepath" + "runtime" "strings" + "sync" +) - "golang.org/x/crypto/blake2b" -) +func checker(jobs chan string, isGood *bool, workers *sync.WaitGroup) { + hasherBLAKE2b256 := blake2b256New() + hasherSHA256 := sha256.New() + digestBuf := make([]byte, 32) + defer workers.Done() + var fd *os.File + var br bufio.Reader + var err error + var digest []byte + for fn := range jobs { + fd, err = os.Open(fn) + if err != nil { + fmt.Println("ERR", fn, err) + *isGood = false + continue + } + + digest, err = os.ReadFile(fn + "." + HashAlgoBLAKE2b256) + if err != nil { + if !errors.Is(err, fs.ErrNotExist) { + fmt.Println("ERR", fn+"."+HashAlgoBLAKE2b256, err) + *isGood = false + } + goto NoBLAKE2b256 + } + hasherBLAKE2b256.Reset() + br.Reset(fd) + _, err = io.Copy(hasherBLAKE2b256, &br) + fd.Seek(0, io.SeekStart) + if err != nil { + fmt.Println("ERR", fn+"."+HashAlgoBLAKE2b256, err) + *isGood = false + goto NoBLAKE2b256 + } + if bytes.Equal(hasherBLAKE2b256.Sum(digestBuf[:0]), digest) { + fmt.Println("GOOD", fn+"."+HashAlgoBLAKE2b256) + } else { + fmt.Println("BAD", fn+"."+HashAlgoBLAKE2b256) + *isGood = false + } + + NoBLAKE2b256: + digest, err = os.ReadFile(fn + "." + HashAlgoSHA256) + if err != nil { + if !errors.Is(err, fs.ErrNotExist) { + fmt.Println("ERR", fn+"."+HashAlgoSHA256, err) + *isGood = false + } + fd.Close() + continue + } + hasherSHA256.Reset() + br.Reset(fd) + _, err = io.Copy(hasherSHA256, &br) + fd.Close() + if err != nil { + fmt.Println("ERR", fn+"."+HashAlgoBLAKE2b256, err) + *isGood = false + continue + } + if bytes.Equal(hasherSHA256.Sum(digestBuf[:0]), digest) { + fmt.Println("GOOD", fn+"."+HashAlgoSHA256) + } else { + fmt.Println("BAD", fn+"."+HashAlgoSHA256) + *isGood = false + } + } +} -func checkFile( - pkgName, fn, fnHash, hasherName string, - hasher hash.Hash, digest []byte, -) bool { - expected, err := os.ReadFile(fnHash) - if err != nil { - log.Fatal(err) +func goodIntegrity() bool { + isGood := true + jobs := make(chan string, 1<<10) + var workers sync.WaitGroup + workers.Add(runtime.NumCPU()) + for i := 0; i < runtime.NumCPU(); i++ { + go checker(jobs, &isGood, &workers) } - fd, err := os.Open(fn) + fd, err := os.Open(Root) if err != nil { - if os.IsNotExist(err) { - return true - } log.Fatal(err) } - _, err = io.Copy(hasher, bufio.NewReader(fd)) + dirs, err := fd.ReadDir(0) fd.Close() if err != nil { log.Fatal(err) } - isEqual := bytes.Equal(hasher.Sum(digest[:0]), expected) - hasher.Reset() - if isEqual { - fmt.Println("GOOD", hasherName, pkgName) - return true - } - fmt.Println("BAD", hasherName, pkgName) - return false -} - -func goodIntegrity() bool { - dirs, err := os.ReadDir(Root) - if err != nil { - log.Fatal(err) - } - hasherSHA256 := sha256.New() - hasherBLAKE2b256 := blake2b256New() - digestSHA256 := make([]byte, sha256.Size) - digestBLAKE2b256 := make([]byte, blake2b.Size256) - isGood := true - var pkgName string for _, dir := range dirs { - files, err := os.ReadDir(filepath.Join(Root, dir.Name())) + fd, err = os.Open(filepath.Join(Root, dir.Name())) + if err != nil { + log.Fatal(err) + } + files, err := fd.ReadDir(0) + fd.Close() if err != nil { log.Fatal(err) } for _, file := range files { - if strings.HasSuffix(file.Name(), "."+HashAlgoSHA256) { - pkgName = strings.TrimSuffix(file.Name(), "."+HashAlgoSHA256) - if !checkFile( - pkgName, - filepath.Join(Root, dir.Name(), pkgName), - filepath.Join(Root, dir.Name(), file.Name()), - "SHA256", hasherSHA256, digestSHA256, - ) { - isGood = false - } - continue - } - if strings.HasSuffix(file.Name(), "."+HashAlgoBLAKE2b256) { - pkgName = strings.TrimSuffix(file.Name(), "."+HashAlgoBLAKE2b256) - if !checkFile( - pkgName, - filepath.Join(Root, dir.Name(), pkgName), - filepath.Join(Root, dir.Name(), file.Name()), - "BLAKE2b-256", hasherBLAKE2b256, digestBLAKE2b256, - ) { - isGood = false + for _, ext := range KnownExts { + if strings.HasSuffix(file.Name(), ext) { + jobs <- filepath.Join(Root, dir.Name(), file.Name()) } } } } + close(jobs) + workers.Wait() return isGood } diff --git a/main.go b/main.go index c3841a4c90de367e0db9a385c2910e1cefcac6fa5feffcf5dbdd39adc54c239a..9f11c21cbb3d4b8d405da3f0b38868202c9a926c19bb90c8094b7d6af26eb55c 100644 --- a/main.go +++ b/main.go @@ -44,7 +44,7 @@ "golang.org/x/net/netutil" ) const ( - Version = "4.0.0" + Version = "4.1.0" UserAgent = "GoCheese/" + Version )