diff --git a/autotests/jobtest.h b/autotests/jobtest.h --- a/autotests/jobtest.h +++ b/autotests/jobtest.h @@ -72,6 +72,7 @@ void moveDirectoryToOtherPartition(); void moveFileNoPermissions(); void moveDirectoryNoPermissions(); + void moveDirectoryToInaccessibleFilesystem(); void deleteFile(); void deleteDirectory(); void deleteSymlink(); diff --git a/autotests/jobtest.cpp b/autotests/jobtest.cpp --- a/autotests/jobtest.cpp +++ b/autotests/jobtest.cpp @@ -984,6 +984,30 @@ QVERIFY(QDir(subdir).removeRecursively()); } +void JobTest::moveDirectoryToInaccessibleFilesystem() +{ +#ifdef Q_OS_WIN + QSKIP("Skipping unaccessible folder test on Windows, cannot remove all permissions from a folder"); +#endif + const QString src_dir = homeTmpDir() + "srcHome"; + const QString dst_dir = homeTmpDir() + "mdnp"; + + createTestDirectory(src_dir); + QString inaccessible = dst_dir; + createTestDirectory(inaccessible); + + QFile(src_dir).setPermissions(QFile::Permissions(QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner)); + QFile(inaccessible).setPermissions(QFile::Permissions()); // Make it inaccessible, moving should throw some errors + + KIO::CopyJob *job = KIO::move(QUrl::fromLocalFile(src_dir), QUrl::fromLocalFile(dst_dir), KIO::HideProgressInfo); + + QSignalSpy spy(job, &KJob::error); + job->setUiDelegate(nullptr); + QVERIFY(!job->exec()); + QCOMPARE(job->error(), (int)KIO::ERR_CANNOT_WRITE); + QCOMPARE(spy.count(), 1); // one error should be emitted by the move job +} + void JobTest::listRecursive() { // Note: many other tests must have been run before since we rely on the files they created diff --git a/src/core/copyjob.cpp b/src/core/copyjob.cpp --- a/src/core/copyjob.cpp +++ b/src/core/copyjob.cpp @@ -848,7 +848,7 @@ } } - // if the file system doesn't support deleting, we do not even stat + // if the source file system doesn't support deleting, we do not even stat if (m_mode == CopyJob::Move && !KProtocolManager::supportsDeleting(m_currentSrcURL)) { QPointer that = q; emit q->warning(q, buildErrorString(ERR_CANNOT_DELETE, m_currentSrcURL.toDisplayString())); @@ -858,6 +858,17 @@ return; } + // if the destination file system doesn't support writing, do not stat + if (m_currentDestURL.isLocalFile()) { + QFileInfo destInfo(m_currentDestURL.toLocalFile()); + if (m_mode && (destInfo.isDir() && destInfo.isWritable())) { + q->setError(ERR_CANNOT_WRITE); + q->setErrorText(buildErrorString(ERR_CANNOT_DELETE, m_currentDestURL.toDisplayString())); + q->emitResult(); + return; + } + } + m_bOnlyRenames = false; // Testing for entry.count()>0 here is not good enough; KFileItem inserts