Merge pull request #1180 from versity/sis/copyobject-posix-errs

fis: Fixes the trailing slash issue in CopyObject destination and source object paths in posix.
This commit is contained in:
Ben McClelland
2025-04-01 10:06:10 -07:00
committed by GitHub
3 changed files with 62 additions and 4 deletions

View File

@@ -3844,8 +3844,8 @@ func (p *Posix) CopyObject(ctx context.Context, input s3response.CopyObjectInput
}
if string(vId) != srcVersionId {
srcBucket = filepath.Join(p.versioningDir, srcBucket)
srcObject = filepath.Join(genObjVersionKey(srcObject), srcVersionId)
srcBucket = joinPathWithTrailer(p.versioningDir, srcBucket)
srcObject = joinPathWithTrailer(genObjVersionKey(srcObject), srcVersionId)
}
}
@@ -3857,7 +3857,7 @@ func (p *Posix) CopyObject(ctx context.Context, input s3response.CopyObjectInput
return nil, fmt.Errorf("stat bucket: %w", err)
}
objPath := filepath.Join(srcBucket, srcObject)
objPath := joinPathWithTrailer(srcBucket, srcObject)
f, err := os.Open(objPath)
if errors.Is(err, fs.ErrNotExist) || errors.Is(err, syscall.ENOTDIR) {
if p.versioningEnabled() && vEnabled {
@@ -3896,7 +3896,7 @@ func (p *Posix) CopyObject(ctx context.Context, input s3response.CopyObjectInput
var crc64nvme *string
var chType types.ChecksumType
dstObjdPath := filepath.Join(dstBucket, dstObject)
dstObjdPath := joinPathWithTrailer(dstBucket, dstObject)
if dstObjdPath == objPath {
if input.MetadataDirective == types.MetadataDirectiveCopy {
return &s3.CopyObjectOutput{}, s3err.GetAPIError(s3err.ErrInvalidCopyDest)
@@ -4917,3 +4917,11 @@ func getString(str *string) string {
}
return *str
}
func joinPathWithTrailer(paths ...string) string {
joined := filepath.Join(paths...)
if strings.HasSuffix(paths[len(paths)-1], "/") {
joined += "/"
}
return joined
}

View File

@@ -641,6 +641,8 @@ func TestPosix(s *S3Conf) {
PutObject_name_too_long(s)
HeadObject_name_too_long(s)
DeleteObject_name_too_long(s)
CopyObject_overwrite_same_dir_object(s)
CopyObject_overwrite_same_file_object(s)
DeleteObject_directory_not_empty(s)
// posix specific versioning tests
if !s.versioningEnabled {
@@ -912,6 +914,8 @@ func GetIntTests() IntTests {
"DeleteObject_non_existing_object": DeleteObject_non_existing_object,
"DeleteObject_directory_object_noslash": DeleteObject_directory_object_noslash,
"DeleteObject_name_too_long": DeleteObject_name_too_long,
"CopyObject_overwrite_same_dir_object": CopyObject_overwrite_same_dir_object,
"CopyObject_overwrite_same_file_object": CopyObject_overwrite_same_file_object,
"DeleteObject_non_existing_dir_object": DeleteObject_non_existing_dir_object,
"DeleteObject_directory_object": DeleteObject_directory_object,
"DeleteObject_success": DeleteObject_success,

View File

@@ -14635,6 +14635,52 @@ func DeleteObject_name_too_long(s *S3Conf) error {
})
}
func CopyObject_overwrite_same_dir_object(s *S3Conf) error {
testName := "CopyObject_overwrite_same_dir_object"
return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {
_, err := putObjects(s3client, []string{"foo/"}, bucket)
if err != nil {
return err
}
ctx, cancel := context.WithTimeout(context.Background(), shortTimeout)
_, err = s3client.CopyObject(ctx, &s3.CopyObjectInput{
Bucket: &bucket,
Key: getPtr("foo"),
CopySource: getPtr(fmt.Sprintf("%v/%v", bucket, "foo/")),
})
cancel()
if err := checkApiErr(err, s3err.GetAPIError(s3err.ErrExistingObjectIsDirectory)); err != nil {
return err
}
return nil
})
}
func CopyObject_overwrite_same_file_object(s *S3Conf) error {
testName := "CopyObject_overwrite_same_file_object"
return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {
_, err := putObjects(s3client, []string{"foo"}, bucket)
if err != nil {
return err
}
ctx, cancel := context.WithTimeout(context.Background(), shortTimeout)
_, err = s3client.CopyObject(ctx, &s3.CopyObjectInput{
Bucket: &bucket,
Key: getPtr("foo/"),
CopySource: getPtr(fmt.Sprintf("%v/%v", bucket, "foo")),
})
cancel()
if err := checkApiErr(err, s3err.GetAPIError(s3err.ErrObjectParentIsFile)); err != nil {
return err
}
return nil
})
}
// Versioning tests
func PutBucketVersioning_non_existing_bucket(s *S3Conf) error {
testName := "PutBucketVersioning_non_existing_bucket"