summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/io/qabstractfileengine.cpp15
-rw-r--r--src/corelib/io/qabstractfileengine_p.h7
-rw-r--r--src/corelib/io/qfiledevice.cpp32
-rw-r--r--src/corelib/io/qfiledevice.h7
-rw-r--r--src/corelib/io/qfileinfo.cpp32
-rw-r--r--src/corelib/io/qfileinfo_p.h15
-rw-r--r--src/corelib/io/qfilesystemengine.cpp7
-rw-r--r--src/corelib/io/qfilesystemengine_unix.cpp6
-rw-r--r--src/corelib/io/qfilesystemengine_win.cpp22
-rw-r--r--src/corelib/io/qfilesystemmetadata_p.h41
-rw-r--r--src/corelib/io/qfsfileengine_win.cpp2
-rw-r--r--src/plugins/platforms/winrt/qwinrtfileengine.cpp3
-rw-r--r--tests/auto/corelib/io/qabstractfileengine/tst_qabstractfileengine.cpp8
-rw-r--r--tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp212
-rw-r--r--tests/auto/corelib/io/qfilesystemmetadata/tst_qfilesystemmetadata.cpp6
15 files changed, 229 insertions, 186 deletions
diff --git a/src/corelib/io/qabstractfileengine.cpp b/src/corelib/io/qabstractfileengine.cpp
index 7a603544f3..1163234b62 100644
--- a/src/corelib/io/qabstractfileengine.cpp
+++ b/src/corelib/io/qabstractfileengine.cpp
@@ -328,7 +328,8 @@ QAbstractFileEngine *QAbstractFileEngine::create(const QString &fileName)
These are used by the fileTime() function.
- \value CreationTime When the file was created.
+ \value BirthTime When the file was born (created).
+ \value MetadataChangeTime When the file's metadata was last changed.
\value ModificationTime When the file was most recently modified.
\value AccessTime When the file was most recently accessed (e.g.
read or written to).
@@ -756,12 +757,12 @@ bool QAbstractFileEngine::setFileTime(const QDateTime &newDate, FileTime time)
}
/*!
- If \a time is \c CreationTime, return when the file was created.
- If \a time is \c ModificationTime, return when the file was most
- recently modified. If \a time is \c AccessTime, return when the
- file was most recently accessed (e.g. read or written).
- If the time cannot be determined return QDateTime() (an invalid
- date time).
+ If \a time is \c BirthTime, return when the file was born (created). If \a
+ time is \c MetadataChangeTime, return when the file's metadata was last
+ changed. If \a time is \c ModificationTime, return when the file was most
+ recently modified. If \a time is \c AccessTime, return when the file was
+ most recently accessed (e.g. read or written). If the time cannot be
+ determined return QDateTime() (an invalid date time).
This virtual function must be reimplemented by all subclasses.
diff --git a/src/corelib/io/qabstractfileengine_p.h b/src/corelib/io/qabstractfileengine_p.h
index 47b3a624fe..c3f7619268 100644
--- a/src/corelib/io/qabstractfileengine_p.h
+++ b/src/corelib/io/qabstractfileengine_p.h
@@ -113,9 +113,10 @@ public:
OwnerGroup
};
enum FileTime {
- CreationTime,
- ModificationTime,
- AccessTime
+ AccessTime,
+ BirthTime,
+ MetadataChangeTime,
+ ModificationTime
};
virtual ~QAbstractFileEngine();
diff --git a/src/corelib/io/qfiledevice.cpp b/src/corelib/io/qfiledevice.cpp
index b642add7f6..ab37d6f4d7 100644
--- a/src/corelib/io/qfiledevice.cpp
+++ b/src/corelib/io/qfiledevice.cpp
@@ -744,29 +744,23 @@ bool QFileDevice::unmap(uchar *address)
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 setFileTime(), fileTime()
+ \value FileAccessTime When the file was most recently accessed
+ (e.g. read or written to).
+ \value FileBirthTime When the file was created (may not be not
+ supported on UNIX).
+ \value FileMetadataChangeTime When the file's metadata was last changed.
+ \value FileModificationTime When the file was most recently modified.
+
+ \sa setFileTime(), fileTime(), QFileInfo::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;
+ Q_STATIC_ASSERT(int(QFileDevice::FileAccessTime) == int(QAbstractFileEngine::AccessTime));
+ Q_STATIC_ASSERT(int(QFileDevice::FileBirthTime) == int(QAbstractFileEngine::BirthTime));
+ Q_STATIC_ASSERT(int(QFileDevice::FileMetadataChangeTime) == int(QAbstractFileEngine::MetadataChangeTime));
+ Q_STATIC_ASSERT(int(QFileDevice::FileModificationTime) == int(QAbstractFileEngine::ModificationTime));
+ return QAbstractFileEngine::FileTime(time);
}
/*!
diff --git a/src/corelib/io/qfiledevice.h b/src/corelib/io/qfiledevice.h
index 3519a049a9..e941781c25 100644
--- a/src/corelib/io/qfiledevice.h
+++ b/src/corelib/io/qfiledevice.h
@@ -75,9 +75,10 @@ public:
};
enum FileTime {
- FileCreationTime,
- FileModificationTime,
- FileAccessTime
+ FileAccessTime,
+ FileBirthTime,
+ FileMetadataChangeTime,
+ FileModificationTime
};
enum Permission {
diff --git a/src/corelib/io/qfileinfo.cpp b/src/corelib/io/qfileinfo.cpp
index bb4eb5aeb2..104a171e99 100644
--- a/src/corelib/io/qfileinfo.cpp
+++ b/src/corelib/io/qfileinfo.cpp
@@ -194,8 +194,11 @@ QDateTime &QFileInfoPrivate::getFileTime(QAbstractFileEngine::FileTime request)
case QAbstractFileEngine::AccessTime:
cf = CachedATime;
break;
- case QAbstractFileEngine::CreationTime:
- cf = CachedCTime;
+ case QAbstractFileEngine::BirthTime:
+ cf = CachedBTime;
+ break;
+ case QAbstractFileEngine::MetadataChangeTime:
+ cf = CachedMCTime;
break;
case QAbstractFileEngine::ModificationTime:
cf = CachedMTime;
@@ -1316,7 +1319,10 @@ qint64 QFileInfo::size() const
*/
QDateTime QFileInfo::created() const
{
- return fileTime(QFile::FileCreationTime);
+ QDateTime d = fileTime(QFile::FileBirthTime);
+ if (d.isValid())
+ return d;
+ return fileTime(QFile::FileMetadataChangeTime);
}
#endif
@@ -1331,7 +1337,7 @@ QDateTime QFileInfo::created() const
*/
QDateTime QFileInfo::birthTime() const
{
- return fileTime(QFile::FileCreationTime);
+ return fileTime(QFile::FileBirthTime);
}
/*!
@@ -1345,7 +1351,7 @@ QDateTime QFileInfo::birthTime() const
*/
QDateTime QFileInfo::metadataChangeTime() const
{
- return fileTime(QFile::FileCreationTime);
+ return fileTime(QFile::FileMetadataChangeTime);
}
/*!
@@ -1373,16 +1379,17 @@ QDateTime QFileInfo::lastRead() const
/*!
\since 5.10
- Returns the file time specified by \a time.
- If the time cannot be determined return QDateTime() (an invalid
- date time).
+
+ Returns the file time specified by \a time. If the time cannot be
+ determined, an invalid date time is returned.
\sa QFile::FileTime, QDateTime::isValid()
*/
QDateTime QFileInfo::fileTime(QFile::FileTime time) const
{
Q_STATIC_ASSERT(int(QFile::FileAccessTime) == int(QAbstractFileEngine::AccessTime));
- Q_STATIC_ASSERT(int(QFile::FileCreationTime) == int(QAbstractFileEngine::CreationTime));
+ Q_STATIC_ASSERT(int(QFile::FileBirthTime) == int(QAbstractFileEngine::BirthTime));
+ Q_STATIC_ASSERT(int(QFile::FileMetadataChangeTime) == int(QAbstractFileEngine::MetadataChangeTime));
Q_STATIC_ASSERT(int(QFile::FileModificationTime) == int(QAbstractFileEngine::ModificationTime));
Q_D(const QFileInfo);
@@ -1397,8 +1404,11 @@ QDateTime QFileInfo::fileTime(QFile::FileTime time) const
case QFile::FileAccessTime:
flag = QFileSystemMetaData::AccessTime;
break;
- case QFile::FileCreationTime:
- flag = QFileSystemMetaData::CreationTime;
+ case QFile::FileBirthTime:
+ flag = QFileSystemMetaData::BirthTime;
+ break;
+ case QFile::FileMetadataChangeTime:
+ flag = QFileSystemMetaData::MetadataChangeTime;
break;
case QFile::FileModificationTime:
flag = QFileSystemMetaData::ModificationTime;
diff --git a/src/corelib/io/qfileinfo_p.h b/src/corelib/io/qfileinfo_p.h
index d45cf6be33..923247c62c 100644
--- a/src/corelib/io/qfileinfo_p.h
+++ b/src/corelib/io/qfileinfo_p.h
@@ -66,9 +66,18 @@ QT_BEGIN_NAMESPACE
class QFileInfoPrivate : public QSharedData
{
public:
- enum { CachedFileFlags=0x01, CachedLinkTypeFlag=0x02, CachedBundleTypeFlag=0x04,
- CachedMTime=0x10, CachedCTime=0x20, CachedATime=0x40,
- CachedSize =0x08, CachedPerms=0x80 };
+ enum {
+ // note: cachedFlags is only 30-bits wide
+ CachedFileFlags = 0x01,
+ CachedLinkTypeFlag = 0x02,
+ CachedBundleTypeFlag = 0x04,
+ CachedSize = 0x08,
+ CachedATime = 0x10,
+ CachedBTime = 0x20,
+ CachedMCTime = 0x40,
+ CachedMTime = 0x80,
+ CachedPerms = 0x100
+ };
inline QFileInfoPrivate()
: QSharedData(), fileEngine(0),
diff --git a/src/corelib/io/qfilesystemengine.cpp b/src/corelib/io/qfilesystemengine.cpp
index f3205ae6e2..1af5c6f4ed 100644
--- a/src/corelib/io/qfilesystemengine.cpp
+++ b/src/corelib/io/qfilesystemengine.cpp
@@ -293,15 +293,14 @@ void QFileSystemMetaData::fillFromStatBuf(const QT_STATBUF &statBuffer)
#endif
// Times
+ birthTime_ = 0;
#if _POSIX_VERSION >= 200809L
modificationTime_ = timespecToMSecs(statBuffer.st_mtim);
- creationTime_ = timespecToMSecs(statBuffer.st_ctim);
- if (!creationTime_)
- creationTime_ = modificationTime_;
+ metadataChangeTime_ = timespecToMSecs(statBuffer.st_ctim);
accessTime_ = timespecToMSecs(statBuffer.st_atim);
#else
- creationTime_ = qint64(statBuffer.st_ctime ? statBuffer.st_ctime : statBuffer.st_mtime) * 1000;
modificationTime_ = qint64(statBuffer.st_mtime) * 1000;
+ metadataChangeTime_ = qint64(statBuffer.st_ctime) * 1000;
accessTime_ = qint64(statBuffer.st_atime) * 1000;
#endif
userId_ = statBuffer.st_uid;
diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp
index 89250c52f3..a1108e0fe6 100644
--- a/src/corelib/io/qfilesystemengine_unix.cpp
+++ b/src/corelib/io/qfilesystemengine_unix.cpp
@@ -518,7 +518,8 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM
data.fillFromStatBuf(statBuffer);
else {
entryExists = false;
- data.creationTime_ = 0;
+ data.birthTime_ = 0;
+ data.metadataChangeTime_ = 0;
data.modificationTime_ = 0;
data.accessTime_ = 0;
data.size_ = 0;
@@ -844,7 +845,8 @@ bool QFileSystemEngine::setPermissions(int fd, QFile::Permissions permissions, Q
//static
bool QFileSystemEngine::setFileTime(int fd, const QDateTime &newDate, QAbstractFileEngine::FileTime time, QSystemError &error)
{
- if (!newDate.isValid() || time == QAbstractFileEngine::CreationTime) {
+ if (!newDate.isValid() || time == QAbstractFileEngine::BirthTime ||
+ time == QAbstractFileEngine::MetadataChangeTime) {
error = QSystemError(EINVAL, QSystemError::StandardLibraryError);
return false;
}
diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp
index 5796b1ba66..e171de9e9f 100644
--- a/src/corelib/io/qfilesystemengine_win.cpp
+++ b/src/corelib/io/qfilesystemengine_win.cpp
@@ -412,7 +412,8 @@ void QFileSystemEngine::clearWinStatData(QFileSystemMetaData &data)
{
data.size_ = 0;
data.fileAttribute_ = 0;
- data.creationTime_ = FILETIME();
+ data.birthTime_ = FILETIME();
+ data.changeTime_ = FILETIME();
data.lastAccessTime_ = FILETIME();
data.lastWriteTime_ = FILETIME();
}
@@ -610,7 +611,7 @@ bool QFileSystemEngine::setFileTime(HANDLE fHandle, const QDateTime &newDate,
pLastAccess = &fTime;
break;
- case QAbstractFileEngine::CreationTime:
+ case QAbstractFileEngine::BirthTime:
pCreationTime = &fTime;
break;
@@ -889,8 +890,10 @@ bool QFileSystemEngine::fillMetaData(HANDLE fHandle, QFileSystemMetaData &data,
FILE_BASIC_INFO fileBasicInfo;
if (GetFileInformationByHandleEx(fHandle, FileBasicInfo, &fileBasicInfo, sizeof(fileBasicInfo))) {
data.fillFromFileAttribute(fileBasicInfo.FileAttributes);
- data.creationTime_.dwHighDateTime = fileBasicInfo.CreationTime.HighPart;
- data.creationTime_.dwLowDateTime = fileBasicInfo.CreationTime.LowPart;
+ data.birthTime_.dwHighDateTime = fileBasicInfo.CreationTime.HighPart;
+ data.birthTime_.dwLowDateTime = fileBasicInfo.CreationTime.LowPart;
+ data.changeTime_.dwHighDateTime = fileBasicInfo.ChangeTime.HighPart;
+ data.changeTime_.dwLowDateTime = fileBasicInfo.ChangeTime.LowPart;
data.lastAccessTime_.dwHighDateTime = fileBasicInfo.LastAccessTime.HighPart;
data.lastAccessTime_.dwLowDateTime = fileBasicInfo.LastAccessTime.LowPart;
data.lastWriteTime_.dwHighDateTime = fileBasicInfo.LastWriteTime.HighPart;
@@ -1347,6 +1350,9 @@ bool QFileSystemEngine::setPermissions(const QFileSystemEntry &entry, QFile::Per
static inline QDateTime fileTimeToQDateTime(const FILETIME *time)
{
+ if (time->dwHighDateTime == 0 && time->dwLowDateTime == 0)
+ return QDateTime();
+
SYSTEMTIME sTime;
FileTimeToSystemTime(time, &sTime);
return QDateTime(QDate(sTime.wYear, sTime.wMonth, sTime.wDay),
@@ -1354,9 +1360,13 @@ static inline QDateTime fileTimeToQDateTime(const FILETIME *time)
Qt::UTC);
}
-QDateTime QFileSystemMetaData::creationTime() const
+QDateTime QFileSystemMetaData::birthTime() const
+{
+ return fileTimeToQDateTime(&birthTime_);
+}
+QDateTime QFileSystemMetaData::metadataChangeTime() const
{
- return fileTimeToQDateTime(&creationTime_);
+ return fileTimeToQDateTime(&changeTime_);
}
QDateTime QFileSystemMetaData::modificationTime() const
{
diff --git a/src/corelib/io/qfilesystemmetadata_p.h b/src/corelib/io/qfilesystemmetadata_p.h
index 2f25721bee..3eeb26247f 100644
--- a/src/corelib/io/qfilesystemmetadata_p.h
+++ b/src/corelib/io/qfilesystemmetadata_p.h
@@ -129,12 +129,13 @@ public:
Attributes = HiddenAttribute | SizeAttribute | ExistsAttribute | WasDeletedAttribute,
- // Times
- CreationTime = 0x01000000, // Note: overlaps with QAbstractFileEngine::Refresh
+ // Times - if we know one of them, we know them all
+ AccessTime = 0x02000000,
+ BirthTime = 0x02000000,
+ MetadataChangeTime = 0x02000000,
ModificationTime = 0x02000000,
- AccessTime = 0x04000000,
- Times = CreationTime | ModificationTime | AccessTime,
+ Times = AccessTime | BirthTime | MetadataChangeTime | ModificationTime,
// Owner IDs
UserId = 0x10000000,
@@ -208,9 +209,10 @@ public:
QFile::Permissions permissions() const { return QFile::Permissions(Permissions & entryFlags); }
- QDateTime creationTime() const;
- QDateTime modificationTime() const;
QDateTime accessTime() const;
+ QDateTime birthTime() const;
+ QDateTime metadataChangeTime() const;
+ QDateTime modificationTime() const;
QDateTime fileTime(QAbstractFileEngine::FileTime time) const;
uint userId() const;
@@ -240,14 +242,16 @@ private:
// Platform-specific data goes here:
#if defined(Q_OS_WIN)
DWORD fileAttribute_;
- FILETIME creationTime_;
+ FILETIME birthTime_;
+ FILETIME changeTime_;
FILETIME lastAccessTime_;
FILETIME lastWriteTime_;
#else
// msec precision
- qint64 creationTime_;
- qint64 modificationTime_;
qint64 accessTime_;
+ qint64 birthTime_;
+ qint64 metadataChangeTime_;
+ qint64 modificationTime_;
uint userId_;
uint groupId_;
@@ -275,8 +279,11 @@ inline QDateTime QFileSystemMetaData::fileTime(QAbstractFileEngine::FileTime tim
case QAbstractFileEngine::AccessTime:
return accessTime();
- case QAbstractFileEngine::CreationTime:
- return creationTime();
+ case QAbstractFileEngine::BirthTime:
+ return birthTime();
+
+ case QAbstractFileEngine::MetadataChangeTime:
+ return metadataChangeTime();
}
return QDateTime();
@@ -284,7 +291,9 @@ inline QDateTime QFileSystemMetaData::fileTime(QAbstractFileEngine::FileTime tim
#endif
#if defined(Q_OS_UNIX)
-inline QDateTime QFileSystemMetaData::creationTime() const { return QDateTime::fromMSecsSinceEpoch(creationTime_); }
+inline QDateTime QFileSystemMetaData::birthTime() const
+{ return birthTime_ ? QDateTime::fromMSecsSinceEpoch(birthTime_) : QDateTime(); }
+inline QDateTime QFileSystemMetaData::metadataChangeTime() const { return QDateTime::fromMSecsSinceEpoch(metadataChangeTime_); }
inline QDateTime QFileSystemMetaData::modificationTime() const { return QDateTime::fromMSecsSinceEpoch(modificationTime_); }
inline QDateTime QFileSystemMetaData::accessTime() const { return QDateTime::fromMSecsSinceEpoch(accessTime_); }
@@ -325,9 +334,9 @@ inline void QFileSystemMetaData::fillFromFileAttribute(DWORD fileAttribute,bool
inline void QFileSystemMetaData::fillFromFindData(WIN32_FIND_DATA &findData, bool setLinkType, bool isDriveRoot)
{
fillFromFileAttribute(findData.dwFileAttributes, isDriveRoot);
- creationTime_ = findData.ftCreationTime;
+ birthTime_ = findData.ftCreationTime;
lastAccessTime_ = findData.ftLastAccessTime;
- lastWriteTime_ = findData.ftLastWriteTime;
+ changeTime_ = lastWriteTime_ = findData.ftLastWriteTime;
if (fileAttribute_ & FILE_ATTRIBUTE_DIRECTORY) {
size_ = 0;
} else {
@@ -350,9 +359,9 @@ inline void QFileSystemMetaData::fillFromFindData(WIN32_FIND_DATA &findData, boo
inline void QFileSystemMetaData::fillFromFindInfo(BY_HANDLE_FILE_INFORMATION &fileInfo)
{
fillFromFileAttribute(fileInfo.dwFileAttributes);
- creationTime_ = fileInfo.ftCreationTime;
+ birthTime_ = fileInfo.ftCreationTime;
lastAccessTime_ = fileInfo.ftLastAccessTime;
- lastWriteTime_ = fileInfo.ftLastWriteTime;
+ changeTime_ = lastWriteTime_ = fileInfo.ftLastWriteTime;
if (fileAttribute_ & FILE_ATTRIBUTE_DIRECTORY) {
size_ = 0;
} else {
diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp
index 50a8a0e55a..97fefe8927 100644
--- a/src/corelib/io/qfsfileengine_win.cpp
+++ b/src/corelib/io/qfsfileengine_win.cpp
@@ -864,7 +864,7 @@ bool QFSFileEngine::setFileTime(const QDateTime &newDate, FileTime time)
return false;
}
- if (!newDate.isValid()) {
+ if (!newDate.isValid() || time == QAbstractFileEngine::MetadataChangeTime) {
setError(QFile::UnspecifiedError, qt_error_string(ERROR_INVALID_PARAMETER));
return false;
}
diff --git a/src/plugins/platforms/winrt/qwinrtfileengine.cpp b/src/plugins/platforms/winrt/qwinrtfileengine.cpp
index 58375d331c..f037c516b5 100644
--- a/src/plugins/platforms/winrt/qwinrtfileengine.cpp
+++ b/src/plugins/platforms/winrt/qwinrtfileengine.cpp
@@ -414,10 +414,11 @@ QDateTime QWinRTFileEngine::fileTime(FileTime type) const
HRESULT hr;
DateTime dateTime = { 0 };
switch (type) {
- case CreationTime:
+ case BirthTime:
hr = d->file->get_DateCreated(&dateTime);
RETURN_IF_FAILED("Failed to get file creation time", return QDateTime());
break;
+ case MetadataChangeTime:
case ModificationTime:
case AccessTime: {
ComPtr<IAsyncOperation<FileProperties::BasicProperties *>> op;
diff --git a/tests/auto/corelib/io/qabstractfileengine/tst_qabstractfileengine.cpp b/tests/auto/corelib/io/qabstractfileengine/tst_qabstractfileengine.cpp
index 68fc628a41..1072cb44f9 100644
--- a/tests/auto/corelib/io/qabstractfileengine/tst_qabstractfileengine.cpp
+++ b/tests/auto/corelib/io/qabstractfileengine/tst_qabstractfileengine.cpp
@@ -341,8 +341,10 @@ public:
if (file) {
QMutexLocker lock(&file->mutex);
switch (time) {
- case CreationTime:
- return file->creation;
+ case BirthTime:
+ return file->birth;
+ case MetadataChangeTime:
+ return file->change;
case ModificationTime:
return file->modification;
case AccessTime:
@@ -456,7 +458,7 @@ protected:
uint userId, groupId;
QAbstractFileEngine::FileFlags fileFlags;
- QDateTime creation, modification, access;
+ QDateTime birth, change, modification, access;
QByteArray content;
};
diff --git a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp
index b269e3e1e4..94273e2394 100644
--- a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp
+++ b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp
@@ -35,6 +35,7 @@
#include <qtemporarydir.h>
#include <qdir.h>
#include <qfileinfo.h>
+#include <qstorageinfo.h>
#ifdef Q_OS_UNIX
#include <errno.h>
#include <fcntl.h>
@@ -64,84 +65,38 @@
#define Q_NO_SYMLINKS
#endif
-
-#if defined(Q_OS_UNIX) && !defined(Q_OS_VXWORKS)
-inline bool qt_isEvilFsTypeName(const char *name)
-{
- return (qstrncmp(name, "nfs", 3) == 0
- || qstrncmp(name, "autofs", 6) == 0
- || qstrncmp(name, "cachefs", 7) == 0);
-}
-
-#if defined(Q_OS_BSD4) && !defined(Q_OS_NETBSD)
-# include <sys/param.h>
-# include <sys/mount.h>
-
-bool qIsLikelyToBeNfs(int handle)
-{
- struct statfs buf;
- if (fstatfs(handle, &buf) != 0)
- return false;
- return qt_isEvilFsTypeName(buf.f_fstypename);
-}
-
-#elif defined(Q_OS_LINUX) || defined(Q_OS_HURD)
-
-# include <sys/vfs.h>
-# ifdef QT_LINUXBASE
- // LSB 3.2 has fstatfs in sys/statfs.h, sys/vfs.h is just an empty dummy header
-# include <sys/statfs.h>
-# endif
-
-# ifndef NFS_SUPER_MAGIC
-# define NFS_SUPER_MAGIC 0x00006969
-# endif
-# ifndef AUTOFS_SUPER_MAGIC
-# define AUTOFS_SUPER_MAGIC 0x00000187
-# endif
-# ifndef AUTOFSNG_SUPER_MAGIC
-# define AUTOFSNG_SUPER_MAGIC 0x7d92b1a0
-# endif
-
-bool qIsLikelyToBeNfs(int handle)
+inline bool qIsLikelyToBeFat(const QString &path)
{
- struct statfs buf;
- if (fstatfs(handle, &buf) != 0)
- return false;
- return buf.f_type == NFS_SUPER_MAGIC
- || buf.f_type == AUTOFS_SUPER_MAGIC
- || buf.f_type == AUTOFSNG_SUPER_MAGIC;
+ QByteArray name = QStorageInfo(path).fileSystemType().toLower();
+ return name.contains("fat") || name.contains("msdos");
}
-#elif defined(Q_OS_SOLARIS) || defined(Q_OS_IRIX) || defined(Q_OS_AIX) || defined(Q_OS_HPUX) \
- || defined(Q_OS_OSF) || defined(Q_OS_QNX) || defined(Q_OS_SCO) \
- || defined(Q_OS_UNIXWARE) || defined(Q_OS_RELIANT) || defined(Q_OS_NETBSD)
-
-# include <sys/statvfs.h>
-
-bool qIsLikelyToBeNfs(int handle)
+inline bool qIsLikelyToBeNfs(const QString &path)
{
- struct statvfs buf;
- if (fstatvfs(handle, &buf) != 0)
- return false;
-#if defined(Q_OS_NETBSD)
- return qt_isEvilFsTypeName(buf.f_fstypename);
+#ifdef Q_OS_WIN
+ Q_UNUSED(path);
+ return false;
#else
- return qt_isEvilFsTypeName(buf.f_basetype);
+ QByteArray type = QStorageInfo(path).fileSystemType();
+ const char *name = type.constData();
+
+ return (qstrncmp(name, "nfs", 3) == 0
+ || qstrncmp(name, "autofs", 6) == 0
+ || qstrncmp(name, "autofsng", 8) == 0
+ || qstrncmp(name, "cachefs", 7) == 0);
#endif
}
-#else
-inline bool qIsLikelyToBeNfs(int /* handle */)
-{
- return false;
-}
-#endif
-#endif
static QString seedAndTemplate()
{
- qsrand(QDateTime::currentSecsSinceEpoch());
- return QDir::tempPath() + "/tst_qfileinfo-XXXXXX";
+ QString base;
+#if defined(Q_OS_UNIX) && !defined(Q_OS_ANDROID)
+ // use XDG_RUNTIME_DIR as it's a fully-capable FS
+ base = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation);
+#endif
+ if (base.isEmpty())
+ base = QDir::tempPath();
+ return base + "/tst_qfileinfo-XXXXXX";
}
static QByteArray msgDoesNotExist(const QString &name)
@@ -1129,43 +1084,92 @@ void tst_QFileInfo::fileTimes_data()
void tst_QFileInfo::fileTimes()
{
- int sleepTime = 2000;
+ auto datePairString = [](const QDateTime &actual, const QDateTime &before) {
+ return (actual.toString(Qt::ISODateWithMs) + " (should be >) " + before.toString(Qt::ISODateWithMs))
+ .toLatin1();
+ };
+
QFETCH(QString, fileName);
+ int sleepTime = 100;
+
+ // on Linux and Windows, the filesystem timestamps may be slightly out of
+ // sync with the system clock (maybe they're using CLOCK_REALTIME_COARSE),
+ // so add a margin of error to our comparisons
+ int fsClockSkew = 10;
+#ifdef Q_OS_WIN
+ fsClockSkew = 500;
+#endif
+
+ // NFS clocks may be WAY out of sync
+ if (qIsLikelyToBeNfs(fileName))
+ QSKIP("This test doesn't work on NFS");
+
+ bool noAccessTime = false;
+ {
+ // try to guess if file times on this filesystem round to the second
+ QFileInfo cwd(".");
+ if (cwd.lastModified().toMSecsSinceEpoch() % 1000 == 0
+ && cwd.lastRead().toMSecsSinceEpoch() % 1000 == 0) {
+ fsClockSkew = sleepTime = 1000;
+
+ noAccessTime = qIsLikelyToBeFat(fileName);
+ if (noAccessTime) {
+ // FAT filesystems (but maybe not exFAT) store timestamps with 2-second
+ // granularity and access time with 1-day granularity
+ fsClockSkew = sleepTime = 2000;
+ }
+ }
+ }
+
if (QFile::exists(fileName)) {
QVERIFY(QFile::remove(fileName));
}
- QTest::qSleep(sleepTime);
+
+ QDateTime beforeBirth, beforeWrite, beforeMetadataChange, beforeRead;
+ QDateTime birthTime, writeTime, metadataChangeTime, readTime;
+
+ // --- Create file and write to it
+ beforeBirth = QDateTime::currentDateTime().addMSecs(-fsClockSkew);
{
QFile file(fileName);
QVERIFY(file.open(QFile::WriteOnly | QFile::Text));
-#if defined(Q_OS_UNIX) && !defined(Q_OS_VXWORKS)
- if (qIsLikelyToBeNfs(file.handle()))
- QSKIP("This Test doesn't work on NFS");
-#endif
+ QFileInfo fileInfo(fileName);
+ birthTime = fileInfo.birthTime();
+ QVERIFY2(!birthTime.isValid() || birthTime > beforeBirth,
+ datePairString(birthTime, beforeBirth));
+
+ QTest::qSleep(sleepTime);
+ beforeWrite = QDateTime::currentDateTime().addMSecs(-fsClockSkew);
QTextStream ts(&file);
ts << fileName << endl;
}
- QTest::qSleep(sleepTime);
- QDateTime beforeWrite = QDateTime::currentDateTime();
- QTest::qSleep(sleepTime);
{
QFileInfo fileInfo(fileName);
- QVERIFY(!fileInfo.birthTime().isValid() || fileInfo.birthTime() < beforeWrite);
- QVERIFY(fileInfo.metadataChangeTime() < beforeWrite);
- QVERIFY(fileInfo.created() < beforeWrite);
- QFile file(fileName);
- QVERIFY(file.open(QFile::ReadWrite | QFile::Text));
- QTextStream ts(&file);
- ts << fileName << endl;
+ writeTime = fileInfo.lastModified();
+ QVERIFY2(writeTime > beforeWrite, datePairString(writeTime, beforeWrite));
+ QCOMPARE(fileInfo.birthTime(), birthTime); // mustn't have changed
}
+
+ // --- Change the file's metadata
QTest::qSleep(sleepTime);
- QDateTime beforeRead = QDateTime::currentDateTime();
- QTest::qSleep(sleepTime);
+ beforeMetadataChange = QDateTime::currentDateTime().addMSecs(-fsClockSkew);
+ {
+ QFile file(fileName);
+ file.setPermissions(file.permissions());
+ }
{
QFileInfo fileInfo(fileName);
- QVERIFY(!fileInfo.birthTime().isValid() || fileInfo.birthTime() < beforeWrite);
- QVERIFY(fileInfo.metadataChangeTime() > beforeWrite);
- QVERIFY(fileInfo.lastModified() > beforeWrite);
+ metadataChangeTime = fileInfo.metadataChangeTime();
+ QVERIFY2(metadataChangeTime > beforeMetadataChange,
+ datePairString(metadataChangeTime, beforeMetadataChange));
+ QVERIFY(metadataChangeTime >= writeTime); // not all filesystems can store both times
+ QCOMPARE(fileInfo.birthTime(), birthTime); // mustn't have changed
+ }
+
+ // --- Read the file
+ QTest::qSleep(sleepTime);
+ beforeRead = QDateTime::currentDateTime().addMSecs(-fsClockSkew);
+ {
QFile file(fileName);
QVERIFY(file.open(QFile::ReadOnly | QFile::Text));
QTextStream ts(&file);
@@ -1174,13 +1178,17 @@ void tst_QFileInfo::fileTimes()
}
QFileInfo fileInfo(fileName);
- QVERIFY(!fileInfo.birthTime().isValid() || fileInfo.birthTime() < beforeWrite);
- QVERIFY(fileInfo.metadataChangeTime() > beforeWrite);
-
+ readTime = fileInfo.lastRead();
+ QCOMPARE(fileInfo.lastModified(), writeTime); // mustn't have changed
+ QCOMPARE(fileInfo.birthTime(), birthTime); // mustn't have changed
+ QVERIFY(readTime.isValid());
+
+#if defined(Q_OS_WINRT) || defined(Q_OS_QNX) || defined(Q_OS_ANDROID)
+ noAccessTime = true;
+#elif defined(Q_OS_WIN)
//In Vista the last-access timestamp is not updated when the file is accessed/touched (by default).
//To enable this the HKLM\SYSTEM\CurrentControlSet\Control\FileSystem\NtfsDisableLastAccessUpdate
//is set to 0, in the test machine.
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
HKEY key;
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\FileSystem",
0, KEY_READ, &key)) {
@@ -1189,22 +1197,16 @@ void tst_QFileInfo::fileTimes()
LONG error = RegQueryValueEx(key, L"NtfsDisableLastAccessUpdate"
, NULL, NULL, (LPBYTE)&disabledAccessTimes, &size);
if (ERROR_SUCCESS == error && disabledAccessTimes)
- QEXPECT_FAIL("", "File access times are disabled in windows registry (this is the default setting)", Continue);
+ noAccessTime = true;
RegCloseKey(key);
}
#endif
-#if defined(Q_OS_WINRT)
- QEXPECT_FAIL("", "WinRT does not allow timestamp handling change in the filesystem due to sandboxing", Continue);
-#elif defined(Q_OS_QNX)
- QEXPECT_FAIL("", "QNX uses the noatime filesystem option", Continue);
-#elif defined(Q_OS_ANDROID)
- if (fileInfo.lastRead() <= beforeRead)
- QEXPECT_FAIL("", "Android may use relatime or noatime on mounts", Continue);
-#endif
- QVERIFY(fileInfo.lastRead() > beforeRead);
- QVERIFY(fileInfo.lastModified() > beforeWrite);
- QVERIFY(fileInfo.lastModified() < beforeRead);
+ if (noAccessTime)
+ return;
+
+ QVERIFY2(readTime > beforeRead, datePairString(readTime, beforeRead));
+ QVERIFY(writeTime < beforeRead);
}
void tst_QFileInfo::fileTimes_oldFile()
diff --git a/tests/auto/corelib/io/qfilesystemmetadata/tst_qfilesystemmetadata.cpp b/tests/auto/corelib/io/qfilesystemmetadata/tst_qfilesystemmetadata.cpp
index 1c104688a5..ea4da39cd5 100644
--- a/tests/auto/corelib/io/qfilesystemmetadata/tst_qfilesystemmetadata.cpp
+++ b/tests/auto/corelib/io/qfilesystemmetadata/tst_qfilesystemmetadata.cpp
@@ -66,14 +66,16 @@ void tst_QFileSystemMetaData::timeSinceEpoch()
/* data.ftLastAccessTime = data.ftLastWriteTime = */
data.ftCreationTime = epochToFileTime(afterEpochUtc);
meta.fillFromFindData(data);
+ QCOMPARE(meta.birthTime().toUTC(),
+ QDateTime::fromMSecsSinceEpoch(afterEpochUtc * qint64(1000), Qt::UTC));
#else
QT_STATBUF data;
memset(&data, 0, sizeof(data));
data.st_ctime = afterEpochUtc;
meta.fillFromStatBuf(data);
-#endif
- QCOMPARE(meta.creationTime().toUTC(),
+ QCOMPARE(meta.metadataChangeTime().toUTC(),
QDateTime::fromMSecsSinceEpoch(afterEpochUtc * qint64(1000), Qt::UTC));
+#endif
}
#else // i.e. no Q_AUTOTEST_EXPORT
void tst_QFileSystemMetaData::timeSinceEpoch()