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
68 struct statx;
69 #endif
70
71 QT_BEGIN_NAMESPACE
72
73 class QFileSystemEngine;
74
75 class Q_AUTOTEST_EXPORT QFileSystemMetaData
76 {
77 public:
QFileSystemMetaData()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 };
Q_DECLARE_FLAGS(MetaDataFlags,MetaDataFlag)174 Q_DECLARE_FLAGS(MetaDataFlags, MetaDataFlag)
175
176 bool hasFlags(MetaDataFlags flags) const
177 {
178 return ((knownFlagsMask & flags) == flags);
179 }
180
missingFlags(MetaDataFlags flags)181 MetaDataFlags missingFlags(MetaDataFlags flags)
182 {
183 return flags & ~knownFlagsMask;
184 }
185
clear()186 void clear()
187 {
188 knownFlagsMask = {};
189 }
190
191 void clearFlags(MetaDataFlags flags = AllMetaDataFlags)
192 {
193 knownFlagsMask &= ~flags;
194 }
195
exists()196 bool exists() const { return (entryFlags & ExistsAttribute); }
197
isLink()198 bool isLink() const { return (entryFlags & LinkType); }
isFile()199 bool isFile() const { return (entryFlags & FileType); }
isDirectory()200 bool isDirectory() const { return (entryFlags & DirectoryType); }
201 bool isBundle() const;
202 bool isAlias() const;
isLegacyLink()203 bool isLegacyLink() const { return (entryFlags & LegacyLinkType); }
isSequential()204 bool isSequential() const { return (entryFlags & SequentialType); }
isHidden()205 bool isHidden() const { return (entryFlags & HiddenAttribute); }
wasDeleted()206 bool wasDeleted() const { return (entryFlags & WasDeletedAttribute); }
207 #if defined(Q_OS_WIN)
isLnkFile()208 bool isLnkFile() const { return (entryFlags & WinLnkType); }
isJunction()209 bool isJunction() const { return (entryFlags & JunctionType); }
210 #else
isLnkFile()211 bool isLnkFile() const { return false; }
isJunction()212 bool isJunction() const { return false; }
213 #endif
214
size()215 qint64 size() const { return size_; }
216
permissions()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 # ifndef Q_OS_WINRT
239 inline void fillFromFindInfo(BY_HANDLE_FILE_INFORMATION &fileInfo);
240 # endif
241 #endif
242 private:
243 friend class QFileSystemEngine;
244
245 MetaDataFlags knownFlagsMask;
246 MetaDataFlags entryFlags;
247
248 qint64 size_;
249
250 // Platform-specific data goes here:
251 #if defined(Q_OS_WIN)
252 DWORD fileAttribute_;
253 FILETIME birthTime_;
254 FILETIME changeTime_;
255 FILETIME lastAccessTime_;
256 FILETIME lastWriteTime_;
257 #else
258 // msec precision
259 qint64 accessTime_;
260 qint64 birthTime_;
261 qint64 metadataChangeTime_;
262 qint64 modificationTime_;
263
264 uint userId_;
265 uint groupId_;
266 #endif
267
268 };
269
Q_DECLARE_OPERATORS_FOR_FLAGS(QFileSystemMetaData::MetaDataFlags)270 Q_DECLARE_OPERATORS_FOR_FLAGS(QFileSystemMetaData::MetaDataFlags)
271
272 #if defined(Q_OS_DARWIN)
273 inline bool QFileSystemMetaData::isBundle() const { return (entryFlags & BundleType); }
isAlias()274 inline bool QFileSystemMetaData::isAlias() const { return (entryFlags & AliasType); }
275 #else
276 inline bool QFileSystemMetaData::isBundle() const { return false; }
277 inline bool QFileSystemMetaData::isAlias() const { return false; }
278 #endif
279
280 #if defined(Q_OS_UNIX) || defined (Q_OS_WIN)
fileTime(QAbstractFileEngine::FileTime time)281 inline QDateTime QFileSystemMetaData::fileTime(QAbstractFileEngine::FileTime time) const
282 {
283 switch (time) {
284 case QAbstractFileEngine::ModificationTime:
285 return modificationTime();
286
287 case QAbstractFileEngine::AccessTime:
288 return accessTime();
289
290 case QAbstractFileEngine::BirthTime:
291 return birthTime();
292
293 case QAbstractFileEngine::MetadataChangeTime:
294 return metadataChangeTime();
295 }
296
297 return QDateTime();
298 }
299 #endif
300
301 #if defined(Q_OS_UNIX)
birthTime()302 inline QDateTime QFileSystemMetaData::birthTime() const
303 { return birthTime_ ? QDateTime::fromMSecsSinceEpoch(birthTime_) : QDateTime(); }
metadataChangeTime()304 inline QDateTime QFileSystemMetaData::metadataChangeTime() const
305 { return metadataChangeTime_ ? QDateTime::fromMSecsSinceEpoch(metadataChangeTime_) : QDateTime(); }
modificationTime()306 inline QDateTime QFileSystemMetaData::modificationTime() const
307 { return modificationTime_ ? QDateTime::fromMSecsSinceEpoch(modificationTime_) : QDateTime(); }
accessTime()308 inline QDateTime QFileSystemMetaData::accessTime() const
309 { return accessTime_ ? QDateTime::fromMSecsSinceEpoch(accessTime_) : QDateTime(); }
310
userId()311 inline uint QFileSystemMetaData::userId() const { return userId_; }
groupId()312 inline uint QFileSystemMetaData::groupId() const { return groupId_; }
313
ownerId(QAbstractFileEngine::FileOwner owner)314 inline uint QFileSystemMetaData::ownerId(QAbstractFileEngine::FileOwner owner) const
315 {
316 if (owner == QAbstractFileEngine::OwnerUser)
317 return userId();
318 else
319 return groupId();
320 }
321 #endif
322
323 #if defined(Q_OS_WIN)
userId()324 inline uint QFileSystemMetaData::userId() const { return (uint) -2; }
groupId()325 inline uint QFileSystemMetaData::groupId() const { return (uint) -2; }
ownerId(QAbstractFileEngine::FileOwner owner)326 inline uint QFileSystemMetaData::ownerId(QAbstractFileEngine::FileOwner owner) const
327 {
328 if (owner == QAbstractFileEngine::OwnerUser)
329 return userId();
330 else
331 return groupId();
332 }
333
fillFromFileAttribute(DWORD fileAttribute,bool isDriveRoot)334 inline void QFileSystemMetaData::fillFromFileAttribute(DWORD fileAttribute,bool isDriveRoot)
335 {
336 fileAttribute_ = fileAttribute;
337 // Ignore the hidden attribute for drives.
338 if (!isDriveRoot && (fileAttribute_ & FILE_ATTRIBUTE_HIDDEN))
339 entryFlags |= HiddenAttribute;
340 entryFlags |= ((fileAttribute & FILE_ATTRIBUTE_DIRECTORY) ? DirectoryType: FileType);
341 entryFlags |= ExistsAttribute;
342 knownFlagsMask |= FileType | DirectoryType | HiddenAttribute | ExistsAttribute;
343 }
344
fillFromFindData(WIN32_FIND_DATA & findData,bool setLinkType,bool isDriveRoot)345 inline void QFileSystemMetaData::fillFromFindData(WIN32_FIND_DATA &findData, bool setLinkType, bool isDriveRoot)
346 {
347 fillFromFileAttribute(findData.dwFileAttributes, isDriveRoot);
348 birthTime_ = findData.ftCreationTime;
349 lastAccessTime_ = findData.ftLastAccessTime;
350 changeTime_ = lastWriteTime_ = findData.ftLastWriteTime;
351 if (fileAttribute_ & FILE_ATTRIBUTE_DIRECTORY) {
352 size_ = 0;
353 } else {
354 size_ = findData.nFileSizeHigh;
355 size_ <<= 32;
356 size_ += findData.nFileSizeLow;
357 }
358 knownFlagsMask |= Times | SizeAttribute;
359 if (setLinkType) {
360 knownFlagsMask |= LinkType;
361 entryFlags &= ~LinkType;
362 if (fileAttribute_ & FILE_ATTRIBUTE_REPARSE_POINT) {
363 if (findData.dwReserved0 == IO_REPARSE_TAG_SYMLINK) {
364 entryFlags |= LinkType;
365 #if defined(IO_REPARSE_TAG_MOUNT_POINT)
366 } else if ((fileAttribute_ & FILE_ATTRIBUTE_DIRECTORY)
367 && (findData.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT)) {
368 entryFlags |= JunctionType;
369 #endif
370 }
371 }
372 }
373 }
374
375 #ifndef Q_OS_WINRT
fillFromFindInfo(BY_HANDLE_FILE_INFORMATION & fileInfo)376 inline void QFileSystemMetaData::fillFromFindInfo(BY_HANDLE_FILE_INFORMATION &fileInfo)
377 {
378 fillFromFileAttribute(fileInfo.dwFileAttributes);
379 birthTime_ = fileInfo.ftCreationTime;
380 lastAccessTime_ = fileInfo.ftLastAccessTime;
381 changeTime_ = lastWriteTime_ = fileInfo.ftLastWriteTime;
382 if (fileAttribute_ & FILE_ATTRIBUTE_DIRECTORY) {
383 size_ = 0;
384 } else {
385 size_ = fileInfo.nFileSizeHigh;
386 size_ <<= 32;
387 size_ += fileInfo.nFileSizeLow;
388 }
389 knownFlagsMask |= Times | SizeAttribute;
390 }
391 #endif // !Q_OS_WINRT
392 #endif // Q_OS_WIN
393
394 QT_END_NAMESPACE
395
396 #endif // include guard
397