From 7bf3e267c0126208c709fd9fcc0d841f989ce03f Mon Sep 17 00:00:00 2001 From: Joakim Plate Date: Sun, 16 Nov 2014 17:20:29 +0100 Subject: Revert "[vfs] [posix] SMBFile: fix reading files opened with READ_TRUNCATED flag" This reverts commit b202cd09426d1ce1e8921b827a84476472cf35fe. This change is invalid. The whole point of READ_TRUNCATED is to allow lower layer file systems to return any amount of data less than or equal to requested size. This is for efficiency reasons. After this change each request of X bytes from xbmc would result in multiple network roundtrips --- xbmc/filesystem/SMBFile.cpp | 40 ++++++++++++---------------------------- 1 file changed, 12 insertions(+), 28 deletions(-) diff --git a/xbmc/filesystem/SMBFile.cpp b/xbmc/filesystem/SMBFile.cpp index e4398e9b7b..43141c04fa 100644 --- a/xbmc/filesystem/SMBFile.cpp +++ b/xbmc/filesystem/SMBFile.cpp @@ -532,37 +532,21 @@ ssize_t CSMBFile::Read(void *lpBuf, size_t uiBufSize) /* also worse, a request of exactly 64k will return */ /* as if eof, client has a workaround for windows */ /* thou it seems other servers are affected too */ - // FIXME: does this workaround still required? - ssize_t totalRead = 0; - uint8_t* buf = (uint8_t*)lpBuf; - do - { - const ssize_t readSize = (uiBufSize >= 64 * 1024 - 2) ? 64 * 1024 - 2 : uiBufSize; - ssize_t r = smbc_read(m_fd, buf + totalRead, readSize); - if (r < 0) - { - if (errno == EINVAL) - { - CLog::LogF(LOGWARNING, "Error %d: \"%s\" - Retrying", errno, strerror(errno)); - r = smbc_read(m_fd, buf + totalRead, readSize); - } - if (r < 0) - { - CLog::LogF(LOGERROR, "Error %d: \"%s\"", errno, strerror(errno)); - if (totalRead == 0) - return -1; + if( uiBufSize >= 64*1024-2 ) + uiBufSize = 64*1024-2; - break; - } - } + ssize_t bytesRead = smbc_read(m_fd, lpBuf, (int)uiBufSize); + + if ( bytesRead < 0 && errno == EINVAL ) + { + CLog::Log(LOGERROR, "%s - Error( %d, %d, %s ) - Retrying", __FUNCTION__, bytesRead, errno, strerror(errno)); + bytesRead = smbc_read(m_fd, lpBuf, (int)uiBufSize); + } - totalRead += r; - uiBufSize -= r; - if (r != readSize) - break; - } while (uiBufSize > 0); + if ( bytesRead < 0 ) + CLog::Log(LOGERROR, "%s - Error( %d, %d, %s )", __FUNCTION__, bytesRead, errno, strerror(errno)); - return totalRead; + return bytesRead; } int64_t CSMBFile::Seek(int64_t iFilePosition, int iWhence) -- cgit v1.2.3 From 82469f39b60a1b6d178005caa868f3727b994d48 Mon Sep 17 00:00:00 2001 From: Joakim Plate Date: Thu, 11 Sep 2014 00:15:41 +0200 Subject: smb: set workgroup using standard api smb.conf file is only written once, thus changes in GUI will not have any effect --- xbmc/filesystem/SMBFile.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/xbmc/filesystem/SMBFile.cpp b/xbmc/filesystem/SMBFile.cpp index 43141c04fa..2f20461117 100644 --- a/xbmc/filesystem/SMBFile.cpp +++ b/xbmc/filesystem/SMBFile.cpp @@ -133,9 +133,6 @@ void CSMB::Init() if (g_advancedSettings.m_sambadoscodepage.length() > 0) fprintf(f, "\tdos charset = %s\n", g_advancedSettings.m_sambadoscodepage.c_str()); - // if no workgroup string is specified, samba will use the default value 'WORKGROUP' - if ( CSettings::Get().GetString("smb.workgroup").length() > 0 ) - fprintf(f, "\tworkgroup = %s\n", CSettings::Get().GetString("smb.workgroup").c_str()); fclose(f); } } @@ -154,6 +151,8 @@ void CSMB::Init() smbc_setOptionOneSharePerServer(m_context, false); smbc_setOptionBrowseMaxLmbCount(m_context, 0); smbc_setTimeout(m_context, g_advancedSettings.m_sambaclienttimeout * 1000); + if (CSettings::Get().GetString("smb.workgroup").length() > 0) + smbc_setWorkgroup(m_context, strdup(CSettings::Get().GetString("smb.workgroup").c_str())); smbc_setUser(m_context, strdup("guest")); #else m_context->debug = (g_advancedSettings.CanLogComponent(LOGSAMBA) ? 10 : 0); @@ -163,6 +162,8 @@ void CSMB::Init() m_context->options.one_share_per_server = false; m_context->options.browse_max_lmb_count = 0; m_context->timeout = g_advancedSettings.m_sambaclienttimeout * 1000; + if (CSettings::Get().GetString("smb.workgroup").length() > 0) + m_context->workgroup = strdup(CSettings::Get().GetString("smb.workgroup").c_str()); m_context->user = strdup("guest"); #endif -- cgit v1.2.3 From 81bf95dbce7db02d268ecaf806d4124f0a8f7c02 Mon Sep 17 00:00:00 2001 From: Joakim Plate Date: Sun, 9 Nov 2014 13:57:30 +0100 Subject: smb: don't add : for empty password libsmbclient parser can't handle that --- xbmc/filesystem/SMBFile.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/xbmc/filesystem/SMBFile.cpp b/xbmc/filesystem/SMBFile.cpp index 2f20461117..c70c15e3fb 100644 --- a/xbmc/filesystem/SMBFile.cpp +++ b/xbmc/filesystem/SMBFile.cpp @@ -222,8 +222,11 @@ std::string CSMB::URLEncode(const CURL &url) if(url.GetUserName().length() > 0 /* || url.GetPassWord().length() > 0 */) { flat += URLEncode(url.GetUserName()); - flat += ":"; - flat += URLEncode(url.GetPassWord()); + if(url.GetPassWord().length() > 0) + { + flat += ":"; + flat += URLEncode(url.GetPassWord()); + } flat += "@"; } flat += URLEncode(url.GetHostName()); -- cgit v1.2.3 From 2d9a80b9c7111e860eaa8f7b439dc288edb96980 Mon Sep 17 00:00:00 2001 From: Joakim Plate Date: Sun, 16 Nov 2014 13:27:45 +0100 Subject: smb: drop try/catch of exceptions from C api These won't throw catchable exceptions --- xbmc/filesystem/SMBFile.cpp | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/xbmc/filesystem/SMBFile.cpp b/xbmc/filesystem/SMBFile.cpp index c70c15e3fb..6bea4cf6d9 100644 --- a/xbmc/filesystem/SMBFile.cpp +++ b/xbmc/filesystem/SMBFile.cpp @@ -74,16 +74,8 @@ void CSMB::Deinit() /* samba goes loco if deinited while it has some files opened */ if (m_context) { - try - { - smbc_set_context(NULL); - smbc_free_context(m_context, 1); - } - XBMCCOMMONS_HANDLE_UNCHECKED - catch(...) - { - CLog::Log(LOGERROR,"exception on CSMB::Deinit. errno: %d", errno); - } + smbc_set_context(NULL); + smbc_free_context(m_context, 1); m_context = NULL; } } -- cgit v1.2.3 From 887a7762b405daa5f65df2b89694537908c48740 Mon Sep 17 00:00:00 2001 From: Joakim Plate Date: Sun, 16 Nov 2014 15:44:46 +0100 Subject: smb: eliminate smb.Init() calls in non static functions Init is called on CFile constructor. --- xbmc/filesystem/SMBFile.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/xbmc/filesystem/SMBFile.cpp b/xbmc/filesystem/SMBFile.cpp index 6bea4cf6d9..5ecd159771 100644 --- a/xbmc/filesystem/SMBFile.cpp +++ b/xbmc/filesystem/SMBFile.cpp @@ -308,7 +308,6 @@ int64_t CSMBFile::GetPosition() { if (m_fd == -1) return -1; - smb.Init(); CSingleLock lock(smb); return smbc_lseek(m_fd, 0, SEEK_CUR); } @@ -578,7 +577,6 @@ ssize_t CSMBFile::Write(const void* lpBuf, size_t uiBufSize) if (m_fd == -1) return -1; // lpBuf can be safely casted to void* since xbmc_write will only read from it. - smb.Init(); CSingleLock lock(smb); return smbc_write(m_fd, (void*)lpBuf, uiBufSize); @@ -619,7 +617,6 @@ bool CSMBFile::OpenForWrite(const CURL& url, bool bOverWrite) m_fileSize = 0; Close(); - smb.Init(); // we can't open files like smb://file.f or smb://server/file.f // if a file matches the if below return false, it can't exist on a samba share. if (!IsValidFile(url.GetFileName())) return false; -- cgit v1.2.3 From d19270d0fb7dddb09187d8e24a743dab76ef565e Mon Sep 17 00:00:00 2001 From: Joakim Plate Date: Sun, 16 Nov 2014 15:59:37 +0100 Subject: smb: factor out stat to __stat64 conversion We have all other conversions in CUtil so put this one there as well --- xbmc/Util.cpp | 16 ++++++++++++++++ xbmc/Util.h | 1 + xbmc/filesystem/SMBFile.cpp | 30 ++---------------------------- 3 files changed, 19 insertions(+), 28 deletions(-) diff --git a/xbmc/Util.cpp b/xbmc/Util.cpp index ec8d3a853d..1760beb010 100644 --- a/xbmc/Util.cpp +++ b/xbmc/Util.cpp @@ -809,6 +809,22 @@ void CUtil::StatI64ToStat64(struct __stat64 *result, struct _stati64 *stat) #endif } +void CUtil::StatToStat64(struct __stat64 *result, const struct stat *stat) +{ + memset(result, 0, sizeof(*result)); + result->st_dev = stat->st_dev; + result->st_ino = stat->st_ino; + result->st_mode = stat->st_mode; + result->st_nlink = stat->st_nlink; + result->st_uid = stat->st_uid; + result->st_gid = stat->st_gid; + result->st_rdev = stat->st_rdev; + result->st_size = stat->st_size; + result->st_atime = stat->st_atime; + result->st_mtime = stat->st_mtime; + result->st_ctime = stat->st_ctime; +} + void CUtil::Stat64ToStat(struct stat *result, struct __stat64 *stat) { result->st_dev = stat->st_dev; diff --git a/xbmc/Util.h b/xbmc/Util.h index 804bfb80cf..76af6da8d3 100644 --- a/xbmc/Util.h +++ b/xbmc/Util.h @@ -106,6 +106,7 @@ public: static CStdString GetNextFilename(const CStdString &fn_template, int max); static CStdString GetNextPathname(const CStdString &path_template, int max); static void StatToStatI64(struct _stati64 *result, struct stat *stat); + static void StatToStat64(struct __stat64 *result, const struct stat *stat); static void Stat64ToStatI64(struct _stati64 *result, struct __stat64 *stat); static void StatI64ToStat64(struct __stat64 *result, struct _stati64 *stat); static void Stat64ToStat(struct stat *result, struct __stat64 *stat); diff --git a/xbmc/filesystem/SMBFile.cpp b/xbmc/filesystem/SMBFile.cpp index 5ecd159771..9d3cd753bb 100644 --- a/xbmc/filesystem/SMBFile.cpp +++ b/xbmc/filesystem/SMBFile.cpp @@ -441,20 +441,7 @@ int CSMBFile::Stat(struct __stat64* buffer) CSingleLock lock(smb); int iResult = smbc_fstat(m_fd, &tmpBuffer); - - memset(buffer, 0, sizeof(struct __stat64)); - buffer->st_dev = tmpBuffer.st_dev; - buffer->st_ino = tmpBuffer.st_ino; - buffer->st_mode = tmpBuffer.st_mode; - buffer->st_nlink = tmpBuffer.st_nlink; - buffer->st_uid = tmpBuffer.st_uid; - buffer->st_gid = tmpBuffer.st_gid; - buffer->st_rdev = tmpBuffer.st_rdev; - buffer->st_size = tmpBuffer.st_size; - buffer->st_atime = tmpBuffer.st_atime; - buffer->st_mtime = tmpBuffer.st_mtime; - buffer->st_ctime = tmpBuffer.st_ctime; - + CUtil::StatToStat64(buffer, &tmpBuffer); return iResult; } @@ -466,20 +453,7 @@ int CSMBFile::Stat(const CURL& url, struct __stat64* buffer) struct stat tmpBuffer = {0}; int iResult = smbc_stat(strFileName.c_str(), &tmpBuffer); - - memset(buffer, 0, sizeof(struct __stat64)); - buffer->st_dev = tmpBuffer.st_dev; - buffer->st_ino = tmpBuffer.st_ino; - buffer->st_mode = tmpBuffer.st_mode; - buffer->st_nlink = tmpBuffer.st_nlink; - buffer->st_uid = tmpBuffer.st_uid; - buffer->st_gid = tmpBuffer.st_gid; - buffer->st_rdev = tmpBuffer.st_rdev; - buffer->st_size = tmpBuffer.st_size; - buffer->st_atime = tmpBuffer.st_atime; - buffer->st_mtime = tmpBuffer.st_mtime; - buffer->st_ctime = tmpBuffer.st_ctime; - + CUtil::StatToStat64(buffer, &tmpBuffer); return iResult; } -- cgit v1.2.3 From 5e7ad712db94e3b7e12b1e3fb210ceddf3f9345b Mon Sep 17 00:00:00 2001 From: Joakim Plate Date: Sun, 16 Nov 2014 16:07:06 +0100 Subject: smb: drop old (unused) purge code This was only needed before libsmbclient kept to one session per server. --- xbmc/filesystem/SMBFile.cpp | 23 ----------------------- xbmc/filesystem/SMBFile.h | 4 ---- 2 files changed, 27 deletions(-) diff --git a/xbmc/filesystem/SMBFile.cpp b/xbmc/filesystem/SMBFile.cpp index 9d3cd753bb..8f4cc8522a 100644 --- a/xbmc/filesystem/SMBFile.cpp +++ b/xbmc/filesystem/SMBFile.cpp @@ -174,29 +174,6 @@ void CSMB::Init() m_IdleTimeout = 180; } -void CSMB::Purge() -{ -} - -/* - * For each new connection samba creates a new session - * But this is not what we want, we just want to have one session at the time - * This means that we have to call smbc_purge() if samba created a new session - * Samba will create a new session when: - * - connecting to another server - * - connecting to another share on the same server (share, not a different folder!) - * - * We try to avoid lot's of purge commands because it slow samba down. - */ -void CSMB::PurgeEx(const CURL& url) -{ - CSingleLock lock(*this); - std::string strShare = url.GetFileName().substr(0, url.GetFileName().find('/')); - - m_strLastShare = strShare; - m_strLastHost = url.GetHostName(); -} - std::string CSMB::URLEncode(const CURL &url) { /* due to smb wanting encoded urls we have to build it manually */ diff --git a/xbmc/filesystem/SMBFile.h b/xbmc/filesystem/SMBFile.h index 0f6de4256d..a04b387e9e 100644 --- a/xbmc/filesystem/SMBFile.h +++ b/xbmc/filesystem/SMBFile.h @@ -47,8 +47,6 @@ public: ~CSMB(); void Init(); void Deinit(); - void Purge(); - void PurgeEx(const CURL& url); void CheckIfIdle(); void SetActivityTime(); void AddActiveConnection(); @@ -59,8 +57,6 @@ public: DWORD ConvertUnixToNT(int error); private: SMBCCTX *m_context; - std::string m_strLastHost; - std::string m_strLastShare; #ifdef TARGET_POSIX int m_OpenConnections; unsigned int m_IdleTimeout; -- cgit v1.2.3 From d05da4e565cf2ad8c36c94f35ab8c7a1193ad122 Mon Sep 17 00:00:00 2001 From: Joakim Plate Date: Sun, 16 Nov 2014 17:09:29 +0100 Subject: smb: use utility function to convert time_t to local file time --- xbmc/filesystem/SMBDirectory.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/xbmc/filesystem/SMBDirectory.cpp b/xbmc/filesystem/SMBDirectory.cpp index 0815208e07..026bd02b65 100644 --- a/xbmc/filesystem/SMBDirectory.cpp +++ b/xbmc/filesystem/SMBDirectory.cpp @@ -172,9 +172,7 @@ bool CSMBDirectory::GetDirectory(const CURL& url, CFileItemList &items) } FILETIME fileTime, localTime; - LONGLONG ll = Int32x32To64(lTimeDate & 0xffffffff, 10000000) + 116444736000000000ll; - fileTime.dwLowDateTime = (DWORD) (ll & 0xffffffff); - fileTime.dwHighDateTime = (DWORD)(ll >> 32); + TimeTToFileTime(lTimeDate, &fileTime); FileTimeToLocalFileTime(&fileTime, &localTime); if (bIsDir) -- cgit v1.2.3 From f141f51d2e140c491347986a81f3595d1157a8b4 Mon Sep 17 00:00:00 2001 From: Joakim Plate Date: Sun, 16 Nov 2014 19:12:54 +0100 Subject: smb: make sure we deinit samba before global destructor Library can have been unloaded by that point --- xbmc/Application.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp index 415e4c267d..ec53704ca7 100644 --- a/xbmc/Application.cpp +++ b/xbmc/Application.cpp @@ -3555,6 +3555,10 @@ void CApplication::Stop(int exitCode) CSFTPSessionManager::DisconnectAllSessions(); #endif +#if defined(TARGET_POSIX) && defined(HAS_FILESYSTEM_SMB) + smb.Deinit(); +#endif + CLog::Log(LOGNOTICE, "unload skin"); UnloadSkin(); -- cgit v1.2.3 From c685beae2b2c5c3e37c8b22e2a153a85c818e18d Mon Sep 17 00:00:00 2001 From: Joakim Plate Date: Thu, 11 Sep 2014 02:31:01 +0200 Subject: url: share name should always be updated Sharename is used in url authentication logic --- xbmc/URL.cpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/xbmc/URL.cpp b/xbmc/URL.cpp index 74542764fc..ed4549dd4c 100644 --- a/xbmc/URL.cpp +++ b/xbmc/URL.cpp @@ -286,15 +286,7 @@ void CURL::Parse(const std::string& strURL1) } iPos = iSlash + 1; if (iEnd > iPos) - { m_strFileName = strURL.substr(iPos, iEnd - iPos); - - iSlash = m_strFileName.find("/"); - if(iSlash == std::string::npos) - m_strShareName = m_strFileName; - else - m_strShareName = m_strFileName.substr(0, iSlash); - } } // iso9960 doesnt have an hostname;-) @@ -321,7 +313,7 @@ void CURL::Parse(const std::string& strURL1) StringUtils::Replace(m_strFileName, '\\', '/'); - /* update extension */ + /* update extension + sharename */ SetFileName(m_strFileName); /* decode urlencoding on this stuff */ @@ -346,6 +338,12 @@ void CURL::SetFileName(const std::string& strFileName) else m_strFileType = ""; + slash = m_strFileName.find_first_of(GetDirectorySeparator()); + if(slash == std::string::npos) + m_strShareName = m_strFileName; + else + m_strShareName = m_strFileName.substr(0, slash); + StringUtils::Trim(m_strFileType); StringUtils::ToLower(m_strFileType); } -- cgit v1.2.3 From aeebd22d2e88fd14f1b0624d0bdbc6f791a75892 Mon Sep 17 00:00:00 2001 From: Joakim Plate Date: Sun, 16 Nov 2014 13:44:58 +0100 Subject: smb: eliminate unused while loop in OpenDir We loop this at outer level now --- xbmc/filesystem/SMBDirectory.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/xbmc/filesystem/SMBDirectory.cpp b/xbmc/filesystem/SMBDirectory.cpp index 026bd02b65..1fa00e6bff 100644 --- a/xbmc/filesystem/SMBDirectory.cpp +++ b/xbmc/filesystem/SMBDirectory.cpp @@ -253,7 +253,7 @@ int CSMBDirectory::OpenDir(const CURL& url, std::string& strAuth) fd = smbc_opendir(s.c_str()); } - while (fd < 0) /* only to avoid goto in following code */ + if (fd < 0) /* only to avoid goto in following code */ { std::string cError; @@ -261,21 +261,15 @@ int CSMBDirectory::OpenDir(const CURL& url, std::string& strAuth) { if (m_flags & DIR_FLAG_ALLOW_PROMPT) RequireAuthentication(urlIn); - break; } - - if (errno == ENODEV || errno == ENOENT) + else if (errno == ENODEV || errno == ENOENT) cError = StringUtils::Format(g_localizeStrings.Get(770).c_str(),errno); else cError = strerror(errno); if (m_flags & DIR_FLAG_ALLOW_PROMPT) SetErrorDialog(257, cError.c_str()); - break; - } - if (fd < 0) - { // write error to logfile CLog::Log(LOGERROR, "SMBDirectory->GetDirectory: Unable to open directory : '%s'\nunix_err:'%x' error : '%s'", CURL::GetRedacted(strAuth).c_str(), errno, strerror(errno)); } -- cgit v1.2.3