GoHash.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. package main
  2. import (
  3. "crypto/sha256"
  4. "encoding/hex"
  5. "encoding/json"
  6. "flag"
  7. "fmt"
  8. "io"
  9. "io/ioutil"
  10. "log"
  11. "os"
  12. "path/filepath"
  13. "runtime"
  14. "sync"
  15. )
  16. // Fdhashes struct for holding all informations about one folder.
  17. type Fdhashes struct {
  18. Path string
  19. Hashes map[string]string
  20. }
  21. var hashes map[string]Fdhashes
  22. var wg sync.WaitGroup
  23. var mu sync.RWMutex
  24. func main() {
  25. log.Println("starting GoHash")
  26. runtime.GOMAXPROCS(5)
  27. hashes = make(map[string]Fdhashes)
  28. flag.Parse()
  29. myFile := flag.Arg(0)
  30. file, err := os.Stat(myFile)
  31. if os.IsNotExist(err) {
  32. log.Fatalln("File does not exists:", myFile)
  33. }
  34. if file.IsDir() {
  35. log.Println("start with folder:", myFile)
  36. processFolder(myFile)
  37. } else {
  38. log.Printf("file %s has hash %s\n", myFile, getHash(myFile))
  39. }
  40. fmt.Println("waiting")
  41. wg.Wait()
  42. log.Println("done")
  43. }
  44. func getHash(fileStr string) string {
  45. f, err := os.Open(fileStr)
  46. if err != nil {
  47. log.Fatal(err)
  48. }
  49. defer f.Close()
  50. h := sha256.New()
  51. if _, err := io.Copy(h, f); err != nil {
  52. log.Fatal(err)
  53. }
  54. return hex.EncodeToString(h.Sum(nil))
  55. }
  56. func outputHash(fileStr string) {
  57. var hashFile Fdhashes
  58. doHash := true
  59. defer wg.Done()
  60. fmt.Print(".")
  61. dir, fileName := filepath.Split(fileStr)
  62. if fileName == ".fdhashes3" {
  63. return
  64. }
  65. mu.Lock()
  66. hashFile, ok := hashes[dir]
  67. if !ok {
  68. _, err := os.Stat(dir + ".fdhashes3")
  69. if os.IsNotExist(err) {
  70. hashFile = Fdhashes{Path: dir, Hashes: make(map[string]string)}
  71. } else {
  72. hashFile = loadHashfile(dir + ".fdhashes3")
  73. }
  74. hashes[dir] = hashFile
  75. saveHashfile(hashFile)
  76. }
  77. _, ok = hashFile.Hashes[fileName]
  78. doHash = !ok
  79. hashFile = hashes[dir]
  80. mu.Unlock()
  81. if doHash {
  82. hash := getHash(fileStr)
  83. mu.Lock()
  84. hashFile.Hashes[fileName] = hash
  85. saveHashfile(hashFile)
  86. mu.Unlock()
  87. log.Printf("file %s has hash %s\n", fileStr, hash)
  88. }
  89. }
  90. func processFolder(folder string) {
  91. err := filepath.Walk(folder, func(path string, info os.FileInfo, err error) error {
  92. if !info.IsDir() {
  93. wg.Add(1)
  94. go outputHash(path)
  95. }
  96. return nil
  97. })
  98. if err != nil {
  99. panic(err)
  100. }
  101. }
  102. func saveHashfile(hashFile Fdhashes) {
  103. b, err := json.Marshal(hashFile)
  104. if err != nil {
  105. fmt.Println(err)
  106. return
  107. }
  108. err = ioutil.WriteFile(hashFile.Path+".fdhashes3", b, 0644)
  109. if err != nil {
  110. panic(err)
  111. }
  112. }
  113. func loadHashfile(filename string) Fdhashes {
  114. file, err := ioutil.ReadFile(filename)
  115. if err != nil {
  116. panic(err)
  117. }
  118. data := Fdhashes{}
  119. err = json.Unmarshal([]byte(file), &data)
  120. if err != nil {
  121. log.Fatalf("can't read file %s", filename)
  122. }
  123. return data
  124. }