From 56e13acf4eaaaff69156faa21d0a560fb93091d5 Mon Sep 17 00:00:00 2001 From: Ievgenii Meshcheriakov Date: Fri, 22 Oct 2021 13:39:52 +0200 Subject: QAbstractFileEngine: Add permission argument to open() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The new argument allows atomic creation of files with non-default permissions. Task-number: QTBUG-79750 Change-Id: I4c49455b41f924ba87148302c8d0f77f5de0832b Reviewed-by: MÃ¥rten Nordheim --- src/corelib/io/qabstractfileengine.cpp | 8 +++++++- src/corelib/io/qabstractfileengine_p.h | 3 ++- src/corelib/io/qfsfileengine.cpp | 5 +++-- src/corelib/io/qfsfileengine_p.h | 12 ++++++++++-- src/corelib/io/qfsfileengine_unix.cpp | 14 ++++++++++++-- src/corelib/io/qfsfileengine_win.cpp | 11 ++++++++--- src/corelib/io/qresource.cpp | 5 ++++- src/corelib/io/qresource_p.h | 2 +- src/corelib/io/qtemporaryfile.cpp | 5 +++-- src/corelib/io/qtemporaryfile_p.h | 2 +- src/plugins/platforms/android/androidcontentfileengine.cpp | 4 +++- src/plugins/platforms/android/androidcontentfileengine.h | 2 +- .../platforms/android/qandroidassetsfileenginehandler.cpp | 6 ++++-- .../nsphotolibrarysupport/qiosfileengineassetslibrary.h | 2 +- .../nsphotolibrarysupport/qiosfileengineassetslibrary.mm | 5 ++++- .../io/qabstractfileengine/tst_qabstractfileengine.cpp | 4 +++- tests/benchmarks/corelib/io/qfile/tst_bench_qfile.cpp | 8 ++++---- 17 files changed, 71 insertions(+), 27 deletions(-) diff --git a/src/corelib/io/qabstractfileengine.cpp b/src/corelib/io/qabstractfileengine.cpp index 063cee1071..d6b2b6a10e 100644 --- a/src/corelib/io/qabstractfileengine.cpp +++ b/src/corelib/io/qabstractfileengine.cpp @@ -383,10 +383,16 @@ QAbstractFileEngine::~QAbstractFileEngine() The \a mode is an OR combination of QIODevice::OpenMode and QIODevice::HandlingMode values. + + If the file is created as a result of this call, its permissions are + set according to \a permissision. Null value means an implementation- + specific default. */ -bool QAbstractFileEngine::open(QIODevice::OpenMode openMode) +bool QAbstractFileEngine::open(QIODevice::OpenMode openMode, + std::optional permissions) { Q_UNUSED(openMode); + Q_UNUSED(permissions); return false; } diff --git a/src/corelib/io/qabstractfileengine_p.h b/src/corelib/io/qabstractfileengine_p.h index d8ea5c318f..9649e67029 100644 --- a/src/corelib/io/qabstractfileengine_p.h +++ b/src/corelib/io/qabstractfileengine_p.h @@ -124,7 +124,8 @@ public: virtual ~QAbstractFileEngine(); - virtual bool open(QIODevice::OpenMode openMode); + virtual bool open(QIODevice::OpenMode openMode, + std::optional permissions = std::nullopt); virtual bool close(); virtual bool flush(); virtual bool syncToDisk(); diff --git a/src/corelib/io/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp index 6cd25de591..4ba35abacb 100644 --- a/src/corelib/io/qfsfileengine.cpp +++ b/src/corelib/io/qfsfileengine.cpp @@ -226,7 +226,8 @@ void QFSFileEngine::setFileName(const QString &file) /*! \reimp */ -bool QFSFileEngine::open(QIODevice::OpenMode openMode) +bool QFSFileEngine::open(QIODevice::OpenMode openMode, + std::optional permissions) { Q_ASSERT_X(openMode & QIODevice::Unbuffered, "QFSFileEngine::open", "QFSFileEngine no longer supports buffered mode; upper layer must buffer"); @@ -250,7 +251,7 @@ bool QFSFileEngine::open(QIODevice::OpenMode openMode) d->fh = nullptr; d->fd = -1; - return d->nativeOpen(d->openMode); + return d->nativeOpen(d->openMode, permissions); } /*! diff --git a/src/corelib/io/qfsfileengine_p.h b/src/corelib/io/qfsfileengine_p.h index 6cfa6ebbab..4ebba61bb6 100644 --- a/src/corelib/io/qfsfileengine_p.h +++ b/src/corelib/io/qfsfileengine_p.h @@ -59,6 +59,10 @@ #include +#ifdef Q_OS_UNIX +#include // for mode_t +#endif + #ifndef QT_NO_FSFILEENGINE QT_BEGIN_NAMESPACE @@ -81,7 +85,7 @@ public: explicit QFSFileEngine(const QString &file); ~QFSFileEngine(); - bool open(QIODevice::OpenMode openMode) override; + bool open(QIODevice::OpenMode openMode, std::optional permissions) override; bool open(QIODevice::OpenMode flags, FILE *fh); bool close() override; bool flush() override; @@ -156,7 +160,7 @@ public: QFileSystemEntry fileEntry; QIODevice::OpenMode openMode; - bool nativeOpen(QIODevice::OpenMode openMode); + bool nativeOpen(QIODevice::OpenMode openMode, std::optional permissions); bool openFh(QIODevice::OpenMode flags, FILE *fh); bool openFd(QIODevice::OpenMode flags, int fd); bool nativeClose(); @@ -246,6 +250,10 @@ protected: void init(); QAbstractFileEngine::FileFlags getPermissions(QAbstractFileEngine::FileFlags type) const; + +#ifdef Q_OS_UNIX + bool nativeOpenImpl(QIODevice::OpenMode openMode, mode_t mode); +#endif }; QT_END_NAMESPACE diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index 5815d6bc9c..d071c85cb3 100644 --- a/src/corelib/io/qfsfileengine_unix.cpp +++ b/src/corelib/io/qfsfileengine_unix.cpp @@ -39,6 +39,7 @@ #include "qplatformdefs.h" #include "private/qabstractfileengine_p.h" +#include "private/qfiledevice_p.h" #include "private/qfsfileengine_p.h" #include "private/qcore_unix_p.h" #include "qfilesystementry_p.h" @@ -107,7 +108,16 @@ static inline QString msgOpenDirectory() /*! \internal */ -bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode) +bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode, + std::optional permissions) +{ + return nativeOpenImpl(openMode, permissions ? QtPrivate::toMode_t(*permissions) : 0666); +} + +/*! + \internal +*/ +bool QFSFileEnginePrivate::nativeOpenImpl(QIODevice::OpenMode openMode, mode_t mode) { Q_Q(QFSFileEngine); @@ -118,7 +128,7 @@ bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode) // Try to open the file in unbuffered mode. do { - fd = QT_OPEN(fileEntry.nativeFilePath().constData(), flags, 0666); + fd = QT_OPEN(fileEntry.nativeFilePath().constData(), flags, mode); } while (fd == -1 && errno == EINTR); // On failure, return and report the error. diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp index 394b4ab69e..60e25d34f1 100644 --- a/src/corelib/io/qfsfileengine_win.cpp +++ b/src/corelib/io/qfsfileengine_win.cpp @@ -39,6 +39,7 @@ #include "qplatformdefs.h" #include "private/qabstractfileengine_p.h" +#include "private/qfiledevice_p.h" #include "private/qfsfileengine_p.h" #include "qfilesystemengine_p.h" #include @@ -95,7 +96,8 @@ QString QFSFileEnginePrivate::longFileName(const QString &path) /* \internal */ -bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode) +bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode, + std::optional permissions) { Q_Q(QFSFileEngine); @@ -115,11 +117,14 @@ bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode) ? OPEN_ALWAYS : OPEN_EXISTING; // Create the file handle. - SECURITY_ATTRIBUTES securityAtts = { sizeof(SECURITY_ATTRIBUTES), NULL, FALSE }; + QNativeFilePermissions nativePermissions(permissions, false); + if (!nativePermissions.isOk()) + return false; + fileHandle = CreateFile((const wchar_t*)fileEntry.nativeFilePath().utf16(), accessRights, shareMode, - &securityAtts, + nativePermissions.securityAttributes(), creationDisp, FILE_ATTRIBUTE_NORMAL, NULL); diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp index 8f0440ef2e..af0b9429af 100644 --- a/src/corelib/io/qresource.cpp +++ b/src/corelib/io/qresource.cpp @@ -1409,8 +1409,11 @@ void QResourceFileEngine::setFileName(const QString &file) d->resource.setFileName(file); } -bool QResourceFileEngine::open(QIODevice::OpenMode flags) +bool QResourceFileEngine::open(QIODevice::OpenMode flags, + std::optional permissions) { + Q_UNUSED(permissions); + Q_D(QResourceFileEngine); if (d->resource.fileName().isEmpty()) { qWarning("QResourceFileEngine::open: Missing file name"); diff --git a/src/corelib/io/qresource_p.h b/src/corelib/io/qresource_p.h index 31753b9a4f..19db6b24cd 100644 --- a/src/corelib/io/qresource_p.h +++ b/src/corelib/io/qresource_p.h @@ -66,7 +66,7 @@ public: void setFileName(const QString &file) override; - bool open(QIODevice::OpenMode flags) override; + bool open(QIODevice::OpenMode flags, std::optional permissions) override; bool close() override; bool flush() override; qint64 size() const override; diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp index 5ccb959288..4b587857a8 100644 --- a/src/corelib/io/qtemporaryfile.cpp +++ b/src/corelib/io/qtemporaryfile.cpp @@ -340,7 +340,8 @@ void QTemporaryFileEngine::setFileName(const QString &file) QFSFileEngine::setFileName(file); } -bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode) +bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode, + std::optional permissions) { Q_D(QFSFileEngine); Q_ASSERT(!isReallyOpen()); @@ -348,7 +349,7 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode) openMode |= QIODevice::ReadWrite; if (!filePathIsTemplate) - return QFSFileEngine::open(openMode); + return QFSFileEngine::open(openMode, permissions); QTemporaryFileName tfn(templateName); diff --git a/src/corelib/io/qtemporaryfile_p.h b/src/corelib/io/qtemporaryfile_p.h index 6bcff936b4..ac9c239d21 100644 --- a/src/corelib/io/qtemporaryfile_p.h +++ b/src/corelib/io/qtemporaryfile_p.h @@ -133,7 +133,7 @@ public: bool isReallyOpen() const; void setFileName(const QString &file) override; - bool open(QIODevice::OpenMode flags) override; + bool open(QIODevice::OpenMode flags, std::optional permissions) override; bool remove() override; bool rename(const QString &newName) override; bool renameOverwrite(const QString &newName) override; diff --git a/src/plugins/platforms/android/androidcontentfileengine.cpp b/src/plugins/platforms/android/androidcontentfileengine.cpp index 2c47b71c88..b18c81e896 100644 --- a/src/plugins/platforms/android/androidcontentfileengine.cpp +++ b/src/plugins/platforms/android/androidcontentfileengine.cpp @@ -54,8 +54,10 @@ AndroidContentFileEngine::AndroidContentFileEngine(const QString &f) setFileName(f); } -bool AndroidContentFileEngine::open(QIODevice::OpenMode openMode) +bool AndroidContentFileEngine::open(QIODevice::OpenMode openMode, + std::optional permissions) { + Q_UNUSED(permissions); QString openModeStr; if (openMode & QFileDevice::ReadOnly) { openModeStr += QLatin1Char('r'); diff --git a/src/plugins/platforms/android/androidcontentfileengine.h b/src/plugins/platforms/android/androidcontentfileengine.h index 31eaf9b0ab..531d0f80ff 100644 --- a/src/plugins/platforms/android/androidcontentfileengine.h +++ b/src/plugins/platforms/android/androidcontentfileengine.h @@ -46,7 +46,7 @@ class AndroidContentFileEngine : public QFSFileEngine { public: AndroidContentFileEngine(const QString &fileName); - bool open(QIODevice::OpenMode openMode) override; + bool open(QIODevice::OpenMode openMode, std::optional permissions) override; qint64 size() const override; FileFlags fileFlags(FileFlags type = FileInfoAll) const override; QString fileName(FileName file = DefaultName) const override; diff --git a/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp b/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp index 7326889222..0c6fb92ffb 100644 --- a/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp +++ b/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp @@ -261,8 +261,10 @@ public: close(); } - bool open(QIODevice::OpenMode openMode) override + bool open(QIODevice::OpenMode openMode, std::optional permissions) override { + Q_UNUSED(permissions); + if (m_isFolder || (openMode & QIODevice::WriteOnly)) return false; close(); @@ -358,7 +360,7 @@ public: m_fileName = cleanedAssetPath(file); switch (FolderIterator::fileType(m_fileName)) { case AssetItem::Type::File: - open(QIODevice::ReadOnly); + open(QIODevice::ReadOnly, std::nullopt); break; case AssetItem::Type::Folder: m_isFolder = true; diff --git a/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileengineassetslibrary.h b/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileengineassetslibrary.h index c3283436a6..3bb9fab1fc 100644 --- a/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileengineassetslibrary.h +++ b/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileengineassetslibrary.h @@ -54,7 +54,7 @@ public: QIOSFileEngineAssetsLibrary(const QString &fileName); ~QIOSFileEngineAssetsLibrary(); - bool open(QIODevice::OpenMode openMode) override; + bool open(QIODevice::OpenMode openMode, std::optional permissions) override; bool close() override; FileFlags fileFlags(FileFlags type) const override; qint64 size() const override; diff --git a/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileengineassetslibrary.mm b/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileengineassetslibrary.mm index e2f35dc1bf..9cb38a3461 100644 --- a/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileengineassetslibrary.mm +++ b/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileengineassetslibrary.mm @@ -353,8 +353,11 @@ ALAsset *QIOSFileEngineAssetsLibrary::loadAsset() const return m_data->m_asset; } -bool QIOSFileEngineAssetsLibrary::open(QIODevice::OpenMode openMode) +bool QIOSFileEngineAssetsLibrary::open(QIODevice::OpenMode openMode, + std::optional permissions) { + Q_UNUSED(permissions); + if (openMode & (QIODevice::WriteOnly | QIODevice::Text)) return false; return loadAsset(); diff --git a/tests/auto/corelib/io/qabstractfileengine/tst_qabstractfileengine.cpp b/tests/auto/corelib/io/qabstractfileengine/tst_qabstractfileengine.cpp index fc55208bbb..edb5ec05a5 100644 --- a/tests/auto/corelib/io/qabstractfileengine/tst_qabstractfileengine.cpp +++ b/tests/auto/corelib/io/qabstractfileengine/tst_qabstractfileengine.cpp @@ -76,8 +76,10 @@ public: { } - bool open(QIODevice::OpenMode openMode) override + bool open(QIODevice::OpenMode openMode, std::optional permissions) override { + Q_UNUSED(permissions); + if (openForRead_ || openForWrite_) { qWarning("%s: file is already open for %s", Q_FUNC_INFO, diff --git a/tests/benchmarks/corelib/io/qfile/tst_bench_qfile.cpp b/tests/benchmarks/corelib/io/qfile/tst_bench_qfile.cpp index cbe0bf81c9..015c49ed04 100644 --- a/tests/benchmarks/corelib/io/qfile/tst_bench_qfile.cpp +++ b/tests/benchmarks/corelib/io/qfile/tst_bench_qfile.cpp @@ -263,7 +263,7 @@ void tst_qfile::readBigFile() #ifdef QT_BUILD_INTERNAL case QFSFileEngineBenchmark: { QFSFileEngine fse(tempDir.filename); - fse.open(QIODevice::ReadOnly|textMode|bufferedMode); + fse.open(QIODevice::ReadOnly | textMode | bufferedMode, std::nullopt); QBENCHMARK { //qWarning() << fse.supportsExtension(QAbstractFileEngine::AtEndExtension); while (fse.read(buffer, blockSize)) {} @@ -349,7 +349,7 @@ void tst_qfile::seek() #ifdef QT_BUILD_INTERNAL case QFSFileEngineBenchmark: { QFSFileEngine fse(tempDir.filename); - fse.open(QIODevice::ReadOnly | QIODevice::Unbuffered); + fse.open(QIODevice::ReadOnly | QIODevice::Unbuffered, std::nullopt); QBENCHMARK { i=(i+1)%sp_size; fse.seek(seekpos[i]); @@ -426,7 +426,7 @@ void tst_qfile::open() case QFSFileEngineBenchmark: { QBENCHMARK { QFSFileEngine fse(tempDir.filename); - fse.open(QIODevice::ReadOnly | QIODevice::Unbuffered); + fse.open(QIODevice::ReadOnly | QIODevice::Unbuffered, std::nullopt); fse.close(); } } @@ -550,7 +550,7 @@ void tst_qfile::readSmallFiles() QList fileList; for (const QString &file : files) { QFSFileEngine *fse = new QFSFileEngine(tempDir.filePath(file)); - fse->open(QIODevice::ReadOnly|textMode|bufferedMode); + fse->open(QIODevice::ReadOnly | textMode | bufferedMode, std::nullopt); fileList.append(fse); } -- cgit v1.2.3