Git commit 6ea1737605dceb5563db7c1c82a153c57d33a043 by Harald Sitter. Committed on 04/07/2022 at 07:28. Pushed by sitter into branch 'master'.
smb: port to workerbase M +5 -5 doc/kioslave/smb/index.docbook M +2 -2 smb/CMakeLists.txt M +38 -34 smb/autotests/shouldresumetest.cpp M +4 -4 smb/kded/kded_smbwatcher.desktop M +1 -1 smb/kded/notifier.cpp M +7 -29 smb/kio_smb.cpp M +33 -47 smb/kio_smb.h M +14 -11 smb/kio_smb_auth.cpp M +55 -69 smb/kio_smb_browse.cpp M +1 -1 smb/kio_smb_config.cpp M +116 -193 smb/kio_smb_dir.cpp M +66 -84 smb/kio_smb_file.cpp M +9 -16 smb/kio_smb_mount.cpp M +3 -3 smb/main.cpp M +1 -1 smb/smbauthenticator.cpp M +2 -2 smb/smbauthenticator.h M +4 -4 smb/smbcdiscoverer.cpp M +2 -2 smb/smbcdiscoverer.h M +1 -1 smb/smbcontext.cpp M +1 -1 smb/smburl.cpp M +2 -2 smb/smburl.h M +12 -13 smb/transfer_resume.h https://invent.kde.org/network/kio-extras/commit/6ea1737605dceb5563db7c1c82a153c57d33a043 diff --git a/doc/kioslave/smb/index.docbook b/doc/kioslave/smb/index.docbook index b711be849..d9fe65f9d 100644 --- a/doc/kioslave/smb/index.docbook +++ b/doc/kioslave/smb/index.docbook @@ -4,7 +4,7 @@ <!ENTITY % addindex "IGNORE"> <!ENTITY % English "INCLUDE" > <!-- change language only here --> ]> - + <article lang="&language;" id="smb"> <title>SMB</title> <articleinfo> @@ -16,7 +16,7 @@ <releaseinfo>Applications 16.12</releaseinfo> </articleinfo> <para> -The smb ioslave enables you to browse the shares of a &Windows; (or Samba) +The smb worker enables you to browse the shares of a &Windows; (or Samba) network. </para> @@ -42,16 +42,16 @@ or </para> <para> -The smb ioslave requires that you have libsmbclient to use this ioslave. +The smb worker requires that you have libsmbclient to use this worker. </para> <para> -You can set your default user name and password in the &systemsettings; +You can set your default user name and password in the &systemsettings; category <guilabel>Network</guilabel> in <menuchoice><guisubmenu>Connectivity</guisubmenu><guimenuitem> Windows Shares</guimenuitem></menuchoice>. This is especially useful if you are a member of a &Windows; <acronym>NT</acronym> domain. There you can also set your -workgroup name, but in most cases this is not required. The kioslave will ask for your username and password if a default is not set. +workgroup name, but in most cases this is not required. The worker will ask for your username and password if a default is not set. </para> </article> diff --git a/smb/CMakeLists.txt b/smb/CMakeLists.txt index d1ee5056f..f7d53914d 100644 --- a/smb/CMakeLists.txt +++ b/smb/CMakeLists.txt @@ -66,8 +66,8 @@ target_sources(kio_smb_static PRIVATE ecm_qt_declare_logging_category(kio_smb_static HEADER smb-logsettings.h IDENTIFIER KIO_SMB_LOG - CATEGORY_NAME kf.kio.slaves.smb - OLD_CATEGORY_NAMES log_kio_smb + CATEGORY_NAME kf.kio.workers.smb + OLD_CATEGORY_NAMES log_kio_smb kf.kio.slaves.smb DESCRIPTION "KIO smb" EXPORT KIO_EXTRAS ) diff --git a/smb/autotests/shouldresumetest.cpp b/smb/autotests/shouldresumetest.cpp index 7df840e7f..0c28baa0d 100644 --- a/smb/autotests/shouldresumetest.cpp +++ b/smb/autotests/shouldresumetest.cpp @@ -79,18 +79,19 @@ private Q_SLOTS: auto url = tmpUrl("noResumeButPartial/thing"); auto partUrl = tmpUrl("noResumeButPartial/thing.part"); - auto resume = Transfer::shouldResume<QFileResumeIO>(url, KIO::JobFlags(), &worker); - QVERIFY(resume.has_value()); - QCOMPARE(resume->resuming, false); - QCOMPARE(resume->destination, partUrl); - QCOMPARE(resume->completeDestination, url); - QCOMPARE(resume->partDestination, partUrl); + auto resumeVariant = Transfer::shouldResume<QFileResumeIO>(url, KIO::JobFlags(), &worker); + QVERIFY(std::holds_alternative<TransferContext>(resumeVariant)); + auto resume = std::get<TransferContext>(resumeVariant); + QCOMPARE(resume.resuming, false); + QCOMPARE(resume.destination, partUrl); + QCOMPARE(resume.completeDestination, url); + QCOMPARE(resume.partDestination, partUrl); QDir().mkdir(tmpPath("noResumeButPartial")); QFile part(partUrl.toLocalFile()); QVERIFY(part.open(QFile::WriteOnly)); part.write(""); - QCOMPARE(Transfer::concludeResumeHasError<QFileResumeIO>(false, resume.value(), &worker), false); + QVERIFY(Transfer::concludeResumeHasError<QFileResumeIO>(WorkerResult::pass(), resume, &worker).success()); QVERIFY(QFileInfo::exists(url.toLocalFile())); QVERIFY(!QFileInfo::exists(partUrl.toLocalFile())); } @@ -103,14 +104,15 @@ private Q_SLOTS: auto url = tmpUrl("noResumeAndNoPartial/thing"); - auto resume = Transfer::shouldResume<QFileResumeIO>(url, KIO::JobFlags(), &worker); + auto resumeVariant = Transfer::shouldResume<QFileResumeIO>(url, KIO::JobFlags(), &worker); worker.debugErrors(); - QVERIFY(resume.has_value()); - QCOMPARE(resume->resuming, false); - QCOMPARE(resume->destination, url); - QCOMPARE(resume->completeDestination, url); - QCOMPARE(resume->partDestination, QUrl()); - QCOMPARE(Transfer::concludeResumeHasError<QFileResumeIO>(false, resume.value(), &worker), false); + QVERIFY(std::holds_alternative<TransferContext>(resumeVariant)); + auto resume = std::get<TransferContext>(resumeVariant); + QCOMPARE(resume.resuming, false); + QCOMPARE(resume.destination, url); + QCOMPARE(resume.completeDestination, url); + QCOMPARE(resume.partDestination, QUrl()); + QVERIFY(Transfer::concludeResumeHasError<QFileResumeIO>(WorkerResult::pass(), resume, &worker).success()); } void resume() @@ -119,14 +121,15 @@ private Q_SLOTS: auto url = tmpUrl("resume/thing"); auto partUrl = tmpUrl("resume/thing.part"); - auto resume = Transfer::shouldResume<QFileResumeIO>(url, KIO::JobFlags(), &worker); - QVERIFY(resume.has_value()); - QCOMPARE(resume->resuming, true); - QCOMPARE(resume->destination, partUrl); - QCOMPARE(resume->completeDestination, url); - QCOMPARE(resume->partDestination, partUrl); - - QCOMPARE(Transfer::concludeResumeHasError<QFileResumeIO>(false, resume.value(), &worker), false); + auto resumeVariant = Transfer::shouldResume<QFileResumeIO>(url, KIO::JobFlags(), &worker); + QVERIFY(std::holds_alternative<TransferContext>(resumeVariant)); + auto resume = std::get<TransferContext>(resumeVariant); + QCOMPARE(resume.resuming, true); + QCOMPARE(resume.destination, partUrl); + QCOMPARE(resume.completeDestination, url); + QCOMPARE(resume.partDestination, partUrl); + + QVERIFY(Transfer::concludeResumeHasError<QFileResumeIO>(WorkerResult::pass(), resume, &worker).success()); QVERIFY(QFileInfo::exists(url.toLocalFile())); QVERIFY(!QFileInfo::exists(partUrl.toLocalFile())); } @@ -136,14 +139,15 @@ private Q_SLOTS: FakeWorker worker; auto url = tmpUrl("resumeInPlace/thing"); - auto resume = Transfer::shouldResume<QFileResumeIO>(url, KIO::Resume, &worker); - QVERIFY(resume.has_value()); - QCOMPARE(resume->resuming, true); - QCOMPARE(resume->destination, url); - QCOMPARE(resume->completeDestination, url); - QCOMPARE(resume->partDestination, url); - - QCOMPARE(Transfer::concludeResumeHasError<QFileResumeIO>(false, resume.value(), &worker), false); + auto resumeVariant = Transfer::shouldResume<QFileResumeIO>(url, KIO::Resume, &worker); + QVERIFY(std::holds_alternative<TransferContext>(resumeVariant)); + auto resume = std::get<TransferContext>(resumeVariant); + QCOMPARE(resume.resuming, true); + QCOMPARE(resume.destination, url); + QCOMPARE(resume.completeDestination, url); + QCOMPARE(resume.partDestination, url); + + QVERIFY(Transfer::concludeResumeHasError<QFileResumeIO>(WorkerResult::pass(), resume, &worker).success()); QVERIFY(QFileInfo::exists(url.toLocalFile())); } @@ -152,10 +156,10 @@ private Q_SLOTS: FakeWorker worker; auto url = tmpUrl("resumeInPlace/thing"); // intentionally the same path this scenario errors out - auto resume = Transfer::shouldResume<QFileResumeIO>(url, KIO::JobFlags(), &worker); - QVERIFY(!resume.has_value()); - QCOMPARE(worker.m_errors.size(), 1); - QCOMPARE(worker.m_errors.at(0).id, KIO::ERR_FILE_ALREADY_EXIST); + auto resumeVariant = Transfer::shouldResume<QFileResumeIO>(url, KIO::JobFlags(), &worker); + QVERIFY(std::holds_alternative<WorkerResult>(resumeVariant)); + auto result = std::get<WorkerResult>(resumeVariant); + QCOMPARE(result.error(), KIO::ERR_FILE_ALREADY_EXIST); } }; diff --git a/smb/kded/kded_smbwatcher.desktop b/smb/kded/kded_smbwatcher.desktop index cbbff97ad..ea28cbce0 100644 --- a/smb/kded/kded_smbwatcher.desktop +++ b/smb/kded/kded_smbwatcher.desktop @@ -2,10 +2,10 @@ Type=Service X-KDE-ServiceTypes=KDEDModule X-KDE-Kded-autoload=true -# We need this module loaded all the time, lazy loading on slave use wouldn't -# be sufficient as the kdirnotify signal is already out by the time the slave +# We need this module loaded all the time, lazy loading on worker use wouldn't +# be sufficient as the kdirnotify signal is already out by the time the worker # is initalized so the first opened dir wouldn't be watched then. -# It'd be better if we had a general monitor module that slaves can register +# It'd be better if we had a general monitor module that workers can register # with. The monitor would then listen to kdirnotify and check the schemes # to decide which watcher to load, and then simply forward the call to the watcher # in-process. Would also save us from having to connect to dbus in every watcher. @@ -66,7 +66,7 @@ Comment[es]=Monitoriza cambios en directorios del protocolo smb:/ Comment[et]=smb:/ protokolli kaudu ühendatud kataloogide muutuste jälgimine Comment[eu]=«smb:/» protokoloko direktorioak zelatatzen ditu aldaketa bila Comment[fi]=Tarkkailee smb:/-yhteyskäytännön kansioiden muutoksia -Comment[fr]=Surveille les modifications pour les dossiers gérés par le protocole « smb:/ » +Comment[fr]=Surveille les modifications pour les dossiers gérés par le protocole « smb:/ » Comment[hu]=Könyvtárak változásainak monitorozása az smb:/ protokollon Comment[ia]=Il monitora le directorios pro variationes sur le protocollo smb:/ Comment[id]=Memantau direktori di protokol smb:/ terhadap perubahan diff --git a/smb/kded/notifier.cpp b/smb/kded/notifier.cpp index 0bf4f6392..9997dac9d 100644 --- a/smb/kded/notifier.cpp +++ b/smb/kded/notifier.cpp @@ -21,7 +21,7 @@ #include <errno.h> -// Frontend implementation in place of slavebase +// Frontend implementation in place of workerbase class Frontend : public SMBAbstractFrontend { KPasswdServerClient m_passwd; diff --git a/smb/kio_smb.cpp b/smb/kio_smb.cpp index ad9247451..8550eebb4 100644 --- a/smb/kio_smb.cpp +++ b/smb/kio_smb.cpp @@ -12,7 +12,7 @@ class KIOPluginForMetaData : public QObject { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.kde.kio.slave.smb" FILE "smb.json") + Q_PLUGIN_METADATA(IID "org.kde.kio.worker.smb" FILE "smb.json") }; bool needsEEXISTWorkaround() @@ -40,43 +40,21 @@ bool needsEEXISTWorkaround() return false; } -SMBSlave::SMBSlave(const QByteArray &pool, const QByteArray &app) - : SlaveBase("smb", pool, app) +SMBWorker::SMBWorker(const QByteArray &pool, const QByteArray &app) + : WorkerBase("smb", pool, app) , m_openFd(-1) , m_enableEEXISTWorkaround(needsEEXISTWorkaround()) { } -SMBSlave::~SMBSlave() = default; - -void SMBSlave::virtual_hook(int id, void *data) -{ - switch (id) { - case SlaveBase::GetFileSystemFreeSpace: { - QUrl *url = static_cast<QUrl *>(data); - fileSystemFreeSpace(*url); - } - break; - case SlaveBase::Truncate: { - auto length = static_cast<KIO::filesize_t *>(data); - truncate(*length); - } - break; - default: { - SlaveBase::virtual_hook(id, data); - } - break; - } -} - -SlaveFrontend::SlaveFrontend(SMBSlave &slave) - : m_slave(slave) +WorkerFrontend::WorkerFrontend(SMBWorker &worker) + : m_worker(worker) { } -bool SlaveFrontend::checkCachedAuthentication(AuthInfo &info) +bool WorkerFrontend::checkCachedAuthentication(AuthInfo &info) { - return m_slave.checkCachedAuthentication(info); + return m_worker.checkCachedAuthentication(info); } #include "kio_smb.moc" diff --git a/smb/kio_smb.h b/smb/kio_smb.h index 628cd61e0..78fc00e16 100644 --- a/smb/kio_smb.h +++ b/smb/kio_smb.h @@ -16,7 +16,7 @@ // KF includes //-------------- #include <KIO/Global> -#include <KIO/SlaveBase> +#include <KIO/WorkerBase> //----------------------------- // Standard C library includes @@ -56,24 +56,25 @@ extern "C" { #include "smbcontext.h" using namespace KIO; -class SMBSlave; +class SMBWorker; -class SlaveFrontend : public SMBAbstractFrontend +class WorkerFrontend : public SMBAbstractFrontend { public: - SlaveFrontend(SMBSlave &slave); + explicit WorkerFrontend(SMBWorker &worker); bool checkCachedAuthentication(AuthInfo &info) override; private: - SMBSlave &m_slave; + SMBWorker &m_worker; }; -class SMBSlave : public QObject, public KIO::SlaveBase +class SMBWorker : public QObject, public KIO::WorkerBase { Q_OBJECT friend class SMBCDiscoverer; friend class SMBResumeIO; - SlaveFrontend m_frontend { *this }; - SMBContext m_context { new SMBAuthenticator(m_frontend) }; + WorkerFrontend m_frontend { *this }; + SMBContext m_context{new SMBAuthenticator(m_frontend)}; + Q_DISABLE_COPY(SMBWorker) private: @@ -184,66 +185,51 @@ protected: */ QUrl checkURL(const QUrl &kurl) const; - void reportError(const SMBUrl &url, const int errNum); + Q_REQUIRED_RESULT WorkerResult reportError(const SMBUrl &url, const int errNum); void reportWarning(const SMBUrl &url, const int errNum); public: - //----------------------------------------------------------------------- - // Overwritten functions from the base class that define the operation of - // this slave. (See the base class headerfile slavebase.h for more - // details) - //----------------------------------------------------------------------- - // Functions overwritten in kio_smb.cpp - SMBSlave(const QByteArray &pool, const QByteArray &app); - ~SMBSlave() override; + SMBWorker(const QByteArray &pool, const QByteArray &app); + ~SMBWorker() override = default; // Functions overwritten in kio_smb_browse.cpp - void listDir(const QUrl &url) override; - void stat(const QUrl &url) override; + Q_REQUIRED_RESULT WorkerResult listDir(const QUrl &url) override; + Q_REQUIRED_RESULT WorkerResult stat(const QUrl &url) override; // Functions overwritten in kio_smb_config.cpp void reparseConfiguration() override; // Functions overwritten in kio_smb_dir.cpp - void copy(const QUrl &src, const QUrl &dst, int permissions, KIO::JobFlags flags) override; - void del(const QUrl &kurl, bool isfile) override; - void mkdir(const QUrl &kurl, int permissions) override; - void rename(const QUrl &src, const QUrl &dest, KIO::JobFlags flags) override; + Q_REQUIRED_RESULT WorkerResult copy(const QUrl &src, const QUrl &dst, int permissions, KIO::JobFlags flags) override; + Q_REQUIRED_RESULT WorkerResult del(const QUrl &kurl, bool isfile) override; + Q_REQUIRED_RESULT WorkerResult mkdir(const QUrl &kurl, int permissions) override; + Q_REQUIRED_RESULT WorkerResult rename(const QUrl &src, const QUrl &dest, KIO::JobFlags flags) override; // Functions overwritten in kio_smb_file.cpp - void get(const QUrl &kurl) override; - void put(const QUrl &kurl, int permissions, KIO::JobFlags flags) override; - void open(const QUrl &kurl, QIODevice::OpenMode mode) override; - void read(KIO::filesize_t bytesRequested) override; - void write(const QByteArray &fileData) override; - void seek(KIO::filesize_t offset) override; - void truncate(KIO::filesize_t length); - void close() override; - - // Functions not implemented (yet) - // virtual void setHost(const QString& host, int port, const QString& user, const QString& pass); - // virtual void openConnection(); - // virtual void closeConnection(); - // virtual void slave_status(); - void special(const QByteArray &) override; - -protected: - void virtual_hook(int id, void *data) override; + Q_REQUIRED_RESULT WorkerResult get(const QUrl &kurl) override; + Q_REQUIRED_RESULT WorkerResult put(const QUrl &kurl, int permissions, KIO::JobFlags flags) override; + Q_REQUIRED_RESULT WorkerResult open(const QUrl &kurl, QIODevice::OpenMode mode) override; + Q_REQUIRED_RESULT WorkerResult read(KIO::filesize_t bytesRequested) override; + Q_REQUIRED_RESULT WorkerResult write(const QByteArray &fileData) override; + Q_REQUIRED_RESULT WorkerResult seek(KIO::filesize_t offset) override; + Q_REQUIRED_RESULT WorkerResult truncate(KIO::filesize_t size) override; + Q_REQUIRED_RESULT WorkerResult close() override; + Q_REQUIRED_RESULT WorkerResult fileSystemFreeSpace(const QUrl &url) override; + Q_REQUIRED_RESULT WorkerResult special(const QByteArray &) override; private: SMBError errnumToKioError(const SMBUrl &url, const int errNum); - void smbCopy(const QUrl &src, const QUrl &dst, int permissions, KIO::JobFlags flags); - void smbCopyGet(const QUrl &ksrc, const QUrl &kdst, int permissions, KIO::JobFlags flags); - void smbCopyPut(const QUrl &ksrc, const QUrl &kdst, int permissions, KIO::JobFlags flags); + Q_REQUIRED_RESULT WorkerResult smbCopy(const QUrl &src, const QUrl &dst, int permissions, KIO::JobFlags flags); + Q_REQUIRED_RESULT WorkerResult smbCopyGet(const QUrl &ksrc, const QUrl &kdst, int permissions, KIO::JobFlags flags); + Q_REQUIRED_RESULT WorkerResult smbCopyPut(const QUrl &ksrc, const QUrl &kdst, int permissions, KIO::JobFlags flags); bool workaroundEEXIST(const int errNum) const; int statToUDSEntry(const QUrl &url, const struct stat &st, KIO::UDSEntry &udsentry); - void fileSystemFreeSpace(const QUrl &url); /** * Used in open(), read(), write(), and close() * FIXME Placing these in the private section above causes m_openUrl = kurl - * to fail in SMBSlave::open. Need to find out why this is. + * to fail in SMBWorker::open. Need to find out why this is. */ int m_openFd; SMBUrl m_openUrl; @@ -288,7 +274,7 @@ private: }; //=========================================================================== -// Main slave entrypoint (see kio_smb.cpp) +// Main worker entrypoint (see kio_smb.cpp) extern "C" { int kdemain(int argc, char **argv); } diff --git a/smb/kio_smb_auth.cpp b/smb/kio_smb_auth.cpp index efe02308d..e8ad7dbcb 100644 --- a/smb/kio_smb_auth.cpp +++ b/smb/kio_smb_auth.cpp @@ -13,7 +13,7 @@ #include <KConfigGroup> #include <KLocalizedString> -int SMBSlave::checkPassword(SMBUrl &url) +int SMBWorker::checkPassword(SMBUrl &url) { qCDebug(KIO_SMB_LOG) << "checkPassword for " << url; @@ -23,10 +23,12 @@ int SMBSlave::checkPassword(SMBUrl &url) QString share = url.path(); int index = share.indexOf('/', 1); - if (index > 1) + if (index > 1) { share = share.left(index); - if (share.at(0) == '/') + } + if (share.at(0) == '/') { share = share.mid(1); + } info.url.setPath('/' + share); info.verifyPath = true; info.keepPassword = true; @@ -44,20 +46,21 @@ int SMBSlave::checkPassword(SMBUrl &url) "<para><placeholder>anonymous</placeholder>: Anonymous logins can be attempted using empty username and password. Depending on server configuration non-empty usernames may be required</para>" )); - if (share.isEmpty()) + if (share.isEmpty()) { info.prompt = i18n("<qt>Please enter authentication information for <b>%1</b></qt>", url.host()); - else + } else { info.prompt = i18n( - "Please enter authentication information for:\n" - "Server = %1\n" - "Share = %2", - url.host(), - share); + "Please enter authentication information for:\n" + "Server = %1\n" + "Share = %2", + url.host(), + share); + } info.username = url.userName(); qCDebug(KIO_SMB_LOG) << "call openPasswordDialog for " << info.url; - const int passwordDialogErrorCode = openPasswordDialogV2(info); + const int passwordDialogErrorCode = openPasswordDialog(info); if (passwordDialogErrorCode == KJob::NoError) { qCDebug(KIO_SMB_LOG) << "openPasswordDialog returned " << info.username; url.setUser(info.username); diff --git a/smb/kio_smb_browse.cpp b/smb/kio_smb_browse.cpp index 58b1d904a..3bc25d83e 100644 --- a/smb/kio_smb_browse.cpp +++ b/smb/kio_smb_browse.cpp @@ -1,13 +1,15 @@ /* SPDX-License-Identifier: GPL-2.0-or-later SPDX-FileCopyrightText: 2000 Caldera Systems Inc. - SPDX-FileCopyrightText: 2018-2021 Harald Sitter <sit...@kde.org> + SPDX-FileCopyrightText: 2018-2022 Harald Sitter <sit...@kde.org> SPDX-FileContributor: Matthew Peterson <mpeter...@caldera.com> */ #include "kio_smb.h" #include "smburl.h" +#include <utility> + #include <KDNSSD/RemoteService> #include <KDNSSD/ServiceBrowser> #include <KIO/Job> @@ -26,7 +28,7 @@ using namespace KIO; -int SMBSlave::cache_stat(const SMBUrl &url, struct stat *st) +int SMBWorker::cache_stat(const SMBUrl &url, struct stat *st) { int cacheStatErr = 0; int result = smbc_stat(url.toSmbcUrl(), st); @@ -39,7 +41,7 @@ int SMBSlave::cache_stat(const SMBUrl &url, struct stat *st) return cacheStatErr; } -int SMBSlave::browse_stat_path(const SMBUrl &url, UDSEntry &udsentry) +int SMBWorker::browse_stat_path(const SMBUrl &url, UDSEntry &udsentry) { int cacheStatErr = cache_stat(url, &st); if (cacheStatErr == 0) { @@ -49,7 +51,7 @@ int SMBSlave::browse_stat_path(const SMBUrl &url, UDSEntry &udsentry) return cacheStatErr; } -int SMBSlave::statToUDSEntry(const QUrl &url, const struct stat &st, KIO::UDSEntry &udsentry) +int SMBWorker::statToUDSEntry(const QUrl &url, const struct stat &st, KIO::UDSEntry &udsentry) { if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode)) { qCDebug(KIO_SMB_LOG) << "mode: "<< st.st_mode; @@ -110,7 +112,7 @@ int SMBSlave::statToUDSEntry(const QUrl &url, const struct stat &st, KIO::UDSEnt return 0; } -void SMBSlave::stat(const QUrl &kurl) +WorkerResult SMBWorker::stat(const QUrl &kurl) { qCDebug(KIO_SMB_LOG) << kurl; // make a valid URL @@ -120,8 +122,7 @@ void SMBSlave::stat(const QUrl &kurl) if (url != kurl) { qCDebug(KIO_SMB_LOG) << "redirection " << url; redirection(url); - finished(); - return; + return WorkerResult::pass(); } m_current_url = url; @@ -132,20 +133,14 @@ void SMBSlave::stat(const QUrl &kurl) switch (m_current_url.getType()) { case SMBURLTYPE_UNKNOWN: - error(ERR_MALFORMED_URL, url.toDisplayString()); - return; - + return WorkerResult::fail(ERR_MALFORMED_URL, url.toDisplayString()); case SMBURLTYPE_PRINTER: - error(ERR_UNSUPPORTED_ACTION, url.toDisplayString()); - return; - + return WorkerResult::fail(ERR_UNSUPPORTED_ACTION, url.toDisplayString()); case SMBURLTYPE_ENTIRE_NETWORK: case SMBURLTYPE_WORKGROUP_OR_SERVER: udsentry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); statEntry(udsentry); - finished(); - return; - + return WorkerResult::pass(); case SMBURLTYPE_SHARE_OR_PATH: { int ret = browse_stat_path(m_current_url, udsentry); @@ -155,35 +150,32 @@ void SMBSlave::stat(const QUrl &kurl) const int passwordError = checkPassword(smbUrl); if (passwordError == KJob::NoError) { redirection(smbUrl); - finished(); - } else if (passwordError == KIO::ERR_USER_CANCELED) { - reportError(url, ret); - } else { - error(passwordError, url.toString()); + return WorkerResult::pass(); } - - return; - } else if (ret != 0) { + if (passwordError == KIO::ERR_USER_CANCELED) { + return reportError(url, ret); + } + return WorkerResult::fail(passwordError, url.toString()); + } + if (ret != 0) { qCDebug(KIO_SMB_LOG) << "stat() error" << ret << url; - reportError(url, ret); - return; + return reportError(url, ret); } statEntry(udsentry); - finished(); - return; + return WorkerResult::pass(); } } qCDebug(KIO_SMB_LOG) << "UNKNOWN " << url; - finished(); + return WorkerResult::pass(); } // TODO: complete checking <-- what does that even mean? // TODO: why is this not part of SMBUrl or at the very least URL validation should // be 100% shared between this and SMBUrl. Notably SMBUrl has code that looks // to do a similar thing but is much less complete. -QUrl SMBSlave::checkURL(const QUrl &kurl_) const +QUrl SMBWorker::checkURL(const QUrl &kurl_) const { qCDebug(KIO_SMB_LOG) << "checkURL " << kurl_; @@ -262,23 +254,24 @@ QUrl SMBSlave::checkURL(const QUrl &kurl_) const // if there's a valid host, don't have an empty path QUrl url(kurl); - if (url.path().isEmpty()) + if (url.path().isEmpty()) { url.setPath("/"); + } qCDebug(KIO_SMB_LOG) << "checkURL return3 " << url; return url; } -SMBSlave::SMBError SMBSlave::errnumToKioError(const SMBUrl &url, const int errNum) +SMBWorker::SMBError SMBWorker::errnumToKioError(const SMBUrl &url, const int errNum) { qCDebug(KIO_SMB_LOG) << "errNum" << errNum; switch (errNum) { case ENOENT: - if (url.getType() == SMBURLTYPE_ENTIRE_NETWORK) + if (url.getType() == SMBURLTYPE_ENTIRE_NETWORK) { return SMBError {ERR_WORKER_DEFINED, i18n("Unable to find any workgroups in your local network. This might be caused by an enabled firewall.")}; - else - return SMBError {ERR_DOES_NOT_EXIST, url.toDisplayString()}; + } + return SMBError {ERR_DOES_NOT_EXIST, url.toDisplayString()}; #ifdef ENOMEDIUM case ENOMEDIUM: return SMBError {ERR_WORKER_DEFINED, i18n("No media in device for %1", url.toDisplayString())}; @@ -298,10 +291,10 @@ SMBSlave::SMBError SMBSlave::errnumToKioError(const SMBUrl &url, const int errNu return SMBError {ERR_ACCESS_DENIED, url.toDisplayString()}; case EIO: case ENETUNREACH: - if (url.getType() == SMBURLTYPE_ENTIRE_NETWORK || url.getType() == SMBURLTYPE_WORKGROUP_OR_SERVER) + if (url.getType() == SMBURLTYPE_ENTIRE_NETWORK || url.getType() == SMBURLTYPE_WORKGROUP_OR_SERVER) { return SMBError {ERR_WORKER_DEFINED, i18n("Error while connecting to server responsible for %1", url.toDisplayString())}; - else - return SMBError {ERR_CONNECTION_BROKEN, url.toDisplayString()}; + } + return SMBError {ERR_CONNECTION_BROKEN, url.toDisplayString()}; case ENOMEM: return SMBError {ERR_OUT_OF_MEMORY, url.toDisplayString()}; case ENODEV: @@ -345,14 +338,13 @@ SMBSlave::SMBError SMBSlave::errnumToKioError(const SMBUrl &url, const int errNu } } -void SMBSlave::reportError(const SMBUrl &url, const int errNum) +WorkerResult SMBWorker::reportError(const SMBUrl &url, const int errNum) { const SMBError smbErr = errnumToKioError(url, errNum); - - error(smbErr.kioErrorId, smbErr.errorString); + return WorkerResult::fail(smbErr.kioErrorId, smbErr.errorString); } -void SMBSlave::reportWarning(const SMBUrl &url, const int errNum) +void SMBWorker::reportWarning(const SMBUrl &url, const int errNum) { const SMBError smbErr = errnumToKioError(url, errNum); const QString errorString = buildErrorString(smbErr.kioErrorId, smbErr.errorString); @@ -360,7 +352,7 @@ void SMBSlave::reportWarning(const SMBUrl &url, const int errNum) warning(xi18n("Error occurred while trying to access %1<nl/>%2", url.url(), errorString)); } -void SMBSlave::listDir(const QUrl &kurl) +WorkerResult SMBWorker::listDir(const QUrl &kurl) { qCDebug(KIO_SMB_LOG) << kurl; @@ -369,8 +361,7 @@ void SMBSlave::listDir(const QUrl &kurl) // if URL is not valid we have to redirect to correct URL if (url != kurl) { redirection(url); - finished(); - return; + return WorkerResult::pass(); } m_current_url = kurl; @@ -388,7 +379,7 @@ void SMBSlave::listDir(const QUrl &kurl) list.clear(); }; - // Since slavebase has no eventloop it wont publish results + // Since WorkerBase has no eventloop it wont publish results // on a timer, since we do not know how long our discovery // will take this is super meh because we may appear // stuck for a while. Implement our own listing system @@ -418,7 +409,7 @@ void SMBSlave::listDir(const QUrl &kurl) auto maybeFinished = [&] { // finishes if all discoveries finished bool allFinished = true; - for (const auto &discoverer : discoverers) { + for (const auto &discoverer : std::as_const(discoverers)) { allFinished = allFinished && discoverer->isFinished(); } if (allFinished) { @@ -466,21 +457,18 @@ void SMBSlave::listDir(const QUrl &kurl) const int passwordError = checkPassword(m_current_url); if (passwordError == KJob::NoError) { redirection(m_current_url); - finished(); - } else if (passwordError == KIO::ERR_USER_CANCELED) { + return WorkerResult::pass(); + } + if (passwordError == KIO::ERR_USER_CANCELED) { qCDebug(KIO_SMB_LOG) << "user cancelled password request"; - reportError(m_current_url, err); - } else { - qCDebug(KIO_SMB_LOG) << "generic password error:" << passwordError; - error(passwordError, m_current_url.toString()); + return reportError(m_current_url, err); } - - return; + qCDebug(KIO_SMB_LOG) << "generic password error:" << passwordError; + return WorkerResult::fail(passwordError, m_current_url.toString()); } qCDebug(KIO_SMB_LOG) << "reporting generic error:" << err; - reportError(m_current_url, err); - return; + return reportError(m_current_url, err); } UDSEntry udsentry; @@ -502,14 +490,13 @@ void SMBSlave::listDir(const QUrl &kurl) } listEntry(udsentry); - finished(); + return WorkerResult::pass(); } -void SMBSlave::fileSystemFreeSpace(const QUrl &url) +WorkerResult SMBWorker::fileSystemFreeSpace(const QUrl &url) { if (url.host().endsWith("kio-discovery-wsd")) { - error(KIO::ERR_UNKNOWN_HOST, url.url()); - return; + return WorkerResult::fail(KIO::ERR_UNKNOWN_HOST, url.url()); } qCDebug(KIO_SMB_LOG) << url; @@ -517,19 +504,18 @@ void SMBSlave::fileSystemFreeSpace(const QUrl &url) // requesting free space for smb:// which doesn't // make sense to do to begin with if (url.host().isEmpty()) { - error(KIO::ERR_CANNOT_STAT, url.url()); - return; + return WorkerResult::fail(KIO::ERR_CANNOT_STAT, url.url()); } - SMBUrl smbcUrl = url; + SMBUrl smbUrl = url; struct statvfs dirStat { }; memset(&dirStat, 0, sizeof(struct statvfs)); - const int err = smbc_statvfs(smbcUrl.toSmbcUrl().data(), &dirStat); + auto smbcUrl = smbUrl.toSmbcUrl(); // do not use temporary in function call, makes clazy happy + const int err = smbc_statvfs(smbcUrl.data(), &dirStat); if (err < 0) { - error(KIO::ERR_CANNOT_STAT, url.url()); - return; + return WorkerResult::fail(KIO::ERR_CANNOT_STAT, url.url()); } // libsmb_stat.c has very awkward conditional branching that results @@ -552,10 +538,10 @@ void SMBSlave::fileSystemFreeSpace(const QUrl &url) setMetaData("total", QString::number(total)); setMetaData("available", QString::number(available)); - finished(); + return WorkerResult::pass(); } -bool SMBSlave::workaroundEEXIST(const int errNum) const +bool SMBWorker::workaroundEEXIST(const int errNum) const { return (errNum == EEXIST) && m_enableEEXISTWorkaround; } diff --git a/smb/kio_smb_config.cpp b/smb/kio_smb_config.cpp index 79d0afcec..6aa80adcd 100644 --- a/smb/kio_smb_config.cpp +++ b/smb/kio_smb_config.cpp @@ -11,7 +11,7 @@ #include <QTextCodec> -void SMBSlave::reparseConfiguration() +void SMBWorker::reparseConfiguration() { m_context.authenticator()->loadConfiguration(); } diff --git a/smb/kio_smb_dir.cpp b/smb/kio_smb_dir.cpp index c4b9a488b..9e1d7811a 100644 --- a/smb/kio_smb_dir.cpp +++ b/smb/kio_smb_dir.cpp @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-or-later SPDX-FileCopyrightText: 2000 Caldera Systems Inc. - SPDX-FileCopyrightText: 2021 Harald Sitter <sit...@kde.org> + SPDX-FileCopyrightText: 2021-2022 Harald Sitter <sit...@kde.org> SPDX-FileContributor: Matthew Peterson <mpeter...@caldera.com> */ @@ -10,6 +10,7 @@ #include <QFile> #include <QFileInfo> +#include <QScopeGuard> #include <KConfigGroup> #include <kio/ioworker_defaults.h> @@ -19,23 +20,23 @@ #include "transfer.h" #include "transfer_resume.h" -void SMBSlave::copy(const QUrl &src, const QUrl &dst, int permissions, KIO::JobFlags flags) +WorkerResult SMBWorker::copy(const QUrl &src, const QUrl &dst, int permissions, KIO::JobFlags flags) { const bool isSourceLocal = src.isLocalFile(); const bool isDestinationLocal = dst.isLocalFile(); if (!isSourceLocal && isDestinationLocal) { - smbCopyGet(src, dst, permissions, flags); - } else if (isSourceLocal && !isDestinationLocal) { - smbCopyPut(src, dst, permissions, flags); - } else { - smbCopy(src, dst, permissions, flags); + return smbCopyGet(src, dst, permissions, flags); + } + if (isSourceLocal && !isDestinationLocal) { + return smbCopyPut(src, dst, permissions, flags); } + return smbCopy(src, dst, permissions, flags); } -void SMBSlave::smbCopy(const QUrl &ksrc, const QUrl &kdst, int permissions, KIO::JobFlags flags) +WorkerResult SMBWorker::smbCopy(const QUrl &ksrc, const QUrl &kdst, int permissions, KIO::JobFlags flags) { - qCDebug(KIO_SMB_LOG) << "SMBSlave::copy with src = " << ksrc << "and dest = " << kdst << flags; + qCDebug(KIO_SMB_LOG) << "SMBWorker::copy with src = " << ksrc << "and dest = " << kdst << flags; // setup urls SMBUrl src = ksrc; @@ -45,15 +46,12 @@ void SMBSlave::smbCopy(const QUrl &ksrc, const QUrl &kdst, int permissions, KIO: int errNum = cache_stat(src, &st); if (errNum != 0) { if (errNum == EACCES) { - error(KIO::ERR_ACCESS_DENIED, src.toDisplayString()); - } else { - error(KIO::ERR_DOES_NOT_EXIST, src.toDisplayString()); + return WorkerResult::fail(KIO::ERR_ACCESS_DENIED, src.toDisplayString()); } - return; + return WorkerResult::fail(KIO::ERR_DOES_NOT_EXIST, src.toDisplayString()); } if (S_ISDIR(st.st_mode)) { - error(KIO::ERR_IS_DIRECTORY, src.toDisplayString()); - return; + return WorkerResult::fail(KIO::ERR_IS_DIRECTORY, src.toDisplayString()); } const auto srcSize = st.st_size; totalSize(srcSize); @@ -62,33 +60,23 @@ void SMBSlave::smbCopy(const QUrl &ksrc, const QUrl &kdst, int permissions, KIO: errNum = cache_stat(dst, &st); if (errNum == 0) { if (S_ISDIR(st.st_mode)) { - error(KIO::ERR_DIR_ALREADY_EXIST, dst.toDisplayString()); - return; + return WorkerResult::fail(KIO::ERR_DIR_ALREADY_EXIST, dst.toDisplayString()); } if (!(flags & KIO::Overwrite)) { - error(KIO::ERR_FILE_ALREADY_EXIST, dst.toDisplayString()); - return; + return WorkerResult::fail(KIO::ERR_FILE_ALREADY_EXIST, dst.toDisplayString()); } } // Open the source file - int srcfd = smbc_open(src.toSmbcUrl(), O_RDONLY, 0); + const int srcfd = smbc_open(src.toSmbcUrl(), O_RDONLY, 0); + auto closeSrcFd = qScopeGuard([srcfd]{ smbc_close(srcfd); }); if (srcfd < 0) { - errNum = errno; - } else { - errNum = 0; - } - - if (srcfd < 0) { - if (errNum == EACCES) { - error(KIO::ERR_ACCESS_DENIED, src.toDisplayString()); - } else { - error(KIO::ERR_DOES_NOT_EXIST, src.toDisplayString()); + if (errno == EACCES) { + return WorkerResult::fail(KIO::ERR_ACCESS_DENIED, src.toDisplayString()); } - return; + return WorkerResult::fail(KIO::ERR_CANNOT_OPEN_FOR_READING, src.toDisplayString()); } - mode_t initialmode = 0; // Determine initial creation mode if (permissions != -1) { @@ -102,24 +90,13 @@ void SMBSlave::smbCopy(const QUrl &ksrc, const QUrl &kdst, int permissions, KIO: if (!(flags & KIO::Overwrite)) { dstflags |= O_EXCL; } - int dstfd = smbc_open(dst.toSmbcUrl(), dstflags, initialmode); + const int dstfd = smbc_open(dst.toSmbcUrl(), dstflags, initialmode); + auto closeDstFd = qScopeGuard([dstfd]{ smbc_close(dstfd); }); if (dstfd < 0) { - errNum = errno; - } else { - errNum = 0; - } - - if (dstfd < 0) { - if (errNum == EACCES) { - error(KIO::ERR_WRITE_ACCESS_DENIED, dst.toDisplayString()); - } else { - error(KIO::ERR_CANNOT_OPEN_FOR_READING, dst.toDisplayString()); - } - - if (srcfd >= 0) { - smbc_close(srcfd); + if (errno == EACCES) { + return WorkerResult::fail(KIO::ERR_WRITE_ACCESS_DENIED, dst.toDisplayString()); } - return; + return WorkerResult::fail(KIO::ERR_CANNOT_OPEN_FOR_WRITING, dst.toDisplayString()); } // Perform copy @@ -133,9 +110,8 @@ void SMBSlave::smbCopy(const QUrl &ksrc, const QUrl &kdst, int permissions, KIO: if (n > 0) { n = smbc_write(dstfd, segment.buf.data(), n); if (n == -1) { - qCDebug(KIO_SMB_LOG) << "SMBSlave::copy copy now KIO::ERR_CANNOT_WRITE"; - error(KIO::ERR_CANNOT_WRITE, dst.toDisplayString()); - break; + qCDebug(KIO_SMB_LOG) << "SMBWorker::copy copy now KIO::ERR_CANNOT_WRITE"; + return WorkerResult::fail(KIO::ERR_CANNOT_WRITE, dst.toDisplayString()); } processed_size += n; @@ -143,32 +119,26 @@ void SMBSlave::smbCopy(const QUrl &ksrc, const QUrl &kdst, int permissions, KIO: } else if (n == 0) { break; // finished } else { - error(KIO::ERR_CANNOT_READ, src.toDisplayString()); - break; + return WorkerResult::fail(KIO::ERR_CANNOT_READ, src.toDisplayString()); } } // FINISHED: - if (srcfd >= 0) { - smbc_close(srcfd); - } + smbc_close(srcfd);\ - if (dstfd >= 0) { - if (smbc_close(dstfd) == 0) { - // TODO: set final permissions - } else { - error(KIO::ERR_CANNOT_WRITE, dst.toDisplayString()); - return; - } + if (smbc_close(dstfd) == 0) { + // TODO: set final permissions + } else { + return WorkerResult::fail(KIO::ERR_CANNOT_WRITE, dst.toDisplayString()); } applyMTimeSMBC(dst); - finished(); + return WorkerResult::pass(); } -void SMBSlave::smbCopyGet(const QUrl &ksrc, const QUrl &kdst, int permissions, KIO::JobFlags flags) +WorkerResult SMBWorker::smbCopyGet(const QUrl &ksrc, const QUrl &kdst, int permissions, KIO::JobFlags flags) { qCDebug(KIO_SMB_LOG) << "src = " << ksrc << ", dest = " << kdst << flags; @@ -178,21 +148,19 @@ void SMBSlave::smbCopyGet(const QUrl &ksrc, const QUrl &kdst, int permissions, K if (dstInfo.exists()) { if (dstInfo.isDir()) { - error(ERR_IS_DIRECTORY, kdst.toDisplayString()); - return; + return WorkerResult::fail(ERR_IS_DIRECTORY, kdst.toDisplayString()); } if (!(flags & KIO::Overwrite)) { - error(ERR_FILE_ALREADY_EXIST, kdst.toDisplayString()); - return; + return WorkerResult::fail(ERR_FILE_ALREADY_EXIST, kdst.toDisplayString()); } } - auto optionalResume = Transfer::shouldResume<QFileResumeIO>(kdst, flags, this); - if (!optionalResume.has_value()) { // had error - return; + auto resumeVariant = Transfer::shouldResume<QFileResumeIO>(kdst, flags, this); + if (std::holds_alternative<WorkerResult>(resumeVariant)) { + return std::get<WorkerResult>(resumeVariant); } - const auto resume = optionalResume.value(); + const auto resume = std::get<TransferContext>(resumeVariant); // open the output file... const QFile::OpenMode mode = resume.resuming ? (QFile::WriteOnly | QFile::Append) : (QFile::WriteOnly | QFile::Truncate); @@ -213,19 +181,15 @@ void SMBSlave::smbCopyGet(const QUrl &ksrc, const QUrl &kdst, int permissions, K switch (file.error()) { case QFile::OpenError: if (resume.resuming) { - error(ERR_CANNOT_RESUME, kdst.toDisplayString()); - } else { - error(ERR_CANNOT_OPEN_FOR_WRITING, kdst.toDisplayString()); + return WorkerResult::fail(ERR_CANNOT_RESUME, kdst.toDisplayString()); } - break; + return WorkerResult::fail(ERR_CANNOT_OPEN_FOR_WRITING, kdst.toDisplayString()); case QFile::PermissionsError: - error(ERR_WRITE_ACCESS_DENIED, kdst.toDisplayString()); - break; + return WorkerResult::fail(ERR_WRITE_ACCESS_DENIED, kdst.toDisplayString()); default: - error(ERR_CANNOT_OPEN_FOR_WRITING, kdst.toDisplayString()); break; } - return; + return WorkerResult::fail(ERR_CANNOT_OPEN_FOR_WRITING, kdst.toDisplayString()); } // setup the source urls @@ -235,46 +199,34 @@ void SMBSlave::smbCopyGet(const QUrl &ksrc, const QUrl &kdst, int permissions, K int errNum = cache_stat(src, &st); if (errNum != 0) { if (errNum == EACCES) { - error(KIO::ERR_ACCESS_DENIED, src.toDisplayString()); - } else { - error(KIO::ERR_DOES_NOT_EXIST, src.toDisplayString()); + return WorkerResult::fail(KIO::ERR_ACCESS_DENIED, src.toDisplayString()); } - return; + return WorkerResult::fail(KIO::ERR_DOES_NOT_EXIST, src.toDisplayString()); } if (S_ISDIR(st.st_mode)) { - error(KIO::ERR_IS_DIRECTORY, src.toDisplayString()); - return; + return WorkerResult::fail(KIO::ERR_IS_DIRECTORY, src.toDisplayString()); } totalSize(st.st_size); // Open the source file KIO::filesize_t processed_size = 0; - int srcfd = smbc_open(src.toSmbcUrl(), O_RDONLY, 0); + const int srcfd = smbc_open(src.toSmbcUrl(), O_RDONLY, 0); + auto closeSrcFd = qScopeGuard([srcfd]{ smbc_close(srcfd); }); if (srcfd < 0) { - errNum = errno; - } else { - errNum = 0; - if (resume.resuming) { - qCDebug(KIO_SMB_LOG) << "seeking to size" << resume.destinationOffset; - off_t offset = smbc_lseek(srcfd, resume.destinationOffset, SEEK_SET); - if (offset == -1) { - error(KIO::ERR_CANNOT_SEEK, src.toDisplayString()); - smbc_close(srcfd); - return; - } else { - processed_size += offset; - } + if (errno == EACCES) { + return WorkerResult::fail(KIO::ERR_ACCESS_DENIED, src.toDisplayString()); } + return WorkerResult::fail(KIO::ERR_DOES_NOT_EXIST, src.toDisplayString()); } - - if (srcfd < 0) { - if (errNum == EACCES) { - error(KIO::ERR_ACCESS_DENIED, src.toDisplayString()); - } else { - error(KIO::ERR_DOES_NOT_EXIST, src.toDisplayString()); + errNum = 0; + if (resume.resuming) { + qCDebug(KIO_SMB_LOG) << "seeking to size" << resume.destinationOffset; + off_t offset = smbc_lseek(srcfd, resume.destinationOffset, SEEK_SET); + if (offset == -1) { + return WorkerResult::fail(KIO::ERR_CANNOT_SEEK, src.toDisplayString()); } - return; + processed_size += offset; } std::atomic<bool> isErr(false); @@ -296,6 +248,7 @@ void SMBSlave::smbCopyGet(const QUrl &ksrc, const QUrl &kdst, int permissions, K return KJob::NoError; }); + WorkerResult result = WorkerResult::pass(); while (true) { TransferSegment *segment = buffer.pop(); if (!segment) { // done, no more segments pending @@ -305,7 +258,7 @@ void SMBSlave::smbCopyGet(const QUrl &ksrc, const QUrl &kdst, int permissions, K const qint64 bytesWritten = file.write(segment->buf.data(), segment->size); if (bytesWritten == -1) { qCDebug(KIO_SMB_LOG) << "copy now KIO::ERR_CANNOT_WRITE"; - error(KIO::ERR_CANNOT_WRITE, kdst.toDisplayString()); + result = WorkerResult::fail(KIO::ERR_CANNOT_WRITE, kdst.toDisplayString()); isErr = true; buffer.unpop(); break; @@ -315,11 +268,10 @@ void SMBSlave::smbCopyGet(const QUrl &ksrc, const QUrl &kdst, int permissions, K processedSize(processed_size); buffer.unpop(); } - if (isErr) { // writing failed + if (!result.success()) { // writing failed future.wait(); } else if (future.get() != KJob::NoError) { // check if read had an error - error(future.get(), ksrc.toDisplayString()); - isErr = true; + result = WorkerResult::fail(future.get(), ksrc.toDisplayString()); } // FINISHED @@ -327,8 +279,8 @@ void SMBSlave::smbCopyGet(const QUrl &ksrc, const QUrl &kdst, int permissions, K // Handle error condition. - if (Transfer::concludeResumeHasError<QFileResumeIO>(isErr, resume, this)) { - return; // NB: error() called inside if applicable + if (auto conclusionResult = Transfer::concludeResumeHasError<QFileResumeIO>(result, resume, this); !conclusionResult.success()) { + return conclusionResult; // NB: error() called inside if applicable } // set modification time (if applicable) @@ -337,49 +289,43 @@ void SMBSlave::smbCopyGet(const QUrl &ksrc, const QUrl &kdst, int permissions, K utime(QFile::encodeName(dstFile).constData(), &utbuf); }); - finished(); + return WorkerResult::pass(); } -void SMBSlave::smbCopyPut(const QUrl &ksrc, const QUrl &kdst, int permissions, KIO::JobFlags flags) +WorkerResult SMBWorker::smbCopyPut(const QUrl &ksrc, const QUrl &kdst, int permissions, KIO::JobFlags flags) { qCDebug(KIO_SMB_LOG) << "src = " << ksrc << ", dest = " << kdst << flags; QFile srcFile(ksrc.toLocalFile()); const QFileInfo srcInfo(srcFile); - if (srcInfo.exists()) { - if (srcInfo.isDir()) { - error(KIO::ERR_IS_DIRECTORY, ksrc.toDisplayString()); - return; - } - } else { - error(KIO::ERR_DOES_NOT_EXIST, ksrc.toDisplayString()); - return; + if (!srcInfo.exists()) { + return WorkerResult::fail(KIO::ERR_DOES_NOT_EXIST, ksrc.toDisplayString()); + } + if (srcInfo.isDir()) { + return WorkerResult::fail(KIO::ERR_IS_DIRECTORY, ksrc.toDisplayString()); } if (!srcFile.open(QFile::ReadOnly)) { qCDebug(KIO_SMB_LOG) << "could not read from" << ksrc; switch (srcFile.error()) { case QFile::PermissionsError: - error(KIO::ERR_WRITE_ACCESS_DENIED, ksrc.toDisplayString()); - break; - case QFile::OpenError: + return WorkerResult::fail(KIO::ERR_WRITE_ACCESS_DENIED, ksrc.toDisplayString()); default: - error(KIO::ERR_CANNOT_OPEN_FOR_READING, ksrc.toDisplayString()); break; } - return; + return WorkerResult::fail(KIO::ERR_CANNOT_OPEN_FOR_READING, ksrc.toDisplayString()); } totalSize(static_cast<filesize_t>(srcInfo.size())); const SMBUrl dstOrigUrl(kdst); - const std::optional<TransferContext> resumeOptional = Transfer::shouldResume<SMBResumeIO>(dstOrigUrl, flags, this); - if (!resumeOptional.has_value()) { // had an error - return; + auto resumeVariant = Transfer::shouldResume<SMBResumeIO>(dstOrigUrl, flags, this); + if (std::holds_alternative<WorkerResult>(resumeVariant)) { // had an error + return std::get<WorkerResult>(resumeVariant); } - const TransferContext &resume = resumeOptional.value(); + const TransferContext &resume = std::get<TransferContext>(resumeVariant); KIO::filesize_t processed_size = 0; const SMBUrl dstUrl(resume.destination); @@ -395,17 +341,15 @@ void SMBSlave::smbCopyPut(const QUrl &ksrc, const QUrl &kdst, int permissions, K } else { const off_t offset = smbc_lseek(dstfd, 0, SEEK_END); if (offset == (off_t)-1) { - error(KIO::ERR_CANNOT_SEEK, dstUrl.toDisplayString()); smbc_close(dstfd); - return; - } else { - processed_size = offset; + return WorkerResult::fail(KIO::ERR_CANNOT_SEEK, dstUrl.toDisplayString()); } + processed_size = offset; } } else { - mode_t mode; + mode_t mode = 0; if (permissions == -1) { - mode = 600; + mode = S_IRUSR | S_IWUSR; } else { mode = permissions | S_IRUSR | S_IWUSR; } @@ -420,15 +364,13 @@ void SMBSlave::smbCopyPut(const QUrl &ksrc, const QUrl &kdst, int permissions, K if (dstfd < 0) { if (errNum == EACCES) { qCDebug(KIO_SMB_LOG) << "access denied"; - error(KIO::ERR_WRITE_ACCESS_DENIED, dstUrl.toDisplayString()); - } else { - qCDebug(KIO_SMB_LOG) << "can not open for writing"; - error(KIO::ERR_CANNOT_OPEN_FOR_WRITING, dstUrl.toDisplayString()); + return WorkerResult::fail(KIO::ERR_WRITE_ACCESS_DENIED, dstUrl.toDisplayString()); } - return; + qCDebug(KIO_SMB_LOG) << "can not open for writing"; + return WorkerResult::fail(KIO::ERR_CANNOT_OPEN_FOR_WRITING, dstUrl.toDisplayString()); } - bool isErr = false; + WorkerResult result = WorkerResult::pass(); if (processed_size == 0 || srcFile.seek(processed_size)) { // Perform the copy TransferSegment segment(srcInfo.size()); @@ -436,16 +378,14 @@ void SMBSlave::smbCopyPut(const QUrl &ksrc, const QUrl &kdst, int permissions, K const ssize_t bytesRead = srcFile.read(segment.buf.data(), segment.buf.size()); if (bytesRead <= 0) { if (bytesRead < 0) { - error(KIO::ERR_CANNOT_READ, ksrc.toDisplayString()); - isErr = true; + result = WorkerResult::fail(KIO::ERR_CANNOT_READ, ksrc.toDisplayString()); } break; } const qint64 bytesWritten = smbc_write(dstfd, segment.buf.data(), bytesRead); if (bytesWritten == -1) { - error(KIO::ERR_CANNOT_WRITE, kdst.toDisplayString()); - isErr = true; + result = WorkerResult::fail(KIO::ERR_CANNOT_WRITE, kdst.toDisplayString()); break; } @@ -453,28 +393,25 @@ void SMBSlave::smbCopyPut(const QUrl &ksrc, const QUrl &kdst, int permissions, K processedSize(processed_size); } } else { - isErr = true; - error(KIO::ERR_CANNOT_SEEK, ksrc.toDisplayString()); + result = WorkerResult::fail(KIO::ERR_CANNOT_SEEK, ksrc.toDisplayString()); } // FINISHED if (smbc_close(dstfd) < 0) { qCDebug(KIO_SMB_LOG) << dstUrl << "could not write"; - error(KIO::ERR_CANNOT_WRITE, dstUrl.toDisplayString()); - return; + return WorkerResult::fail(KIO::ERR_CANNOT_WRITE, dstUrl.toDisplayString()); } - if (Transfer::concludeResumeHasError<SMBResumeIO>(isErr, resume, this)) { - return; // NB: error() called inside if applicable + if (auto conclusionResult = Transfer::concludeResumeHasError<SMBResumeIO>(result, resume, this); !conclusionResult.success()) { + return conclusionResult; } applyMTimeSMBC(dstOrigUrl); - // We have done our job => finish - finished(); + return WorkerResult::pass(); } -void SMBSlave::del(const QUrl &kurl, bool isfile) +WorkerResult SMBWorker::del(const QUrl &kurl, bool isfile) { qCDebug(KIO_SMB_LOG) << kurl; m_current_url = kurl; @@ -502,13 +439,12 @@ void SMBSlave::del(const QUrl &kurl, bool isfile) } if (errNum != 0) { - reportError(kurl, errNum); - } else { - finished(); + return reportError(kurl, errNum); } + return WorkerResult::pass(); } -void SMBSlave::mkdir(const QUrl &kurl, int permissions) +WorkerResult SMBWorker::mkdir(const QUrl &kurl, int permissions) { qCDebug(KIO_SMB_LOG) << kurl; int errNum = 0; @@ -526,22 +462,19 @@ void SMBSlave::mkdir(const QUrl &kurl, int permissions) if (errNum == EEXIST) { errNum = cache_stat(m_current_url, &st); if (errNum == 0 && S_ISDIR(st.st_mode)) { - error(KIO::ERR_DIR_ALREADY_EXIST, m_current_url.toDisplayString()); - } else { - error(KIO::ERR_FILE_ALREADY_EXIST, m_current_url.toDisplayString()); + return WorkerResult::fail(KIO::ERR_DIR_ALREADY_EXIST, m_current_url.toDisplayString()); } - } else { - reportError(kurl, errNum); + return WorkerResult::fail(KIO::ERR_FILE_ALREADY_EXIST, m_current_url.toDisplayString()); } qCDebug(KIO_SMB_LOG) << "exit with error " << kurl; - } else // success - { - if (permissions != -1) { - // TODO enable the following when complete - // smbc_chmod( url.toSmbcUrl(), permissions ); - } - finished(); + return reportError(kurl, errNum); + } + + if (permissions != -1) { + // TODO enable the following when complete + // smbc_chmod( url.toSmbcUrl(), permissions ); } + return WorkerResult::pass(); } static bool sameInodeStat(bool hasSrcStat, const struct stat srcStat, const struct stat dstStat) @@ -561,7 +494,7 @@ static bool sameInodeStat(bool hasSrcStat, const struct stat srcStat, const stru return equal; } -void SMBSlave::rename(const QUrl &ksrc, const QUrl &kdest, KIO::JobFlags flags) +WorkerResult SMBWorker::rename(const QUrl &ksrc, const QUrl &kdest, KIO::JobFlags flags) { SMBUrl src; SMBUrl dst; @@ -592,13 +525,11 @@ void SMBSlave::rename(const QUrl &ksrc, const QUrl &kdest, KIO::JobFlags flags) if (errNum == 0 && !sameInodeStat(hasSrcStat, srcStat, st)) { if (S_ISDIR(st.st_mode)) { qCDebug(KIO_SMB_LOG) << "KIO::ERR_DIR_ALREADY_EXIST"; - error(KIO::ERR_DIR_ALREADY_EXIST, dst.toDisplayString()); - return; + return WorkerResult::fail(KIO::ERR_DIR_ALREADY_EXIST, dst.toDisplayString()); } if (!(flags & KIO::Overwrite)) { qCDebug(KIO_SMB_LOG) << "KIO::ERR_FILE_ALREADY_EXIST"; - error(KIO::ERR_FILE_ALREADY_EXIST, dst.toDisplayString()); - return; + return WorkerResult::fail(KIO::ERR_FILE_ALREADY_EXIST, dst.toDisplayString()); } } @@ -618,29 +549,21 @@ void SMBSlave::rename(const QUrl &ksrc, const QUrl &kdest, KIO::JobFlags flags) if (errNum != 0) { if (errNum == EACCES) { qCDebug(KIO_SMB_LOG) << "KIO::ERR_ACCESS_DENIED"; - error(KIO::ERR_ACCESS_DENIED, src.toDisplayString()); - } else { - qCDebug(KIO_SMB_LOG) << "KIO::ERR_DOES_NOT_EXIST"; - error(KIO::ERR_DOES_NOT_EXIST, src.toDisplayString()); + return WorkerResult::fail(KIO::ERR_ACCESS_DENIED, src.toDisplayString()); } + qCDebug(KIO_SMB_LOG) << "KIO::ERR_DOES_NOT_EXIST"; + return WorkerResult::fail(KIO::ERR_DOES_NOT_EXIST, src.toDisplayString()); } break; - case EACCES: case EPERM: qCDebug(KIO_SMB_LOG) << "KIO::ERR_ACCESS_DENIED"; - error(KIO::ERR_ACCESS_DENIED, dst.toDisplayString()); - break; - - default: - qCDebug(KIO_SMB_LOG) << "KIO::ERR_CANNOT_RENAME"; - error(KIO::ERR_CANNOT_RENAME, src.toDisplayString()); + return WorkerResult::fail(KIO::ERR_ACCESS_DENIED, dst.toDisplayString()); } - qCDebug(KIO_SMB_LOG) << "exit with error"; - return; + return WorkerResult::fail(KIO::ERR_CANNOT_RENAME, src.toDisplayString()); } qCDebug(KIO_SMB_LOG) << "everything fine\n"; - finished(); + return WorkerResult::pass(); } diff --git a/smb/kio_smb_file.cpp b/smb/kio_smb_file.cpp index 51f0757f6..3335e589a 100644 --- a/smb/kio_smb_file.cpp +++ b/smb/kio_smb_file.cpp @@ -19,7 +19,7 @@ #include "transfer.h" -void SMBSlave::get(const QUrl &kurl) +WorkerResult SMBWorker::get(const QUrl &kurl) { qCDebug(KIO_SMB_LOG) << kurl; @@ -28,28 +28,24 @@ void SMBSlave::get(const QUrl &kurl) // if URL is not valid we have to redirect to correct URL if (kvurl != kurl) { redirection(kvurl); - finished(); - return; + return WorkerResult::pass(); } if (!m_context.isValid()) { - SlaveBase::error(ERR_INTERNAL, i18n("libsmbclient failed to create context")); - return; + return WorkerResult::fail(ERR_INTERNAL, i18n("libsmbclient failed to create context")); } // Stat SMBUrl url = kurl; int errNum = cache_stat(url, &st); if (errNum != 0) { - if (errNum == EACCES) - error(KIO::ERR_ACCESS_DENIED, url.toDisplayString()); - else - error(KIO::ERR_DOES_NOT_EXIST, url.toDisplayString()); - return; + if (errNum == EACCES) { + return WorkerResult::fail(KIO::ERR_ACCESS_DENIED, url.toDisplayString()); + } + return WorkerResult::fail(KIO::ERR_DOES_NOT_EXIST, url.toDisplayString()); } if (S_ISDIR(st.st_mode)) { - error(KIO::ERR_IS_DIRECTORY, url.toDisplayString()); - return; + return WorkerResult::fail(KIO::ERR_IS_DIRECTORY, url.toDisplayString()); } // Set the total size @@ -58,8 +54,7 @@ void SMBSlave::get(const QUrl &kurl) // Open and read the file int filefd = smbc_open(url.toSmbcUrl(), O_RDONLY, 0); if (filefd < 0) { - error(KIO::ERR_CANNOT_OPEN_FOR_READING, url.toDisplayString()); - return; + return WorkerResult::fail(KIO::ERR_CANNOT_OPEN_FOR_READING, url.toDisplayString()); } auto filefdClose = qScopeGuard([filefd] { smbc_close(filefd); @@ -110,8 +105,7 @@ void SMBSlave::get(const QUrl &kurl) buffer.unpop(); } if (future.get() != KJob::NoError) { // check if read had an error - error(future.get(), url.toDisplayString()); - return; + return WorkerResult::fail(future.get(), url.toDisplayString()); } data(QByteArray()); @@ -120,10 +114,10 @@ void SMBSlave::get(const QUrl &kurl) } processedSize(static_cast<KIO::filesize_t>(st.st_size)); - finished(); + return WorkerResult::pass(); } -void SMBSlave::open(const QUrl &kurl, QIODevice::OpenMode mode) +WorkerResult SMBWorker::open(const QUrl &kurl, QIODevice::OpenMode mode) { int errNum = 0; qCDebug(KIO_SMB_LOG) << kurl; @@ -134,33 +128,29 @@ void SMBSlave::open(const QUrl &kurl, QIODevice::OpenMode mode) // if URL is not valid we have to redirect to correct URL if (kvurl != kurl) { redirection(kvurl); - finished(); - return; + return WorkerResult::pass(); } if (!m_context.isValid()) { - error(KIO::ERR_ACCESS_DENIED, kurl.toDisplayString()); - return; + return WorkerResult::fail(KIO::ERR_ACCESS_DENIED, kurl.toDisplayString()); } // Save the URL as a private member // FIXME For some reason m_openUrl has be be declared in bottom private - // section of the class SMBSlave declaration instead of the top section + // section of the class SMBWorker declaration instead of the top section // or else this assignment fails m_openUrl = kurl; // Stat errNum = cache_stat(m_openUrl, &st); if (errNum != 0) { - if (errNum == EACCES) - error(KIO::ERR_ACCESS_DENIED, m_openUrl.toDisplayString()); - else - error(KIO::ERR_DOES_NOT_EXIST, m_openUrl.toDisplayString()); - return; + if (errNum == EACCES) { + return WorkerResult::fail(KIO::ERR_ACCESS_DENIED, m_openUrl.toDisplayString()); + } + return WorkerResult::fail(KIO::ERR_DOES_NOT_EXIST, m_openUrl.toDisplayString()); } if (S_ISDIR(st.st_mode)) { - error(KIO::ERR_IS_DIRECTORY, m_openUrl.toDisplayString()); - return; + return WorkerResult::fail(KIO::ERR_IS_DIRECTORY, m_openUrl.toDisplayString()); } // Set the total size @@ -187,12 +177,11 @@ void SMBSlave::open(const QUrl &kurl, QIODevice::OpenMode mode) // Open the file m_openFd = smbc_open(m_openUrl.toSmbcUrl(), flags, 0); if (m_openFd < 0) { - error(KIO::ERR_CANNOT_OPEN_FOR_READING, m_openUrl.toDisplayString()); - return; + return WorkerResult::fail(KIO::ERR_CANNOT_OPEN_FOR_READING, m_openUrl.toDisplayString()); } // Determine the mimetype of the file to be retrieved, and emit it. - // This is mandatory in all slaves (for KRun/BrowserRun to work). + // This is mandatory in all workers (for KRun/BrowserRun to work). // If we're not opening the file ReadOnly or ReadWrite, don't attempt to // read the file and send the mimetype. if (mode & QIODevice::ReadOnly) { @@ -201,29 +190,26 @@ void SMBSlave::open(const QUrl &kurl, QIODevice::OpenMode mode) QVarLengthArray<char> buffer(bytesRequested); bytesRead = smbc_read(m_openFd, buffer.data(), bytesRequested); if (bytesRead < 0) { - error(KIO::ERR_CANNOT_READ, m_openUrl.toDisplayString()); closeWithoutFinish(); - return; - } else { - QByteArray fileData = QByteArray::fromRawData(buffer.data(), bytesRead); - QMimeDatabase db; - QMimeType type = db.mimeTypeForFileNameAndData(m_openUrl.fileName(), fileData); - mimeType(type.name()); + return WorkerResult::fail(KIO::ERR_CANNOT_READ, m_openUrl.toDisplayString()); + } + QByteArray fileData = QByteArray::fromRawData(buffer.data(), bytesRead); + QMimeDatabase db; + QMimeType type = db.mimeTypeForFileNameAndData(m_openUrl.fileName(), fileData); + mimeType(type.name()); - off_t res = smbc_lseek(m_openFd, 0, SEEK_SET); - if (res == (off_t)-1) { - error(KIO::ERR_CANNOT_SEEK, m_openUrl.path()); - closeWithoutFinish(); - return; - } + off_t res = smbc_lseek(m_openFd, 0, SEEK_SET); + if (res == (off_t)-1) { + closeWithoutFinish(); + return WorkerResult::fail(KIO::ERR_CANNOT_SEEK, m_openUrl.path()); } } position(0); - opened(); + return WorkerResult::pass(); } -void SMBSlave::read(KIO::filesize_t bytesRequested) +WorkerResult SMBWorker::read(KIO::filesize_t bytesRequested) { Q_ASSERT(m_openFd != -1); @@ -235,16 +221,16 @@ void SMBSlave::read(KIO::filesize_t bytesRequested) if (bytesRead < 0) { qCDebug(KIO_SMB_LOG) << "Could not read " << m_openUrl; - error(KIO::ERR_CANNOT_READ, m_openUrl.toDisplayString()); closeWithoutFinish(); - return; + return WorkerResult::fail(KIO::ERR_CANNOT_READ, m_openUrl.toDisplayString()); } QByteArray fileData = QByteArray::fromRawData(buffer.data(), bytesRead); data(fileData); + return WorkerResult::pass(); } -void SMBSlave::write(const QByteArray &fileData) +WorkerResult SMBWorker::write(const QByteArray &fileData) { Q_ASSERT(m_openFd != -1); @@ -253,50 +239,50 @@ void SMBSlave::write(const QByteArray &fileData) ssize_t size = smbc_write(m_openFd, buf.data(), buf.size()); if (size < 0) { qCDebug(KIO_SMB_LOG) << "Could not write to " << m_openUrl; - error(KIO::ERR_CANNOT_WRITE, m_openUrl.toDisplayString()); closeWithoutFinish(); - return; + return WorkerResult::fail(KIO::ERR_CANNOT_WRITE, m_openUrl.toDisplayString()); } written(size); + return WorkerResult::pass(); } -void SMBSlave::seek(KIO::filesize_t offset) +WorkerResult SMBWorker::seek(KIO::filesize_t offset) { off_t res = smbc_lseek(m_openFd, static_cast<off_t>(offset), SEEK_SET); if (res == (off_t)-1) { - error(KIO::ERR_CANNOT_SEEK, m_openUrl.path()); closeWithoutFinish(); - } else { - qCDebug(KIO_SMB_LOG) << "res" << res; - position(res); + return WorkerResult::fail(KIO::ERR_CANNOT_SEEK, m_openUrl.path()); } + qCDebug(KIO_SMB_LOG) << "res" << res; + position(res); + return WorkerResult::pass(); } -void SMBSlave::truncate(KIO::filesize_t length) +WorkerResult SMBWorker::truncate(KIO::filesize_t length) { off_t res = smbc_ftruncate(m_openFd, static_cast<off_t>(length)); if (res < 0) { - error(KIO::ERR_CANNOT_TRUNCATE, m_openUrl.path()); closeWithoutFinish(); - } else { - qCDebug(KIO_SMB_LOG) << "res" << res; - truncated(length); + return WorkerResult::fail(KIO::ERR_CANNOT_TRUNCATE, m_openUrl.path()); } + qCDebug(KIO_SMB_LOG) << "res" << res; + truncated(length); + return WorkerResult::pass(); } -void SMBSlave::closeWithoutFinish() +void SMBWorker::closeWithoutFinish() { smbc_close(m_openFd); } -void SMBSlave::close() +WorkerResult SMBWorker::close() { closeWithoutFinish(); - finished(); + return WorkerResult::pass(); } -void SMBSlave::put(const QUrl &kurl, int permissions, KIO::JobFlags flags) +WorkerResult SMBWorker::put(const QUrl &kurl, int permissions, KIO::JobFlags flags) { void *buf; size_t bufsize; @@ -317,12 +303,10 @@ void SMBSlave::put(const QUrl &kurl, int permissions, KIO::JobFlags flags) if (exists && !(flags & KIO::Overwrite) && !(flags & KIO::Resume)) { if (S_ISDIR(st.st_mode)) { qCDebug(KIO_SMB_LOG) << kurl << " already isdir !!"; - error(KIO::ERR_DIR_ALREADY_EXIST, m_current_url.toDisplayString()); - } else { - qCDebug(KIO_SMB_LOG) << kurl << " already exist !!"; - error(KIO::ERR_FILE_ALREADY_EXIST, m_current_url.toDisplayString()); + return WorkerResult::fail(KIO::ERR_DIR_ALREADY_EXIST, m_current_url.toDisplayString()); } - return; + qCDebug(KIO_SMB_LOG) << kurl << " already exist !!"; + return WorkerResult::fail(KIO::ERR_FILE_ALREADY_EXIST, m_current_url.toDisplayString()); } if (exists && !(flags & KIO::Resume) && (flags & KIO::Overwrite)) { @@ -350,7 +334,7 @@ void SMBSlave::put(const QUrl &kurl, int permissions, KIO::JobFlags flags) if (permissions != -1) { mode = permissions | S_IWUSR | S_IRUSR; } else { - mode = 600; // 0666; + mode = S_IWUSR | S_IRUSR; } qCDebug(KIO_SMB_LOG) << "NO resume " << m_current_url.toSmbcUrl(); @@ -365,13 +349,14 @@ void SMBSlave::put(const QUrl &kurl, int permissions, KIO::JobFlags flags) if (filefd < 0) { if (errNum == EACCES) { qCDebug(KIO_SMB_LOG) << "error " << kurl << " access denied !!"; - error(KIO::ERR_WRITE_ACCESS_DENIED, m_current_url.toDisplayString()); - } else { - qCDebug(KIO_SMB_LOG) << "error " << kurl << " can not open for writing !!"; - error(KIO::ERR_CANNOT_OPEN_FOR_WRITING, m_current_url.toDisplayString()); + return WorkerResult::fail(KIO::ERR_WRITE_ACCESS_DENIED, m_current_url.toDisplayString()); } - return; + qCDebug(KIO_SMB_LOG) << "error " << kurl << " can not open for writing !!"; + return WorkerResult::fail(KIO::ERR_CANNOT_OPEN_FOR_WRITING, m_current_url.toDisplayString()); } + auto closeFileFd = qScopeGuard([filefd] { + smbc_close(filefd); + }); // Loop until we got 0 (end of data) while (true) { @@ -389,8 +374,7 @@ void SMBSlave::put(const QUrl &kurl, int permissions, KIO::JobFlags flags) ssize_t size = smbc_write(filefd, buf, bufsize); if (size < 0) { qCDebug(KIO_SMB_LOG) << "error " << kurl << "could not write !!"; - error(KIO::ERR_CANNOT_WRITE, m_current_url.toDisplayString()); - return; + return WorkerResult::fail(KIO::ERR_CANNOT_WRITE, m_current_url.toDisplayString()); } qCDebug(KIO_SMB_LOG) << "wrote " << size; } @@ -398,8 +382,7 @@ void SMBSlave::put(const QUrl &kurl, int permissions, KIO::JobFlags flags) if (smbc_close(filefd) < 0) { qCDebug(KIO_SMB_LOG) << kurl << "could not write !!"; - error(KIO::ERR_CANNOT_WRITE, m_current_url.toDisplayString()); - return; + return WorkerResult::fail(KIO::ERR_CANNOT_WRITE, m_current_url.toDisplayString()); } // set final permissions, if the file was just created @@ -411,6 +394,5 @@ void SMBSlave::put(const QUrl &kurl, int permissions, KIO::JobFlags flags) applyMTimeSMBC(m_current_url); - // We have done our job => finish - finished(); + return WorkerResult::pass(); } diff --git a/smb/kio_smb_mount.cpp b/smb/kio_smb_mount.cpp index b3fe45e64..38baeec86 100644 --- a/smb/kio_smb_mount.cpp +++ b/smb/kio_smb_mount.cpp @@ -14,7 +14,7 @@ #include <QDir> #include <unistd.h> -void SMBSlave::special(const QByteArray &data) +WorkerResult SMBWorker::special(const QByteArray &data) { qCDebug(KIO_SMB_LOG) << "Smb::special()"; int tmp; @@ -44,8 +44,7 @@ void SMBSlave::special(const QByteArray &data) if (tmp == 3) { if (!QDir().mkpath(mountPoint)) { - error(KIO::ERR_CANNOT_MKDIR, mountPoint); - return; + return WorkerResult::fail(KIO::ERR_CANNOT_MKDIR, mountPoint); } } @@ -55,8 +54,7 @@ void SMBSlave::special(const QByteArray &data) const int passwordError = checkPassword(smburl); if (passwordError != KJob::NoError && passwordError != KIO::ERR_USER_CANCELED) { - error(passwordError, smburl.toString()); - return; + return WorkerResult::fail(passwordError, smburl.toString()); } // using smbmount instead of "mount -t smbfs", because mount does not allow a non-root @@ -89,8 +87,7 @@ void SMBSlave::special(const QByteArray &data) proc.start(); if (!proc.waitForFinished()) { - error(KIO::ERR_CANNOT_LAUNCH_PROCESS, "smbmount" + i18n("\nMake sure that the samba package is installed properly on your system.")); - return; + return WorkerResult::fail(KIO::ERR_CANNOT_LAUNCH_PROCESS, "smbmount" + i18n("\nMake sure that the samba package is installed properly on your system.")); } QString mybuf = QString::fromLocal8Bit(proc.readAllStandardOutput()); @@ -99,8 +96,7 @@ void SMBSlave::special(const QByteArray &data) qCDebug(KIO_SMB_LOG) << "mount exit " << proc.exitCode() << "stdout:" << mybuf << "\nstderr:" << mystderr; if (proc.exitCode() != 0) { - error(KIO::ERR_CANNOT_MOUNT, i18n("Mounting of share \"%1\" from host \"%2\" by user \"%3\" failed.\n%4", share, host, user, mybuf + '\n' + mystderr)); - return; + return WorkerResult::fail(KIO::ERR_CANNOT_MOUNT, i18n("Mounting of share \"%1\" from host \"%2\" by user \"%3\" failed.\n%4", share, host, user, mybuf + '\n' + mystderr)); } } break; @@ -116,8 +112,7 @@ void SMBSlave::special(const QByteArray &data) proc.start(); if (!proc.waitForFinished()) { - error(KIO::ERR_CANNOT_LAUNCH_PROCESS, "smbumount" + i18n("\nMake sure that the samba package is installed properly on your system.")); - return; + return WorkerResult::fail(KIO::ERR_CANNOT_LAUNCH_PROCESS, "smbumount" + i18n("\nMake sure that the samba package is installed properly on your system.")); } QString mybuf = QString::fromLocal8Bit(proc.readAllStandardOutput()); @@ -126,8 +121,7 @@ void SMBSlave::special(const QByteArray &data) qCDebug(KIO_SMB_LOG) << "smbumount exit " << proc.exitCode() << "stdout:" << mybuf << "\nstderr:" << mystderr; if (proc.exitCode() != 0) { - error(KIO::ERR_CANNOT_UNMOUNT, i18n("Unmounting of mountpoint \"%1\" failed.\n%2", mountPoint, mybuf + '\n' + mystderr)); - return; + return WorkerResult::fail(KIO::ERR_CANNOT_UNMOUNT, i18n("Unmounting of mountpoint \"%1\" failed.\n%2", mountPoint, mybuf + '\n' + mystderr)); } if (tmp == 4) { @@ -143,8 +137,7 @@ void SMBSlave::special(const QByteArray &data) } if (!ok) { - error(KIO::ERR_CANNOT_RMDIR, mountPoint); - return; + return WorkerResult::fail(KIO::ERR_CANNOT_RMDIR, mountPoint); } } } @@ -152,5 +145,5 @@ void SMBSlave::special(const QByteArray &data) default: break; } - finished(); + return WorkerResult::pass(); } diff --git a/smb/main.cpp b/smb/main.cpp index 9e42f8ea5..d02bd0311 100644 --- a/smb/main.cpp +++ b/smb/main.cpp @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-or-later SPDX-FileCopyrightText: 2000 Caldera Systems Inc. - SPDX-FileCopyrightText: 2020 Harald Sitter <sit...@kde.org> + SPDX-FileCopyrightText: 2020-2022 Harald Sitter <sit...@kde.org> SPDX-FileContributor: Matthew Peterson <mpeter...@caldera.com> */ @@ -17,8 +17,8 @@ extern "C" int Q_DECL_EXPORT kdemain(int argc, char **argv) return -1; } - SMBSlave slave(argv[2], argv[3]); - slave.dispatchLoop(); + SMBWorker worker(argv[2], argv[3]); + worker.dispatchLoop(); return 0; } diff --git a/smb/smbauthenticator.cpp b/smb/smbauthenticator.cpp index 9483bbfb4..96f1101f5 100644 --- a/smb/smbauthenticator.cpp +++ b/smb/smbauthenticator.cpp @@ -32,7 +32,7 @@ void SMBAuthenticator::loadConfiguration() QString m_encoding = QTextCodec::codecForLocale()->name(); m_defaultEncoding = group.readEntry("Encoding", m_encoding.toLower()); - // unscramble, taken from Nicola Brodu's smb ioslave + // unscramble, taken from Nicola Brodu's smb ioworker // not really secure, but better than storing the plain password QString scrambled = group.readEntry("Password"); m_defaultPassword = ""; diff --git a/smb/smbauthenticator.h b/smb/smbauthenticator.h index 6a9ed0b6d..f7f302be1 100644 --- a/smb/smbauthenticator.h +++ b/smb/smbauthenticator.h @@ -11,8 +11,8 @@ namespace KIO { class AuthInfo; } -// Abstracts SlaveBase API so Authenticator may be used without -// a SlaveBase for the KDirNotify implementation) +// Abstracts WorkerBase API so Authenticator may be used without +// a WorkerBase for the KDirNotify implementation) class SMBAbstractFrontend { public: diff --git a/smb/smbcdiscoverer.cpp b/smb/smbcdiscoverer.cpp index 47b3bc168..c188118ec 100644 --- a/smb/smbcdiscoverer.cpp +++ b/smb/smbcdiscoverer.cpp @@ -104,10 +104,10 @@ KIO::UDSEntry SMBCDiscovery::toEntry() const return m_entry; } -SMBCDiscoverer::SMBCDiscoverer(const SMBUrl &url, QEventLoop *loop, SMBSlave *slave) +SMBCDiscoverer::SMBCDiscoverer(const SMBUrl &url, QEventLoop *loop, SMBWorker *worker) : m_url(url) , m_loop(loop) - , m_slave(slave) + , m_worker(worker) { } @@ -146,7 +146,7 @@ bool SMBCDiscoverer::discoverNextFileInfo() entry.fastInsert(KIO::UDSEntry::UDS_NAME, name); m_url.addPath(name); - m_slave->statToUDSEntry(m_url, st, entry); // won't produce useful error + m_worker->statToUDSEntry(m_url, st, entry); // won't produce useful error Q_EMIT newDiscovery(Discovery::Ptr(new SMBCDiscovery(entry))); m_url.cdUp(); return true; @@ -235,7 +235,7 @@ void SMBCDiscoverer::discoverNext() } else if (dirp->smbc_type == SMBC_FILE || dirp->smbc_type == SMBC_DIR) { // Set stat information m_url.addPath(name); - const int statErr = m_slave->browse_stat_path(m_url, entry); + const int statErr = m_worker->browse_stat_path(m_url, entry); if (statErr != 0) { // The entry can disappear in the time span between // listing and the stat call. There's nothing we or the user diff --git a/smb/smbcdiscoverer.h b/smb/smbcdiscoverer.h index 6711f093b..c48ca9630 100644 --- a/smb/smbcdiscoverer.h +++ b/smb/smbcdiscoverer.h @@ -31,7 +31,7 @@ class SMBCDiscoverer : public QObject, public Discoverer { Q_OBJECT public: - SMBCDiscoverer(const SMBUrl &url, QEventLoop *discoverNext, SMBSlave *slave); + SMBCDiscoverer(const SMBUrl &url, QEventLoop *discoverNext, SMBWorker *worker); ~SMBCDiscoverer() override; void start() override; @@ -72,7 +72,7 @@ private: SMBUrl m_url; QEventLoop *m_loop = nullptr; - SMBSlave *m_slave = nullptr; + SMBWorker *m_worker = nullptr; bool m_finished = false; int m_error = 0; bool m_dirWasRoot = true; diff --git a/smb/smbcontext.cpp b/smb/smbcontext.cpp index 277f4a446..aec644374 100644 --- a/smb/smbcontext.cpp +++ b/smb/smbcontext.cpp @@ -62,7 +62,7 @@ SMBContext::SMBContext(SMBAuthenticator *authenticator) // TODO: refactor; checkPassword should query this on // demand to not run into situations where we may have cached // the workgroup early on and it changed since. Needs context - // being held in the slave though, which opens us up to nullptr + // being held in the worker though, which opens us up to nullptr // problems should checkPassword be called without init first. authenticator->setDefaultWorkgroup(smbc_getWorkgroup(*this)); diff --git a/smb/smburl.cpp b/smb/smburl.cpp index 57cfb737c..a136f94dd 100644 --- a/smb/smburl.cpp +++ b/smb/smburl.cpp @@ -21,7 +21,7 @@ SMBUrl::SMBUrl(const QUrl &kurl) // https://bugs.kde.org/show_bug.cgi?id=327295 // It's not IANA registered and also libsmbc internally expects // smb URIs so we do very broadly coerce cifs to smb. - // Also see SMBSlave::checkURL. + // Also see SMBWorker::checkURL. if (scheme() == "cifs") { setScheme("smb"); } diff --git a/smb/smburl.h b/smb/smburl.h index c765ca174..d9f7061c6 100644 --- a/smb/smburl.h +++ b/smb/smburl.h @@ -1,10 +1,10 @@ ///////////////////////////////////////////////////////////////////////////// // -// Project: SMB kioslave for KDE2 +// Project: SMB kioworker for KDE2 // // File: smburl.h // -// Abstract: Utility classes used by SMBSlave +// Abstract: Utility classes used by SMBWorker // // Author(s): Matthew Peterson <mpeter...@caldera.com> // Frank Schwanz <schw...@fh-brandenburg.de> diff --git a/smb/transfer_resume.h b/smb/transfer_resume.h index 515baf080..9dade6c5c 100644 --- a/smb/transfer_resume.h +++ b/smb/transfer_resume.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL - SPDX-FileCopyrightText: 2021 Harald Sitter <sit...@kde.org> + SPDX-FileCopyrightText: 2021-2022 Harald Sitter <sit...@kde.org> */ #pragma once @@ -13,6 +13,7 @@ #include "kio_smb.h" + // Carries the context of a file transfer. struct TransferContext { // When resuming a file. This is false when starting a new .part! @@ -37,7 +38,7 @@ public: explicit SMBResumeIO(const SMBUrl &url) : m_url(url) // m_stat implicitly init'd by the stat for m_exists - , m_exists(SMBSlave::cache_stat(m_url, &m_stat) == 0) + , m_exists(SMBWorker::cache_stat(m_url, &m_stat) == 0) { } @@ -113,11 +114,11 @@ namespace Transfer // Check if we should resume the upload to destination. // This returns nullopt when an error has ocurred. The error() function is called internally. -// NB: WorkerInterface is intentionally duck-typed so we can unit test with a mock entity that looks like a SlaveBase but isn't one. +// NB: WorkerInterface is intentionally duck-typed so we can unit test with a mock entity that looks like a WorkerBase but isn't one. // Similarly ResumeIO is duck-typed so we can use QFileInfo as as base class in one implementation but not the other, // allowing us to cut down on boilerplate call-forwarding code. template<typename ResumeIO, typename WorkerInterface> -Q_REQUIRED_RESULT std::optional<TransferContext> shouldResume(const SMBUrl &destination, KIO::JobFlags flags, WorkerInterface *worker) +Q_REQUIRED_RESULT std::variant<TransferContext, WorkerResult> shouldResume(const SMBUrl &destination, KIO::JobFlags flags, WorkerInterface *worker) { // Resumption has two presentations: // a) partial resumption - when a .part file is left behind and we pick up where that part left off @@ -135,8 +136,7 @@ Q_REQUIRED_RESULT std::optional<TransferContext> shouldResume(const SMBUrl &dest // Not a resume operation -> if we also were not told to overwrite then we can't process this copy at all // because the ultimate destination already exists. if (!(flags & KIO::Overwrite)) { - worker->error(destIO.isDir() ? KIO::ERR_IS_DIRECTORY : KIO::ERR_FILE_ALREADY_EXIST, destination.toDisplayString()); - return std::nullopt; + return WorkerResult::fail(destIO.isDir() ? KIO::ERR_IS_DIRECTORY : KIO::ERR_FILE_ALREADY_EXIST, destination.toDisplayString()); } } @@ -159,31 +159,30 @@ Q_REQUIRED_RESULT std::optional<TransferContext> shouldResume(const SMBUrl &dest // the partial file may get discarded (depending on it existing and having an insufficient size). // The return value is true when an error has occurred. When isError was true this can only ever return true. template<typename ResumeIO, typename WorkerInterface> -Q_REQUIRED_RESULT bool concludeResumeHasError(bool isError, const TransferContext &resume, WorkerInterface *worker) +Q_REQUIRED_RESULT WorkerResult concludeResumeHasError(const WorkerResult &result, const TransferContext &resume, WorkerInterface *worker) { qDebug() << "concluding" << resume.destination << resume.partDestination << resume.completeDestination; if (resume.destination == resume.completeDestination) { - return isError; + return result; } // Handle error condition. - if (isError) { + if (!result.success()) { const off_t minimumSize = worker->configValue(QStringLiteral("MinimumKeepSize"), DEFAULT_MINIMUM_KEEP_SIZE); // TODO should this be partdestination? if (ResumeIO destIO(resume.destination); destIO.exists() && destIO.size() < minimumSize) { destIO.remove(); } - return true; + return result; } // Rename partial file to its original name. The ResumeIO takes care of potential removing of the destination. if (ResumeIO partIO(resume.partDestination); !partIO.renameTo(resume.completeDestination)) { - worker->error(ERR_CANNOT_RENAME_PARTIAL, resume.partDestination.toDisplayString()); - return true; + return WorkerResult::fail(ERR_CANNOT_RENAME_PARTIAL, resume.partDestination.toDisplayString()); } - return isError; + return result; } } // namespace Transfer