Commit 5745deb0 authored by Jonathan Marten's avatar Jonathan Marten
Browse files

nfs: Protocol version settings (general and host-specific)

This limits the maximum NFS protocol version that will be tried, and the
minimum protocol version that will be accepted.  It can be set in the
'kionfsrc' file either as a general setting, or overridden by
host-specific settings.

Also implement a setting for whether READDIRPLUS3 is to be used - some
servers don't seem to implement it properly.
parent c624d71e
......@@ -36,7 +36,9 @@
#include <QHostInfo>
#include <QCoreApplication>
#include <KLocalizedString>
#include <klocalizedstring.h>
#include <ksharedconfig.h>
#include <kconfiggroup.h>
#include <kio/global.h>
#include "nfsv2.h"
......@@ -82,6 +84,7 @@ static QUrl cleanPath(const QUrl &url)
NFSSlave::NFSSlave(const QByteArray& pool, const QByteArray& app)
: KIO::SlaveBase("nfs", pool, app),
m_protocol(nullptr),
m_usedirplus3(true),
m_errorId(KIO::Error(0))
{
qCDebug(LOG_KIO_NFS) << pool << app;
......@@ -96,62 +99,82 @@ void NFSSlave::openConnection()
{
qCDebug(LOG_KIO_NFS);
if (m_protocol != nullptr) {
if (m_protocol != nullptr)
{
m_protocol->openConnection();
} else {
bool connectionError = false;
return;
}
int version = 4;
while (version > 1) {
qCDebug(LOG_KIO_NFS) << "Trying NFS version" << version;
const KSharedConfig::Ptr cfg = KSharedConfig::openConfig("kionfsrc");
// We need to create a new NFS protocol handler
switch (version) {
case 4: {
// TODO
qCDebug(LOG_KIO_NFS) << "NFSv4 is not supported at this time";
}
const KConfigGroup grp1 = cfg->group("Default"); // default for all hosts
int minproto = grp1.readEntry("minproto", 2); // minimum NFS version to accept
int maxproto = grp1.readEntry("maxproto", 4); // maximum NFS version to try
m_usedirplus3 = grp1.readEntry("usedirplus3", true); // use READDIRPLUS3 for listing
const KConfigGroup grp2 = cfg->group("Host "+m_host);
if (grp2.exists()) // look for host-specific settings
{ // with default values from above
minproto = grp2.readEntry("minproto", minproto);
maxproto = grp2.readEntry("maxproto", maxproto);
m_usedirplus3 = grp2.readEntry("usedirplus3", m_usedirplus3);
}
minproto = qBound(2, minproto, 4); // enforce limits
maxproto = qBound(minproto, maxproto, 4);
qCDebug(LOG_KIO_NFS) << "configuration for" << m_host;
qCDebug(LOG_KIO_NFS) << "minproto" << minproto << "maxproto" << maxproto << "usedirplus3" << m_usedirplus3;
bool connectionError = false;
int version = maxproto;
while (version >= minproto)
{
qCDebug(LOG_KIO_NFS) << "Trying NFS version" << version;
// Try to create an NFS protocol handler for that version
switch (version)
{
case 4: // TODO
qCDebug(LOG_KIO_NFS) << "NFSv4 is not supported at this time";
break;
case 3: {
m_protocol = new NFSProtocolV3(this);
}
case 3: m_protocol = new NFSProtocolV3(this);
break;
case 2: {
m_protocol = new NFSProtocolV2(this);
}
case 2: m_protocol = new NFSProtocolV2(this);
break;
}
}
// Unimplemented protocol version
if (m_protocol == nullptr) {
version--;
continue;
}
if (m_protocol != nullptr) // created protocol for that version
{
m_protocol->setHost(m_host); // try to make initial connection
if (m_protocol->isCompatible(connectionError)) break;
}
m_protocol->setHost(m_host);
if (m_protocol->isCompatible(connectionError)) {
break;
}
delete m_protocol; // no point using that protocol
--version; // try the next lower
m_protocol = nullptr; // try again with new protocol
}
version--;
delete m_protocol;
m_protocol = nullptr;
if (m_protocol == nullptr) // failed to find a protocol
{
if (!connectionError) // but connection was possible
{
setError(KIO::ERR_SLAVE_DEFINED, i18n("Cannot find an NFS version that host '%1' supports", m_host));
}
if (m_protocol == nullptr) {
// If we could not find a compatible protocol, send an error.
if (!connectionError) {
setError(KIO::ERR_SLAVE_DEFINED, i18n("Cannot find an NFS version that host '%1' supports", m_host));
} else {
setError(KIO::ERR_CANNOT_CONNECT, m_host);
}
} else {
// Otherwise we open the connection
m_protocol->openConnection();
else // connection failed
{
setError(KIO::ERR_CANNOT_CONNECT, m_host);
}
}
else // usable protocol was created
{
m_protocol->openConnection(); // open the connection
}
}
void NFSSlave::closeConnection()
{
qCDebug(LOG_KIO_NFS);
......
......@@ -68,6 +68,8 @@ public:
void finished() = delete;
void error(int errid, const QString &text) = delete;
bool usedirplus3() const { return (m_usedirplus3); }
protected:
// Verifies the URL, current protocol and connection state, returns true if valid.
bool verifyProtocol(const QUrl &url);
......@@ -79,6 +81,7 @@ private:
// We need to cache this because the @openConnection call is responsible
// for creating the protocol, and the @setHost call might happen before that.
QString m_host;
bool m_usedirplus3;
KIO::Error m_errorId;
QString m_errorText;
......
......@@ -68,7 +68,7 @@ NFSProtocolV2::NFSProtocolV2(NFSSlave* slave)
m_nfsClient(nullptr),
m_nfsSock(-1)
{
qCDebug(LOG_KIO_NFS) << "NFS2::NFS2";
qCDebug(LOG_KIO_NFS);
clnt_timeout.tv_sec = 20;
clnt_timeout.tv_usec = 0;
......@@ -105,7 +105,7 @@ bool NFSProtocolV2::isCompatible(bool& connectionError)
CLNT_DESTROY(client);
}
qCDebug(LOG_KIO_NFS) << ret;
qCDebug(LOG_KIO_NFS) << "RPC status" << ret << "connectionError" << connectionError;
return (ret == RPC_SUCCESS);
}
......
......@@ -87,8 +87,6 @@ NFSProtocolV3::~NFSProtocolV3()
bool NFSProtocolV3::isCompatible(bool& connectionError)
{
qCDebug(LOG_KIO_NFS);
int ret = -1;
CLIENT* client = nullptr;
......@@ -118,8 +116,7 @@ bool NFSProtocolV3::isCompatible(bool& connectionError)
CLNT_DESTROY(client);
}
qCDebug(LOG_KIO_NFS) << ret;
qCDebug(LOG_KIO_NFS) << "RPC status" << ret << "connectionError" << connectionError;
return (ret == RPC_SUCCESS);
}
......@@ -340,6 +337,12 @@ void NFSProtocolV3::listDir(const QUrl& url)
initPreferredSizes(fh);
}
if (!slave()->usedirplus3()) // want compatibility mode listing
{
listDirCompat(url);
return;
}
READDIRPLUS3args listargs;
memset(&listargs, 0, sizeof(listargs));
listargs.dircount = m_readDirSize;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment