Upstream: no Reason: qmake fails when installing under sydbox From bb93dd016f2174339ae511608e998a1ceb3cab52 Mon Sep 17 00:00:00 2001 From: Heiko Becker Date: Fri, 16 Feb 2018 15:22:27 +0100 Subject: [PATCH 1/2] Revert "QTemporaryFile: hide the O_TMPFILE feature behind a check for linkat()" This reverts commit 490b24b06408e90e9684d8331fd3fe8b0c51b0b5. --- src/corelib/configure.json | 15 --------------- src/corelib/global/minimum-linux_p.h | 2 +- src/corelib/global/qconfig-bootstrapped.h | 5 ----- src/corelib/io/qtemporaryfile_p.h | 2 +- 4 files changed, 2 insertions(+), 22 deletions(-) diff --git a/src/corelib/configure.json b/src/corelib/configure.json index 8cd73d6ce4..fdb0fca66e 100644 --- a/src/corelib/configure.json +++ b/src/corelib/configure.json @@ -349,15 +349,6 @@ "qmake": "linux: LIBS += -lpthread -lrt" } }, - "linkat": { - "label": "linkat()", - "type": "compile", - "test": { - "head": "#define _ATFILE_SOURCE 1", - "include": [ "fcntl.h", "unistd.h" ], - "main": "linkat(AT_FDCWD, \"foo\", AT_FDCWD, \"bar\", AT_SYMLINK_FOLLOW);" - } - }, "ppoll": { "label": "ppoll()", "type": "compile", @@ -549,12 +540,6 @@ "condition": "libs.journald", "output": [ "privateFeature" ] }, - "linkat": { - "label": "linkat()", - "autoDetect": "config.linux", - "condition": "tests.linkat", - "output": [ "privateFeature" ] - }, "std-atomic64": { "label": "64 bit atomic operations", "condition": "libs.libatomic", diff --git a/src/corelib/global/minimum-linux_p.h b/src/corelib/global/minimum-linux_p.h index bad2488b4d..324744b856 100644 --- a/src/corelib/global/minimum-linux_p.h +++ b/src/corelib/global/minimum-linux_p.h @@ -67,7 +67,7 @@ QT_BEGIN_NAMESPACE * - inotify_init1 before 2.6.12-rc12 * - futex(2) before 2.6.12-rc12 * - FUTEX_WAKE_OP 2.6.14 FUTEX_OP - * - linkat(2) 2.6.17 O_TMPFILE && QT_CONFIG(linkat) + * - linkat(2) 2.6.17 O_TMPFILE * - FUTEX_PRIVATE_FLAG 2.6.22 * - O_CLOEXEC 2.6.23 * - eventfd 2.6.23 diff --git a/src/corelib/global/qconfig-bootstrapped.h b/src/corelib/global/qconfig-bootstrapped.h index dabb715607..2164d7f21f 100644 --- a/src/corelib/global/qconfig-bootstrapped.h +++ b/src/corelib/global/qconfig-bootstrapped.h @@ -87,11 +87,6 @@ #define QT_FEATURE_futimens -1 #define QT_FEATURE_futimes -1 #define QT_FEATURE_library -1 -#ifdef __linux__ -# define QT_FEATURE_linkat 1 -#else -# define QT_FEATURE_linkat -1 -#endif #define QT_NO_QOBJECT #define QT_FEATURE_process -1 #define QT_FEATURE_renameat2 -1 diff --git a/src/corelib/io/qtemporaryfile_p.h b/src/corelib/io/qtemporaryfile_p.h index fb8887af53..6f98ceed90 100644 --- a/src/corelib/io/qtemporaryfile_p.h +++ b/src/corelib/io/qtemporaryfile_p.h @@ -58,7 +58,7 @@ #include "private/qfile_p.h" #include "qtemporaryfile.h" -#if defined(Q_OS_LINUX) && QT_CONFIG(linkat) +#ifdef Q_OS_LINUX # include # ifdef O_TMPFILE // some early libc support had the wrong values for O_TMPFILE -- 2.16.1 From 93a451315dee5dd7cc482af7263681342beb72bc Mon Sep 17 00:00:00 2001 From: Heiko Becker Date: Fri, 16 Feb 2018 15:29:14 +0100 Subject: [PATCH 2/2] Revert "QTemporaryFile: Add support for Linux's O_TMPFILE" This reverts commit 189e9c93d7ed42202ad51507c8944d64e9a7888d. Change-Id: I5e8e17c66320f0e58a47f0cf35d0f59e0c7d40d2 --- src/corelib/io/qfile.cpp | 8 +- src/corelib/io/qtemporaryfile.cpp | 192 ++------------------- src/corelib/io/qtemporaryfile_p.h | 18 -- .../io/qtemporaryfile/tst_qtemporaryfile.cpp | 81 +-------- .../qnetworkdiskcache/tst_qnetworkdiskcache.cpp | 1 - 5 files changed, 20 insertions(+), 280 deletions(-) diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp index e4888e9523..36b2467253 100644 --- a/src/corelib/io/qfile.cpp +++ b/src/corelib/io/qfile.cpp @@ -557,9 +557,7 @@ bool QFile::rename(const QString &newName) { Q_D(QFile); - - // if this is a QTemporaryFile, the virtual fileName() call here may do something - if (fileName().isEmpty()) { + if (d->fileName.isEmpty()) { qWarning("QFile::rename: Empty or null file name"); return false; } @@ -720,7 +718,7 @@ bool QFile::link(const QString &linkName) { Q_D(QFile); - if (fileName().isEmpty()) { + if (d->fileName.isEmpty()) { qWarning("QFile::link: Empty or null file name"); return false; } @@ -766,7 +764,7 @@ bool QFile::copy(const QString &newName) { Q_D(QFile); - if (fileName().isEmpty()) { + if (d->fileName.isEmpty()) { qWarning("QFile::copy: Empty or null file name"); return false; } diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp index 35699d52df..1b4dcd4ff1 100644 --- a/src/corelib/io/qtemporaryfile.cpp +++ b/src/corelib/io/qtemporaryfile.cpp @@ -1,7 +1,6 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2017 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -265,53 +264,6 @@ static bool createFileFromTemplate(NativeFileHandle &file, QTemporaryFileName &t return false; } -enum class CreateUnnamedFileStatus { - Success = 0, - NotSupported, - OtherError -}; - -static CreateUnnamedFileStatus -createUnnamedFile(NativeFileHandle &file, QTemporaryFileName &tfn, quint32 mode, QSystemError *error) -{ -#ifdef LINUX_UNNAMED_TMPFILE - // first, check if we have /proc, otherwise can't make the file exist later - // (no error message set, as caller will try regular temporary file) - if (!qt_haveLinuxProcfs()) - return CreateUnnamedFileStatus::NotSupported; - - const char *p = "."; - int lastSlash = tfn.path.lastIndexOf('/'); - if (lastSlash != -1) { - tfn.path[lastSlash] = '\0'; - p = tfn.path.data(); - } - - file = QT_OPEN(p, O_TMPFILE | QT_OPEN_RDWR | QT_OPEN_LARGEFILE, - static_cast(mode)); - if (file != -1) - return CreateUnnamedFileStatus::Success; - - if (errno == EOPNOTSUPP || errno == EISDIR) { - // fs or kernel doesn't support O_TMPFILE, so - // put the slash back so we may try a regular file - if (lastSlash != -1) - tfn.path[lastSlash] = '/'; - return CreateUnnamedFileStatus::NotSupported; - } - - // real error - *error = QSystemError(errno, QSystemError::NativeError); - return CreateUnnamedFileStatus::OtherError; -#else - Q_UNUSED(file); - Q_UNUSED(tfn); - Q_UNUSED(mode); - Q_UNUSED(error); - return CreateUnnamedFileStatus::NotSupported; -#endif -} - //************* QTemporaryFileEngine QTemporaryFileEngine::~QTemporaryFileEngine() { @@ -361,24 +313,19 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode) NativeFileHandle &file = d->fd; #endif - CreateUnnamedFileStatus st = createUnnamedFile(file, tfn, fileMode, &error); - if (st == CreateUnnamedFileStatus::Success) { - unnamedFile = true; - d->fileEntry.clear(); - } else if (st == CreateUnnamedFileStatus::NotSupported && - createFileFromTemplate(file, tfn, fileMode, error)) { - filePathIsTemplate = false; - unnamedFile = false; - d->fileEntry = QFileSystemEntry(tfn.path, QFileSystemEntry::FromNativePath()); - } else { + if (!createFileFromTemplate(file, tfn, fileMode, error)) { setError(QFile::OpenError, error.toString()); return false; } + d->fileEntry = QFileSystemEntry(tfn.path, QFileSystemEntry::FromNativePath()); + #if !defined(Q_OS_WIN) || defined(Q_OS_WINRT) d->closeFileHandle = true; #endif + filePathIsTemplate = false; + d->openMode = openMode; d->lastFlushFailed = false; d->tried_stat = 0; @@ -393,9 +340,7 @@ bool QTemporaryFileEngine::remove() // we must explicitly call QFSFileEngine::close() before we remove it. d->unmapAll(); QFSFileEngine::close(); - if (isUnnamedFile()) - return true; - if (!filePathIsTemplate && QFSFileEngine::remove()) { + if (QFSFileEngine::remove()) { d->fileEntry.clear(); // If a QTemporaryFile is constructed using a template file path, the path // is generated in QTemporaryFileEngine::open() and then filePathIsTemplate @@ -410,22 +355,12 @@ bool QTemporaryFileEngine::remove() bool QTemporaryFileEngine::rename(const QString &newName) { - if (isUnnamedFile()) { - bool ok = materializeUnnamedFile(newName, DontOverwrite); - QFSFileEngine::close(); - return ok; - } QFSFileEngine::close(); return QFSFileEngine::rename(newName); } bool QTemporaryFileEngine::renameOverwrite(const QString &newName) { - if (isUnnamedFile()) { - bool ok = materializeUnnamedFile(newName, Overwrite); - QFSFileEngine::close(); - return ok; - } QFSFileEngine::close(); return QFSFileEngine::renameOverwrite(newName); } @@ -438,91 +373,6 @@ bool QTemporaryFileEngine::close() return true; } -QString QTemporaryFileEngine::fileName(QAbstractFileEngine::FileName file) const -{ - if (isUnnamedFile()) { - if (file == LinkName) { - // we know our file isn't (won't be) a symlink - return QString(); - } - - // for all other cases, materialize the file - const_cast(this)->materializeUnnamedFile(templateName, NameIsTemplate); - } - return QFSFileEngine::fileName(file); -} - -bool QTemporaryFileEngine::materializeUnnamedFile(const QString &newName, QTemporaryFileEngine::MaterializationMode mode) -{ - Q_ASSERT(isUnnamedFile()); - -#ifdef LINUX_UNNAMED_TMPFILE - Q_D(QFSFileEngine); - const QByteArray src = "/proc/self/fd/" + QByteArray::number(d->fd); - auto materializeAt = [=](const QFileSystemEntry &dst) { - return ::linkat(AT_FDCWD, src, AT_FDCWD, dst.nativeFilePath(), AT_SYMLINK_FOLLOW) == 0; - }; -#else - auto materializeAt = [](const QFileSystemEntry &) { return false; }; -#endif - - auto success = [this](const QFileSystemEntry &entry) { - filePathIsTemplate = false; - unnamedFile = false; - d_func()->fileEntry = entry; - return true; - }; - - auto materializeAsTemplate = [=](const QString &newName) { - QTemporaryFileName tfn(newName); - static const int maxAttempts = 16; - for (int attempt = 0; attempt < maxAttempts; ++attempt) { - tfn.generateNext(); - QFileSystemEntry entry(tfn.path, QFileSystemEntry::FromNativePath()); - if (materializeAt(entry)) - return success(entry); - } - return false; - }; - - if (mode == NameIsTemplate) { - if (materializeAsTemplate(newName)) - return true; - } else { - // Use linkat to materialize the file - QFileSystemEntry dst(newName); - if (materializeAt(dst)) - return success(dst); - - if (errno == EEXIST && mode == Overwrite) { - // retry by first creating a temporary file in the right dir - if (!materializeAsTemplate(templateName)) - return false; - - // then rename the materialized file to target (same as renameOverwrite) - QFSFileEngine::close(); - return QFSFileEngine::renameOverwrite(newName); - } - } - - // failed - setError(QFile::RenameError, QSystemError(errno, QSystemError::NativeError).toString()); - return false; -} - -bool QTemporaryFileEngine::isUnnamedFile() const -{ -#ifdef LINUX_UNNAMED_TMPFILE - if (unnamedFile) { - Q_ASSERT(d_func()->fileEntry.isEmpty()); - Q_ASSERT(filePathIsTemplate); - } - return unnamedFile; -#else - return false; -#endif -} - //************* QTemporaryFilePrivate QTemporaryFilePrivate::QTemporaryFilePrivate() @@ -559,17 +409,6 @@ void QTemporaryFilePrivate::resetFileEngine() const tef->initialize(fileName, 0600, false); } -void QTemporaryFilePrivate::materializeUnnamedFile() -{ -#ifdef LINUX_UNNAMED_TMPFILE - if (!fileName.isEmpty() || !fileEngine) - return; - - auto *tef = static_cast(fileEngine); - fileName = tef->fileName(QAbstractFileEngine::DefaultName); -#endif -} - QString QTemporaryFilePrivate::defaultTemplateName() { QString baseName; @@ -789,10 +628,6 @@ void QTemporaryFile::setAutoRemove(bool b) QString QTemporaryFile::fileName() const { Q_D(const QTemporaryFile); - auto tef = static_cast(d->fileEngine); - if (tef && tef->isReallyOpen()) - const_cast(d)->materializeUnnamedFile(); - if(d->fileName.isEmpty()) return QString(); return d->engine()->fileName(QAbstractFileEngine::DefaultName); @@ -946,10 +781,11 @@ QTemporaryFile *QTemporaryFile::createNativeFile(QFile &file) bool QTemporaryFile::open(OpenMode flags) { Q_D(QTemporaryFile); - auto tef = static_cast(d->fileEngine); - if (tef && tef->isReallyOpen()) { - setOpenMode(flags); - return true; + if (!d->fileName.isEmpty()) { + if (static_cast(d->engine())->isReallyOpen()) { + setOpenMode(flags); + return true; + } } // reset the engine state so it creates a new, unique file name from the template; @@ -960,11 +796,7 @@ bool QTemporaryFile::open(OpenMode flags) d->resetFileEngine(); if (QFile::open(flags)) { - tef = static_cast(d->fileEngine); - if (tef->isUnnamedFile()) - d->fileName.clear(); - else - d->fileName = tef->fileName(QAbstractFileEngine::DefaultName); + d->fileName = d->fileEngine->fileName(QAbstractFileEngine::DefaultName); return true; } return false; diff --git a/src/corelib/io/qtemporaryfile_p.h b/src/corelib/io/qtemporaryfile_p.h index 6f98ceed90..4aa8ca876f 100644 --- a/src/corelib/io/qtemporaryfile_p.h +++ b/src/corelib/io/qtemporaryfile_p.h @@ -58,17 +58,6 @@ #include "private/qfile_p.h" #include "qtemporaryfile.h" -#ifdef Q_OS_LINUX -# include -# ifdef O_TMPFILE -// some early libc support had the wrong values for O_TMPFILE -// (see https://bugzilla.gnome.org/show_bug.cgi?id=769453#c18) -# if (O_TMPFILE & O_DIRECTORY) == O_DIRECTORY -# define LINUX_UNNAMED_TMPFILE -# endif -# endif -#endif - QT_BEGIN_NAMESPACE struct QTemporaryFileName @@ -94,7 +83,6 @@ public: QAbstractFileEngine *engine() const override; void resetFileEngine() const; - void materializeUnnamedFile(); bool autoRemove = true; QString templateName = defaultTemplateName(); @@ -136,17 +124,11 @@ public: bool rename(const QString &newName) override; bool renameOverwrite(const QString &newName) override; bool close() override; - QString fileName(FileName file) const override; - - enum MaterializationMode { Overwrite, DontOverwrite, NameIsTemplate }; - bool materializeUnnamedFile(const QString &newName, MaterializationMode mode); - bool isUnnamedFile() const override final; const QString &templateName; quint32 fileMode; bool filePathIsTemplate; bool filePathWasTemplate; - bool unnamedFile = false; }; #endif // QT_NO_TEMPORARYFILE diff --git a/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp b/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp index dbc3d68e93..186bf5155d 100644 --- a/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp +++ b/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp @@ -1,7 +1,6 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2017 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. @@ -33,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -67,7 +65,7 @@ private slots: void fileNameIsEmpty(); void autoRemove(); void nonWritableCurrentDir(); - void io(); + void write(); void openCloseOpenClose(); void removeAndReOpen(); void removeUnnamed(); @@ -281,18 +279,6 @@ void tst_QTemporaryFile::autoRemove() fileName = file.fileName(); file.close(); } - QVERIFY(!fileName.isEmpty()); - QVERIFY(!QFile::exists(fileName)); - - // same, but gets the file name after closing - { - QTemporaryFile file("tempXXXXXX"); - file.setAutoRemove(true); - QVERIFY(file.open()); - file.close(); - fileName = file.fileName(); - } - QVERIFY(!fileName.isEmpty()); QVERIFY(!QFile::exists(fileName)); // Test if disabling auto remove works. @@ -303,19 +289,6 @@ void tst_QTemporaryFile::autoRemove() fileName = file.fileName(); file.close(); } - QVERIFY(!fileName.isEmpty()); - QVERIFY(QFile::exists(fileName)); - QVERIFY(QFile::remove(fileName)); - - // same, but gets the file name after closing - { - QTemporaryFile file("tempXXXXXX"); - file.setAutoRemove(false); - QVERIFY(file.open()); - file.close(); - fileName = file.fileName(); - } - QVERIFY(!fileName.isEmpty()); QVERIFY(QFile::exists(fileName)); QVERIFY(QFile::remove(fileName)); @@ -366,51 +339,17 @@ void tst_QTemporaryFile::nonWritableCurrentDir() #endif } -void tst_QTemporaryFile::io() +void tst_QTemporaryFile::write() { QByteArray data("OLE\nOLE\nOLE"); QTemporaryFile file; - QDateTime before = QDateTime::currentDateTimeUtc().addMSecs(-250); - - // discard msec component (round down) - not all FSs and OSs support them - before.setSecsSinceEpoch(before.toSecsSinceEpoch()); - QVERIFY(file.open()); - QVERIFY(file.readLink().isEmpty()); // it's not a link! - QFile::Permissions perm = file.permissions(); - QVERIFY(perm & QFile::ReadOwner); - QVERIFY(file.setPermissions(perm)); - - QCOMPARE(int(file.size()), 0); - QVERIFY(file.resize(data.size())); - QCOMPARE(int(file.size()), data.size()); QCOMPARE((int)file.write(data), data.size()); - QCOMPARE(int(file.size()), data.size()); - - QDateTime mtime = file.fileTime(QFile::FileModificationTime).toUTC(); - QDateTime btime = file.fileTime(QFile::FileBirthTime).toUTC(); - QDateTime ctime = file.fileTime(QFile::FileMetadataChangeTime).toUTC(); - QDateTime atime = file.fileTime(QFile::FileAccessTime).toUTC(); - - QDateTime after = QDateTime::currentDateTimeUtc().toUTC().addMSecs(250); - // round msecs up - after.setSecsSinceEpoch(after.toSecsSinceEpoch() + 1); - - // mtime must be valid, the rest could fail - QVERIFY(mtime <= after && mtime >= before); - QVERIFY(!btime.isValid() || (btime <= after && btime >= before)); - QVERIFY(!ctime.isValid() || (ctime <= after && ctime >= before)); - QVERIFY(!btime.isValid() || (btime <= after && btime >= before)); - - QVERIFY(file.setFileTime(before.addSecs(-10), QFile::FileModificationTime)); - mtime = file.fileTime(QFile::FileModificationTime).toUTC(); - QCOMPARE(mtime, before.addSecs(-10)); - file.reset(); QFile compare(file.fileName()); compare.open(QIODevice::ReadOnly); QCOMPARE(compare.readAll() , data); - QCOMPARE(compare.fileTime(QFile::FileModificationTime), mtime); + file.close(); } void tst_QTemporaryFile::openCloseOpenClose() @@ -476,19 +415,17 @@ void tst_QTemporaryFile::size() { QTemporaryFile file; QVERIFY(file.open()); + QVERIFY(file.exists()); QVERIFY(!file.isSequential()); QByteArray str("foobar"); file.write(str); - + QVERIFY(QFile::exists(file.fileName())); // On CE it takes more time for the filesystem to update // the information. Usually you have to close it or seek // to get latest information. flush() does not help either. QCOMPARE(file.size(), qint64(6)); file.seek(0); QCOMPARE(file.size(), qint64(6)); - - QVERIFY(QFile::exists(file.fileName())); - QVERIFY(file.exists()); } void tst_QTemporaryFile::resize() @@ -885,14 +822,6 @@ void tst_QTemporaryFile::QTBUG_4796() QCOMPARE(file5.open(), openResult); QCOMPARE(file6.open(), openResult); - // force the files to exist, if they are supposed to - QCOMPARE(!file1.fileName().isEmpty(), openResult); - QCOMPARE(!file2.fileName().isEmpty(), openResult); - QCOMPARE(!file3.fileName().isEmpty(), openResult); - QCOMPARE(!file4.fileName().isEmpty(), openResult); - QCOMPARE(!file5.fileName().isEmpty(), openResult); - QCOMPARE(!file6.fileName().isEmpty(), openResult); - QCOMPARE(file1.exists(), openResult); QCOMPARE(file2.exists(), openResult); QCOMPARE(file3.exists(), openResult); diff --git a/tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp b/tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp index 856033fb63..7ba09a4e7f 100644 --- a/tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp +++ b/tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp @@ -282,7 +282,6 @@ void tst_QNetworkDiskCache::clear() // don't delete files that it didn't create QTemporaryFile file(cacheDirectory + "/XXXXXX"); if (file.open()) { - file.fileName(); // make sure it exists with a name QCOMPARE(countFiles(cacheDirectory).count(), NUM_SUBDIRECTORIES + 3); cache.clear(); QCOMPARE(countFiles(cacheDirectory).count(), NUM_SUBDIRECTORIES + 3); -- 2.16.1