Ver código fonte

Bug 1677: Do not fail transfer if file selected for transfer, but excluded by file mask, is deleted during operation

https://winscp.net/tracker/1677

Source commit: 88d21caaae8bbd140229a313bd8aadb159706750
Martin Prikryl 7 anos atrás
pai
commit
93fc1a2807

+ 6 - 0
source/core/Common.cpp

@@ -1421,6 +1421,12 @@ bool __fastcall FileSearchRec(const UnicodeString FileName, TSearchRec & Rec)
   return Result;
 }
 //---------------------------------------------------------------------------
+void CopySearchRec(const TSearchRec & Source, TSearchRec & Dest)
+{
+  // Strangely isses a compiler warning (W8111 due to TSearchRec::Time), when used in Script.cpp, but not here.
+  Dest = Source;
+}
+//---------------------------------------------------------------------------
 bool __fastcall IsRealFile(const UnicodeString & FileName)
 {
   return (FileName != THISDIRECTORY) && (FileName != PARENTDIRECTORY);

+ 1 - 0
source/core/Common.h

@@ -192,6 +192,7 @@ private:
 typedef void __fastcall (__closure* TProcessLocalFileEvent)
   (const UnicodeString & FileName, const TSearchRecSmart & Rec, void * Param);
 bool __fastcall FileSearchRec(const UnicodeString FileName, TSearchRec & Rec);
+void CopySearchRec(const TSearchRec & Source, TSearchRec & Dest);
 struct TSearchRecChecked : public TSearchRecSmart
 {
   UnicodeString Path;

+ 1 - 1
source/core/ScpFileSystem.cpp

@@ -1710,7 +1710,7 @@ void __fastcall TSCPFileSystem::SCPSource(const UnicodeString FileName,
 
   OperationProgress->SetFile(FileName, false);
 
-  if (!FTerminal->AllowLocalFileTransfer(FileName, CopyParam, OperationProgress))
+  if (!FTerminal->AllowLocalFileTransfer(FileName, NULL, CopyParam, OperationProgress))
   {
     throw ESkipFile();
   }

+ 5 - 2
source/core/Script.cpp

@@ -716,9 +716,10 @@ TStrings * __fastcall TScript::CreateFileList(TScriptProcParams * Parameters, in
 TStrings * __fastcall TScript::CreateLocalFileList(TScriptProcParams * Parameters,
   int Start, int End, TFileListType ListType)
 {
-  TStrings * Result = new TStringList();
+  TStringList * Result = new TStringList();
   try
   {
+    Result->OwnsObjects = true;
     UnicodeString LatestFileName;
     TDateTime LatestModification; // initialized to 0
 
@@ -748,7 +749,9 @@ TStrings * __fastcall TScript::CreateLocalFileList(TScriptProcParams * Parameter
             if (SearchRec.IsRealFile())
             {
               UnicodeString FileName = Directory + SearchRec.Name;
-              Result->Add(FileName);
+              TLocalFile * LocalFile = new TLocalFile;
+              CopySearchRec(SearchRec, LocalFile->SearchRec);
+              Result->AddObject(FileName, LocalFile);
               if (SearchRec.TimeStamp > LatestModification)
               {
                 LatestFileName = FileName;

+ 30 - 17
source/core/Terminal.cpp

@@ -5128,37 +5128,42 @@ bool __fastcall TTerminal::DoAllowRemoteFileTransfer(
        !IsEmptyRemoteDirectory(File, CopyParam, DisallowTemporaryTransferFiles));
 }
 //---------------------------------------------------------------------------
-bool __fastcall TTerminal::AllowLocalFileTransfer(UnicodeString FileName,
+bool __fastcall TTerminal::AllowLocalFileTransfer(
+  const UnicodeString & FileName, const TSearchRecSmart * SearchRec,
   const TCopyParamType * CopyParam, TFileOperationProgressType * OperationProgress)
 {
   bool Result = true;
-  // optimization (though in most uses of the method, the caller actually knows TSearchRec already, so it could pass it here)
+  // optimization (though in most uses of the method, the caller actually knows TSearchRec already, so it passes it here
   if (Log->Logging || !CopyParam->AllowAnyTransfer())
   {
-    TSearchRecSmart SearchRec;
-    FILE_OPERATION_LOOP_BEGIN
+    TSearchRecSmart ASearchRec;
+    if (SearchRec == NULL)
     {
-      if (!FileSearchRec(FileName, SearchRec))
+      FILE_OPERATION_LOOP_BEGIN
       {
-        RaiseLastOSError();
+        if (!FileSearchRec(FileName, ASearchRec))
+        {
+          RaiseLastOSError();
+        }
       }
+      FILE_OPERATION_LOOP_END(FMTLOAD(FILE_NOT_EXISTS, (FileName)));
+      SearchRec = &ASearchRec;
     }
-    FILE_OPERATION_LOOP_END(FMTLOAD(FILE_NOT_EXISTS, (FileName)));
 
-    if (!DoAllowLocalFileTransfer(FileName, SearchRec, CopyParam, false))
+    if (!DoAllowLocalFileTransfer(FileName, *SearchRec, CopyParam, false))
     {
       LogEvent(FORMAT(L"File \"%s\" excluded from transfer", (FileName)));
       Result = false;
     }
-    else if (CopyParam->SkipTransfer(FileName, SearchRec.IsDirectory()))
+    else if (CopyParam->SkipTransfer(FileName, SearchRec->IsDirectory()))
     {
-      OperationProgress->AddSkippedFileSize(SearchRec.Size);
+      OperationProgress->AddSkippedFileSize(SearchRec->Size);
       Result = false;
     }
 
     if (Result)
     {
-      LogFileDetails(FileName, SearchRec.GetLastWriteTime(), SearchRec.Size);
+      LogFileDetails(FileName, SearchRec->GetLastWriteTime(), SearchRec->Size);
     }
   }
   return Result;
@@ -6722,6 +6727,12 @@ void __fastcall TTerminal::DoCopyToRemote(
   {
     bool Success = false;
     UnicodeString FileName = FilesToCopy->Strings[Index];
+    TSearchRecSmart * SearchRec = NULL;
+    if (FilesToCopy->Objects[Index] != NULL)
+    {
+      TLocalFile * LocalFile = dynamic_cast<TLocalFile *>(FilesToCopy->Objects[Index]);
+      SearchRec = &LocalFile->SearchRec;
+    }
 
     try
     {
@@ -6737,7 +6748,7 @@ void __fastcall TTerminal::DoCopyToRemote(
             DirectoryModified(FullTargetDir + FileNameOnly, true);
           }
         }
-        SourceRobust(FileName, FullTargetDir, CopyParam, Params, OperationProgress, Flags | tfFirstLevel);
+        SourceRobust(FileName, SearchRec, FullTargetDir, CopyParam, Params, OperationProgress, Flags | tfFirstLevel);
         Success = true;
       }
       catch (ESkipFile & E)
@@ -6758,7 +6769,8 @@ void __fastcall TTerminal::DoCopyToRemote(
 }
 //---------------------------------------------------------------------------
 void __fastcall TTerminal::SourceRobust(
-  const UnicodeString & FileName, const UnicodeString & TargetDir, const TCopyParamType * CopyParam, int Params,
+  const UnicodeString & FileName, const TSearchRecSmart * SearchRec,
+  const UnicodeString & TargetDir, const TCopyParamType * CopyParam, int Params,
   TFileOperationProgressType * OperationProgress, unsigned int Flags)
 {
   TUploadSessionAction Action(ActionLog);
@@ -6770,7 +6782,7 @@ void __fastcall TTerminal::SourceRobust(
     bool ChildError = false;
     try
     {
-      Source(FileName, TargetDir, CopyParam, Params, OperationProgress, Flags, Action, ChildError);
+      Source(FileName, SearchRec, TargetDir, CopyParam, Params, OperationProgress, Flags, Action, ChildError);
     }
     catch (Exception & E)
     {
@@ -6847,7 +6859,7 @@ void __fastcall TTerminal::DirectorySource(
       {
         if (SearchRec.IsRealFile())
         {
-          SourceRobust(FileName, DestFullName, CopyParam, Params, OperationProgress, (Flags & ~(tfFirstLevel | tfAutoResume)));
+          SourceRobust(FileName, &SearchRec, DestFullName, CopyParam, Params, OperationProgress, (Flags & ~(tfFirstLevel | tfAutoResume)));
           // FTP: if any file got uploaded (i.e. there were any file in the directory and at least one was not skipped),
           // do not try to create the directory, as it should be already created by FZAPI during upload
           PostCreateDir = false;
@@ -6968,14 +6980,15 @@ void __fastcall TTerminal::UpdateSource(const TLocalFileHandle & Handle, const T
 }
 //---------------------------------------------------------------------------
 void __fastcall TTerminal::Source(
-  const UnicodeString & FileName, const UnicodeString & TargetDir, const TCopyParamType * CopyParam, int Params,
+  const UnicodeString & FileName, const TSearchRecSmart * SearchRec,
+  const UnicodeString & TargetDir, const TCopyParamType * CopyParam, int Params,
   TFileOperationProgressType * OperationProgress, unsigned int Flags, TUploadSessionAction & Action, bool & ChildError)
 {
   Action.FileName(ExpandUNCFileName(FileName));
 
   OperationProgress->SetFile(FileName, false);
 
-  if (!AllowLocalFileTransfer(FileName, CopyParam, OperationProgress))
+  if (!AllowLocalFileTransfer(FileName, SearchRec, CopyParam, OperationProgress))
   {
     throw ESkipFile();
   }

+ 12 - 3
source/core/Terminal.h

@@ -309,7 +309,8 @@ protected:
     __int64 * ATime, __int64 * Size, bool TryWriteReadOnly = true);
   void __fastcall OpenLocalFile(
     const UnicodeString & FileName, unsigned int Access, TLocalFileHandle & Handle, bool TryWriteReadOnly = true);
-  bool __fastcall AllowLocalFileTransfer(UnicodeString FileName,
+  bool __fastcall AllowLocalFileTransfer(
+    const UnicodeString & FileName, const TSearchRecSmart * SearchRec,
     const TCopyParamType * CopyParam, TFileOperationProgressType * OperationProgress);
   bool __fastcall HandleException(Exception * E);
   void __fastcall CalculateFileSize(UnicodeString FileName,
@@ -447,10 +448,12 @@ protected:
     TStrings * FilesToCopy, const UnicodeString & TargetDir, const TCopyParamType * CopyParam, int Params,
     TFileOperationProgressType * OperationProgress, unsigned int Flags, TOnceDoneOperation & OnceDoneOperation);
   void __fastcall SourceRobust(
-    const UnicodeString & FileName, const UnicodeString & TargetDir, const TCopyParamType * CopyParam, int Params,
+    const UnicodeString & FileName, const TSearchRecSmart * SearchRec,
+    const UnicodeString & TargetDir, const TCopyParamType * CopyParam, int Params,
     TFileOperationProgressType * OperationProgress, unsigned int Flags);
   void __fastcall Source(
-    const UnicodeString & FileName, const UnicodeString & TargetDir, const TCopyParamType * CopyParam, int Params,
+    const UnicodeString & FileName, const TSearchRecSmart * SearchRec,
+    const UnicodeString & TargetDir, const TCopyParamType * CopyParam, int Params,
     TFileOperationProgressType * OperationProgress, unsigned int Flags, TUploadSessionAction & Action, bool & ChildError);
   void __fastcall DirectorySource(
     const UnicodeString & DirectoryName, const UnicodeString & TargetDir, const UnicodeString & DestDirectoryName,
@@ -886,4 +889,10 @@ struct TLocalFileHandle
   __int64 Size;
 };
 //---------------------------------------------------------------------------
+class TLocalFile : public TObject
+{
+public:
+  TSearchRecSmart SearchRec;
+};
+//---------------------------------------------------------------------------
 #endif