diff options
author | norbini <norbini@norbini.co.uk> | 2013-01-09 23:08:02 +0000 |
---|---|---|
committer | norbini <norbini@norbini.co.uk> | 2013-01-25 23:14:24 +0000 |
commit | 6e28059b93220b1188461bfc99709cf7d27ae11c (patch) | |
tree | ed81339d0846121ecbe8b3b1ed50425ae93aec37 | |
parent | 9e7d52f3186ebc89ba8b4afba2f890a97a39bcf5 (diff) |
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).
-rw-r--r-- | xbmc/filesystem/SFTPDirectory.cpp | 15 | ||||
-rw-r--r-- | xbmc/filesystem/SFTPDirectory.h | 1 | ||||
-rw-r--r-- | xbmc/filesystem/SFTPFile.cpp | 55 | ||||
-rw-r--r-- | xbmc/filesystem/SFTPFile.h | 4 |
4 files changed, 63 insertions, 12 deletions
diff --git a/xbmc/filesystem/SFTPDirectory.cpp b/xbmc/filesystem/SFTPDirectory.cpp index ed04eb236d..a7d7c93769 100644 --- a/xbmc/filesystem/SFTPDirectory.cpp +++ b/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 diff --git a/xbmc/filesystem/SFTPDirectory.h b/xbmc/filesystem/SFTPDirectory.h index 82ef542a71..bc94a83708 100644 --- a/xbmc/filesystem/SFTPDirectory.h +++ b/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 diff --git a/xbmc/filesystem/SFTPFile.cpp b/xbmc/filesystem/SFTPFile.cpp index d176969835..34b797fd36 100644 --- a/xbmc/filesystem/SFTPFile.cpp +++ b/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"); diff --git a/xbmc/filesystem/SFTPFile.h b/xbmc/filesystem/SFTPFile.h index 7d3574cc8d..1ac83c8d32 100644 --- a/xbmc/filesystem/SFTPFile.h +++ b/xbmc/filesystem/SFTPFile.h @@ -58,7 +58,8 @@ public: 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 @@ private: 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; |