1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
13 type hashCheckWriter struct {
22 // newHashCheckWriter returns a writer that writes through to w, but
23 // stops short if the written content reaches expectSize bytes and
24 // does not match expectDigest according to the given hash
27 // It returns a write error if more than expectSize bytes are written.
29 // Thus, in case of a hash mismatch, fewer than expectSize will be
31 func newHashCheckWriter(writer io.Writer, hash hash.Hash, expectSize int64, expectDigest string) io.Writer {
32 return &hashCheckWriter{
35 expectSize: expectSize,
36 expectDigest: expectDigest,
40 func (hcw *hashCheckWriter) Write(p []byte) (int, error) {
41 if todo := hcw.expectSize - hcw.offset - int64(len(p)); todo < 0 {
42 // Writing beyond expected size returns a checksum
43 // error without even checking the hash.
46 // This isn't the last write, so we pass it through.
47 _, err := hcw.hash.Write(p)
51 n, err := hcw.writer.Write(p)
52 hcw.offset += int64(n)
55 // This is the last write, so we check the hash before
57 _, err := hcw.hash.Write(p)
61 if digest := fmt.Sprintf("%x", hcw.hash.Sum(nil)); digest != hcw.expectDigest {
64 // Ensure subsequent write will fail
65 hcw.offset = hcw.expectSize + 1
66 return hcw.writer.Write(p)