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 : size_(-1)
80 {
81 }
82
83 enum MetaDataFlag {
84 // Permissions, overlaps with QFile::Permissions
85 OtherReadPermission = 0x00000004, OtherWritePermission = 0x00000002, OtherExecutePermission = 0x00000001,
86 GroupReadPermission = 0x00000040, GroupWritePermission = 0x00000020, GroupExecutePermission = 0x00000010,
87 UserReadPermission = 0x00000400, UserWritePermission = 0x00000200, UserExecutePermission = 0x00000100,
88 OwnerReadPermission = 0x00004000, OwnerWritePermission = 0x00002000, OwnerExecutePermission = 0x00001000,
89
90 OtherPermissions = OtherReadPermission | OtherWritePermission | OtherExecutePermission,
91 GroupPermissions = GroupReadPermission | GroupWritePermission | GroupExecutePermission,
92 UserPermissions = UserReadPermission | UserWritePermission | UserExecutePermission,
93 OwnerPermissions = OwnerReadPermission | OwnerWritePermission | OwnerExecutePermission,
94
95 ReadPermissions = OtherReadPermission | GroupReadPermission | UserReadPermission | OwnerReadPermission,
96 WritePermissions = OtherWritePermission | GroupWritePermission | UserWritePermission | OwnerWritePermission,
97 ExecutePermissions = OtherExecutePermission | GroupExecutePermission | UserExecutePermission | OwnerExecutePermission,
98
99 Permissions = OtherPermissions | GroupPermissions | UserPermissions | OwnerPermissions,
100
101 // Type
102 LinkType = 0x00010000,
103 FileType = 0x00020000,
104 DirectoryType = 0x00040000,
105#if defined(Q_OS_DARWIN)
106 BundleType = 0x00080000,
107 AliasType = 0x08000000,
108#else
109 BundleType = 0x0,
110 AliasType = 0x0,
111#endif
112#if defined(Q_OS_WIN)
113 JunctionType = 0x04000000,
114 WinLnkType = 0x08000000, // Note: Uses the same position for AliasType on Mac
115#else
116 JunctionType = 0x0,
117 WinLnkType = 0x0,
118#endif
119 SequentialType = 0x00800000, // Note: overlaps with QAbstractFileEngine::RootFlag
120
121 LegacyLinkType = LinkType | AliasType | WinLnkType,
122
123 Type = LinkType | FileType | DirectoryType | BundleType | SequentialType | AliasType,
124
125 // Attributes
126 HiddenAttribute = 0x00100000,
127 SizeAttribute = 0x00200000, // Note: overlaps with QAbstractFileEngine::LocalDiskFlag
128 ExistsAttribute = 0x00400000, // For historical reasons, indicates existence of data, not the file
129#if defined(Q_OS_WIN)
130 WasDeletedAttribute = 0x0,
131#else
132 WasDeletedAttribute = 0x40000000, // Indicates the file was deleted
133#endif
134
135 Attributes = HiddenAttribute | SizeAttribute | ExistsAttribute | WasDeletedAttribute,
136
137 // Times - if we know one of them, we know them all
138 AccessTime = 0x02000000,
139 BirthTime = 0x02000000,
140 MetadataChangeTime = 0x02000000,
141 ModificationTime = 0x02000000,
142
143 Times = AccessTime | BirthTime | MetadataChangeTime | ModificationTime,
144
145 // Owner IDs
146 UserId = 0x10000000,
147 GroupId = 0x20000000,
148
149 OwnerIds = UserId | GroupId,
150
151 PosixStatFlags = QFileSystemMetaData::OtherPermissions
152 | QFileSystemMetaData::GroupPermissions
153 | QFileSystemMetaData::OwnerPermissions
154 | QFileSystemMetaData::FileType
155 | QFileSystemMetaData::DirectoryType
156 | QFileSystemMetaData::SequentialType
157 | QFileSystemMetaData::SizeAttribute
158 | QFileSystemMetaData::WasDeletedAttribute
159 | QFileSystemMetaData::Times
160 | QFileSystemMetaData::OwnerIds,
161
162#if defined(Q_OS_WIN)
163 WinStatFlags = QFileSystemMetaData::FileType
164 | QFileSystemMetaData::DirectoryType
165 | QFileSystemMetaData::HiddenAttribute
166 | QFileSystemMetaData::ExistsAttribute
167 | QFileSystemMetaData::SizeAttribute
168 | QFileSystemMetaData::Times,
169#endif
170
171 AllMetaDataFlags = 0xFFFFFFFF
172
173 };
174 Q_DECLARE_FLAGS(MetaDataFlags, MetaDataFlag)
175
176 bool hasFlags(MetaDataFlags flags) const
177 {
178 return ((knownFlagsMask & flags) == flags);
179 }
180
181 MetaDataFlags missingFlags(MetaDataFlags flags)
182 {
183 return flags & ~knownFlagsMask;
184 }
185
186 void clear()
187 {
188 knownFlagsMask = {};
189 }
190
191 void clearFlags(MetaDataFlags flags = AllMetaDataFlags)
192 {
193 knownFlagsMask &= ~flags;
194 }
195
196 bool exists() const { return (entryFlags & ExistsAttribute); }
197
198 bool isLink() const { return (entryFlags & LinkType); }
199 bool isFile() const { return (entryFlags & FileType); }
200 bool isDirectory() const { return (entryFlags & DirectoryType); }
201 bool isBundle() const;
202 bool isAlias() const;
203 bool isLegacyLink() const { return (entryFlags & LegacyLinkType); }
204 bool isSequential() const { return (entryFlags & SequentialType); }
205 bool isHidden() const { return (entryFlags & HiddenAttribute); }
206 bool wasDeleted() const { return (entryFlags & WasDeletedAttribute); }
207#if defined(Q_OS_WIN)
208 bool isLnkFile() const { return (entryFlags & WinLnkType); }
209 bool isJunction() const { return (entryFlags & JunctionType); }
210#else
211 bool isLnkFile() const { return false; }
212 bool isJunction() const { return false; }
213#endif
214
215 qint64 size() const { return size_; }
216
217 QFile::Permissions permissions() const { return QFile::Permissions(Permissions & entryFlags); }
218
219 QDateTime accessTime() const;
220 QDateTime birthTime() const;
221 QDateTime metadataChangeTime() const;
222 QDateTime modificationTime() const;
223
224 QDateTime fileTime(QAbstractFileEngine::FileTime time) const;
225 uint userId() const;
226 uint groupId() const;
227 uint ownerId(QAbstractFileEngine::FileOwner owner) const;
228
229#ifdef Q_OS_UNIX
230 void fillFromStatxBuf(const struct statx &statBuffer);
231 void fillFromStatBuf(const QT_STATBUF &statBuffer);
232 void fillFromDirEnt(const QT_DIRENT &statBuffer);
233#endif
234
235#if defined(Q_OS_WIN)
236 inline void fillFromFileAttribute(DWORD fileAttribute, bool isDriveRoot = false);
237 inline void fillFromFindData(WIN32_FIND_DATA &findData, bool setLinkType = false, bool isDriveRoot = false);
238 inline void fillFromFindInfo(BY_HANDLE_FILE_INFORMATION &fileInfo);
239#endif
240private:
241 friend class QFileSystemEngine;
242
243 MetaDataFlags knownFlagsMask;
244 MetaDataFlags entryFlags;
245
246 qint64 size_;
247
248 // Platform-specific data goes here:
249#if defined(Q_OS_WIN)
250 DWORD fileAttribute_;
251 FILETIME birthTime_;
252 FILETIME changeTime_;
253 FILETIME lastAccessTime_;
254 FILETIME lastWriteTime_;
255#else
256 // msec precision
257 qint64 accessTime_;
258 qint64 birthTime_;
259 qint64 metadataChangeTime_;
260 qint64 modificationTime_;
261
262 uint userId_;
263 uint groupId_;
264#endif
265
266};
267
268Q_DECLARE_OPERATORS_FOR_FLAGS(QFileSystemMetaData::MetaDataFlags)
269
270#if defined(Q_OS_DARWIN)
271inline bool QFileSystemMetaData::isBundle() const { return (entryFlags & BundleType); }
272inline bool QFileSystemMetaData::isAlias() const { return (entryFlags & AliasType); }
273#else
274inline bool QFileSystemMetaData::isBundle() const { return false; }
275inline bool QFileSystemMetaData::isAlias() const { return false; }
276#endif
277
278#if defined(Q_OS_UNIX) || defined (Q_OS_WIN)
279inline QDateTime QFileSystemMetaData::fileTime(QAbstractFileEngine::FileTime time) const
280{
281 switch (time) {
282 case QAbstractFileEngine::ModificationTime:
283 return modificationTime();
284
285 case QAbstractFileEngine::AccessTime:
286 return accessTime();
287
288 case QAbstractFileEngine::BirthTime:
289 return birthTime();
290
291 case QAbstractFileEngine::MetadataChangeTime:
292 return metadataChangeTime();
293 }
294
295 return QDateTime();
296}
297#endif
298
299#if defined(Q_OS_UNIX)
300inline QDateTime QFileSystemMetaData::birthTime() const
301{ return birthTime_ ? QDateTime::fromMSecsSinceEpoch(birthTime_) : QDateTime(); }
302inline QDateTime QFileSystemMetaData::metadataChangeTime() const
303{ return metadataChangeTime_ ? QDateTime::fromMSecsSinceEpoch(metadataChangeTime_) : QDateTime(); }
304inline QDateTime QFileSystemMetaData::modificationTime() const
305{ return modificationTime_ ? QDateTime::fromMSecsSinceEpoch(modificationTime_) : QDateTime(); }
306inline QDateTime QFileSystemMetaData::accessTime() const
307{ return accessTime_ ? QDateTime::fromMSecsSinceEpoch(accessTime_) : QDateTime(); }
308
309inline uint QFileSystemMetaData::userId() const { return userId_; }
310inline uint QFileSystemMetaData::groupId() const { return groupId_; }
311
312inline uint QFileSystemMetaData::ownerId(QAbstractFileEngine::FileOwner owner) const
313{
314 if (owner == QAbstractFileEngine::OwnerUser)
315 return userId();
316 else
317 return groupId();
318}
319#endif
320
321#if defined(Q_OS_WIN)
322inline uint QFileSystemMetaData::userId() const { return (uint) -2; }
323inline uint QFileSystemMetaData::groupId() const { return (uint) -2; }
324inline uint QFileSystemMetaData::ownerId(QAbstractFileEngine::FileOwner owner) const
325{
326 if (owner == QAbstractFileEngine::OwnerUser)
327 return userId();
328 else
329 return groupId();
330}
331
332inline void QFileSystemMetaData::fillFromFileAttribute(DWORD fileAttribute,bool isDriveRoot)
333{
334 fileAttribute_ = fileAttribute;
335 // Ignore the hidden attribute for drives.
336 if (!isDriveRoot && (fileAttribute_ & FILE_ATTRIBUTE_HIDDEN))
337 entryFlags |= HiddenAttribute;
338 entryFlags |= ((fileAttribute & FILE_ATTRIBUTE_DIRECTORY) ? DirectoryType: FileType);
339 entryFlags |= ExistsAttribute;
340 knownFlagsMask |= FileType | DirectoryType | HiddenAttribute | ExistsAttribute;
341}
342
343inline void QFileSystemMetaData::fillFromFindData(WIN32_FIND_DATA &findData, bool setLinkType, bool isDriveRoot)
344{
345 fillFromFileAttribute(findData.dwFileAttributes, isDriveRoot);
346 birthTime_ = findData.ftCreationTime;
347 lastAccessTime_ = findData.ftLastAccessTime;
348 changeTime_ = lastWriteTime_ = findData.ftLastWriteTime;
349 if (fileAttribute_ & FILE_ATTRIBUTE_DIRECTORY) {
350 size_ = 0;
351 } else {
352 size_ = findData.nFileSizeHigh;
353 size_ <<= 32;
354 size_ += findData.nFileSizeLow;
355 }
356 knownFlagsMask |= Times | SizeAttribute;
357 if (setLinkType) {
358 knownFlagsMask |= LinkType;
359 entryFlags &= ~LinkType;
360 if (fileAttribute_ & FILE_ATTRIBUTE_REPARSE_POINT) {
361 if (findData.dwReserved0 == IO_REPARSE_TAG_SYMLINK) {
362 entryFlags |= LinkType;
363#if defined(IO_REPARSE_TAG_MOUNT_POINT)
364 } else if ((fileAttribute_ & FILE_ATTRIBUTE_DIRECTORY)
365 && (findData.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT)) {
366 entryFlags |= JunctionType;
367#endif
368 }
369 }
370 }
371}
372
373inline void QFileSystemMetaData::fillFromFindInfo(BY_HANDLE_FILE_INFORMATION &fileInfo)
374{
375 fillFromFileAttribute(fileInfo.dwFileAttributes);
376 birthTime_ = fileInfo.ftCreationTime;
377 lastAccessTime_ = fileInfo.ftLastAccessTime;
378 changeTime_ = lastWriteTime_ = fileInfo.ftLastWriteTime;
379 if (fileAttribute_ & FILE_ATTRIBUTE_DIRECTORY) {
380 size_ = 0;
381 } else {
382 size_ = fileInfo.nFileSizeHigh;
383 size_ <<= 32;
384 size_ += fileInfo.nFileSizeLow;
385 }
386 knownFlagsMask |= Times | SizeAttribute;
387}
388#endif // Q_OS_WIN
389
390QT_END_NAMESPACE
391
392#endif // include guard
393