|
@@ -0,0 +1,135 @@
|
|
|
|
+package main
|
|
|
|
+
|
|
|
|
+import (
|
|
|
|
+ "crypto/sha256"
|
|
|
|
+ "encoding/hex"
|
|
|
|
+ "encoding/json"
|
|
|
|
+ "flag"
|
|
|
|
+ "fmt"
|
|
|
|
+ "io"
|
|
|
|
+ "io/ioutil"
|
|
|
|
+ "log"
|
|
|
|
+ "os"
|
|
|
|
+ "path/filepath"
|
|
|
|
+ "runtime"
|
|
|
|
+ "sync"
|
|
|
|
+)
|
|
|
|
+
|
|
|
|
+type Fdhashes struct {
|
|
|
|
+ Path string
|
|
|
|
+ Hashes map[string]string
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+var hashes map[string]Fdhashes
|
|
|
|
+
|
|
|
|
+var wg sync.WaitGroup
|
|
|
|
+var mu sync.RWMutex
|
|
|
|
+
|
|
|
|
+func main() {
|
|
|
|
+ runtime.GOMAXPROCS(5)
|
|
|
|
+ hashes = make(map[string]Fdhashes)
|
|
|
|
+ flag.Parse()
|
|
|
|
+ myFile := flag.Arg(0)
|
|
|
|
+ file, err := os.Stat(myFile)
|
|
|
|
+ if os.IsNotExist(err) {
|
|
|
|
+ log.Fatalln("File does not exists:", myFile)
|
|
|
|
+ }
|
|
|
|
+ if file.IsDir() {
|
|
|
|
+ log.Println("start with folder:", myFile)
|
|
|
|
+ processFolder(myFile)
|
|
|
|
+ } else {
|
|
|
|
+ log.Printf("file %s has hash %s\n", myFile, getHash(myFile))
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ fmt.Println("waiting")
|
|
|
|
+ wg.Wait()
|
|
|
|
+ log.Println("done")
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func getHash(fileStr string) string {
|
|
|
|
+ f, err := os.Open(fileStr)
|
|
|
|
+ if err != nil {
|
|
|
|
+ log.Fatal(err)
|
|
|
|
+ }
|
|
|
|
+ defer f.Close()
|
|
|
|
+
|
|
|
|
+ h := sha256.New()
|
|
|
|
+ if _, err := io.Copy(h, f); err != nil {
|
|
|
|
+ log.Fatal(err)
|
|
|
|
+ }
|
|
|
|
+ return hex.EncodeToString(h.Sum(nil))
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func outputHash(fileStr string) {
|
|
|
|
+ var hashFile Fdhashes
|
|
|
|
+ doHash := true
|
|
|
|
+ defer wg.Done()
|
|
|
|
+ fmt.Print(".")
|
|
|
|
+ dir, fileName := filepath.Split(fileStr)
|
|
|
|
+ if fileName == ".fdhashes3" {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ mu.Lock()
|
|
|
|
+ hashFile, ok := hashes[dir]
|
|
|
|
+ if !ok {
|
|
|
|
+ _, err := os.Stat(dir + ".fdhashes3")
|
|
|
|
+ if os.IsNotExist(err) {
|
|
|
|
+ hashFile = Fdhashes{Path: dir, Hashes: make(map[string]string)}
|
|
|
|
+ } else {
|
|
|
|
+ hashFile = loadHashfile(dir + ".fdhashes3")
|
|
|
|
+ }
|
|
|
|
+ hashes[dir] = hashFile
|
|
|
|
+ saveHashfile(hashFile)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ _, ok = hashFile.Hashes[fileName]
|
|
|
|
+ doHash = !ok
|
|
|
|
+ hashFile = hashes[dir]
|
|
|
|
+ mu.Unlock()
|
|
|
|
+ if doHash {
|
|
|
|
+ hash := getHash(fileStr)
|
|
|
|
+ mu.Lock()
|
|
|
|
+ hashFile.Hashes[fileName] = hash
|
|
|
|
+ saveHashfile(hashFile)
|
|
|
|
+ mu.Unlock()
|
|
|
|
+ log.Printf("file %s has hash %s\n", fileStr, hash)
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func processFolder(folder string) {
|
|
|
|
+ err := filepath.Walk(folder, func(path string, info os.FileInfo, err error) error {
|
|
|
|
+ if !info.IsDir() {
|
|
|
|
+ wg.Add(1)
|
|
|
|
+ go outputHash(path)
|
|
|
|
+ }
|
|
|
|
+ return nil
|
|
|
|
+ })
|
|
|
|
+ if err != nil {
|
|
|
|
+ panic(err)
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func saveHashfile(hashFile Fdhashes) {
|
|
|
|
+ b, err := json.Marshal(hashFile)
|
|
|
|
+ if err != nil {
|
|
|
|
+ fmt.Println(err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ err = ioutil.WriteFile(hashFile.Path+".fdhashes3", b, 0644)
|
|
|
|
+ if err != nil {
|
|
|
|
+ panic(err)
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func loadHashfile(filename string) Fdhashes {
|
|
|
|
+ file, err := ioutil.ReadFile(filename)
|
|
|
|
+ if err != nil {
|
|
|
|
+ panic(err)
|
|
|
|
+ }
|
|
|
|
+ data := Fdhashes{}
|
|
|
|
+ err = json.Unmarshal([]byte(file), &data)
|
|
|
|
+ if err != nil {
|
|
|
|
+ panic(err)
|
|
|
|
+ }
|
|
|
|
+ return data
|
|
|
|
+}
|