blocks.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. // Copyright (C) 2014 The Syncthing Authors.
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this file,
  5. // You can obtain one at http://mozilla.org/MPL/2.0/.
  6. package scanner
  7. import (
  8. "bytes"
  9. "crypto/sha256"
  10. "fmt"
  11. "io"
  12. "sync/atomic"
  13. "github.com/syncthing/syncthing/lib/protocol"
  14. )
  15. var SHA256OfNothing = []uint8{0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}
  16. // Blocks returns the blockwise hash of the reader.
  17. func Blocks(r io.Reader, blocksize int, sizehint int64, counter *int64) ([]protocol.BlockInfo, error) {
  18. hf := sha256.New()
  19. hashLength := hf.Size()
  20. var blocks []protocol.BlockInfo
  21. var hashes, thisHash []byte
  22. if sizehint > 0 {
  23. // Allocate contiguous blocks for the BlockInfo structures and their
  24. // hashes once and for all.
  25. numBlocks := int(sizehint / int64(blocksize))
  26. blocks = make([]protocol.BlockInfo, 0, numBlocks)
  27. hashes = make([]byte, 0, hashLength*numBlocks)
  28. }
  29. // A 32k buffer is used for copying into the hash function.
  30. buf := make([]byte, 32<<10)
  31. var offset int64
  32. for {
  33. lr := io.LimitReader(r, int64(blocksize))
  34. n, err := copyBuffer(hf, lr, buf)
  35. if err != nil {
  36. return nil, err
  37. }
  38. if n == 0 {
  39. break
  40. }
  41. if counter != nil {
  42. atomic.AddInt64(counter, int64(n))
  43. }
  44. // Carve out a hash-sized chunk of "hashes" to store the hash for this
  45. // block.
  46. hashes = hf.Sum(hashes)
  47. thisHash, hashes = hashes[:hashLength], hashes[hashLength:]
  48. b := protocol.BlockInfo{
  49. Size: int32(n),
  50. Offset: offset,
  51. Hash: thisHash,
  52. }
  53. blocks = append(blocks, b)
  54. offset += int64(n)
  55. hf.Reset()
  56. }
  57. if len(blocks) == 0 {
  58. // Empty file
  59. blocks = append(blocks, protocol.BlockInfo{
  60. Offset: 0,
  61. Size: 0,
  62. Hash: SHA256OfNothing,
  63. })
  64. }
  65. return blocks, nil
  66. }
  67. // PopulateOffsets sets the Offset field on each block
  68. func PopulateOffsets(blocks []protocol.BlockInfo) {
  69. var offset int64
  70. for i := range blocks {
  71. blocks[i].Offset = offset
  72. offset += int64(blocks[i].Size)
  73. }
  74. }
  75. // BlockDiff returns lists of common and missing (to transform src into tgt)
  76. // blocks. Both block lists must have been created with the same block size.
  77. func BlockDiff(src, tgt []protocol.BlockInfo) (have, need []protocol.BlockInfo) {
  78. if len(tgt) == 0 && len(src) != 0 {
  79. return nil, nil
  80. }
  81. if len(tgt) != 0 && len(src) == 0 {
  82. // Copy the entire file
  83. return nil, tgt
  84. }
  85. for i := range tgt {
  86. if i >= len(src) || bytes.Compare(tgt[i].Hash, src[i].Hash) != 0 {
  87. // Copy differing block
  88. need = append(need, tgt[i])
  89. } else {
  90. have = append(have, tgt[i])
  91. }
  92. }
  93. return have, need
  94. }
  95. // Verify returns nil or an error describing the mismatch between the block
  96. // list and actual reader contents
  97. func Verify(r io.Reader, blocksize int, blocks []protocol.BlockInfo) error {
  98. hf := sha256.New()
  99. for i, block := range blocks {
  100. lr := &io.LimitedReader{R: r, N: int64(blocksize)}
  101. _, err := io.Copy(hf, lr)
  102. if err != nil {
  103. return err
  104. }
  105. hash := hf.Sum(nil)
  106. hf.Reset()
  107. if bytes.Compare(hash, block.Hash) != 0 {
  108. return fmt.Errorf("hash mismatch %x != %x for block %d", hash, block.Hash, i)
  109. }
  110. }
  111. // We should have reached the end now
  112. bs := make([]byte, 1)
  113. n, err := r.Read(bs)
  114. if n != 0 || err != io.EOF {
  115. return fmt.Errorf("file continues past end of blocks")
  116. }
  117. return nil
  118. }
  119. func VerifyBuffer(buf []byte, block protocol.BlockInfo) ([]byte, error) {
  120. if len(buf) != int(block.Size) {
  121. return nil, fmt.Errorf("length mismatch %d != %d", len(buf), block.Size)
  122. }
  123. hf := sha256.New()
  124. _, err := hf.Write(buf)
  125. if err != nil {
  126. return nil, err
  127. }
  128. hash := hf.Sum(nil)
  129. if !bytes.Equal(hash, block.Hash) {
  130. return hash, fmt.Errorf("hash mismatch %x != %x", hash, block.Hash)
  131. }
  132. return hash, nil
  133. }
  134. // BlocksEqual returns whether two slices of blocks are exactly the same hash
  135. // and index pair wise.
  136. func BlocksEqual(src, tgt []protocol.BlockInfo) bool {
  137. if len(tgt) != len(src) {
  138. return false
  139. }
  140. for i, sblk := range src {
  141. if !bytes.Equal(sblk.Hash, tgt[i].Hash) {
  142. return false
  143. }
  144. }
  145. return true
  146. }
  147. // This is a copy & paste of io.copyBuffer from the Go 1.5 standard library,
  148. // as we want this but also want to build with Go 1.3+.
  149. // copyBuffer is the actual implementation of Copy and CopyBuffer.
  150. // if buf is nil, one is allocated.
  151. func copyBuffer(dst io.Writer, src io.Reader, buf []byte) (written int64, err error) {
  152. // If the reader has a WriteTo method, use it to do the copy.
  153. // Avoids an allocation and a copy.
  154. if wt, ok := src.(io.WriterTo); ok {
  155. return wt.WriteTo(dst)
  156. }
  157. // Similarly, if the writer has a ReadFrom method, use it to do the copy.
  158. if rt, ok := dst.(io.ReaderFrom); ok {
  159. return rt.ReadFrom(src)
  160. }
  161. if buf == nil {
  162. buf = make([]byte, 32*1024)
  163. }
  164. for {
  165. nr, er := src.Read(buf)
  166. if nr > 0 {
  167. nw, ew := dst.Write(buf[0:nr])
  168. if nw > 0 {
  169. written += int64(nw)
  170. }
  171. if ew != nil {
  172. err = ew
  173. break
  174. }
  175. if nr != nw {
  176. err = io.ErrShortWrite
  177. break
  178. }
  179. }
  180. if er == io.EOF {
  181. break
  182. }
  183. if er != nil {
  184. err = er
  185. break
  186. }
  187. }
  188. return written, err
  189. }