diff --git a/cmd/erasure-multipart.go b/cmd/erasure-multipart.go index 266a9d704..1435109ea 100644 --- a/cmd/erasure-multipart.go +++ b/cmd/erasure-multipart.go @@ -1137,8 +1137,9 @@ func (er erasureObjects) CompleteMultipartUpload(ctx context.Context, bucket str } } if checksumType.IsSet() { + checksumType |= hash.ChecksumMultipart cs := hash.NewChecksumFromData(checksumType, checksumCombined) - fi.Checksum = cs.AppendTo(nil) + fi.Checksum = cs.AppendTo(nil, len(fi.Parts)) if opts.EncryptFn != nil { fi.Checksum = opts.EncryptFn("object-checksum", fi.Checksum) } diff --git a/cmd/erasure-object.go b/cmd/erasure-object.go index ebe8b5851..cf6a880b6 100644 --- a/cmd/erasure-object.go +++ b/cmd/erasure-object.go @@ -1081,7 +1081,7 @@ func (er erasureObjects) putObject(ctx context.Context, bucket string, object st } fi.DataDir = mustGetUUID() - fi.Checksum = opts.WantChecksum.AppendTo(nil) + fi.Checksum = opts.WantChecksum.AppendTo(nil, 0) if opts.EncryptFn != nil { fi.Checksum = opts.EncryptFn("object-checksum", fi.Checksum) } diff --git a/internal/hash/checksum.go b/internal/hash/checksum.go index e2f3afe5d..98781e4b2 100644 --- a/internal/hash/checksum.go +++ b/internal/hash/checksum.go @@ -22,6 +22,7 @@ import ( "crypto/sha1" "encoding/base64" "encoding/binary" + "fmt" "hash" "hash/crc32" "net/http" @@ -53,6 +54,8 @@ const ( ChecksumCRC32C // ChecksumInvalid indicates an invalid checksum. ChecksumInvalid + // ChecksumMultipart indicates the checksum is from a multipart upload. + ChecksumMultipart // ChecksumNone indicates no checksum. ChecksumNone ChecksumType = 0 @@ -194,8 +197,17 @@ func ReadCheckSums(b []byte) map[string]string { if length == 0 || len(b) < length { break } - res[typ.String()] = base64.StdEncoding.EncodeToString(b[:length]) + cs := base64.StdEncoding.EncodeToString(b[:length]) b = b[length:] + if typ.Is(ChecksumMultipart) { + t, n := binary.Uvarint(b) + if n < 0 { + break + } + cs = fmt.Sprintf("%s-%d", cs, t) + b = b[n:] + } + res[typ.String()] = cs } if len(res) == 0 { res = nil @@ -225,8 +237,9 @@ func NewChecksumString(alg, value string) *Checksum { } // AppendTo will append the checksum to b. +// 'parts' is used when checksum has ChecksumMultipart set. // ReadCheckSums reads the values back. -func (c *Checksum) AppendTo(b []byte) []byte { +func (c *Checksum) AppendTo(b []byte, parts int) []byte { if c == nil { return nil } @@ -238,6 +251,13 @@ func (c *Checksum) AppendTo(b []byte) []byte { } b = append(b, tmp[:n]...) b = append(b, crc...) + if c.Type.Is(ChecksumMultipart) { + if parts < 0 { + parts = 0 + } + n := binary.PutUvarint(tmp[:], uint64(parts)) + b = append(b, tmp[:n]...) + } return b }