Browse Source

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 b5da4a17fb457e179317ce34518fba5eb1dc1cfa)

# Conflicts:
#	source/core/S3FileSystem.cpp

Source commit: 3a43413dfe2a7542631e7a64b5584d2565a9af47
Martin Prikryl 4 years ago
parent
commit
362cf8c299
1 changed files with 14 additions and 14 deletions
  1. 14 14
      source/core/S3FileSystem.cpp

+ 14 - 14
source/core/S3FileSystem.cpp

@@ -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);