395 lines
15 KiB
C++
395 lines
15 KiB
C++
/****************************************************************************
|
|
**
|
|
** Copyright (C) 2016 The Qt Company Ltd.
|
|
** Contact: https://www.qt.io/licensing/
|
|
**
|
|
** This file is part of the QtCore module 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$
|
|
**
|
|
****************************************************************************/
|
|
|
|
#ifndef QFILESYSTEMMETADATA_P_H
|
|
#define QFILESYSTEMMETADATA_P_H
|
|
|
|
//
|
|
// W A R N I N G
|
|
// -------------
|
|
//
|
|
// This file is not part of the Qt API. It exists purely as an
|
|
// implementation detail. This header file may change from version to
|
|
// version without notice, or even be removed.
|
|
//
|
|
// We mean it.
|
|
//
|
|
|
|
#include "qplatformdefs.h"
|
|
#include <QtCore/qglobal.h>
|
|
#include <QtCore/qdatetime.h>
|
|
#include <QtCore/private/qabstractfileengine_p.h>
|
|
|
|
// Platform-specific includes
|
|
#ifdef Q_OS_WIN
|
|
# include <QtCore/qt_windows.h>
|
|
# ifndef IO_REPARSE_TAG_SYMLINK
|
|
# define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
|
|
# endif
|
|
#endif
|
|
|
|
#ifdef Q_OS_UNIX
|
|
struct statx;
|
|
#endif
|
|
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
class QFileSystemEngine;
|
|
|
|
class Q_AUTOTEST_EXPORT QFileSystemMetaData
|
|
{
|
|
public:
|
|
QFileSystemMetaData()
|
|
: size_(-1)
|
|
{
|
|
}
|
|
|
|
enum MetaDataFlag {
|
|
// Permissions, overlaps with QFile::Permissions
|
|
OtherReadPermission = 0x00000004, OtherWritePermission = 0x00000002, OtherExecutePermission = 0x00000001,
|
|
GroupReadPermission = 0x00000040, GroupWritePermission = 0x00000020, GroupExecutePermission = 0x00000010,
|
|
UserReadPermission = 0x00000400, UserWritePermission = 0x00000200, UserExecutePermission = 0x00000100,
|
|
OwnerReadPermission = 0x00004000, OwnerWritePermission = 0x00002000, OwnerExecutePermission = 0x00001000,
|
|
|
|
OtherPermissions = OtherReadPermission | OtherWritePermission | OtherExecutePermission,
|
|
GroupPermissions = GroupReadPermission | GroupWritePermission | GroupExecutePermission,
|
|
UserPermissions = UserReadPermission | UserWritePermission | UserExecutePermission,
|
|
OwnerPermissions = OwnerReadPermission | OwnerWritePermission | OwnerExecutePermission,
|
|
|
|
ReadPermissions = OtherReadPermission | GroupReadPermission | UserReadPermission | OwnerReadPermission,
|
|
WritePermissions = OtherWritePermission | GroupWritePermission | UserWritePermission | OwnerWritePermission,
|
|
ExecutePermissions = OtherExecutePermission | GroupExecutePermission | UserExecutePermission | OwnerExecutePermission,
|
|
|
|
Permissions = OtherPermissions | GroupPermissions | UserPermissions | OwnerPermissions,
|
|
|
|
// Type
|
|
LinkType = 0x00010000,
|
|
FileType = 0x00020000,
|
|
DirectoryType = 0x00040000,
|
|
#if defined(Q_OS_DARWIN)
|
|
BundleType = 0x00080000,
|
|
AliasType = 0x08000000,
|
|
#else
|
|
BundleType = 0x0,
|
|
AliasType = 0x0,
|
|
#endif
|
|
#if defined(Q_OS_WIN)
|
|
JunctionType = 0x04000000,
|
|
WinLnkType = 0x08000000, // Note: Uses the same position for AliasType on Mac
|
|
#else
|
|
JunctionType = 0x0,
|
|
WinLnkType = 0x0,
|
|
#endif
|
|
SequentialType = 0x00800000, // Note: overlaps with QAbstractFileEngine::RootFlag
|
|
|
|
LegacyLinkType = LinkType | AliasType | WinLnkType,
|
|
|
|
Type = LinkType | FileType | DirectoryType | BundleType | SequentialType | AliasType,
|
|
|
|
// Attributes
|
|
HiddenAttribute = 0x00100000,
|
|
SizeAttribute = 0x00200000, // Note: overlaps with QAbstractFileEngine::LocalDiskFlag
|
|
ExistsAttribute = 0x00400000, // For historical reasons, indicates existence of data, not the file
|
|
#if defined(Q_OS_WIN)
|
|
WasDeletedAttribute = 0x0,
|
|
#else
|
|
WasDeletedAttribute = 0x40000000, // Indicates the file was deleted
|
|
#endif
|
|
|
|
Attributes = HiddenAttribute | SizeAttribute | ExistsAttribute | WasDeletedAttribute,
|
|
|
|
// Times - if we know one of them, we know them all
|
|
AccessTime = 0x02000000,
|
|
BirthTime = 0x02000000,
|
|
MetadataChangeTime = 0x02000000,
|
|
ModificationTime = 0x02000000,
|
|
|
|
Times = AccessTime | BirthTime | MetadataChangeTime | ModificationTime,
|
|
|
|
// Owner IDs
|
|
UserId = 0x10000000,
|
|
GroupId = 0x20000000,
|
|
|
|
OwnerIds = UserId | GroupId,
|
|
|
|
PosixStatFlags = QFileSystemMetaData::OtherPermissions
|
|
| QFileSystemMetaData::GroupPermissions
|
|
| QFileSystemMetaData::OwnerPermissions
|
|
| QFileSystemMetaData::FileType
|
|
| QFileSystemMetaData::DirectoryType
|
|
| QFileSystemMetaData::SequentialType
|
|
| QFileSystemMetaData::SizeAttribute
|
|
| QFileSystemMetaData::WasDeletedAttribute
|
|
| QFileSystemMetaData::Times
|
|
| QFileSystemMetaData::OwnerIds,
|
|
|
|
#if defined(Q_OS_WIN)
|
|
WinStatFlags = QFileSystemMetaData::FileType
|
|
| QFileSystemMetaData::DirectoryType
|
|
| QFileSystemMetaData::HiddenAttribute
|
|
| QFileSystemMetaData::ExistsAttribute
|
|
| QFileSystemMetaData::SizeAttribute
|
|
| QFileSystemMetaData::Times,
|
|
#endif
|
|
|
|
AllMetaDataFlags = 0xFFFFFFFF
|
|
|
|
};
|
|
Q_DECLARE_FLAGS(MetaDataFlags, MetaDataFlag)
|
|
|
|
bool hasFlags(MetaDataFlags flags) const
|
|
{
|
|
return ((knownFlagsMask & flags) == flags);
|
|
}
|
|
|
|
MetaDataFlags missingFlags(MetaDataFlags flags)
|
|
{
|
|
return flags & ~knownFlagsMask;
|
|
}
|
|
|
|
void clear()
|
|
{
|
|
knownFlagsMask = {};
|
|
}
|
|
|
|
void clearFlags(MetaDataFlags flags = AllMetaDataFlags)
|
|
{
|
|
knownFlagsMask &= ~flags;
|
|
}
|
|
|
|
bool exists() const { return entryFlags.testAnyFlag(ExistsAttribute); }
|
|
|
|
bool isLink() const { return entryFlags.testAnyFlag(LinkType); }
|
|
bool isFile() const { return entryFlags.testAnyFlag(FileType); }
|
|
bool isDirectory() const { return entryFlags.testAnyFlag(DirectoryType); }
|
|
bool isBundle() const;
|
|
bool isAlias() const;
|
|
bool isLegacyLink() const { return entryFlags.testAnyFlag(LegacyLinkType); }
|
|
bool isSequential() const { return entryFlags.testAnyFlag(SequentialType); }
|
|
bool isHidden() const { return entryFlags.testAnyFlag(HiddenAttribute); }
|
|
bool wasDeleted() const { return entryFlags.testAnyFlag(WasDeletedAttribute); }
|
|
#if defined(Q_OS_WIN)
|
|
bool isLnkFile() const { return entryFlags.testAnyFlag(WinLnkType); }
|
|
bool isJunction() const { return entryFlags.testAnyFlag(JunctionType); }
|
|
#else
|
|
bool isLnkFile() const { return false; }
|
|
bool isJunction() const { return false; }
|
|
#endif
|
|
|
|
qint64 size() const { return size_; }
|
|
|
|
QFile::Permissions permissions() const;
|
|
|
|
QDateTime accessTime() const;
|
|
QDateTime birthTime() const;
|
|
QDateTime metadataChangeTime() const;
|
|
QDateTime modificationTime() const;
|
|
|
|
QDateTime fileTime(QAbstractFileEngine::FileTime time) const;
|
|
uint userId() const;
|
|
uint groupId() const;
|
|
uint ownerId(QAbstractFileEngine::FileOwner owner) const;
|
|
|
|
#ifdef Q_OS_UNIX
|
|
void fillFromStatxBuf(const struct statx &statBuffer);
|
|
void fillFromStatBuf(const QT_STATBUF &statBuffer);
|
|
void fillFromDirEnt(const QT_DIRENT &statBuffer);
|
|
#endif
|
|
|
|
#if defined(Q_OS_WIN)
|
|
inline void fillFromFileAttribute(DWORD fileAttribute, bool isDriveRoot = false);
|
|
inline void fillFromFindData(WIN32_FIND_DATA &findData, bool setLinkType = false, bool isDriveRoot = false);
|
|
inline void fillFromFindInfo(BY_HANDLE_FILE_INFORMATION &fileInfo);
|
|
#endif
|
|
private:
|
|
friend class QFileSystemEngine;
|
|
|
|
MetaDataFlags knownFlagsMask;
|
|
MetaDataFlags entryFlags;
|
|
|
|
qint64 size_;
|
|
|
|
// Platform-specific data goes here:
|
|
#if defined(Q_OS_WIN)
|
|
DWORD fileAttribute_;
|
|
FILETIME birthTime_;
|
|
FILETIME changeTime_;
|
|
FILETIME lastAccessTime_;
|
|
FILETIME lastWriteTime_;
|
|
#else
|
|
// msec precision
|
|
qint64 accessTime_;
|
|
qint64 birthTime_;
|
|
qint64 metadataChangeTime_;
|
|
qint64 modificationTime_;
|
|
|
|
uint userId_;
|
|
uint groupId_;
|
|
#endif
|
|
|
|
};
|
|
|
|
Q_DECLARE_OPERATORS_FOR_FLAGS(QFileSystemMetaData::MetaDataFlags)
|
|
|
|
inline QFile::Permissions QFileSystemMetaData::permissions() const { return QFile::Permissions::fromInt((Permissions & entryFlags).toInt()); }
|
|
|
|
#if defined(Q_OS_DARWIN)
|
|
inline bool QFileSystemMetaData::isBundle() const { return entryFlags.testAnyFlag(BundleType); }
|
|
inline bool QFileSystemMetaData::isAlias() const { return entryFlags.testAnyFlag(AliasType); }
|
|
#else
|
|
inline bool QFileSystemMetaData::isBundle() const { return false; }
|
|
inline bool QFileSystemMetaData::isAlias() const { return false; }
|
|
#endif
|
|
|
|
#if defined(Q_OS_UNIX) || defined (Q_OS_WIN)
|
|
inline QDateTime QFileSystemMetaData::fileTime(QAbstractFileEngine::FileTime time) const
|
|
{
|
|
switch (time) {
|
|
case QAbstractFileEngine::ModificationTime:
|
|
return modificationTime();
|
|
|
|
case QAbstractFileEngine::AccessTime:
|
|
return accessTime();
|
|
|
|
case QAbstractFileEngine::BirthTime:
|
|
return birthTime();
|
|
|
|
case QAbstractFileEngine::MetadataChangeTime:
|
|
return metadataChangeTime();
|
|
}
|
|
|
|
return QDateTime();
|
|
}
|
|
#endif
|
|
|
|
#if defined(Q_OS_UNIX)
|
|
inline QDateTime QFileSystemMetaData::birthTime() const
|
|
{ return birthTime_ ? QDateTime::fromMSecsSinceEpoch(birthTime_, Qt::UTC) : QDateTime(); }
|
|
inline QDateTime QFileSystemMetaData::metadataChangeTime() const
|
|
{ return metadataChangeTime_ ? QDateTime::fromMSecsSinceEpoch(metadataChangeTime_, Qt::UTC) : QDateTime(); }
|
|
inline QDateTime QFileSystemMetaData::modificationTime() const
|
|
{ return modificationTime_ ? QDateTime::fromMSecsSinceEpoch(modificationTime_, Qt::UTC) : QDateTime(); }
|
|
inline QDateTime QFileSystemMetaData::accessTime() const
|
|
{ return accessTime_ ? QDateTime::fromMSecsSinceEpoch(accessTime_, Qt::UTC) : QDateTime(); }
|
|
|
|
inline uint QFileSystemMetaData::userId() const { return userId_; }
|
|
inline uint QFileSystemMetaData::groupId() const { return groupId_; }
|
|
|
|
inline uint QFileSystemMetaData::ownerId(QAbstractFileEngine::FileOwner owner) const
|
|
{
|
|
if (owner == QAbstractFileEngine::OwnerUser)
|
|
return userId();
|
|
else
|
|
return groupId();
|
|
}
|
|
#endif
|
|
|
|
#if defined(Q_OS_WIN)
|
|
inline uint QFileSystemMetaData::userId() const { return (uint) -2; }
|
|
inline uint QFileSystemMetaData::groupId() const { return (uint) -2; }
|
|
inline uint QFileSystemMetaData::ownerId(QAbstractFileEngine::FileOwner owner) const
|
|
{
|
|
if (owner == QAbstractFileEngine::OwnerUser)
|
|
return userId();
|
|
else
|
|
return groupId();
|
|
}
|
|
|
|
inline void QFileSystemMetaData::fillFromFileAttribute(DWORD fileAttribute,bool isDriveRoot)
|
|
{
|
|
fileAttribute_ = fileAttribute;
|
|
// Ignore the hidden attribute for drives.
|
|
if (!isDriveRoot && (fileAttribute_ & FILE_ATTRIBUTE_HIDDEN))
|
|
entryFlags |= HiddenAttribute;
|
|
entryFlags |= ((fileAttribute & FILE_ATTRIBUTE_DIRECTORY) ? DirectoryType: FileType);
|
|
entryFlags |= ExistsAttribute;
|
|
knownFlagsMask |= FileType | DirectoryType | HiddenAttribute | ExistsAttribute;
|
|
}
|
|
|
|
inline void QFileSystemMetaData::fillFromFindData(WIN32_FIND_DATA &findData, bool setLinkType, bool isDriveRoot)
|
|
{
|
|
fillFromFileAttribute(findData.dwFileAttributes, isDriveRoot);
|
|
birthTime_ = findData.ftCreationTime;
|
|
lastAccessTime_ = findData.ftLastAccessTime;
|
|
changeTime_ = lastWriteTime_ = findData.ftLastWriteTime;
|
|
if (fileAttribute_ & FILE_ATTRIBUTE_DIRECTORY) {
|
|
size_ = 0;
|
|
} else {
|
|
size_ = findData.nFileSizeHigh;
|
|
size_ <<= 32;
|
|
size_ += findData.nFileSizeLow;
|
|
}
|
|
knownFlagsMask |= Times | SizeAttribute;
|
|
if (setLinkType) {
|
|
knownFlagsMask |= LinkType;
|
|
entryFlags &= ~LinkType;
|
|
if (fileAttribute_ & FILE_ATTRIBUTE_REPARSE_POINT) {
|
|
if (findData.dwReserved0 == IO_REPARSE_TAG_SYMLINK) {
|
|
entryFlags |= LinkType;
|
|
#if defined(IO_REPARSE_TAG_MOUNT_POINT)
|
|
} else if ((fileAttribute_ & FILE_ATTRIBUTE_DIRECTORY)
|
|
&& (findData.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT)) {
|
|
entryFlags |= JunctionType;
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
inline void QFileSystemMetaData::fillFromFindInfo(BY_HANDLE_FILE_INFORMATION &fileInfo)
|
|
{
|
|
fillFromFileAttribute(fileInfo.dwFileAttributes);
|
|
birthTime_ = fileInfo.ftCreationTime;
|
|
lastAccessTime_ = fileInfo.ftLastAccessTime;
|
|
changeTime_ = lastWriteTime_ = fileInfo.ftLastWriteTime;
|
|
if (fileAttribute_ & FILE_ATTRIBUTE_DIRECTORY) {
|
|
size_ = 0;
|
|
} else {
|
|
size_ = fileInfo.nFileSizeHigh;
|
|
size_ <<= 32;
|
|
size_ += fileInfo.nFileSizeLow;
|
|
}
|
|
knownFlagsMask |= Times | SizeAttribute;
|
|
}
|
|
#endif // Q_OS_WIN
|
|
|
|
QT_END_NAMESPACE
|
|
|
|
#endif // include guard
|