1
0
mirror of https://github.com/winscp/winscp.git synced 2026-10-24 02:28:55 +03:00

Bug 1959: Cannot enter an S3 folder that only contains a subfolder with an empty name

https://winscp.net/tracker/1959
(cherry picked from commit b5da4a17fb)

# Conflicts:
#	source/core/S3FileSystem.cpp

Source commit: 3a43413dfe2a7542631e7a64b5584d2565a9af47
This commit is contained in:
Martin Prikryl
2021-03-12 13:49:04 +00:00
parent 11bff6a98b
commit 362cf8c299

View File

@@ -463,6 +463,7 @@ struct TLibS3BucketContext : S3BucketContext
struct TLibS3ListBucketCallbackData : TLibS3CallbackData
{
TRemoteFileList * FileList;
bool Any;
int KeyCount;
UTF8String NextMarker;
bool IsTruncated;
@@ -809,6 +810,7 @@ S3Status TS3FileSystem::LibS3ListBucketCallback(
for (int Index = 0; Index < ContentsCount; Index++)
{
Data.Any = true;
const S3ListBucketContent * Content = &Contents[Index];
UnicodeString FileName = UnixExtractFileName(StrFromS3(Content->key));
if (!FileName.IsEmpty())
@@ -822,15 +824,11 @@ S3Status TS3FileSystem::LibS3ListBucketCallback(
File->Owner = Data.FileSystem->MakeRemoteToken(Content->ownerId, Content->ownerDisplayName);
Data.FileList->AddFile(File.release());
}
else
{
// We needs this to distinguish empty and non-existing folders, see comments in ReadDirectoryInternal.
Data.FileList->AddFile(new TRemoteParentDirectory(Data.FileSystem->FTerminal));
}
}
for (int Index = 0; Index < CommonPrefixesCount; Index++)
{
Data.Any = true;
UnicodeString CommonPrefix = StrFromS3(CommonPrefixes[Index]);
UnicodeString FileName = UnixExtractFileName(UnixExcludeTrailingBackslash(CommonPrefix));
// Have seen prefixes like "/" or "path/subpath//"
@@ -854,6 +852,7 @@ void TS3FileSystem::DoListBucket(
{
S3ListBucketHandler ListBucketHandler = { CreateResponseHandler(), &LibS3ListBucketCallback };
RequestInit(Data);
Data.Any = false;
Data.KeyCount = 0;
Data.FileList = FileList;
Data.IsTruncated = false;
@@ -953,17 +952,18 @@ void TS3FileSystem::ReadDirectoryInternal(
} while (Continue);
// Listing bucket root directory will report an error if the bucket does not exist.
// But there won't be any prefix/ entry, so no ".." entry is created, so we have to add it explicitly
if (Prefix.IsEmpty())
// But there won't be any prefix/ entry, so if the bucket is ampty, the Data.Any is false.
// But when listing a prefix, we do not get any error, when the "prefix" does not exist.
// But when the prefix does exist, there's at least the prefix/ entry. If there's none, it means that the path does not exist.
// Even an empty-named entry/subprefix (which are ignored for other purposes) still indicate that the prefix exists.
if (Prefix.IsEmpty() || Data.Any)
{
FileList->AddFile(new TRemoteParentDirectory(FTerminal));
}
else
{
// We do not get any error, when the "prefix" does not exist. But when prefix does exist, there's at least
// prefix/ entry (translated to ..). If there's none, it means that the path does not exist.
// When called from DoReadFile (FileName is set), leaving error handling to the caller.
if ((FileList->Count == 0) && FileName.IsEmpty())
if (FileName.IsEmpty())
{
throw Exception(FMTLOAD(FILE_NOT_EXISTS, (APath)));
}
@@ -1021,10 +1021,10 @@ void __fastcall TS3FileSystem::DeleteFile(const UnicodeString AFileName,
UnicodeString BucketName, Key;
ParsePath(FileName, BucketName, Key);
if (!Key.IsEmpty() && Dir)
{
Key = GetFolderKey(Key);
}
if (!Key.IsEmpty() && Dir)
{
Key = GetFolderKey(Key);
}
TLibS3BucketContext BucketContext = GetBucketContext(BucketName, Key);