diff --git a/src/corelib/compat/removed_api.cpp b/src/corelib/compat/removed_api.cpp index 01a899418a2..033be09c368 100644 --- a/src/corelib/compat/removed_api.cpp +++ b/src/corelib/compat/removed_api.cpp @@ -1380,6 +1380,23 @@ QUuid::Version QUuid::version() const noexcept #if QT_CORE_REMOVED_SINCE(6, 10) +#include "qdir.h" + +bool QDir::mkdir(const QString &dirName) const +{ + return mkdir(dirName, std::nullopt); +} + +bool QDir::mkdir(const QString &dirName, QFile::Permissions permissions) const +{ + return mkdir(dirName, std::optional{permissions}); +} + +bool QDir::mkpath(const QString &dirPath) const +{ + return mkpath(dirPath, std::nullopt); +} + #if QT_CONFIG(future) #include "qfuture.h" // for ContinuationWrapper #include "qfutureinterface.h" diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp index 956236f95d5..4945d2b66ff 100644 --- a/src/corelib/io/qdir.cpp +++ b/src/corelib/io/qdir.cpp @@ -1495,8 +1495,13 @@ QFileInfoList QDir::entryInfoList(const QStringList &nameFilters, Filters filter /*! Creates a sub-directory called \a dirName with the given \a permissions. + If \a permissions is \c std::nullopt (the default) this function will + set the default permissions. + Returns \c true on success; returns \c false if the operation failed or - the directory already existed. + \a dirName already existed. + + If \a dirName already existed, this method won't change its permissions. //! [dir-creation-mode-bits-unix] On POSIX systems \a permissions are modified by the @@ -1505,18 +1510,24 @@ QFileInfoList QDir::entryInfoList(const QStringList &nameFilters, Filters filter bits might be disabled. //! [dir-creation-mode-bits-unix] +//! [windows-permissions-acls] On Windows, by default, a new directory inherits its permissions from its parent directory. \a permissions are emulated using ACLs. These ACLs may be in non-canonical order when the group is granted less permissions than others. Files and directories with such permissions will generate warnings when the Security tab of the Properties dialog is opened. Granting the group all permissions granted to others avoids such warnings. +//! [windows-permissions-acls] + + \note Qt 6.10 added the \a permissions parameter. To get the old behavior + (using the default platform-specific permissions) of \c{mkdir(const QString &)} + set \a permissions to \c std::nullopt (the default). This new method also + transparently replaces the \c {mkdir(const QString &, QFile::Permissions)} + overload. \sa rmdir(), mkpath(), rmpath() - - \since 6.3 */ -bool QDir::mkdir(const QString &dirName, QFile::Permissions permissions) const +bool QDir::mkdir(const QString &dirName, std::optional permissions) const { Q_D(const QDir); @@ -1531,40 +1542,6 @@ bool QDir::mkdir(const QString &dirName, QFile::Permissions permissions) const return d->fileEngine->mkdir(fn, false, permissions); } -/*! - \overload - Creates a sub-directory called \a dirName with the platform-specific - default permissions. - - Returns \c true on success; returns \c false if the operation failed or - the directory already existed. - -//! [windows-permissions-acls] - On Windows, by default, a new directory inherits its permissions from its - parent directory. Permissions are emulated using ACLs. These ACLs may be - in non-canonical order when the group is granted less permissions than - others. Files and directories with such permissions will generate warnings - when the Security tab of the Properties dialog is opened. Granting the - group all permissions granted to others avoids such warnings. -//! [windows-permissions-acls] - - \sa rmdir(), mkpath(), rmpath() -*/ -bool QDir::mkdir(const QString &dirName) const -{ - Q_D(const QDir); - - if (dirName.isEmpty()) { - qWarning("QDir::mkdir: Empty or null file name"); - return false; - } - - QString fn = filePath(dirName); - if (!d->fileEngine) - return QFileSystemEngine::mkdir(QFileSystemEntry(fn)); - return d->fileEngine->mkdir(fn, false); -} - /*! Removes the directory specified by \a dirName. @@ -1594,16 +1571,28 @@ bool QDir::rmdir(const QString &dirName) const Creates a directory named \a dirPath. If \a dirPath doesn't already exist, this method will create it - along with - any nonexistent parent directories - with the default permissions. + any nonexistent parent directories - with \a permissions. + + If \a dirPath already existed, this method won't change its permissions; + the same goes for any already existing parent directories. + + If \a permissions is \c std::nullopt (the default value) this function will + set the default permissions. Returns \c true on success or if \a dirPath already existed; otherwise returns \c false. + \include qdir.cpp dir-creation-mode-bits-unix + \include qdir.cpp windows-permissions-acls + \note Qt 6.10 added the \a permissions parameter. To get the old behavior + (using the default platform-specific permissions) of \c{mkpath(const QString &)} + set \a permissions to \c std::nullopt (the default). + \sa rmpath(), mkdir(), rmdir() */ -bool QDir::mkpath(const QString &dirPath) const +bool QDir::mkpath(const QString &dirPath, std::optional permissions) const { Q_D(const QDir); @@ -1614,8 +1603,8 @@ bool QDir::mkpath(const QString &dirPath) const QString fn = filePath(dirPath); if (!d->fileEngine) - return QFileSystemEngine::mkpath(QFileSystemEntry(fn)); - return d->fileEngine->mkdir(fn, true); + return QFileSystemEngine::mkpath(QFileSystemEntry(fn), permissions); + return d->fileEngine->mkdir(fn, true, permissions); } /*! diff --git a/src/corelib/io/qdir.h b/src/corelib/io/qdir.h index 2e44a7bffd1..e485700311e 100644 --- a/src/corelib/io/qdir.h +++ b/src/corelib/io/qdir.h @@ -169,10 +169,16 @@ public: QFileInfoList entryInfoList(const QStringList &nameFilters, Filters filters = NoFilter, SortFlags sort = NoSort) const; +#if QT_CORE_REMOVED_SINCE(6, 10) bool mkdir(const QString &dirName) const; bool mkdir(const QString &dirName, QFile::Permissions permissions) const; +#endif + bool mkdir(const QString &dirName, std::optional p = std::nullopt) const; bool rmdir(const QString &dirName) const; +#if QT_CORE_REMOVED_SINCE(6, 10) bool mkpath(const QString &dirPath) const; +#endif + bool mkpath(const QString &dirPath, std::optional p = std::nullopt) const; bool rmpath(const QString &dirPath) const; bool removeRecursively(); diff --git a/tests/auto/corelib/io/qdir/tst_qdir.cpp b/tests/auto/corelib/io/qdir/tst_qdir.cpp index 0e5b997eccb..bfe5b7082f9 100644 --- a/tests/auto/corelib/io/qdir/tst_qdir.cpp +++ b/tests/auto/corelib/io/qdir/tst_qdir.cpp @@ -92,7 +92,7 @@ private slots: void mkdirRmdir(); void mkdirOnSymlink(); void mkdirWithPermissions_data(); - void mkdirWithPermissions(); + void mkdirWithPermissions(); // QDir::{mkdir,mkpath}() void makedirReturnCode(); @@ -508,6 +508,7 @@ void tst_QDir::mkdirWithPermissions() QFile::ReadOwner, QFile::WriteOwner, QFile::ExeOwner }; + { const QString path = u"tmpdir"_s; QDir dir; auto deleteDirectory = qScopeGuard([&dir, &path] { dir.rmdir(path); }); @@ -517,6 +518,22 @@ void tst_QDir::mkdirWithPermissions() QCOMPARE(actualPermissions & setPermissions, permissions); QVERIFY(dir.rmdir(path)); deleteDirectory.dismiss(); + } + + { + // On Unix we need at least 'wx' permissions to be able to create "subdir" + if (permissions.testFlags(QFile::WriteOwner | QFile::ExeOwner)) { + const QString path = u"mkpath-tmpdir/subdir"_s; + QDir dir; + auto deleteDirectory = qScopeGuard([&dir, &path] { dir.rmpath(path); }); + + QVERIFY(dir.mkpath(path, permissions)); + auto actualPermissions = QFileInfo(path).permissions(); + QCOMPARE(actualPermissions & setPermissions, permissions); + QVERIFY(dir.rmpath(path)); + deleteDirectory.dismiss(); + } + } } void tst_QDir::makedirReturnCode()