Browse Source

Bug 1392: Error when accessing a local directory junction on Windows XP/2003

https://winscp.net/tracker/1392

Source commit: 7216bebc9d2f75544dde776dc969c4712048fda9
Martin Prikryl 9 years ago
parent
commit
a9b012420b

+ 13 - 0
source/core/Common.cpp

@@ -1287,6 +1287,19 @@ void __fastcall ProcessLocalDirectory(UnicodeString DirName,
   }
 }
 //---------------------------------------------------------------------------
+int __fastcall FileGetAttrFix(const UnicodeString FileName)
+{
+  // The default for FileGetAttr is to follow links
+  bool FollowLink = true;
+  // But the FileGetAttr whe called for link with FollowLink set will always fail
+  // as its calls InternalGetFileNameFromSymLink, which test for CheckWin32Version(6, 0)
+  if (!IsWinVista())
+  {
+    FollowLink = false;
+  }
+  return FileGetAttr(FileName, FollowLink);
+}
+//---------------------------------------------------------------------------
 TDateTime __fastcall EncodeDateVerbose(Word Year, Word Month, Word Day)
 {
   try

+ 1 - 0
source/core/Common.h

@@ -156,6 +156,7 @@ int __fastcall FindFirstChecked(const UnicodeString & Path, int Attr, TSearchRec
 int __fastcall FindNextChecked(TSearchRecChecked & F);
 void __fastcall ProcessLocalDirectory(UnicodeString DirName,
   TProcessLocalFileEvent CallBackFunc, void * Param = NULL, int FindAttrs = -1);
+int __fastcall FileGetAttrFix(const UnicodeString FileName);
 //---------------------------------------------------------------------------
 extern const wchar_t * DSTModeNames;
 enum TDSTMode

+ 3 - 3
source/core/FtpFileSystem.cpp

@@ -1633,7 +1633,7 @@ void __fastcall TFTPFileSystem::Sink(const UnicodeString FileName,
     {
       FILE_OPERATION_LOOP_BEGIN
       {
-        int Attrs = FileGetAttr(ApiPath(DestFullName));
+        int Attrs = FileGetAttrFix(ApiPath(DestFullName));
         if (FLAGCLEAR(Attrs, faDirectory))
         {
           EXCEPTION;
@@ -1687,7 +1687,7 @@ void __fastcall TFTPFileSystem::Sink(const UnicodeString FileName,
     int Attrs;
     FILE_OPERATION_LOOP_BEGIN
     {
-      Attrs = FileGetAttr(ApiPath(DestFullName));
+      Attrs = FileGetAttrFix(ApiPath(DestFullName));
       if ((Attrs >= 0) && FLAGSET(Attrs, faDirectory))
       {
         EXCEPTION;
@@ -1725,7 +1725,7 @@ void __fastcall TFTPFileSystem::Sink(const UnicodeString FileName,
     if (DestFileName != UserData.FileName)
     {
       DestFullName = TargetDir + UserData.FileName;
-      Attrs = FileGetAttr(ApiPath(DestFullName));
+      Attrs = FileGetAttrFix(ApiPath(DestFullName));
     }
 
     Action.Destination(ExpandUNCFileName(DestFullName));

+ 2 - 2
source/core/ScpFileSystem.cpp

@@ -1992,7 +1992,7 @@ void __fastcall TSCPFileSystem::SCPDirectorySource(const UnicodeString Directory
   // Get directory attributes
   FILE_OPERATION_LOOP_BEGIN
   {
-    Attrs = FileGetAttr(ApiPath(DirectoryName));
+    Attrs = FileGetAttrFix(ApiPath(DirectoryName));
     if (Attrs < 0) RaiseLastOSError();
   }
   FILE_OPERATION_LOOP_END(FMTLOAD(CANT_GET_ATTRS, (DirectoryName)));
@@ -2435,7 +2435,7 @@ void __fastcall TSCPFileSystem::SCPSink(const UnicodeString TargetDir,
         UnicodeString DestFileName =
           IncludeTrailingBackslash(TargetDir) + DestFileNameOnly;
 
-        FileData.Attrs = FileGetAttr(ApiPath(DestFileName));
+        FileData.Attrs = FileGetAttrFix(ApiPath(DestFileName));
         // If getting attrs fails, we suppose, that file/folder doesn't exists
         FileData.Exists = (FileData.Attrs != -1);
         if (Dir)

+ 2 - 2
source/core/SftpFileSystem.cpp

@@ -5556,7 +5556,7 @@ void __fastcall TSFTPFileSystem::SFTPSink(const UnicodeString FileName,
     {
       FILE_OPERATION_LOOP_BEGIN
       {
-        int Attrs = FileGetAttr(ApiPath(DestFullName));
+        int Attrs = FileGetAttrFix(ApiPath(DestFullName));
         if ((Attrs & faDirectory) == 0) EXCEPTION;
       }
       FILE_OPERATION_LOOP_END(FMTLOAD(NOT_DIRECTORY_ERROR, (DestFullName)));
@@ -5648,7 +5648,7 @@ void __fastcall TSFTPFileSystem::SFTPSink(const UnicodeString FileName,
     int Attrs;
     FILE_OPERATION_LOOP_BEGIN
     {
-      Attrs = FileGetAttr(ApiPath(DestFullName));
+      Attrs = FileGetAttrFix(ApiPath(DestFullName));
       if ((Attrs >= 0) && (Attrs & faDirectory)) EXCEPTION;
     }
     FILE_OPERATION_LOOP_END(FMTLOAD(NOT_FILE_ERROR, (DestFullName)));

+ 2 - 2
source/core/Terminal.cpp

@@ -4173,7 +4173,7 @@ bool __fastcall TTerminal::DoCreateLocalFile(const UnicodeString FileName,
       int LastError = GetLastError();
       int FileAttr;
       if (::FileExists(ApiPath(FileName)) &&
-        (((FileAttr = FileGetAttr(ApiPath(FileName))) & (faReadOnly | faHidden)) != 0))
+        (((FileAttr = FileGetAttrFix(ApiPath(FileName))) & (faReadOnly | faHidden)) != 0))
       {
         if (FLAGSET(FileAttr, faReadOnly))
         {
@@ -4264,7 +4264,7 @@ void __fastcall TTerminal::OpenLocalFile(const UnicodeString FileName,
   FILE_OPERATION_LOOP_BEGIN
   {
     UnicodeString FileNameApi = ApiPath(FileName);
-    Attrs = FileGetAttr(FileNameApi);
+    Attrs = FileGetAttrFix(FileNameApi);
     if (Attrs < 0)
     {
       RaiseLastOSError();

+ 2 - 2
source/core/WebDAVFileSystem.cpp

@@ -1963,7 +1963,7 @@ void __fastcall TWebDAVFileSystem::Sink(const UnicodeString FileName,
     {
       FILE_OPERATION_LOOP_BEGIN
       {
-        int Attrs = FileGetAttr(ApiPath(DestFullName));
+        int Attrs = FileGetAttrFix(ApiPath(DestFullName));
         if (FLAGCLEAR(Attrs, faDirectory)) { EXCEPTION; }
       }
       FILE_OPERATION_LOOP_END(FMTLOAD(NOT_DIRECTORY_ERROR, (DestFullName)));
@@ -2026,7 +2026,7 @@ void __fastcall TWebDAVFileSystem::Sink(const UnicodeString FileName,
     int Attrs = -1;
     FILE_OPERATION_LOOP_BEGIN
     {
-      Attrs = FileGetAttr(ApiPath(DestFullName));
+      Attrs = FileGetAttrFix(ApiPath(DestFullName));
       if ((Attrs >= 0) && FLAGSET(Attrs, faDirectory)) { EXCEPTION; }
     }
     FILE_OPERATION_LOOP_END(FMTLOAD(NOT_FILE_ERROR, (DestFullName)));