fix: adds the surrounding quotes on ETag in PutObject for dir objects and in UploadPartCopy.

Fixes #1277
Fixes #1235

Adds surrounding quotes on `ETag` when creating a directory object. Adds the quotes in `UploadPartCopy` as well.
This commit is contained in:
niksis02
2025-05-09 00:29:23 +04:00
parent 3a9f8c6525
commit 3740d79173
3 changed files with 18 additions and 22 deletions

View File

@@ -19,6 +19,7 @@ import (
"encoding/hex"
"errors"
"fmt"
"hash"
"io"
"io/fs"
"net/url"
@@ -391,3 +392,14 @@ func MoveFile(source, destination string, perm os.FileMode) error {
return nil
}
// GenerateEtag generates a new quoted etag from the provided hash.Hash
func GenerateEtag(h hash.Hash) string {
dataSum := h.Sum(nil)
return fmt.Sprintf("\"%s\"", hex.EncodeToString(dataSum[:]))
}
// AreEtagsSame compares 2 etags by ignoring quotes
func AreEtagsSame(e1, e2 string) bool {
return strings.Trim(e1, `"`) == strings.Trim(e2, `"`)
}

View File

@@ -18,11 +18,9 @@ import (
"context"
"crypto/md5"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"hash"
"io"
"io/fs"
"net/http"
@@ -95,7 +93,7 @@ const (
contentDispHdr = "content-disposition"
cacheCtrlHdr = "cache-control"
expiresHdr = "expires"
emptyMD5 = "d41d8cd98f00b204e9800998ecf8427e"
emptyMD5 = "\"d41d8cd98f00b204e9800998ecf8427e\""
aclkey = "acl"
ownershipkey = "ownership"
etagkey = "etag"
@@ -1472,7 +1470,7 @@ func (p *Posix) CompleteMultipartUpload(ctx context.Context, input *s3.CompleteM
if err != nil {
etag = ""
}
if parts[i].ETag == nil || !areEtagsSame(etag, *parts[i].ETag) {
if parts[i].ETag == nil || !backend.AreEtagsSame(etag, *parts[i].ETag) {
return res, "", s3err.GetAPIError(s3err.ErrInvalidPart)
}
@@ -2406,7 +2404,7 @@ func (p *Posix) UploadPart(ctx context.Context, input *s3.UploadPartInput) (*s3.
return nil, fmt.Errorf("write part data: %w", err)
}
etag := generateEtag(hash)
etag := backend.GenerateEtag(hash)
err = p.meta.StoreAttribute(f.File(), bucket, partPath, etagkey, []byte(etag))
if err != nil {
return nil, fmt.Errorf("set etag attr: %w", err)
@@ -2645,8 +2643,7 @@ func (p *Posix) UploadPartCopy(ctx context.Context, upi *s3.UploadPartCopyInput)
}
}
dataSum := hash.Sum(nil)
etag := hex.EncodeToString(dataSum)
etag := backend.GenerateEtag(hash)
err = p.meta.StoreAttribute(f.File(), *upi.Bucket, partPath, etagkey, []byte(etag))
if err != nil {
return s3response.CopyPartResult{}, fmt.Errorf("set etag attr: %w", err)
@@ -2855,7 +2852,7 @@ func (p *Posix) PutObject(ctx context.Context, po s3response.PutObjectInput) (s3
}
}
etag := generateEtag(hash)
etag := backend.GenerateEtag(hash)
// if the versioning is enabled, generate a new versionID for the object
var versionID string
@@ -5006,12 +5003,3 @@ func joinPathWithTrailer(paths ...string) string {
}
return joined
}
func generateEtag(h hash.Hash) string {
dataSum := h.Sum(nil)
return fmt.Sprintf("\"%s\"", hex.EncodeToString(dataSum[:]))
}
func areEtagsSame(e1, e2 string) bool {
return strings.Trim(e1, `"`) == strings.Trim(e2, `"`)
}

View File

@@ -287,7 +287,7 @@ func (s *ScoutFS) CompleteMultipartUpload(ctx context.Context, input *s3.Complet
if err != nil {
etag = ""
}
if parts[i].ETag == nil || !areEtagsSame(etag, *parts[i].ETag) {
if parts[i].ETag == nil || !backend.AreEtagsSame(etag, *parts[i].ETag) {
return res, "", s3err.GetAPIError(s3err.ErrInvalidPart)
}
@@ -1033,7 +1033,3 @@ func isNoAttr(err error) bool {
}
return false
}
func areEtagsSame(e1, e2 string) bool {
return strings.Trim(e1, `"`) == strings.Trim(e2, `"`)
}