1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QFILESYSTEMMETADATA_P_H
5#define QFILESYSTEMMETADATA_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include "qplatformdefs.h"
19#include <QtCore/qglobal.h>
20#include <QtCore/qdatetime.h>
21#include <QtCore/qtimezone.h>
22#include <QtCore/private/qabstractfileengine_p.h>
23
24// Platform-specific includes
25#ifdef Q_OS_WIN
26# include <QtCore/qt_windows.h>
27# ifndef IO_REPARSE_TAG_SYMLINK
28# define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
29# endif
30#endif
31
32#ifdef Q_OS_UNIX
33struct statx;
34#endif
35
36QT_BEGIN_NAMESPACE
37
38class QFileSystemEngine;
39
40class Q_AUTOTEST_EXPORT QFileSystemMetaData
41{
42public:
43 QFileSystemMetaData()
44 : size_(-1)
45 {
46 }
47
48 enum MetaDataFlag {
49 // Permissions, overlaps with QFile::Permissions
50 OtherReadPermission = 0x00000004, OtherWritePermission = 0x00000002, OtherExecutePermission = 0x00000001,
51 GroupReadPermission = 0x00000040, GroupWritePermission = 0x00000020, GroupExecutePermission = 0x00000010,
52 UserReadPermission = 0x00000400, UserWritePermission = 0x00000200, UserExecutePermission = 0x00000100,
53 OwnerReadPermission = 0x00004000, OwnerWritePermission = 0x00002000, OwnerExecutePermission = 0x00001000,
54
55 OtherPermissions = OtherReadPermission | OtherWritePermission | OtherExecutePermission,
56 GroupPermissions = GroupReadPermission | GroupWritePermission | GroupExecutePermission,
57 UserPermissions = UserReadPermission | UserWritePermission | UserExecutePermission,
58 OwnerPermissions = OwnerReadPermission | OwnerWritePermission | OwnerExecutePermission,
59
60 ReadPermissions = OtherReadPermission | GroupReadPermission | UserReadPermission | OwnerReadPermission,
61 WritePermissions = OtherWritePermission | GroupWritePermission | UserWritePermission | OwnerWritePermission,
62 ExecutePermissions = OtherExecutePermission | GroupExecutePermission | UserExecutePermission | OwnerExecutePermission,
63
64 Permissions = OtherPermissions | GroupPermissions | UserPermissions | OwnerPermissions,
65
66 // Type
67 LinkType = 0x00010000,
68 FileType = 0x00020000,
69 DirectoryType = 0x00040000,
70#if defined(Q_OS_DARWIN)
71 BundleType = 0x00080000,
72 AliasType = 0x08000000,
73#else
74 BundleType = 0x0,
75 AliasType = 0x0,
76#endif
77#if defined(Q_OS_WIN)
78 JunctionType = 0x04000000,
79 WinLnkType = 0x08000000, // Note: Uses the same position for AliasType on Mac
80#else
81 JunctionType = 0x0,
82 WinLnkType = 0x0,
83#endif
84 SequentialType = 0x00800000, // Note: overlaps with QAbstractFileEngine::RootFlag
85
86 LegacyLinkType = LinkType | AliasType | WinLnkType,
87
88 Type = LinkType | FileType | DirectoryType | BundleType | SequentialType | AliasType,
89
90 // Attributes
91 HiddenAttribute = 0x00100000,
92 SizeAttribute = 0x00200000, // Note: overlaps with QAbstractFileEngine::LocalDiskFlag
93 ExistsAttribute = 0x00400000, // For historical reasons, indicates existence of data, not the file
94#if defined(Q_OS_WIN)
95 WasDeletedAttribute = 0x0,
96#else
97 WasDeletedAttribute = 0x40000000, // Indicates the file was deleted
98#endif
99
100 Attributes = HiddenAttribute | SizeAttribute | ExistsAttribute | WasDeletedAttribute,
101
102 // Times - if we know one of them, we know them all
103 AccessTime = 0x02000000,
104 BirthTime = 0x02000000,
105 MetadataChangeTime = 0x02000000,
106 ModificationTime = 0x02000000,
107
108 Times = AccessTime | BirthTime | MetadataChangeTime | ModificationTime,
109
110 // Owner IDs
111 UserId = 0x10000000,
112 GroupId = 0x20000000,
113
114 OwnerIds = UserId | GroupId,
115
116 PosixStatFlags = QFileSystemMetaData::OtherPermissions
117 | QFileSystemMetaData::GroupPermissions
118 | QFileSystemMetaData::OwnerPermissions
119 | QFileSystemMetaData::FileType
120 | QFileSystemMetaData::DirectoryType
121 | QFileSystemMetaData::SequentialType
122 | QFileSystemMetaData::SizeAttribute
123 | QFileSystemMetaData::WasDeletedAttribute
124 | QFileSystemMetaData::Times
125 | QFileSystemMetaData::OwnerIds,
126
127#if defined(Q_OS_WIN)
128 WinStatFlags = QFileSystemMetaData::FileType
129 | QFileSystemMetaData::DirectoryType
130 | QFileSystemMetaData::HiddenAttribute
131 | QFileSystemMetaData::ExistsAttribute
132 | QFileSystemMetaData::SizeAttribute
133 | QFileSystemMetaData::Times,
134#endif
135
136 AllMetaDataFlags = 0xFFFFFFFF
137
138 };
139 Q_DECLARE_FLAGS(MetaDataFlags, MetaDataFlag)
140
141 bool hasFlags(MetaDataFlags flags) const
142 {
143 return ((knownFlagsMask & flags) == flags);
144 }
145
146 MetaDataFlags missingFlags(MetaDataFlags flags)
147 {
148 return flags & ~knownFlagsMask;
149 }
150
151 void clear()
152 {
153 knownFlagsMask = {};
154 }
155
156 void clearFlags(MetaDataFlags flags = AllMetaDataFlags)
157 {
158 knownFlagsMask &= ~flags;
159 }
160
161 bool exists() const { return entryFlags.testAnyFlag(flag: ExistsAttribute); }
162
163 bool isLink() const { return entryFlags.testAnyFlag(flag: LinkType); }
164 bool isFile() const { return entryFlags.testAnyFlag(flag: FileType); }
165 bool isDirectory() const { return entryFlags.testAnyFlag(flag: DirectoryType); }
166 bool isBundle() const;
167 bool isAlias() const;
168 bool isLegacyLink() const { return entryFlags.testAnyFlag(flag: LegacyLinkType); }
169 bool isSequential() const { return entryFlags.testAnyFlag(flag: SequentialType); }
170 bool isHidden() const { return entryFlags.testAnyFlag(flag: HiddenAttribute); }
171 bool wasDeleted() const { return entryFlags.testAnyFlag(flag: WasDeletedAttribute); }
172#if defined(Q_OS_WIN)
173 bool isLnkFile() const { return entryFlags.testAnyFlag(WinLnkType); }
174 bool isJunction() const { return entryFlags.testAnyFlag(JunctionType); }
175#else
176 bool isLnkFile() const { return false; }
177 bool isJunction() const { return false; }
178#endif
179
180 qint64 size() const { return size_; }
181
182 QFile::Permissions permissions() const;
183
184 QDateTime accessTime() const;
185 QDateTime birthTime() const;
186 QDateTime metadataChangeTime() const;
187 QDateTime modificationTime() const;
188
189 QDateTime fileTime(QAbstractFileEngine::FileTime time) const;
190 uint userId() const;
191 uint groupId() const;
192 uint ownerId(QAbstractFileEngine::FileOwner owner) const;
193
194#ifdef Q_OS_UNIX
195 void fillFromStatxBuf(const struct statx &statBuffer);
196 void fillFromStatBuf(const QT_STATBUF &statBuffer);
197 void fillFromDirEnt(const QT_DIRENT &statBuffer);
198#endif
199
200#if defined(Q_OS_WIN)
201 inline void fillFromFileAttribute(DWORD fileAttribute, bool isDriveRoot = false);
202 inline void fillFromFindData(WIN32_FIND_DATA &findData, bool setLinkType = false, bool isDriveRoot = false);
203 inline void fillFromFindInfo(BY_HANDLE_FILE_INFORMATION &fileInfo);
204#endif
205private:
206 friend class QFileSystemEngine;
207
208 MetaDataFlags knownFlagsMask;
209 MetaDataFlags entryFlags;
210
211 qint64 size_ = 0;
212
213 // Platform-specific data goes here:
214#if defined(Q_OS_WIN)
215 DWORD fileAttribute_;
216 FILETIME birthTime_;
217 FILETIME changeTime_;
218 FILETIME lastAccessTime_;
219 FILETIME lastWriteTime_;
220#else
221 // msec precision
222 qint64 accessTime_ = 0;
223 qint64 birthTime_ = 0;
224 qint64 metadataChangeTime_ = 0;
225 qint64 modificationTime_ = 0;
226
227 uint userId_ = (uint) -2;
228 uint groupId_ = (uint) -2;
229#endif
230
231};
232
233Q_DECLARE_OPERATORS_FOR_FLAGS(QFileSystemMetaData::MetaDataFlags)
234
235inline QFile::Permissions QFileSystemMetaData::permissions() const { return QFile::Permissions::fromInt(i: (Permissions & entryFlags).toInt()); }
236
237#if defined(Q_OS_DARWIN)
238inline bool QFileSystemMetaData::isBundle() const { return entryFlags.testAnyFlag(BundleType); }
239inline bool QFileSystemMetaData::isAlias() const { return entryFlags.testAnyFlag(AliasType); }
240#else
241inline bool QFileSystemMetaData::isBundle() const { return false; }
242inline bool QFileSystemMetaData::isAlias() const { return false; }
243#endif
244
245#if defined(Q_OS_UNIX) || defined (Q_OS_WIN)
246inline QDateTime QFileSystemMetaData::fileTime(QAbstractFileEngine::FileTime time) const
247{
248 switch (time) {
249 case QAbstractFileEngine::ModificationTime:
250 return modificationTime();
251
252 case QAbstractFileEngine::AccessTime:
253 return accessTime();
254
255 case QAbstractFileEngine::BirthTime:
256 return birthTime();
257
258 case QAbstractFileEngine::MetadataChangeTime:
259 return metadataChangeTime();
260 }
261
262 return QDateTime();
263}
264#endif
265
266#if defined(Q_OS_UNIX)
267inline QDateTime QFileSystemMetaData::birthTime() const
268{
269 return birthTime_
270 ? QDateTime::fromMSecsSinceEpoch(msecs: birthTime_, timeZone: QTimeZone::UTC)
271 : QDateTime();
272}
273inline QDateTime QFileSystemMetaData::metadataChangeTime() const
274{
275 return metadataChangeTime_
276 ? QDateTime::fromMSecsSinceEpoch(msecs: metadataChangeTime_, timeZone: QTimeZone::UTC)
277 : QDateTime();
278}
279inline QDateTime QFileSystemMetaData::modificationTime() const
280{
281 return modificationTime_
282 ? QDateTime::fromMSecsSinceEpoch(msecs: modificationTime_, timeZone: QTimeZone::UTC)
283 : QDateTime();
284}
285inline QDateTime QFileSystemMetaData::accessTime() const
286{
287 return accessTime_
288 ? QDateTime::fromMSecsSinceEpoch(msecs: accessTime_, timeZone: QTimeZone::UTC)
289 : QDateTime();
290}
291
292inline uint QFileSystemMetaData::userId() const { return userId_; }
293inline uint QFileSystemMetaData::groupId() const { return groupId_; }
294
295inline uint QFileSystemMetaData::ownerId(QAbstractFileEngine::FileOwner owner) const
296{
297 if (owner == QAbstractFileEngine::OwnerUser)
298 return userId();
299 else
300 return groupId();
301}
302#endif
303
304#if defined(Q_OS_WIN)
305inline uint QFileSystemMetaData::userId() const { return (uint) -2; }
306inline uint QFileSystemMetaData::groupId() const { return (uint) -2; }
307inline uint QFileSystemMetaData::ownerId(QAbstractFileEngine::FileOwner owner) const
308{
309 if (owner == QAbstractFileEngine::OwnerUser)
310 return userId();
311 else
312 return groupId();
313}
314
315inline void QFileSystemMetaData::fillFromFileAttribute(DWORD fileAttribute,bool isDriveRoot)
316{
317 fileAttribute_ = fileAttribute;
318 // Ignore the hidden attribute for drives.
319 if (!isDriveRoot && (fileAttribute_ & FILE_ATTRIBUTE_HIDDEN))
320 entryFlags |= HiddenAttribute;
321 entryFlags |= ((fileAttribute & FILE_ATTRIBUTE_DIRECTORY) ? DirectoryType: FileType);
322 entryFlags |= ExistsAttribute;
323 knownFlagsMask |= FileType | DirectoryType | HiddenAttribute | ExistsAttribute;
324}
325
326inline void QFileSystemMetaData::fillFromFindData(WIN32_FIND_DATA &findData, bool setLinkType, bool isDriveRoot)
327{
328 fillFromFileAttribute(findData.dwFileAttributes, isDriveRoot);
329 birthTime_ = findData.ftCreationTime;
330 lastAccessTime_ = findData.ftLastAccessTime;
331 changeTime_ = lastWriteTime_ = findData.ftLastWriteTime;
332 if (fileAttribute_ & FILE_ATTRIBUTE_DIRECTORY) {
333 size_ = 0;
334 } else {
335 size_ = findData.nFileSizeHigh;
336 size_ <<= 32;
337 size_ += findData.nFileSizeLow;
338 }
339 knownFlagsMask |= Times | SizeAttribute;
340 if (setLinkType) {
341 knownFlagsMask |= LinkType;
342 entryFlags &= ~LinkType;
343 if (fileAttribute_ & FILE_ATTRIBUTE_REPARSE_POINT) {
344 if (findData.dwReserved0 == IO_REPARSE_TAG_SYMLINK) {
345 entryFlags |= LinkType;
346#if defined(IO_REPARSE_TAG_MOUNT_POINT)
347 } else if ((fileAttribute_ & FILE_ATTRIBUTE_DIRECTORY)
348 && (findData.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT)) {
349 entryFlags |= JunctionType;
350#endif
351 }
352 }
353 }
354}
355
356inline void QFileSystemMetaData::fillFromFindInfo(BY_HANDLE_FILE_INFORMATION &fileInfo)
357{
358 fillFromFileAttribute(fileInfo.dwFileAttributes);
359 birthTime_ = fileInfo.ftCreationTime;
360 lastAccessTime_ = fileInfo.ftLastAccessTime;
361 changeTime_ = lastWriteTime_ = fileInfo.ftLastWriteTime;
362 if (fileAttribute_ & FILE_ATTRIBUTE_DIRECTORY) {
363 size_ = 0;
364 } else {
365 size_ = fileInfo.nFileSizeHigh;
366 size_ <<= 32;
367 size_ += fileInfo.nFileSizeLow;
368 }
369 knownFlagsMask |= Times | SizeAttribute;
370}
371#endif // Q_OS_WIN
372
373QT_END_NAMESPACE
374
375#endif // include guard
376

source code of qtbase/src/corelib/io/qfilesystemmetadata_p.h