diff --git a/autotests/jobtest.h b/autotests/jobtest.h --- a/autotests/jobtest.h +++ b/autotests/jobtest.h @@ -84,6 +84,9 @@ #endif void mostLocalUrl(); void chmodFile(); +#ifdef Q_OS_UNIX + void chmodSticky(); +#endif void chmodFileError(); void mimeType(); void mimeTypeError(); diff --git a/autotests/jobtest.cpp b/autotests/jobtest.cpp --- a/autotests/jobtest.cpp +++ b/autotests/jobtest.cpp @@ -1473,6 +1473,26 @@ QFile::remove(filePath); } +#ifdef Q_OS_UNIX +void JobTest::chmodSticky() +{ + const QString filePath = homeTmpDir() + "fileForChmodSticky"; + createTestFile(filePath); + KFileItem item(QUrl::fromLocalFile(filePath)); + const mode_t origPerm = item.permissions(); + mode_t newPerm = origPerm ^ S_ISVTX; + QVERIFY(newPerm != origPerm); + KFileItemList items({item}); + KIO::Job *job = KIO::chmod(items, newPerm, S_ISVTX, QString(), QString(), false, KIO::HideProgressInfo); + job->setUiDelegate(nullptr); + QVERIFY(job->exec()); + + KFileItem newItem(QUrl::fromLocalFile(filePath)); + QCOMPARE(QString::number(newItem.permissions(), 8), QString::number(newPerm, 8)); + QFile::remove(filePath); +} +#endif + void JobTest::chmodFileError() { // chown(root) should fail diff --git a/src/ioslaves/file/file.cpp b/src/ioslaves/file/file.cpp --- a/src/ioslaves/file/file.cpp +++ b/src/ioslaves/file/file.cpp @@ -225,7 +225,12 @@ const QString path(url.toLocalFile()); const QByteArray _path(QFile::encodeName(path)); /* FIXME: Should be atomic */ +#ifdef Q_OS_UNIX + // QFile::Permissions does not support special attributes like sticky + if (::chmod(QFile::encodeName(path).constData(), permissions) == -1 || +#else if (!QFile::setPermissions(path, modeToQFilePermissions(permissions)) || +#endif (setACL(_path.data(), permissions, false) == -1) || /* if not a directory, cannot set default ACLs */ (setACL(_path.data(), permissions, true) == -1 && errno != ENOTDIR)) {