forked from External/grumble
53 lines
1.2 KiB
Go
53 lines
1.2 KiB
Go
// Copyright (c) 2011 The Grumble Authors
|
|
// The use of this source code is goverened by a BSD-style
|
|
// license that can be found in the LICENSE-file.
|
|
|
|
package blobstore
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/sha1"
|
|
"encoding/hex"
|
|
"hash"
|
|
"io"
|
|
"os"
|
|
)
|
|
|
|
// blobReader is based on the principles of the checksumReader from the archive/zip
|
|
// package of the Go standard library.
|
|
|
|
// ErrHashMismatch is returned if a blobReader has read a file whose computed hash
|
|
// did not match its key.
|
|
var ErrHashMismatch = os.NewError("hash mismatch")
|
|
|
|
// blobReader reads a blob from disk, hashing all incoming data. On EOF, it checks
|
|
// whether the read data matches the key.
|
|
type blobReader struct {
|
|
rc io.ReadCloser
|
|
sum []byte
|
|
hash hash.Hash
|
|
}
|
|
|
|
func newBlobReader(rc io.ReadCloser, key string) (br *blobReader, err os.Error) {
|
|
sum, err := hex.DecodeString(key)
|
|
if err != nil {
|
|
return
|
|
}
|
|
return &blobReader{rc, sum, sha1.New()}, nil
|
|
}
|
|
|
|
func (r *blobReader) Read(b []byte) (n int, err os.Error) {
|
|
n, err = r.rc.Read(b)
|
|
r.hash.Write(b[:n])
|
|
if err != os.EOF {
|
|
return
|
|
}
|
|
if !bytes.Equal(r.sum, r.hash.Sum()) {
|
|
err = ErrHashMismatch
|
|
}
|
|
return
|
|
}
|
|
|
|
func (r *blobReader) Close() os.Error {
|
|
return r.rc.Close()
|
|
}
|