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