Skip to content
Snippets Groups Projects
Commit c7b46b9a authored by Pawel Rozlach's avatar Pawel Rozlach
Browse files

fix: Fix S3 stat call for partial prefixes

The blob below is never reached, as we do not set Delimiter field in the
call arguments:
```
-	case len(resp.CommonPrefixes) == 1:
-		fi.IsDir = true
```
parent 8234f821
No related branches found
No related tags found
Loading
Pipeline #1690382167 failed
......@@ -377,11 +377,15 @@ func (d *driver) Writer(ctx context.Context, path string, appendParam bool) (sto
// Stat retrieves the FileInfo for the given path, including the current size
// in bytes and the creation time.
func (d *driver) Stat(ctx context.Context, path string) (storagedriver.FileInfo, error) {
s3Path := d.s3Path(path)
resp, err := d.S3.ListObjectsV2WithContext(
ctx,
&s3.ListObjectsV2Input{
Bucket: aws.String(d.Bucket),
Prefix: aws.String(d.s3Path(path)),
Bucket: aws.String(d.Bucket),
Prefix: aws.String(s3Path),
// NOTE(prozlach): Yes, AWS returns objects in lexicographical
// order based on their key names for general purpose buckets.
// https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectsV2.html
MaxKeys: aws.Int64(1),
})
if err != nil {
......@@ -392,18 +396,19 @@ func (d *driver) Stat(ctx context.Context, path string) (storagedriver.FileInfo,
Path: path,
}
switch {
case len(resp.Contents) == 1:
if *resp.Contents[0].Key != d.s3Path(path) {
if len(resp.Contents) == 1 {
entry := resp.Contents[0]
if *entry.Key != s3Path {
if len(*entry.Key) > len(s3Path) && (*entry.Key)[len(s3Path)] != '/' {
return nil, storagedriver.PathNotFoundError{Path: path, DriverName: driverName}
}
fi.IsDir = true
} else {
fi.IsDir = false
fi.Size = *resp.Contents[0].Size
fi.ModTime = *resp.Contents[0].LastModified
fi.Size = *entry.Size
fi.ModTime = *entry.LastModified
}
case len(resp.CommonPrefixes) == 1:
fi.IsDir = true
default:
} else {
return nil, storagedriver.PathNotFoundError{Path: path, DriverName: driverName}
}
......@@ -616,7 +621,11 @@ ListLoop:
}
for _, key := range resp.Contents {
// Stop if we encounter a key that is not a subpath (so that deleting "/a" does not delete "/ab").
// Stop if we encounter a key that is not a subpath (so that
// deleting "/a" does not delete "/ab").
// NOTE(prozlach): Yes, AWS returns objects in lexicographical
// order based on their key names for general purpose buckets.
// https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectsV2.html
if len(*key.Key) > len(s3Path) && (*key.Key)[len(s3Path)] != '/' {
break ListLoop
}
......
......@@ -1652,6 +1652,7 @@ func (s *DriverSuite) TestStatCall() {
dirPathBase := dtestutil.RandomPath(1, 24)
dirA := "foo" + dtestutil.RandomFilename(13)
dirB := "foo" + dtestutil.RandomFilename(13)
partialPath := path.Join(dirPathBase, "foo")
dirPath := path.Join(dirPathBase, dirA)
dirPathAux := path.Join(dirPathBase, dirB)
fileName := dtestutil.RandomFilename(32)
......@@ -1761,6 +1762,18 @@ func (s *DriverSuite) TestStatCall() {
assert.Zero(s.T(), fi.Size())
assert.True(s.T(), fi.IsDir())
})
// Call on a partial name of the directory. This should result in
// not-found, as partial match is still not a match for a directory.
s.Run("DirPartialPrefix", func() {
fi, err := s.StorageDriver.Stat(s.ctx, partialPath)
require.Error(s.T(), err)
assert.ErrorIs(s.T(), err, storagedriver.PathNotFoundError{ // nolint: testifylint
DriverName: s.StorageDriver.Name(),
Path: partialPath,
})
assert.Nil(s.T(), fi)
})
}
// TestPutContentMultipleTimes checks that if storage driver can overwrite the content
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment