[network/kio-extras] /: smb: port to workerbase

Harald Sitter null at kde.org
Mon Jul 4 08:30:07 BST 2022


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 <sitter at kde.org>
+    SPDX-FileCopyrightText: 2018-2022 Harald Sitter <sitter at kde.org>
     SPDX-FileContributor: Matthew Peterson <mpeterson at 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 <sitter at kde.org>
+    SPDX-FileCopyrightText: 2021-2022 Harald Sitter <sitter at kde.org>
     SPDX-FileContributor: Matthew Peterson <mpeterson at 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 <sitter at kde.org>
+    SPDX-FileCopyrightText: 2020-2022 Harald Sitter <sitter at kde.org>
     SPDX-FileContributor: Matthew Peterson <mpeterson at 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 <mpeterson at caldera.com>
 //              Frank Schwanz <schwanz at 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 <sitter at kde.org>
+    SPDX-FileCopyrightText: 2021-2022 Harald Sitter <sitter at 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


More information about the kde-doc-english mailing list