@@ -7,6 +7,7 @@ package scanner
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/syncthing/syncthing/internal/protocol"
|
||||
@@ -88,3 +89,32 @@ func BlockDiff(src, tgt []protocol.BlockInfo) (have, need []protocol.BlockInfo)
|
||||
|
||||
return have, need
|
||||
}
|
||||
|
||||
// Verify returns nil or an error describing the mismatch between the block
|
||||
// list and actual reader contents
|
||||
func Verify(r io.Reader, blocksize int, blocks []protocol.BlockInfo) error {
|
||||
hf := sha256.New()
|
||||
for i, block := range blocks {
|
||||
lr := &io.LimitedReader{R: r, N: int64(blocksize)}
|
||||
_, err := io.Copy(hf, lr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
hash := hf.Sum(nil)
|
||||
hf.Reset()
|
||||
|
||||
if bytes.Compare(hash, block.Hash) != 0 {
|
||||
return fmt.Errorf("hash mismatch %x != %x for block %d", hash, block.Hash, i)
|
||||
}
|
||||
}
|
||||
|
||||
// We should have reached the end now
|
||||
bs := make([]byte, 1)
|
||||
n, err := r.Read(bs)
|
||||
if n != 0 || err != io.EOF {
|
||||
return fmt.Errorf("file continues past end of blocks")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -133,6 +133,50 @@ func TestWalkError(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestVerify(t *testing.T) {
|
||||
blocksize := 16
|
||||
// data should be an even multiple of blocksize long
|
||||
data := []byte("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut e")
|
||||
buf := bytes.NewBuffer(data)
|
||||
|
||||
blocks, err := Blocks(buf, blocksize, 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if exp := len(data) / blocksize; len(blocks) != exp {
|
||||
t.Fatalf("Incorrect number of blocks %d != %d", len(blocks), exp)
|
||||
}
|
||||
|
||||
buf = bytes.NewBuffer(data)
|
||||
err = Verify(buf, blocksize, blocks)
|
||||
t.Log(err)
|
||||
if err != nil {
|
||||
t.Fatal("Unexpected verify failure", err)
|
||||
}
|
||||
|
||||
buf = bytes.NewBuffer(append(data, '\n'))
|
||||
err = Verify(buf, blocksize, blocks)
|
||||
t.Log(err)
|
||||
if err == nil {
|
||||
t.Fatal("Unexpected verify success")
|
||||
}
|
||||
|
||||
buf = bytes.NewBuffer(data[:len(data)-1])
|
||||
err = Verify(buf, blocksize, blocks)
|
||||
t.Log(err)
|
||||
if err == nil {
|
||||
t.Fatal("Unexpected verify success")
|
||||
}
|
||||
|
||||
data[42] = 42
|
||||
buf = bytes.NewBuffer(data)
|
||||
err = Verify(buf, blocksize, blocks)
|
||||
t.Log(err)
|
||||
if err == nil {
|
||||
t.Fatal("Unexpected verify success")
|
||||
}
|
||||
}
|
||||
|
||||
type fileList []protocol.FileInfo
|
||||
|
||||
func (f fileList) Len() int {
|
||||
|
||||
Reference in New Issue
Block a user