Skip to content

Commit

Permalink
fix: return KeyTooLongError when filenames exceed allowed length
Browse files Browse the repository at this point in the history
The posix limits wont exactly match up with the AWS key length
limits because posix has component length limits as well as path
length limits.

This reponds with the aws compatible KeyTooLongError under these
conditions now.

Note that delete object returns success even in the error cases.

Fixes #755
  • Loading branch information
benmcclelland committed Aug 24, 2024
1 parent 77e037a commit 453136b
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 46 deletions.
36 changes: 30 additions & 6 deletions backend/posix/posix.go
Original file line number Diff line number Diff line change
Expand Up @@ -1231,6 +1231,9 @@ func (p *Posix) UploadPartCopy(ctx context.Context, upi *s3.UploadPartCopyInput)
if errors.Is(err, fs.ErrNotExist) {
return s3response.CopyObjectResult{}, s3err.GetAPIError(s3err.ErrNoSuchUpload)
}
if errors.Is(err, syscall.ENAMETOOLONG) {
return s3response.CopyObjectResult{}, s3err.GetAPIError(s3err.ErrKeyTooLong)
}
if err != nil {
return s3response.CopyObjectResult{}, fmt.Errorf("stat uploadid: %w", err)
}
Expand Down Expand Up @@ -1258,6 +1261,9 @@ func (p *Posix) UploadPartCopy(ctx context.Context, upi *s3.UploadPartCopyInput)
if errors.Is(err, fs.ErrNotExist) {
return s3response.CopyObjectResult{}, s3err.GetAPIError(s3err.ErrNoSuchKey)
}
if errors.Is(err, syscall.ENAMETOOLONG) {
return s3response.CopyObjectResult{}, s3err.GetAPIError(s3err.ErrKeyTooLong)
}
if err != nil {
return s3response.CopyObjectResult{}, fmt.Errorf("stat object: %w", err)
}
Expand Down Expand Up @@ -1413,6 +1419,12 @@ func (p *Posix) PutObject(ctx context.Context, po *s3.PutObjectInput) (string, e
if err == nil && d.IsDir() {
return "", s3err.GetAPIError(s3err.ErrExistingObjectIsDirectory)
}
if errors.Is(err, syscall.ENAMETOOLONG) {
return "", s3err.GetAPIError(s3err.ErrKeyTooLong)
}
if err != nil && !errors.Is(err, fs.ErrNotExist) {
return "", fmt.Errorf("stat object: %w", err)
}

f, err := p.openTmpFile(filepath.Join(*po.Bucket, metaTmpDir),
*po.Bucket, *po.Key, contentLength, acct, doFalloc)
Expand Down Expand Up @@ -1516,12 +1528,12 @@ func (p *Posix) DeleteObject(_ context.Context, input *s3.DeleteObjectInput) err
objpath := filepath.Join(bucket, object)

fi, err := os.Stat(objpath)
if errors.Is(err, fs.ErrNotExist) {
// AWS returns success if the object does not exist
return nil
}
if err != nil {
return fmt.Errorf("stat object: %w", err)
// AWS returns success if the object does not exist or
// is invalid somehow.
// TODO: log if !errors.Is(err, fs.ErrNotExist) somewhere?

return nil
}
if strings.HasSuffix(object, "/") && !fi.IsDir() {
// requested object is expecting a directory with a trailing
Expand Down Expand Up @@ -1642,6 +1654,9 @@ func (p *Posix) GetObject(_ context.Context, input *s3.GetObjectInput) (*s3.GetO
if errors.Is(err, fs.ErrNotExist) {
return nil, s3err.GetAPIError(s3err.ErrNoSuchKey)
}
if errors.Is(err, syscall.ENAMETOOLONG) {
return nil, s3err.GetAPIError(s3err.ErrKeyTooLong)
}
if err != nil {
return nil, fmt.Errorf("stat object: %w", err)
}
Expand Down Expand Up @@ -1785,6 +1800,9 @@ func (p *Posix) HeadObject(ctx context.Context, input *s3.HeadObjectInput) (*s3.
if errors.Is(err, fs.ErrNotExist) {
return nil, s3err.GetAPIError(s3err.ErrInvalidPart)
}
if errors.Is(err, syscall.ENAMETOOLONG) {
return nil, s3err.GetAPIError(s3err.ErrKeyTooLong)
}
if err != nil {
return nil, fmt.Errorf("stat part: %w", err)
}
Expand Down Expand Up @@ -1819,6 +1837,9 @@ func (p *Posix) HeadObject(ctx context.Context, input *s3.HeadObjectInput) (*s3.
if errors.Is(err, fs.ErrNotExist) {
return nil, s3err.GetAPIError(s3err.ErrNoSuchKey)
}
if errors.Is(err, syscall.ENAMETOOLONG) {
return nil, s3err.GetAPIError(s3err.ErrKeyTooLong)
}
if err != nil {
return nil, fmt.Errorf("stat object: %w", err)
}
Expand Down Expand Up @@ -1989,8 +2010,11 @@ func (p *Posix) CopyObject(ctx context.Context, input *s3.CopyObjectInput) (*s3.
if errors.Is(err, fs.ErrNotExist) {
return nil, s3err.GetAPIError(s3err.ErrNoSuchKey)
}
if errors.Is(err, syscall.ENAMETOOLONG) {
return nil, s3err.GetAPIError(s3err.ErrKeyTooLong)
}
if err != nil {
return nil, fmt.Errorf("stat object: %w", err)
return nil, fmt.Errorf("open object: %w", err)
}
defer f.Close()

Expand Down
9 changes: 9 additions & 0 deletions backend/scoutfs/scoutfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,9 @@ func (s *ScoutFS) HeadObject(ctx context.Context, input *s3.HeadObjectInput) (*s
if errors.Is(err, fs.ErrNotExist) {
return nil, s3err.GetAPIError(s3err.ErrInvalidPart)
}
if errors.Is(err, syscall.ENAMETOOLONG) {
return nil, s3err.GetAPIError(s3err.ErrKeyTooLong)
}
if err != nil {
return nil, fmt.Errorf("stat part: %w", err)
}
Expand Down Expand Up @@ -492,6 +495,9 @@ func (s *ScoutFS) HeadObject(ctx context.Context, input *s3.HeadObjectInput) (*s
if errors.Is(err, fs.ErrNotExist) {
return nil, s3err.GetAPIError(s3err.ErrNoSuchKey)
}
if errors.Is(err, syscall.ENAMETOOLONG) {
return nil, s3err.GetAPIError(s3err.ErrKeyTooLong)
}
if err != nil {
return nil, fmt.Errorf("stat object: %w", err)
}
Expand Down Expand Up @@ -613,6 +619,9 @@ func (s *ScoutFS) GetObject(_ context.Context, input *s3.GetObjectInput) (*s3.Ge
if errors.Is(err, fs.ErrNotExist) {
return nil, s3err.GetAPIError(s3err.ErrNoSuchKey)
}
if errors.Is(err, syscall.ENAMETOOLONG) {
return nil, s3err.GetAPIError(s3err.ErrKeyTooLong)
}
if err != nil {
return nil, fmt.Errorf("stat object: %w", err)
}
Expand Down
Loading

0 comments on commit 453136b

Please sign in to comment.