GoHash.go 2.5 KB

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