diff --git a/config.tests/unix/futimens/futimens.cpp b/config.tests/unix/futimens/futimens.cpp new file mode 100644 index 00000000000..1b66386ca16 --- /dev/null +++ b/config.tests/unix/futimens/futimens.cpp @@ -0,0 +1,47 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Raphael Gozzo +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the config.tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +int main(int, char **) +{ + futimens(-1,0); + return 0; +} + diff --git a/config.tests/unix/futimens/futimens.pro b/config.tests/unix/futimens/futimens.pro new file mode 100644 index 00000000000..eb3ccc56c56 --- /dev/null +++ b/config.tests/unix/futimens/futimens.pro @@ -0,0 +1 @@ +SOURCES += futimens.cpp diff --git a/config.tests/unix/futimes/futimes.cpp b/config.tests/unix/futimes/futimes.cpp new file mode 100644 index 00000000000..553b39068ea --- /dev/null +++ b/config.tests/unix/futimes/futimes.cpp @@ -0,0 +1,47 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Raphael Gozzo +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the config.tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +int main(int, char **) +{ + futimes(-1,0); + return 0; +} + diff --git a/config.tests/unix/futimes/futimes.pro b/config.tests/unix/futimes/futimes.pro new file mode 100644 index 00000000000..8e7f2c0f626 --- /dev/null +++ b/config.tests/unix/futimes/futimes.pro @@ -0,0 +1 @@ +SOURCES += futimes.cpp diff --git a/config.tests/unix/futimesat/futimesat.cpp b/config.tests/unix/futimesat/futimesat.cpp new file mode 100644 index 00000000000..a0e2c5848d3 --- /dev/null +++ b/config.tests/unix/futimesat/futimesat.cpp @@ -0,0 +1,47 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Raphael Gozzo +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the config.tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +int main(int, char **) +{ + futimesat(-1,0,0); + return 0; +} + diff --git a/config.tests/unix/futimesat/futimesat.pro b/config.tests/unix/futimesat/futimesat.pro new file mode 100644 index 00000000000..1b364e19776 --- /dev/null +++ b/config.tests/unix/futimesat/futimesat.pro @@ -0,0 +1 @@ +SOURCES += futimesat.cpp diff --git a/src/corelib/configure.json b/src/corelib/configure.json index c6c5c93ddbe..0e9830c5e22 100644 --- a/src/corelib/configure.json +++ b/src/corelib/configure.json @@ -139,6 +139,21 @@ "type": "compile", "test": "unix/eventfd" }, + "futimens": { + "label": "futimens()", + "type": "compile", + "test": "unix/futimens" + }, + "futimes": { + "label": "futimes()", + "type": "compile", + "test": "unix/futimes" + }, + "futimesat": { + "label": "futimesat()", + "type": "compile", + "test": "unix/futimesat" + }, "posix-iconv": { "label": "POSIX iconv", "type": "compile", @@ -228,6 +243,21 @@ "condition": "tests.eventfd", "output": [ "feature" ] }, + "futimens": { + "label": "futimens()", + "condition": "!config.win32 && tests.futimens", + "output": [ "privateFeature" ] + }, + "futimes": { + "label": "futimes()", + "condition": "!config.win32 && !features.futimens && tests.futimes", + "output": [ "privateFeature" ] + }, + "futimesat": { + "label": "futimesat()", + "condition": "!config.win32 && !features.futimens && !features.futimes && tests.futimesat", + "output": [ "privateFeature" ] + }, "glib": { "label": "GLib", "autoDetect": "!config.win32", diff --git a/src/corelib/global/qconfig-bootstrapped.h b/src/corelib/global/qconfig-bootstrapped.h index bda8ad79168..5b8fee630af 100644 --- a/src/corelib/global/qconfig-bootstrapped.h +++ b/src/corelib/global/qconfig-bootstrapped.h @@ -71,6 +71,9 @@ #define QT_FEATURE_iconv -1 #define QT_FEATURE_icu -1 #define QT_FEATURE_journald -1 +#define QT_FEATURE_futimens -1 +#define QT_FEATURE_futimes -1 +#define QT_FEATURE_futimesat -1 #define QT_FEATURE_library -1 #define QT_NO_QOBJECT #define QT_FEATURE_process -1 diff --git a/src/corelib/io/qabstractfileengine.cpp b/src/corelib/io/qabstractfileengine.cpp index 5f1f7e381e0..85dc2f33a28 100644 --- a/src/corelib/io/qabstractfileengine.cpp +++ b/src/corelib/io/qabstractfileengine.cpp @@ -726,6 +726,18 @@ QString QAbstractFileEngine::owner(FileOwner owner) const return QString(); } +/*! + \fn bool QAbstractFileEngine::setFileTime(const QDateTime &newDate, FileTime time) + + \since 5.10 + Sets the file \a time to \a newDate, returning true if successful; + otherwise returns false. + + This virtual function must be reimplemented by all subclasses. + + \sa fileTime() +*/ + /*! If \a time is \c CreationTime, return when the file was created. If \a time is \c ModificationTime, return when the file was most diff --git a/src/corelib/io/qabstractfileengine_p.h b/src/corelib/io/qabstractfileengine_p.h index dbf0d77b154..9d0a101b49e 100644 --- a/src/corelib/io/qabstractfileengine_p.h +++ b/src/corelib/io/qabstractfileengine_p.h @@ -144,6 +144,7 @@ public: virtual QString fileName(FileName file=DefaultName) const; virtual uint ownerId(FileOwner) const; virtual QString owner(FileOwner) const; + virtual bool setFileTime(const QDateTime &newDate, FileTime time) = 0; virtual QDateTime fileTime(FileTime time) const; virtual void setFileName(const QString &file); virtual int handle() const; diff --git a/src/corelib/io/qfiledevice.cpp b/src/corelib/io/qfiledevice.cpp index ce9c8275cea..9e2e3fe7411 100644 --- a/src/corelib/io/qfiledevice.cpp +++ b/src/corelib/io/qfiledevice.cpp @@ -738,4 +738,80 @@ bool QFileDevice::unmap(uchar *address) return false; } +/*! + \enum QFileDevice::FileTime + \since 5.10 + + This enum is used by the fileTime() and setFileTime() functions. + + \value FileCreationTime When the file was created (not supported on UNIX). + \value FileModificationTime When the file was most recently modified. + \value FileAccessTime When the file was most recently accessed (e.g. + read or written to). + + \sa setFileName(), fileTime() +*/ + +static inline QAbstractFileEngine::FileTime FileDeviceTimeToAbstractFileEngineTime(QFileDevice::FileTime time) +{ + switch (time) { + case QFileDevice::FileAccessTime: + return QAbstractFileEngine::AccessTime; + + case QFileDevice::FileCreationTime: + return QAbstractFileEngine::CreationTime; + + case QFileDevice::FileModificationTime: + return QAbstractFileEngine::ModificationTime; + } + + Q_UNREACHABLE(); + return QAbstractFileEngine::AccessTime; +} + +/*! + \since 5.10 + Returns the file time specified by \a time. + If the time cannot be determined return QDateTime() (an invalid + date time). + + \sa setFileName(), FileTime, QDateTime::isValid() +*/ +QDateTime QFileDevice::fileTime(QFileDevice::FileTime time) const +{ + Q_D(const QFileDevice); + + if (d->engine()) + return d->engine()->fileTime(FileDeviceTimeToAbstractFileEngineTime(time)); + + return QDateTime(); +} + +/*! + \since 5.10 + Sets the file \a time to \a newDate, returning true if successful; + otherwise returns false. + + \note The file must be open to use this function. + + \sa fileTime(), FileTime +*/ +bool QFileDevice::setFileTime(const QDateTime &newDate, QFileDevice::FileTime fileTime) +{ + Q_D(QFileDevice); + + if (!d->engine()) { + d->setError(QFileDevice::UnspecifiedError, tr("No file engine available")); + return false; + } + + if (!d->fileEngine->setFileTime(newDate, FileDeviceTimeToAbstractFileEngineTime(fileTime))) { + d->setError(d->fileEngine->error(), d->fileEngine->errorString()); + return false; + } + + unsetError(); + return true; +} + QT_END_NAMESPACE diff --git a/src/corelib/io/qfiledevice.h b/src/corelib/io/qfiledevice.h index 4cfda1b044f..3519a049a9b 100644 --- a/src/corelib/io/qfiledevice.h +++ b/src/corelib/io/qfiledevice.h @@ -45,6 +45,7 @@ QT_BEGIN_NAMESPACE +class QDateTime; class QFileDevicePrivate; class Q_CORE_EXPORT QFileDevice : public QIODevice @@ -73,6 +74,12 @@ public: CopyError = 14 }; + enum FileTime { + FileCreationTime, + FileModificationTime, + FileAccessTime + }; + enum Permission { ReadOwner = 0x4000, WriteOwner = 0x2000, ExeOwner = 0x1000, ReadUser = 0x0400, WriteUser = 0x0200, ExeUser = 0x0100, @@ -119,6 +126,9 @@ public: uchar *map(qint64 offset, qint64 size, MemoryMapFlags flags = NoOptions); bool unmap(uchar *address); + QDateTime fileTime(QFileDevice::FileTime time) const; + bool setFileTime(const QDateTime &newDate, QFileDevice::FileTime fileTime); + protected: QFileDevice(); #ifdef QT_NO_QOBJECT diff --git a/src/corelib/io/qfileinfo.cpp b/src/corelib/io/qfileinfo.cpp index 12fd7d3048e..8025587a8b7 100644 --- a/src/corelib/io/qfileinfo.cpp +++ b/src/corelib/io/qfileinfo.cpp @@ -262,8 +262,8 @@ QDateTime &QFileInfoPrivate::getFileTime(QAbstractFileEngine::FileTime request) info objects, just append one to the file name given to the constructors or setFile(). - The file's dates are returned by created(), lastModified() and - lastRead(). Information about the file's access permissions is + The file's dates are returned by created(), lastModified(), lastRead() and + fileTime(). Information about the file's access permissions is obtained with isReadable(), isWritable() and isExecutable(). The file's ownership is available from owner(), ownerId(), group() and groupId(). You can examine a file's permissions and ownership in a @@ -1324,7 +1324,7 @@ QDateTime QFileInfo::created() const /*! Returns the date and local time when the file was last modified. - \sa created(), lastRead() + \sa created(), lastRead(), fileTime() */ QDateTime QFileInfo::lastModified() const { @@ -1346,7 +1346,7 @@ QDateTime QFileInfo::lastModified() const On platforms where this information is not available, returns the same as lastModified(). - \sa created(), lastModified() + \sa created(), lastModified(), fileTime() */ QDateTime QFileInfo::lastRead() const { @@ -1362,6 +1362,45 @@ QDateTime QFileInfo::lastRead() const return d->getFileTime(QAbstractFileEngine::AccessTime).toLocalTime(); } +/*! + \enum QFileInfo::FileTime + \since 5.10 + + This enum is used by the fileTime() function. + + \value FileCreationTime When the file was created (not supported on UNIX). + \value FileModificationTime When the file was most recently modified. + \value FileAccessTime When the file was most recently accessed (e.g. + read or written to). + + \sa fileTime() +*/ + +/*! + \since 5.10 + Returns the file time specified by \a time. + If the time cannot be determined return QDateTime() (an invalid + date time). + + \sa FileTime, QDateTime::isValid() +*/ +QDateTime QFileInfo::fileTime(QFileInfo::FileTime time) const +{ + switch (time) { + case QFileInfo::FileCreationTime: + return created(); + + case QFileInfo::FileModificationTime: + return lastModified(); + + case QFileInfo::FileAccessTime: + return lastRead(); + + default: + Q_UNREACHABLE(); + } +} + /*! \internal */ diff --git a/src/corelib/io/qfileinfo.h b/src/corelib/io/qfileinfo.h index a160e8463e9..669a1b6ad3e 100644 --- a/src/corelib/io/qfileinfo.h +++ b/src/corelib/io/qfileinfo.h @@ -57,6 +57,12 @@ class Q_CORE_EXPORT QFileInfo { friend class QDirIteratorPrivate; public: + enum FileTime { + FileCreationTime, + FileModificationTime, + FileAccessTime + }; + explicit QFileInfo(QFileInfoPrivate *d); QFileInfo(); @@ -132,6 +138,7 @@ public: QDateTime created() const; QDateTime lastModified() const; QDateTime lastRead() const; + QDateTime fileTime(QFileInfo::FileTime time) const; bool caching() const; void setCaching(bool on); diff --git a/src/corelib/io/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp index e5f7e5b418c..75478f04670 100644 --- a/src/corelib/io/qfsfileengine.cpp +++ b/src/corelib/io/qfsfileengine.cpp @@ -899,6 +899,10 @@ bool QFSFileEngine::supportsExtension(Extension extension) const \reimp */ +/*! \fn bool QFSFileEngine::setFileTime(const QDateTime &newDate, FileTime time) + \reimp +*/ + /*! \fn QDateTime QFSFileEngine::fileTime(FileTime time) const \reimp */ diff --git a/src/corelib/io/qfsfileengine_p.h b/src/corelib/io/qfsfileengine_p.h index 742cebad872..80dd9363dbd 100644 --- a/src/corelib/io/qfsfileengine_p.h +++ b/src/corelib/io/qfsfileengine_p.h @@ -96,6 +96,7 @@ public: QString fileName(FileName file) const Q_DECL_OVERRIDE; uint ownerId(FileOwner) const Q_DECL_OVERRIDE; QString owner(FileOwner) const Q_DECL_OVERRIDE; + bool setFileTime(const QDateTime &newDate, FileTime time) Q_DECL_OVERRIDE; QDateTime fileTime(FileTime time) const Q_DECL_OVERRIDE; void setFileName(const QString &file) Q_DECL_OVERRIDE; int handle() const Q_DECL_OVERRIDE; diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index 51938d69670..4617d098742 100644 --- a/src/corelib/io/qfsfileengine_unix.cpp +++ b/src/corelib/io/qfsfileengine_unix.cpp @@ -100,6 +100,44 @@ static inline QString msgOpenDirectory() #endif } +#if !QT_CONFIG(futimens) && (QT_CONFIG(futimes) || QT_CONFIG(futimesat)) +namespace { +namespace GetFileTimes { + +template +static inline typename QtPrivate::QEnableIf<(&T::st_atim, &T::st_mtim, true)>::Type get(const T *p, struct timeval *access, struct timeval *modification) +{ + access->tv_sec = p->st_atim.tv_sec; + access->tv_usec = p->st_atim.tv_nsec / 1000; + + modification->tv_sec = p->st_mtim.tv_sec; + modification->tv_usec = p->st_mtim.tv_nsec / 1000; +} + +template +static inline typename QtPrivate::QEnableIf<(&T::st_atimespec, &T::st_mtimespec, true)>::Type get(const T *p, struct timeval *access, struct timeval *modification) +{ + access->tv_sec = p->st_atimespec.tv_sec; + access->tv_usec = p->st_atimespec.tv_nsec / 1000; + + modification->tv_sec = p->st_mtimespec.tv_sec; + modification->tv_usec = p->st_mtimespec.tv_nsec / 1000; +} + +template +static inline typename QtPrivate::QEnableIf<(&T::st_atimensec, &T::st_mtimensec, true)>::Type get(const T *p, struct timeval *access, struct timeval *modification) +{ + access->tv_sec = p->st_atime; + access->tv_usec = p->st_atimensec / 1000; + + modification->tv_sec = p->st_mtime; + modification->tv_usec = p->st_mtimensec / 1000; +} + +} +} +#endif + /*! \internal */ @@ -584,6 +622,83 @@ bool QFSFileEngine::setSize(qint64 size) return ret; } +bool QFSFileEngine::setFileTime(const QDateTime &newDate, FileTime time) +{ + Q_D(QFSFileEngine); + + if (d->openMode == QIODevice::NotOpen) { + setError(QFile::PermissionsError, qt_error_string(EACCES)); + return false; + } + + if (!newDate.isValid() || time == QAbstractFileEngine::CreationTime) { + setError(QFile::UnspecifiedError, qt_error_string(EINVAL)); + return false; + } + +#if QT_CONFIG(futimens) + struct timespec ts[2]; + + ts[0].tv_sec = ts[1].tv_sec = 0; + ts[0].tv_nsec = ts[1].tv_nsec = UTIME_OMIT; + + const qint64 msecs = newDate.toMSecsSinceEpoch(); + + if (time == QAbstractFileEngine::AccessTime) { + ts[0].tv_sec = msecs / 1000; + ts[0].tv_nsec = (msecs % 1000) * 1000000; + } else if (time == QAbstractFileEngine::ModificationTime) { + ts[1].tv_sec = msecs / 1000; + ts[1].tv_nsec = (msecs % 1000) * 1000000; + } + + if (futimens(d->nativeHandle(), ts) == -1) { + setError(QFile::PermissionsError, qt_error_string()); + return false; + } + + d->metaData.clearFlags(QFileSystemMetaData::Times); + + return true; +#elif QT_CONFIG(futimes) || QT_CONFIG(futimesat) + struct timeval tv[2]; + QT_STATBUF st; + + if (QT_FSTAT(d->nativeHandle(), &st) == -1) { + setError(QFile::PermissionsError, qt_error_string()); + return false; + } + + GetFileTimes::get(&st, &tv[0], &tv[1]); + + const qint64 msecs = newDate.toMSecsSinceEpoch(); + + if (time == QAbstractFileEngine::AccessTime) { + tv[0].tv_sec = msecs / 1000; + tv[0].tv_usec = (msecs % 1000) * 1000; + } else if (time == QAbstractFileEngine::ModificationTime) { + tv[1].tv_sec = msecs / 1000; + tv[1].tv_usec = (msecs % 1000) * 1000; + } + +#if QT_CONFIG(futimes) + if (futimes(d->nativeHandle(), tv) == -1) { +#else + if (futimesat(d->nativeHandle(), NULL, tv) == -1) { +#endif + setError(QFile::PermissionsError, qt_error_string()); + return false; + } + + d->metaData.clearFlags(QFileSystemMetaData::Times); + + return true; +#else + setError(QFile::UnspecifiedError, qt_error_string(ENOSYS)); + return false; +#endif +} + QDateTime QFSFileEngine::fileTime(FileTime time) const { Q_D(const QFSFileEngine); diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp index 4a477b84291..5c6098c3b0b 100644 --- a/src/corelib/io/qfsfileengine_win.cpp +++ b/src/corelib/io/qfsfileengine_win.cpp @@ -80,6 +80,39 @@ static inline bool isUncPath(const QString &path) && path.size() > 2 && path.at(2) != QLatin1Char('.')); } +static inline void QDateTimeToSystemTime(const QDateTime &date, SYSTEMTIME *systemTime) +{ + const QDate d = date.date(); + const QTime t = date.time(); + + systemTime->wYear = d.year(); + systemTime->wMonth = d.month(); + systemTime->wDay = d.day(); + systemTime->wHour = t.hour(); + systemTime->wMinute = t.minute(); + systemTime->wSecond = t.second(); + systemTime->wMilliseconds = t.msec(); + systemTime->wDayOfWeek = d.dayOfWeek() % 7; +} + +static inline bool QDateTimeToFileTime(const QDateTime &date, FILETIME *fileTime) +{ + SYSTEMTIME sTime; + +#if defined(Q_OS_WINCE) + QDateTimeToSystemTime(date, &sTime); +#else + SYSTEMTIME lTime; + + QDateTimeToSystemTime(date, &lTime); + + if (!::TzSpecificLocalTimeToSystemTime(0, &lTime, &sTime)) + return false; +#endif + + return ::SystemTimeToFileTime(&sTime, fileTime); +} + /*! \internal */ @@ -850,6 +883,69 @@ bool QFSFileEngine::setSize(qint64 size) return false; } +bool QFSFileEngine::setFileTime(const QDateTime &newDate, FileTime time) +{ + Q_D(QFSFileEngine); + + if (d->openMode == QFile::NotOpen) { + setError(QFile::PermissionsError, qt_error_string(ERROR_ACCESS_DENIED)); + return false; + } + + if (!newDate.isValid()) { + setError(QFile::UnspecifiedError, qt_error_string(ERROR_INVALID_PARAMETER)); + return false; + } + + HANDLE handle = d->fileHandle; + +#ifndef Q_OS_WINCE + if (handle == INVALID_HANDLE_VALUE) { + if (d->fh) + handle = reinterpret_cast(::_get_osfhandle(QT_FILENO(d->fh))); + else if (d->fd != -1) + handle = reinterpret_cast(::_get_osfhandle(d->fd)); + } +#endif + + if (handle == INVALID_HANDLE_VALUE) { + setError(QFile::PermissionsError, qt_error_string(ERROR_ACCESS_DENIED)); + return false; + } + + FILETIME fTime; + FILETIME *pLastWrite = NULL; + FILETIME *pLastAccess = NULL; + FILETIME *pCreationTime = NULL; + + switch (time) { + case QAbstractFileEngine::ModificationTime: + pLastWrite = &fTime; + break; + + case QAbstractFileEngine::AccessTime: + pLastAccess = &fTime; + break; + + case QAbstractFileEngine::CreationTime: + pCreationTime = &fTime; + break; + } + + if (!QDateTimeToFileTime(newDate, &fTime)) { + setError(QFile::UnspecifiedError, qt_error_string()); + return false; + } + + if (!::SetFileTime(handle, pCreationTime, pLastAccess, pLastWrite)) { + setError(QFile::PermissionsError, qt_error_string()); + return false; + } + + d->metaData.clearFlags(QFileSystemMetaData::Times); + + return true; +} QDateTime QFSFileEngine::fileTime(FileTime time) const { diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp index 984ed238126..ff31524c1cd 100644 --- a/src/corelib/io/qresource.cpp +++ b/src/corelib/io/qresource.cpp @@ -1457,6 +1457,13 @@ QString QResourceFileEngine::owner(FileOwner) const return QString(); } +bool QResourceFileEngine::setFileTime(const QDateTime &newDate, FileTime time) +{ + Q_UNUSED(newDate); + Q_UNUSED(time); + return false; +} + QDateTime QResourceFileEngine::fileTime(FileTime time) const { Q_D(const QResourceFileEngine); diff --git a/src/corelib/io/qresource_p.h b/src/corelib/io/qresource_p.h index e08ba64d2be..1b0f4f66e44 100644 --- a/src/corelib/io/qresource_p.h +++ b/src/corelib/io/qresource_p.h @@ -103,6 +103,7 @@ public: virtual uint ownerId(FileOwner) const Q_DECL_OVERRIDE; virtual QString owner(FileOwner) const Q_DECL_OVERRIDE; + virtual bool setFileTime(const QDateTime &newDate, FileTime time) Q_DECL_OVERRIDE; virtual QDateTime fileTime(FileTime time) const Q_DECL_OVERRIDE; virtual Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames) Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp b/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp index e1dcebfa4c7..953377a3a9f 100644 --- a/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp +++ b/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp @@ -206,6 +206,13 @@ public: return type & flags; } + bool setFileTime(const QDateTime &newDate, FileTime time) override + { + Q_UNUSED(newDate); + Q_UNUSED(time); + return false; + } + QString fileName(FileName file = DefaultName) const override { int pos; diff --git a/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileengineassetslibrary.h b/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileengineassetslibrary.h index 8d7cabf15b5..2387efc1f97 100644 --- a/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileengineassetslibrary.h +++ b/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileengineassetslibrary.h @@ -61,6 +61,7 @@ public: qint64 read(char *data, qint64 maxlen) override; qint64 pos() const override; bool seek(qint64 pos) override; + bool setFileTime(const QDateTime &newDate, FileTime time) override; QString fileName(FileName file) const override; void setFileName(const QString &file) override; QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const override; diff --git a/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileengineassetslibrary.mm b/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileengineassetslibrary.mm index bea28972406..fce257356f1 100644 --- a/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileengineassetslibrary.mm +++ b/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileengineassetslibrary.mm @@ -435,6 +435,13 @@ bool QIOSFileEngineAssetsLibrary::seek(qint64 pos) return true; } +bool QIOSFileEngineAssetsLibrary::setFileTime(const QDateTime &newDate, FileTime time) +{ + Q_UNUSED(newDate); + Q_UNUSED(time); + return false; +} + QString QIOSFileEngineAssetsLibrary::fileName(FileName file) const { Q_UNUSED(file); diff --git a/src/plugins/platforms/winrt/qwinrtfileengine.cpp b/src/plugins/platforms/winrt/qwinrtfileengine.cpp index dab2482ab37..f2f8b83e169 100644 --- a/src/plugins/platforms/winrt/qwinrtfileengine.cpp +++ b/src/plugins/platforms/winrt/qwinrtfileengine.cpp @@ -440,6 +440,14 @@ QDateTime QWinRTFileEngine::fileTime(FileTime type) const return QDateTime(date, time); } +bool QWinRTFileEngine::setFileTime(const QDateTime &newDate, FileTime time) +{ + Q_UNUSED(newDate); + Q_UNUSED(time); + Q_UNIMPLEMENTED(); + return false; +} + qint64 QWinRTFileEngine::read(char *data, qint64 maxlen) { Q_D(QWinRTFileEngine); diff --git a/src/plugins/platforms/winrt/qwinrtfileengine.h b/src/plugins/platforms/winrt/qwinrtfileengine.h index 73ff54b0c83..5db83360ce9 100644 --- a/src/plugins/platforms/winrt/qwinrtfileengine.h +++ b/src/plugins/platforms/winrt/qwinrtfileengine.h @@ -89,6 +89,7 @@ public: bool setPermissions(uint perms) override; QString fileName(FileName type=DefaultName) const override; QDateTime fileTime(FileTime type) const override; + bool setFileTime(const QDateTime &newDate, FileTime time) override; qint64 read(char *data, qint64 maxlen) override; qint64 write(const char *data, qint64 len) override; diff --git a/tests/auto/corelib/io/qabstractfileengine/tst_qabstractfileengine.cpp b/tests/auto/corelib/io/qabstractfileengine/tst_qabstractfileengine.cpp index dba920d1f72..4e5059c1a2a 100644 --- a/tests/auto/corelib/io/qabstractfileengine/tst_qabstractfileengine.cpp +++ b/tests/auto/corelib/io/qabstractfileengine/tst_qabstractfileengine.cpp @@ -353,6 +353,13 @@ public: return QDateTime(); } + bool setFileTime(const QDateTime &newDate, FileTime time) + { + Q_UNUSED(newDate); + Q_UNUSED(time); + return false; + } + void setFileName(const QString &file) { if (openForRead_ || openForWrite_) diff --git a/tests/auto/corelib/io/qfile/tst_qfile.cpp b/tests/auto/corelib/io/qfile/tst_qfile.cpp index 81c11ef085d..9b12aa96166 100644 --- a/tests/auto/corelib/io/qfile/tst_qfile.cpp +++ b/tests/auto/corelib/io/qfile/tst_qfile.cpp @@ -2075,6 +2075,7 @@ public: uint ownerId(FileOwner) const { return 0; } QString owner(FileOwner) const { return QString(); } QDateTime fileTime(FileTime) const { return QDateTime(); } + bool setFileTime(const QDateTime &newDate, FileTime time) { return false; } private: int number;