Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Override CSFTPDirectory::Exists() method to correctly report whether …

…an SFTP url represents a directory or not.

Fixes ticket #13784.

Refactored CSFTPSession::Exists() into FileExists() and DirectoryExists() methods, and have CSFTPFile and CSFTPDirectory classes use them.
This means that Exists() calls on these classes correctly only return true if the url refers to an item of the appropriate type (e.g. a file or a directory).
  • Loading branch information...
commit 6e28059b93220b1188461bfc99709cf7d27ae11c 1 parent 9e7d52f
@norbini norbini authored
View
15 xbmc/filesystem/SFTPDirectory.cpp
@@ -20,6 +20,7 @@
#include "SFTPDirectory.h"
#ifdef HAS_FILESYSTEM_SFTP
+#include "utils/log.h"
#include "URL.h"
using namespace XFILE;
@@ -39,4 +40,18 @@ bool CSFTPDirectory::GetDirectory(const CStdString& strPath, CFileItemList &item
CSFTPSessionPtr session = CSFTPSessionManager::CreateSession(url);
return session->GetDirectory(url.GetWithoutFilename().c_str(), url.GetFileName().c_str(), items);
}
+
+bool CSFTPDirectory::Exists(const char* strPath)
+{
+ CURL url(strPath);
+
+ CSFTPSessionPtr session = CSFTPSessionManager::CreateSession(url);
+ if (session)
+ return session->DirectoryExists(url.GetFileName().c_str());
+ else
+ {
+ CLog::Log(LOGERROR, "SFTPDirectory: Failed to create session to check exists");
+ return false;
+ }
+}
#endif
View
1  xbmc/filesystem/SFTPDirectory.h
@@ -35,6 +35,7 @@ namespace XFILE
CSFTPDirectory(void);
virtual ~CSFTPDirectory(void);
virtual bool GetDirectory(const CStdString& strPath, CFileItemList &items);
+ virtual bool Exists(const char* strPath);
};
}
#endif
View
55 xbmc/filesystem/SFTPFile.cpp
@@ -35,6 +35,11 @@
#pragma comment(lib, "ssh.lib")
#endif
+#ifdef TARGET_WINDOWS
+#define S_ISDIR(m) ((m & _S_IFDIR) != 0)
+#define S_ISREG(m) ((m & _S_IFREG) != 0)
+#endif
+
#ifdef _MSC_VER
#define O_RDONLY _O_RDONLY
#endif
@@ -187,19 +192,20 @@ bool CSFTPSession::GetDirectory(const CStdString &base, const CStdString &folder
return false;
}
-bool CSFTPSession::Exists(const char *path)
+bool CSFTPSession::DirectoryExists(const char *path)
{
bool exists = false;
- CSingleLock lock(m_critSect);
- if(m_connected)
- {
- sftp_attributes attributes = sftp_stat(m_sftp_session, CorrectPath(path).c_str());
- exists = attributes != NULL;
+ uint32_t permissions = 0;
+ exists = GetItemPermissions(path, permissions);
+ return exists && S_ISDIR(permissions);
+}
- if (attributes)
- sftp_attributes_free(attributes);
- }
- return exists;
+bool CSFTPSession::FileExists(const char *path)
+{
+ bool exists = false;
+ uint32_t permissions = 0;
+ exists = GetItemPermissions(path, permissions);
+ return exists && S_ISREG(permissions);
}
int CSFTPSession::Stat(const char *path, struct __stat64* buffer)
@@ -422,6 +428,33 @@ void CSFTPSession::Disconnect()
m_session = NULL;
}
+/*!
+ \brief Gets POSIX compatible permissions information about the specified file or directory.
+ \param path Remote SSH path to the file or directory.
+ \param permissions POSIX compatible permissions information for the file or directory (if it exists). i.e. can use macros S_ISDIR() etc.
+ \return Returns \e true, if it was possible to get permissions for the file or directory, \e false otherwise.
+ */
+bool CSFTPSession::GetItemPermissions(const char *path, uint32_t &permissions)
+{
+ bool gotPermissions = false;
+ CSingleLock lock(m_critSect);
+ if(m_connected)
+ {
+ sftp_attributes attributes = sftp_stat(m_sftp_session, CorrectPath(path).c_str());
+ if (attributes)
+ {
+ if (attributes->flags & SSH_FILEXFER_ATTR_PERMISSIONS)
+ {
+ permissions = attributes->permissions;
+ gotPermissions = true;
+ }
+
+ sftp_attributes_free(attributes);
+ }
+ }
+ return gotPermissions;
+}
+
CCriticalSection CSFTPSessionManager::m_critSect;
map<CStdString, CSFTPSessionPtr> CSFTPSessionManager::sessions;
@@ -554,7 +587,7 @@ bool CSFTPFile::Exists(const CURL& url)
{
CSFTPSessionPtr session = CSFTPSessionManager::CreateSession(url);
if (session)
- return session->Exists(url.GetFileName().c_str());
+ return session->FileExists(url.GetFileName().c_str());
else
{
CLog::Log(LOGERROR, "SFTPFile: Failed to create session to check exists");
View
4 xbmc/filesystem/SFTPFile.h
@@ -58,7 +58,8 @@ class CSFTPSession
sftp_file CreateFileHande(const CStdString &file);
void CloseFileHandle(sftp_file handle);
bool GetDirectory(const CStdString &base, const CStdString &folder, CFileItemList &items);
- bool Exists(const char *path);
+ bool DirectoryExists(const char *path);
+ bool FileExists(const char *path);
int Stat(const char *path, struct __stat64* buffer);
int Seek(sftp_file handle, uint64_t position);
int Read(sftp_file handle, void *buffer, size_t length);
@@ -68,6 +69,7 @@ class CSFTPSession
bool VerifyKnownHost(ssh_session session);
bool Connect(const CStdString &host, unsigned int port, const CStdString &username, const CStdString &password);
void Disconnect();
+ bool GetItemPermissions(const char *path, uint32_t &permissions);
CCriticalSection m_critSect;
bool m_connected;
Please sign in to comment.
Something went wrong with that request. Please try again.