diff --git a/smb/kio_smb.h b/smb/kio_smb.h --- a/smb/kio_smb.h +++ b/smb/kio_smb.h @@ -278,6 +278,7 @@ void smbCopy(const QUrl& src, const QUrl &dest, int permissions, KIO::JobFlags flags); void smbCopyGet(const QUrl& src, const QUrl& dest, int permissions, KIO::JobFlags flags); void smbCopyPut(const QUrl& src, const QUrl& dest, int permissions, KIO::JobFlags flags); + bool workaroundEEXIST(const int errNum) const; void fileSystemFreeSpace(const QUrl &url); @@ -288,6 +289,8 @@ */ int m_openFd; SMBUrl m_openUrl; + + const bool m_enableEEXISTWorkaround; /* Enables a workaround for some broken libsmbclient versions */ }; //========================================================================== diff --git a/smb/kio_smb.cpp b/smb/kio_smb.cpp --- a/smb/kio_smb.cpp +++ b/smb/kio_smb.cpp @@ -31,12 +31,40 @@ #include "kio_smb.h" #include "kio_smb_internal.h" #include +#include Q_LOGGING_CATEGORY(KIO_SMB, "kio_smb") +bool needsEEXISTWorkaround() +{ + /* There is an issue with some libsmbclient versions that return EEXIST + * return code from smbc_opendir() instead of EPERM when the user + * tries to access a resource that requires login authetification. + * We are working around the issue by treating EEXIST as a special case + * of "invalid/unavailable credentials" if we detect that we are using + * the affected versions of libsmbclient + * + * Upstream bug report: https://bugzilla.samba.org/show_bug.cgi?id=13050 + */ + static const QVersionNumber firstBrokenVer{4, 7, 0}; + static const QVersionNumber lastBrokenVer{9, 9, 9}; /* Adjust accordingly when this gets fixed upstream */ + + const QVersionNumber currentVer = QVersionNumber::fromString(smbc_version()); + qCDebug(KIO_SMB) << "Using libsmbclient library version" << currentVer; + + if (currentVer >= firstBrokenVer && currentVer <= lastBrokenVer) { + qCDebug(KIO_SMB) << "Detected broken libsmbclient version" << currentVer; + return true; + } + + return false; +} + //=========================================================================== SMBSlave::SMBSlave(const QByteArray& pool, const QByteArray& app) - : SlaveBase( "smb", pool, app ), m_openFd(-1) + : SlaveBase( "smb", pool, app ), + m_openFd(-1), + m_enableEEXISTWorkaround(needsEEXISTWorkaround()) { m_initialized_smbc = false; diff --git a/smb/kio_smb_browse.cpp b/smb/kio_smb_browse.cpp --- a/smb/kio_smb_browse.cpp +++ b/smb/kio_smb_browse.cpp @@ -469,7 +469,7 @@ } else { - if (errNum == EPERM || errNum == EACCES) { + if (errNum == EPERM || errNum == EACCES || workaroundEEXIST(errNum)) { if (checkPassword(m_current_url)) { redirection( m_current_url ); finished(); @@ -518,3 +518,8 @@ finished(); } +bool SMBSlave::workaroundEEXIST(const int errNum) const +{ + return (errNum == EEXIST) && m_enableEEXISTWorkaround; +} +