diff --git a/packages/mediacenter/xbmc/patches/xbmc-990.12-2058.patch b/packages/mediacenter/xbmc/patches/xbmc-990.12-2058.patch new file mode 100644 index 0000000000..e44ec9bfae --- /dev/null +++ b/packages/mediacenter/xbmc/patches/xbmc-990.12-2058.patch @@ -0,0 +1,174 @@ +From 6e28059b93220b1188461bfc99709cf7d27ae11c Mon Sep 17 00:00:00 2001 +From: norbini +Date: Wed, 9 Jan 2013 23:08:02 +0000 +Subject: [PATCH] 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). +--- + xbmc/filesystem/SFTPDirectory.cpp | 15 ++++++++++ + xbmc/filesystem/SFTPDirectory.h | 1 + + xbmc/filesystem/SFTPFile.cpp | 55 +++++++++++++++++++++++++++++-------- + 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 ed04eb2..a7d7c93 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 82ef542..bc94a83 100644 +--- a/xbmc/filesystem/SFTPDirectory.h ++++ b/xbmc/filesystem/SFTPDirectory.h +@@ -35,6 +35,7 @@ + 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 d176969..34b797f 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 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 7d3574c..1ac83c8 100644 +--- a/xbmc/filesystem/SFTPFile.h ++++ b/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; +-- +1.7.10 +