fileutil.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. /*
  2. * Public Domain Software
  3. *
  4. * I (Matthias Ladkau) am the author of the source code in this file.
  5. * I have placed the source code in this file in the public domain.
  6. *
  7. * For further information see: http://creativecommons.org/publicdomain/zero/1.0/
  8. */
  9. package fileutil
  10. import (
  11. "bytes"
  12. "crypto/sha256"
  13. "fmt"
  14. "io"
  15. "os"
  16. "devt.de/krotik/common/bitutil"
  17. "devt.de/krotik/common/pools"
  18. )
  19. /*
  20. PathExists returns whether the given file or directory exists.
  21. */
  22. func PathExists(path string) (bool, error) {
  23. _, err := os.Stat(path)
  24. if err == nil {
  25. return true, nil
  26. }
  27. if os.IsNotExist(err) {
  28. return false, nil
  29. }
  30. return false, err
  31. }
  32. /*
  33. IsDir returns whether the given path is a directory.
  34. */
  35. func IsDir(path string) (bool, error) {
  36. stat, err := os.Stat(path)
  37. if err != nil {
  38. return false, err
  39. }
  40. return stat.IsDir(), nil
  41. }
  42. /*
  43. CheckSumFile calculates a sha256 checksum of a given file. This function
  44. will read in the whole file.
  45. */
  46. func CheckSumFile(path string) (string, error) {
  47. var checksum = ""
  48. f, err := os.Open(path)
  49. if err == nil {
  50. defer f.Close()
  51. hashFactory := sha256.New()
  52. if _, err = io.Copy(hashFactory, f); err == nil {
  53. checksum = fmt.Sprintf("%x", hashFactory.Sum(nil))
  54. }
  55. }
  56. return checksum, err
  57. }
  58. /*
  59. fastSumSampleSize is the sample size for fast checksum
  60. */
  61. const fastSumSampleSize = 16 * 1024
  62. /*
  63. bufferPool holds buffers which are used for fast checksums.
  64. */
  65. var fastChecksumBigBufferPool = pools.NewByteBufferPool()
  66. var fastChecksumSmallBufferPool = pools.NewByteSlicePool(fastSumSampleSize * 3)
  67. /*
  68. CheckSumFileFast calculates a 32bit MurmurHash3 checksum from a portion
  69. of the given file.
  70. */
  71. func CheckSumFileFast(path string) (string, error) {
  72. var fi os.FileInfo
  73. var checksum = ""
  74. f, err := os.Open(path)
  75. if err == nil {
  76. defer f.Close()
  77. if fi, err = f.Stat(); err == nil {
  78. var res uint32
  79. if fi.Size() < int64(fastSumSampleSize*8) {
  80. buf := fastChecksumBigBufferPool.Get().(*bytes.Buffer)
  81. // Read in the whole file
  82. if _, err = io.Copy(buf, f); err == nil {
  83. if res, err = bitutil.MurMurHashData(buf.Bytes(), 0, buf.Len(), 42); err == nil {
  84. checksum = fmt.Sprintf("%x", res)
  85. }
  86. }
  87. buf.Reset()
  88. fastChecksumBigBufferPool.Put(buf)
  89. } else {
  90. sr := io.NewSectionReader(f, 0, fi.Size())
  91. buf := fastChecksumSmallBufferPool.Get().([]byte)
  92. sr.Read(buf[:fastSumSampleSize])
  93. sr.Seek(sr.Size()/2, 0)
  94. sr.Read(buf[fastSumSampleSize : fastSumSampleSize*2])
  95. sr.Seek(int64(-fastSumSampleSize), 2)
  96. sr.Read(buf[fastSumSampleSize*2:])
  97. if res, err = bitutil.MurMurHashData(buf, 0, len(buf)-1, 42); err == nil {
  98. checksum = fmt.Sprintf("%x", res)
  99. }
  100. fastChecksumSmallBufferPool.Put(buf)
  101. }
  102. }
  103. }
  104. return checksum, err
  105. }