1// Copyright (C) 2020 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#include "qplatformdefs.h"
5#include "qfileinfo.h"
6#include "qglobal.h"
7#include "qdir.h"
8#include "qfileinfo_p.h"
9#include "qdebug.h"
10
11QT_BEGIN_NAMESPACE
12
13using namespace Qt::StringLiterals;
14
15QT_IMPL_METATYPE_EXTERN(QFileInfo)
16
17QString QFileInfoPrivate::getFileName(QAbstractFileEngine::FileName name) const
18{
19 if (cache_enabled && !fileNames[(int)name].isNull())
20 return fileNames[(int)name];
21
22 QString ret;
23 if (fileEngine == nullptr) { // local file; use the QFileSystemEngine directly
24 switch (name) {
25 case QAbstractFileEngine::CanonicalName:
26 case QAbstractFileEngine::CanonicalPathName: {
27 QFileSystemEntry entry = QFileSystemEngine::canonicalName(entry: fileEntry, data&: metaData);
28 if (cache_enabled) { // be smart and store both
29 fileNames[QAbstractFileEngine::CanonicalName] = entry.filePath();
30 fileNames[QAbstractFileEngine::CanonicalPathName] = entry.path();
31 }
32 if (name == QAbstractFileEngine::CanonicalName)
33 ret = entry.filePath();
34 else
35 ret = entry.path();
36 break;
37 }
38 case QAbstractFileEngine::AbsoluteLinkTarget:
39 ret = QFileSystemEngine::getLinkTarget(link: fileEntry, data&: metaData).filePath();
40 break;
41 case QAbstractFileEngine::RawLinkPath:
42 ret = QFileSystemEngine::getRawLinkPath(link: fileEntry, data&: metaData).filePath();
43 break;
44 case QAbstractFileEngine::JunctionName:
45 ret = QFileSystemEngine::getJunctionTarget(link: fileEntry, data&: metaData).filePath();
46 break;
47 case QAbstractFileEngine::BundleName:
48 ret = QFileSystemEngine::bundleName(fileEntry);
49 break;
50 case QAbstractFileEngine::AbsoluteName:
51 case QAbstractFileEngine::AbsolutePathName: {
52 QFileSystemEntry entry = QFileSystemEngine::absoluteName(entry: fileEntry);
53 if (cache_enabled) { // be smart and store both
54 fileNames[QAbstractFileEngine::AbsoluteName] = entry.filePath();
55 fileNames[QAbstractFileEngine::AbsolutePathName] = entry.path();
56 }
57 if (name == QAbstractFileEngine::AbsoluteName)
58 ret = entry.filePath();
59 else
60 ret = entry.path();
61 break;
62 }
63 default: break;
64 }
65 } else {
66 ret = fileEngine->fileName(file: name);
67 }
68 if (ret.isNull())
69 ret = ""_L1;
70 if (cache_enabled)
71 fileNames[(int)name] = ret;
72 return ret;
73}
74
75QString QFileInfoPrivate::getFileOwner(QAbstractFileEngine::FileOwner own) const
76{
77 if (cache_enabled && !fileOwners[(int)own].isNull())
78 return fileOwners[(int)own];
79 QString ret;
80 if (fileEngine == nullptr) {
81 switch (own) {
82 case QAbstractFileEngine::OwnerUser:
83 ret = QFileSystemEngine::resolveUserName(entry: fileEntry, data&: metaData);
84 break;
85 case QAbstractFileEngine::OwnerGroup:
86 ret = QFileSystemEngine::resolveGroupName(entry: fileEntry, data&: metaData);
87 break;
88 }
89 } else {
90 ret = fileEngine->owner(own);
91 }
92 if (ret.isNull())
93 ret = ""_L1;
94 if (cache_enabled)
95 fileOwners[(int)own] = ret;
96 return ret;
97}
98
99uint QFileInfoPrivate::getFileFlags(QAbstractFileEngine::FileFlags request) const
100{
101 Q_ASSERT(fileEngine); // should never be called when using the native FS
102 // We split the testing into tests for for LinkType, BundleType, PermsMask
103 // and the rest.
104 // Tests for file permissions on Windows can be slow, especially on network
105 // paths and NTFS drives.
106 // In order to determine if a file is a symlink or not, we have to lstat().
107 // If we're not interested in that information, we might as well avoid one
108 // extra syscall. Bundle detecton on Mac can be slow, especially on network
109 // paths, so we separate out that as well.
110
111 QAbstractFileEngine::FileFlags req;
112 uint cachedFlags = 0;
113
114 if (request & (QAbstractFileEngine::FlagsMask | QAbstractFileEngine::TypesMask)) {
115 if (!getCachedFlag(c: CachedFileFlags)) {
116 req |= QAbstractFileEngine::FlagsMask;
117 req |= QAbstractFileEngine::TypesMask;
118 req &= (~QAbstractFileEngine::LinkType);
119 req &= (~QAbstractFileEngine::BundleType);
120
121 cachedFlags |= CachedFileFlags;
122 }
123
124 if (request & QAbstractFileEngine::LinkType) {
125 if (!getCachedFlag(c: CachedLinkTypeFlag)) {
126 req |= QAbstractFileEngine::LinkType;
127 cachedFlags |= CachedLinkTypeFlag;
128 }
129 }
130
131 if (request & QAbstractFileEngine::BundleType) {
132 if (!getCachedFlag(c: CachedBundleTypeFlag)) {
133 req |= QAbstractFileEngine::BundleType;
134 cachedFlags |= CachedBundleTypeFlag;
135 }
136 }
137 }
138
139 if (request & QAbstractFileEngine::PermsMask) {
140 if (!getCachedFlag(c: CachedPerms)) {
141 req |= QAbstractFileEngine::PermsMask;
142 cachedFlags |= CachedPerms;
143 }
144 }
145
146 if (req) {
147 if (cache_enabled)
148 req &= (~QAbstractFileEngine::Refresh);
149 else
150 req |= QAbstractFileEngine::Refresh;
151
152 QAbstractFileEngine::FileFlags flags = fileEngine->fileFlags(type: req);
153 fileFlags |= uint(flags.toInt());
154 setCachedFlag(cachedFlags);
155 }
156
157 return fileFlags & request.toInt();
158}
159
160QDateTime &QFileInfoPrivate::getFileTime(QFile::FileTime request) const
161{
162 Q_ASSERT(fileEngine); // should never be called when using the native FS
163 if (!cache_enabled)
164 clearFlags();
165
166 uint cf = 0;
167 switch (request) {
168 case QFile::FileAccessTime:
169 cf = CachedATime;
170 break;
171 case QFile::FileBirthTime:
172 cf = CachedBTime;
173 break;
174 case QFile::FileMetadataChangeTime:
175 cf = CachedMCTime;
176 break;
177 case QFile::FileModificationTime:
178 cf = CachedMTime;
179 break;
180 }
181
182 if (!getCachedFlag(c: cf)) {
183 fileTimes[request] = fileEngine->fileTime(time: request);
184 setCachedFlag(cf);
185 }
186 return fileTimes[request];
187}
188
189//************* QFileInfo
190
191/*!
192 \class QFileInfo
193 \inmodule QtCore
194 \reentrant
195 \brief The QFileInfo class provides an OS-independent API to retrieve
196 information about file system entries.
197
198 \ingroup io
199 \ingroup shared
200
201 \compares equality
202
203 QFileInfo provides information about a file system entry, such as its
204 name, path, access rights and whether it is a regular file, directory or
205 symbolic link. The entry's size and last modified/read times are also
206 available. QFileInfo can also be used to obtain information about a Qt
207 \l{resource system}{resource}.
208
209 A QFileInfo can point to a file system entry with either an absolute or
210 a relative path:
211 \list
212 \li \include qfileinfo.cpp absolute-path-unix-windows
213
214 \li \include qfileinfo.cpp relative-path-note
215 \endlist
216
217 An example of an absolute path is the string \c {"/tmp/quartz"}. A relative
218 path may look like \c {"src/fatlib"}. You can use the function isRelative()
219 to check whether a QFileInfo is using a relative or an absolute path. You
220 can call the function makeAbsolute() to convert a relative QFileInfo's
221 path to an absolute path.
222
223//! [qresource-virtual-fs-colon]
224 \note Paths starting with a colon (\e{:}) are always considered
225 absolute, as they denote a QResource.
226//! [qresource-virtual-fs-colon]
227
228 The file system entry path that the QFileInfo works on is set in the
229 constructor or later with setFile(). Use exists() to see if the entry
230 actually exists and size() to get its size.
231
232 The file system entry's type is obtained with isFile(), isDir(), and
233 isSymLink(). The symLinkTarget() function provides the absolute path of
234 the target the symlink points to.
235
236 The path elements of the file system entry can be extracted with path()
237 and fileName(). The fileName()'s parts can be extracted with baseName(),
238 suffix(), or completeSuffix(). QFileInfo objects referring to directories
239 created by Qt classes will not have a trailing directory separator
240 \c{'/'}. If you wish to use trailing separators in your own file info
241 objects, just append one to the entry's path given to the constructors
242 or setFile().
243
244 Date and time related information are returned by birthTime(), fileTime(),
245 lastModified(), lastRead(), and metadataChangeTime().
246 Information about
247 access permissions can be obtained with isReadable(), isWritable(), and
248 isExecutable(). Ownership information can be obtained with
249 owner(), ownerId(), group(), and groupId(). You can also examine
250 permissions and ownership in a single statement using the permission()
251 function.
252
253 \section1 Symbolic Links and Shortcuts
254
255 On Unix (including \macos and iOS), the property getter functions in
256 this class return the properties such as times and size of the target,
257 not the symlink, because Unix handles symlinks transparently. Opening
258 a symlink using QFile effectively opens the link's target. For example:
259
260 \snippet code/src_corelib_io_qfileinfo.cpp 0
261
262 On Windows, shortcuts (\c .lnk files) are currently treated as symlinks. As
263 on Unix systems, the property getters return the size of the target,
264 not the \c .lnk file itself. This behavior is deprecated and will likely
265 be removed in a future version of Qt, after which \c .lnk files will be
266 treated as regular files.
267
268 \snippet code/src_corelib_io_qfileinfo.cpp 1
269
270 \section1 NTFS permissions
271
272 On NTFS file systems, ownership and permissions checking is
273 disabled by default for performance reasons. To enable it,
274 include the following line:
275
276 \snippet ntfsp.cpp 0
277
278 Permission checking is then turned on and off by incrementing and
279 decrementing \c qt_ntfs_permission_lookup by 1.
280
281 \snippet ntfsp.cpp 1
282
283 \note Since this is a non-atomic global variable, it is only safe
284 to increment or decrement \c qt_ntfs_permission_lookup before any
285 threads other than the main thread have started or after every thread
286 other than the main thread has ended.
287
288 \note From Qt 6.6 the variable \c qt_ntfs_permission_lookup is
289 deprecated. Please use the following alternatives.
290
291 The safe and easy way to manage permission checks is to use the RAII class
292 \c QNtfsPermissionCheckGuard.
293
294 \snippet ntfsp.cpp raii
295
296 If you need more fine-grained control, it is possible to manage the permission
297 with the following functions instead:
298
299 \snippet ntfsp.cpp free-funcs
300
301 \section1 Performance Considerations
302
303 Some of QFileInfo's functions have to query the file system, but for
304 performance reasons, some functions only operate on the path string.
305 For example: To return the absolute path of a relative entry's path,
306 absolutePath() has to query the file system. The path() function, however,
307 can work on the file name directly, and so it is faster.
308
309 QFileInfo also caches information about the file system entry it refers
310 to. Because the file system can be changed by other users or programs,
311 or even by other parts of the same program, there is a function that
312 refreshes the information stored in QFileInfo, namely refresh(). To switch
313 off a QFileInfo's caching (that is, force it to query the underlying file
314 system every time you request information from it), call setCaching(false).
315
316 Fetching information from the file system is typically done by calling
317 (possibly) expensive system functions, so QFileInfo (depending on the
318 implementation) might not fetch all the information from the file system
319 at construction. To make sure that all information is read from the file
320 system immediately, use the stat() member function.
321
322 \l{birthTime()}, \l{fileTime()}, \l{lastModified()}, \l{lastRead()},
323 and \l{metadataChangeTime()} return times in \e{local time} by default.
324 Since native file system API typically uses UTC, this requires a conversion.
325 If you don't actually need the local time, you can avoid this by requesting
326 the time in QTimeZone::UTC directly.
327
328 \section1 Platform Specific Issues
329
330 \include android-content-uri-limitations.qdocinc
331
332 \sa QDir, QFile
333*/
334
335/*!
336 \fn QFileInfo &QFileInfo::operator=(QFileInfo &&other)
337
338 Move-assigns \a other to this QFileInfo instance.
339
340 \since 5.2
341*/
342
343/*!
344 \internal
345*/
346QFileInfo::QFileInfo(QFileInfoPrivate *p) : d_ptr(p)
347{
348}
349
350/*!
351 Constructs an empty QFileInfo object that doesn't refer to any file
352 system entry.
353
354 \sa setFile()
355*/
356QFileInfo::QFileInfo() : d_ptr(new QFileInfoPrivate())
357{
358}
359
360/*!
361 Constructs a QFileInfo that gives information about a file system entry
362 located at \a path that can be absolute or relative.
363
364//! [preserve-relative-path]
365 If \a path is relative, the QFileInfo will also have a relative path.
366//! [preserve-relative-path]
367
368 \sa setFile(), isRelative(), QDir::setCurrent(), QDir::isRelativePath()
369*/
370QFileInfo::QFileInfo(const QString &path) : d_ptr(new QFileInfoPrivate(path))
371{
372}
373
374/*!
375 Constructs a new QFileInfo that gives information about file \a
376 file.
377
378 If the \a file has a relative path, the QFileInfo will also have a
379 relative path.
380
381 \sa isRelative()
382*/
383QFileInfo::QFileInfo(const QFileDevice &file) : d_ptr(new QFileInfoPrivate(file.fileName()))
384{
385}
386
387/*!
388 Constructs a new QFileInfo that gives information about the given
389 file system entry \a path that is relative to the directory \a dir.
390
391//! [preserve-relative-or-absolute]
392 If \a dir has a relative path, the QFileInfo will also have a
393 relative path.
394
395 If \a path is absolute, then the directory specified by \a dir
396 will be disregarded.
397//! [preserve-relative-or-absolute]
398
399 \sa isRelative()
400*/
401QFileInfo::QFileInfo(const QDir &dir, const QString &path)
402 : d_ptr(new QFileInfoPrivate(dir.filePath(fileName: path)))
403{
404}
405
406/*!
407 Constructs a new QFileInfo that is a copy of the given \a fileinfo.
408*/
409QFileInfo::QFileInfo(const QFileInfo &fileinfo)
410 : d_ptr(fileinfo.d_ptr)
411{
412
413}
414
415/*!
416 Destroys the QFileInfo and frees its resources.
417*/
418
419QFileInfo::~QFileInfo()
420{
421}
422
423/*!
424 \fn bool QFileInfo::operator!=(const QFileInfo &lhs, const QFileInfo &rhs)
425
426 Returns \c true if QFileInfo \a lhs refers to a different file system
427 entry than the one referred to by \a rhs; otherwise returns \c false.
428
429 \sa operator==()
430*/
431
432/*!
433 \fn bool QFileInfo::operator==(const QFileInfo &lhs, const QFileInfo &rhs)
434
435 Returns \c true if QFileInfo \a lhs and QFileInfo \a rhs refer to the same
436 entry on the file system; otherwise returns \c false.
437
438 Note that the result of comparing two empty QFileInfo objects, containing
439 no file system entry references (paths that do not exist or are empty),
440 is undefined.
441
442 \warning This will not compare two different symbolic links pointing to
443 the same target.
444
445 \warning On Windows, long and short paths that refer to the same file
446 system entry are treated as if they referred to different entries.
447
448 \sa operator!=()
449*/
450bool comparesEqual(const QFileInfo &lhs, const QFileInfo &rhs)
451{
452 if (rhs.d_ptr == lhs.d_ptr)
453 return true;
454 if (lhs.d_ptr->isDefaultConstructed || rhs.d_ptr->isDefaultConstructed)
455 return false;
456
457 // Assume files are the same if path is the same
458 if (lhs.d_ptr->fileEntry.filePath() == rhs.d_ptr->fileEntry.filePath())
459 return true;
460
461 Qt::CaseSensitivity sensitive;
462 if (lhs.d_ptr->fileEngine == nullptr || rhs.d_ptr->fileEngine == nullptr) {
463 if (lhs.d_ptr->fileEngine != rhs.d_ptr->fileEngine) // one is native, the other is a custom file-engine
464 return false;
465
466 const bool lhsCaseSensitive = QFileSystemEngine::isCaseSensitive(entry: lhs.d_ptr->fileEntry, data&: lhs.d_ptr->metaData);
467 if (lhsCaseSensitive != QFileSystemEngine::isCaseSensitive(entry: rhs.d_ptr->fileEntry, data&: rhs.d_ptr->metaData))
468 return false;
469
470 sensitive = lhsCaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
471 } else {
472 if (lhs.d_ptr->fileEngine->caseSensitive() != rhs.d_ptr->fileEngine->caseSensitive())
473 return false;
474 sensitive = lhs.d_ptr->fileEngine->caseSensitive() ? Qt::CaseSensitive : Qt::CaseInsensitive;
475 }
476
477 // Fallback to expensive canonical path computation
478 return lhs.canonicalFilePath().compare(s: rhs.canonicalFilePath(), cs: sensitive) == 0;
479}
480
481/*!
482 Makes a copy of the given \a fileinfo and assigns it to this QFileInfo.
483*/
484QFileInfo &QFileInfo::operator=(const QFileInfo &fileinfo)
485{
486 d_ptr = fileinfo.d_ptr;
487 return *this;
488}
489
490/*!
491 \fn void QFileInfo::swap(QFileInfo &other)
492 \since 5.0
493
494 Swaps this file info with \a other. This function is very fast and
495 never fails.
496*/
497
498/*!
499 Sets the path of the file system entry that this QFileInfo provides
500 information about to \a path that can be absolute or relative.
501
502//! [absolute-path-unix-windows]
503 On Unix, absolute paths begin with the directory separator \c {'/'}.
504 On Windows, absolute paths begin with a drive specification (for example,
505 \c {D:/}).
506//! [ absolute-path-unix-windows]
507
508//! [relative-path-note]
509 Relative paths begin with a directory name or a regular file name and
510 specify a file system entry's path relative to the current working
511 directory.
512//! [relative-path-note]
513
514 Example:
515 \snippet code/src_corelib_io_qfileinfo.cpp 2
516
517 \sa isRelative(), QDir::setCurrent(), QDir::isRelativePath()
518*/
519void QFileInfo::setFile(const QString &path)
520{
521 bool caching = d_ptr.constData()->cache_enabled;
522 *this = QFileInfo(path);
523 d_ptr->cache_enabled = caching;
524}
525
526/*!
527 \overload
528
529 Sets the file that the QFileInfo provides information about to \a
530 file.
531
532 If \a file includes a relative path, the QFileInfo will also have
533 a relative path.
534
535 \sa isRelative()
536*/
537void QFileInfo::setFile(const QFileDevice &file)
538{
539 setFile(file.fileName());
540}
541
542/*!
543 \overload
544
545 Sets the path of the file system entry that this QFileInfo provides
546 information about to \a path in directory \a dir.
547
548 \include qfileinfo.cpp preserve-relative-or-absolute
549
550 \sa isRelative()
551*/
552void QFileInfo::setFile(const QDir &dir, const QString &path)
553{
554 setFile(dir.filePath(fileName: path));
555}
556
557/*!
558 Returns the absolute full path to the file system entry this QFileInfo
559 refers to, including the entry's name.
560
561 \include qfileinfo.cpp absolute-path-unix-windows
562
563//! [windows-network-shares]
564 On Windows, the paths of network shares that are not mapped to a drive
565 letter begin with \c{//sharename/}.
566//! [windows-network-shares]
567
568 QFileInfo will uppercase drive letters. Note that QDir does not do
569 this. The code snippet below shows this.
570
571 \snippet code/src_corelib_io_qfileinfo.cpp newstuff
572
573 This function returns the same as filePath(), unless isRelative()
574 is true. In contrast to canonicalFilePath(), symbolic links or
575 redundant "." or ".." elements are not necessarily removed.
576
577 \warning If filePath() is empty the behavior of this function
578 is undefined.
579
580 \sa filePath(), canonicalFilePath(), isRelative()
581*/
582QString QFileInfo::absoluteFilePath() const
583{
584 Q_D(const QFileInfo);
585 if (d->isDefaultConstructed)
586 return ""_L1;
587 return d->getFileName(name: QAbstractFileEngine::AbsoluteName);
588}
589
590/*!
591 Returns the file system entry's canonical path, including the entry's
592 name, that is, an absolute path without symbolic links or redundant
593 \c{'.'} or \c{'..'} elements.
594
595 If the entry does not exist, canonicalFilePath() returns an empty
596 string.
597
598 \sa filePath(), absoluteFilePath(), dir()
599*/
600QString QFileInfo::canonicalFilePath() const
601{
602 Q_D(const QFileInfo);
603 if (d->isDefaultConstructed)
604 return ""_L1;
605 return d->getFileName(name: QAbstractFileEngine::CanonicalName);
606}
607
608
609/*!
610 Returns the absolute path of the file system entry this QFileInfo refers to,
611 excluding the entry's name.
612
613 \include qfileinfo.cpp absolute-path-unix-windows
614
615 \include qfileinfo.cpp windows-network-shares
616
617 In contrast to canonicalPath() symbolic links or redundant "." or
618 ".." elements are not necessarily removed.
619
620 \warning If filePath() is empty the behavior of this function
621 is undefined.
622
623 \sa absoluteFilePath(), path(), canonicalPath(), fileName(), isRelative()
624*/
625QString QFileInfo::absolutePath() const
626{
627 Q_D(const QFileInfo);
628
629 if (d->isDefaultConstructed)
630 return ""_L1;
631 return d->getFileName(name: QAbstractFileEngine::AbsolutePathName);
632}
633
634/*!
635 Returns the file system entry's canonical path (excluding the entry's name),
636 i.e. an absolute path without symbolic links or redundant "." or ".." elements.
637
638 If the entry does not exist, this method returns an empty string.
639
640 \sa path(), absolutePath()
641*/
642QString QFileInfo::canonicalPath() const
643{
644 Q_D(const QFileInfo);
645 if (d->isDefaultConstructed)
646 return ""_L1;
647 return d->getFileName(name: QAbstractFileEngine::CanonicalPathName);
648}
649
650/*!
651 Returns the path of the file system entry this QFileInfo refers to,
652 excluding the entry's name.
653
654 \include qfileinfo.cpp path-ends-with-slash-empty-name-component
655 In this case, this function will return the entire path.
656
657 \sa filePath(), absolutePath(), canonicalPath(), dir(), fileName(), isRelative()
658*/
659QString QFileInfo::path() const
660{
661 Q_D(const QFileInfo);
662 if (d->isDefaultConstructed)
663 return ""_L1;
664 return d->fileEntry.path();
665}
666
667/*!
668 \fn bool QFileInfo::isAbsolute() const
669
670 Returns \c true if the file system entry's path is absolute, otherwise
671 returns \c false (that is, the path is relative).
672
673 \include qfileinfo.cpp qresource-virtual-fs-colon
674
675 \sa isRelative()
676*/
677
678/*!
679 Returns \c true if the file system entry's path is relative, otherwise
680 returns \c false (that is, the path is absolute).
681
682 \include qfileinfo.cpp absolute-path-unix-windows
683
684 \include qfileinfo.cpp qresource-virtual-fs-colon
685
686 \sa isAbsolute()
687*/
688bool QFileInfo::isRelative() const
689{
690 Q_D(const QFileInfo);
691 if (d->isDefaultConstructed)
692 return true;
693 if (d->fileEngine == nullptr)
694 return d->fileEntry.isRelative();
695 return d->fileEngine->isRelativePath();
696}
697
698/*!
699 If the file system entry's path is relative, this method converts it to
700 an absolute path and returns \c true; if the path is already absolute,
701 this method returns \c false.
702
703 \sa filePath(), isRelative()
704*/
705bool QFileInfo::makeAbsolute()
706{
707 if (d_ptr.constData()->isDefaultConstructed
708 || !d_ptr.constData()->fileEntry.isRelative())
709 return false;
710
711 setFile(absoluteFilePath());
712 return true;
713}
714
715/*!
716 Returns \c true if the file system entry this QFileInfo refers to exists;
717 otherwise returns \c false.
718
719 \note If the entry is a symlink that points to a non-existing
720 target, this method returns \c false.
721*/
722bool QFileInfo::exists() const
723{
724 Q_D(const QFileInfo);
725 if (d->isDefaultConstructed)
726 return false;
727 if (d->fileEngine == nullptr) {
728 if (!d->cache_enabled || !d->metaData.hasFlags(flags: QFileSystemMetaData::ExistsAttribute))
729 QFileSystemEngine::fillMetaData(entry: d->fileEntry, data&: d->metaData, what: QFileSystemMetaData::ExistsAttribute);
730 return d->metaData.exists();
731 }
732 return d->getFileFlags(request: QAbstractFileEngine::ExistsFlag);
733}
734
735/*!
736 \since 5.2
737
738 Returns \c true if the file system entry \a path exists; otherwise
739 returns \c false.
740
741 \note If \a path is a symlink that points to a non-existing
742 target, this method returns \c false.
743
744 \note Using this function is faster than using
745 \c QFileInfo(path).exists() for file system access.
746*/
747bool QFileInfo::exists(const QString &path)
748{
749 if (path.isEmpty())
750 return false;
751 QFileSystemEntry entry(path);
752 QFileSystemMetaData data;
753 // Expensive fallback to non-QFileSystemEngine implementation
754 if (auto engine = QFileSystemEngine::createLegacyEngine(entry, data))
755 return QFileInfo(new QFileInfoPrivate(entry, data, std::move(engine))).exists();
756
757 QFileSystemEngine::fillMetaData(entry, data, what: QFileSystemMetaData::ExistsAttribute);
758 return data.exists();
759}
760
761/*!
762 Refreshes the information about the file system entry this QFileInfo
763 refers to, that is, reads in information from the file system the next
764 time a cached property is fetched.
765*/
766void QFileInfo::refresh()
767{
768 Q_D(QFileInfo);
769 d->clear();
770}
771
772/*!
773 Returns the path of the file system entry this QFileInfo refers to;
774 the path may be absolute or relative.
775
776 \sa absoluteFilePath(), canonicalFilePath(), isRelative()
777*/
778QString QFileInfo::filePath() const
779{
780 Q_D(const QFileInfo);
781 if (d->isDefaultConstructed)
782 return ""_L1;
783 return d->fileEntry.filePath();
784}
785
786/*!
787 Returns the name of the file system entry this QFileInfo refers to,
788 excluding the path.
789
790 Example:
791 \snippet code/src_corelib_io_qfileinfo.cpp 3
792
793//! [path-ends-with-slash-empty-name-component]
794 \note If this QFileInfo is given a path ending with a directory separator
795 \c{'/'}, the entry's name part is considered empty.
796//! [path-ends-with-slash-empty-name-component]
797
798 \sa isRelative(), filePath(), baseName(), suffix()
799*/
800QString QFileInfo::fileName() const
801{
802 Q_D(const QFileInfo);
803 if (d->isDefaultConstructed)
804 return ""_L1;
805 if (!d->fileEngine)
806 return d->fileEntry.fileName();
807 return d->fileEngine->fileName(file: QAbstractFileEngine::BaseName);
808}
809
810/*!
811 \since 4.3
812 Returns the name of the bundle.
813
814 On \macos and iOS this returns the proper localized name for a bundle if the
815 path isBundle(). On all other platforms an empty QString is returned.
816
817 Example:
818 \snippet code/src_corelib_io_qfileinfo.cpp 4
819
820 \sa isBundle(), filePath(), baseName(), suffix()
821*/
822QString QFileInfo::bundleName() const
823{
824 Q_D(const QFileInfo);
825 if (d->isDefaultConstructed)
826 return ""_L1;
827 return d->getFileName(name: QAbstractFileEngine::BundleName);
828}
829
830/*!
831 Returns the base name of the file without the path.
832
833 The base name consists of all characters in the file up to (but
834 not including) the \e first '.' character.
835
836 Example:
837 \snippet code/src_corelib_io_qfileinfo.cpp 5
838
839
840 The base name of a file is computed equally on all platforms, independent
841 of file naming conventions (e.g., ".bashrc" on Unix has an empty base
842 name, and the suffix is "bashrc").
843
844 \sa fileName(), suffix(), completeSuffix(), completeBaseName()
845*/
846QString QFileInfo::baseName() const
847{
848 Q_D(const QFileInfo);
849 if (d->isDefaultConstructed)
850 return ""_L1;
851 if (!d->fileEngine)
852 return d->fileEntry.baseName();
853 return QFileSystemEntry(d->fileEngine->fileName(file: QAbstractFileEngine::BaseName)).baseName();
854}
855
856/*!
857 Returns the complete base name of the file without the path.
858
859 The complete base name consists of all characters in the file up
860 to (but not including) the \e last '.' character.
861
862 Example:
863 \snippet code/src_corelib_io_qfileinfo.cpp 6
864
865 \sa fileName(), suffix(), completeSuffix(), baseName()
866*/
867QString QFileInfo::completeBaseName() const
868{
869 Q_D(const QFileInfo);
870 if (d->isDefaultConstructed)
871 return ""_L1;
872 if (!d->fileEngine)
873 return d->fileEntry.completeBaseName();
874 const QString fileEngineBaseName = d->fileEngine->fileName(file: QAbstractFileEngine::BaseName);
875 return QFileSystemEntry(fileEngineBaseName).completeBaseName();
876}
877
878/*!
879 Returns the complete suffix (extension) of the file.
880
881 The complete suffix consists of all characters in the file after
882 (but not including) the first '.'.
883
884 Example:
885 \snippet code/src_corelib_io_qfileinfo.cpp 7
886
887 \sa fileName(), suffix(), baseName(), completeBaseName()
888*/
889QString QFileInfo::completeSuffix() const
890{
891 Q_D(const QFileInfo);
892 if (d->isDefaultConstructed)
893 return ""_L1;
894 return d->fileEntry.completeSuffix();
895}
896
897/*!
898 Returns the suffix (extension) of the file.
899
900 The suffix consists of all characters in the file after (but not
901 including) the last '.'.
902
903 Example:
904 \snippet code/src_corelib_io_qfileinfo.cpp 8
905
906 The suffix of a file is computed equally on all platforms, independent of
907 file naming conventions (e.g., ".bashrc" on Unix has an empty base name,
908 and the suffix is "bashrc").
909
910 \sa fileName(), completeSuffix(), baseName(), completeBaseName()
911*/
912QString QFileInfo::suffix() const
913{
914 Q_D(const QFileInfo);
915 if (d->isDefaultConstructed)
916 return ""_L1;
917 return d->fileEntry.suffix();
918}
919
920
921/*!
922 Returns a QDir object representing the path of the parent directory of the
923 file system entry that this QFileInfo refers to.
924
925 \note The QDir returned always corresponds to the object's
926 parent directory, even if the QFileInfo represents a directory.
927
928 For each of the following, dir() returns the QDir
929 \c{"~/examples/191697"}.
930
931 \snippet fileinfo/main.cpp 0
932
933 For each of the following, dir() returns the QDir
934 \c{"."}.
935
936 \snippet fileinfo/main.cpp 1
937
938 \sa absolutePath(), filePath(), fileName(), isRelative(), absoluteDir()
939*/
940QDir QFileInfo::dir() const
941{
942 Q_D(const QFileInfo);
943 return QDir(d->fileEntry.path());
944}
945
946/*!
947 Returns a QDir object representing the absolute path of the parent
948 directory of the file system entry that this QFileInfo refers to.
949
950 \snippet code/src_corelib_io_qfileinfo.cpp 11
951
952 \sa dir(), filePath(), fileName(), isRelative()
953*/
954QDir QFileInfo::absoluteDir() const
955{
956 return QDir(absolutePath());
957}
958
959/*!
960 Returns \c true if the user can read the file system entry this QFileInfo
961 refers to; otherwise returns \c false.
962
963 \include qfileinfo.cpp info-about-target-not-symlink
964
965 \note If the \l{NTFS permissions} check has not been enabled, the result
966 on Windows will merely reflect whether the entry exists.
967
968 \sa isWritable(), isExecutable(), permission()
969*/
970bool QFileInfo::isReadable() const
971{
972 Q_D(const QFileInfo);
973 return d->checkAttribute<bool>(
974 fsFlags: QFileSystemMetaData::UserReadPermission,
975 fsLambda: [d]() { return d->metaData.isReadable(); },
976 engineLambda: [d]() { return d->getFileFlags(request: QAbstractFileEngine::ReadUserPerm); });
977}
978
979/*!
980 Returns \c true if the user can write to the file system entry this
981 QFileInfo refers to; otherwise returns \c false.
982
983 \include qfileinfo.cpp info-about-target-not-symlink
984
985 \note If the \l{NTFS permissions} check has not been enabled, the result on
986 Windows will merely reflect whether the entry is marked as Read Only.
987
988 \sa isReadable(), isExecutable(), permission()
989*/
990bool QFileInfo::isWritable() const
991{
992 Q_D(const QFileInfo);
993 return d->checkAttribute<bool>(
994 fsFlags: QFileSystemMetaData::UserWritePermission,
995 fsLambda: [d]() { return d->metaData.isWritable(); },
996 engineLambda: [d]() { return d->getFileFlags(request: QAbstractFileEngine::WriteUserPerm); });
997}
998
999/*!
1000 Returns \c true if the file system entry this QFileInfo refers to is
1001 executable; otherwise returns \c false.
1002
1003//! [info-about-target-not-symlink]
1004 If the file is a symlink, this function returns information about the
1005 target, not the symlink.
1006//! [info-about-target-not-symlink]
1007
1008 \sa isReadable(), isWritable(), permission()
1009*/
1010bool QFileInfo::isExecutable() const
1011{
1012 Q_D(const QFileInfo);
1013 return d->checkAttribute<bool>(
1014 fsFlags: QFileSystemMetaData::UserExecutePermission,
1015 fsLambda: [d]() { return d->metaData.isExecutable(); },
1016 engineLambda: [d]() { return d->getFileFlags(request: QAbstractFileEngine::ExeUserPerm); });
1017}
1018
1019/*!
1020 Returns \c true if the file system entry this QFileInfo refers to is
1021 `hidden'; otherwise returns \c false.
1022
1023 \b{Note:} This function returns \c true for the special entries "." and
1024 ".." on Unix, even though QDir::entryList treats them as shown. And note
1025 that, since this function inspects the file name, on Unix it will inspect
1026 the name of the symlink, if this file is a symlink, not the target's name.
1027
1028 On Windows, this function returns \c true if the target file is hidden (not
1029 the symlink).
1030*/
1031bool QFileInfo::isHidden() const
1032{
1033 Q_D(const QFileInfo);
1034 return d->checkAttribute<bool>(
1035 fsFlags: QFileSystemMetaData::HiddenAttribute,
1036 fsLambda: [d]() { return d->metaData.isHidden(); },
1037 engineLambda: [d]() { return d->getFileFlags(request: QAbstractFileEngine::HiddenFlag); });
1038}
1039
1040/*!
1041 \since 5.0
1042 Returns \c true if the file path can be used directly with native APIs.
1043 Returns \c false if the file is otherwise supported by a virtual file system
1044 inside Qt, such as \l{the Qt Resource System}.
1045
1046 \b{Note:} Native paths may still require conversion of path separators
1047 and character encoding, depending on platform and input requirements of the
1048 native API.
1049
1050 \sa QDir::toNativeSeparators(), QFile::encodeName(), filePath(),
1051 absoluteFilePath(), canonicalFilePath()
1052*/
1053bool QFileInfo::isNativePath() const
1054{
1055 Q_D(const QFileInfo);
1056 if (d->isDefaultConstructed)
1057 return false;
1058 if (d->fileEngine == nullptr)
1059 return true;
1060 return d->getFileFlags(request: QAbstractFileEngine::LocalDiskFlag);
1061}
1062
1063/*!
1064 Returns \c true if this object points to a file or to a symbolic
1065 link to a file. Returns \c false if the
1066 object points to something that is not a file (such as a directory)
1067 or that does not exist.
1068
1069 \include qfileinfo.cpp info-about-target-not-symlink
1070
1071 \sa isDir(), isSymLink(), isBundle()
1072*/
1073bool QFileInfo::isFile() const
1074{
1075 Q_D(const QFileInfo);
1076 return d->checkAttribute<bool>(
1077 fsFlags: QFileSystemMetaData::FileType,
1078 fsLambda: [d]() { return d->metaData.isFile(); },
1079 engineLambda: [d]() { return d->getFileFlags(request: QAbstractFileEngine::FileType); });
1080}
1081
1082/*!
1083 Returns \c true if this object points to a directory or to a symbolic
1084 link to a directory. Returns \c false if the
1085 object points to something that is not a directory (such as a file)
1086 or that does not exist.
1087
1088 \include qfileinfo.cpp info-about-target-not-symlink
1089
1090 \sa isFile(), isSymLink(), isBundle()
1091*/
1092bool QFileInfo::isDir() const
1093{
1094 Q_D(const QFileInfo);
1095 return d->checkAttribute<bool>(
1096 fsFlags: QFileSystemMetaData::DirectoryType,
1097 fsLambda: [d]() { return d->metaData.isDirectory(); },
1098 engineLambda: [d]() { return d->getFileFlags(request: QAbstractFileEngine::DirectoryType); });
1099}
1100
1101
1102/*!
1103 \since 4.3
1104 Returns \c true if this object points to a bundle or to a symbolic
1105 link to a bundle on \macos and iOS; otherwise returns \c false.
1106
1107 \include qfileinfo.cpp info-about-target-not-symlink
1108
1109 \sa isDir(), isSymLink(), isFile()
1110*/
1111bool QFileInfo::isBundle() const
1112{
1113 Q_D(const QFileInfo);
1114 return d->checkAttribute<bool>(
1115 fsFlags: QFileSystemMetaData::BundleType,
1116 fsLambda: [d]() { return d->metaData.isBundle(); },
1117 engineLambda: [d]() { return d->getFileFlags(request: QAbstractFileEngine::BundleType); });
1118}
1119
1120/*!
1121 Returns \c true if this object points to a symbolic link, shortcut,
1122 or alias; otherwise returns \c false.
1123
1124 Symbolic links exist on Unix (including \macos and iOS) and Windows
1125 and are typically created by the \c{ln -s} or \c{mklink} commands,
1126 respectively. Opening a symbolic link effectively opens
1127 the \l{symLinkTarget()}{link's target}.
1128
1129 In addition, true will be returned for shortcuts (\c *.lnk files) on
1130 Windows, and aliases on \macos. This behavior is deprecated and will
1131 likely change in a future version of Qt. Opening a shortcut or alias
1132 will open the \c .lnk or alias file itself.
1133
1134 Example:
1135
1136 \snippet code/src_corelib_io_qfileinfo.cpp 9
1137
1138//! [symlink-target-exists-behavior]
1139 \note exists() returns \c true if the symlink points to an existing
1140 target, otherwise it returns \c false.
1141//! [symlink-target-exists-behavior]
1142
1143 \sa isFile(), isDir(), symLinkTarget()
1144*/
1145bool QFileInfo::isSymLink() const
1146{
1147 Q_D(const QFileInfo);
1148 return d->checkAttribute<bool>(
1149 fsFlags: QFileSystemMetaData::LegacyLinkType,
1150 fsLambda: [d]() { return d->metaData.isLegacyLink(); },
1151 engineLambda: [d]() { return d->getFileFlags(request: QAbstractFileEngine::LinkType); });
1152}
1153
1154/*!
1155 Returns \c true if this object points to a symbolic link;
1156 otherwise returns \c false.
1157
1158 Symbolic links exist on Unix (including \macos and iOS) and Windows
1159 (NTFS-symlink) and are typically created by the \c{ln -s} or \c{mklink}
1160 commands, respectively.
1161
1162 Unix handles symlinks transparently. Opening a symbolic link effectively
1163 opens the \l{symLinkTarget()}{link's target}.
1164
1165 In contrast to isSymLink(), false will be returned for shortcuts
1166 (\c *.lnk files) on Windows and aliases on \macos. Use QFileInfo::isShortcut()
1167 and QFileInfo::isAlias() instead.
1168
1169 \include qfileinfo.cpp symlink-target-exists-behavior
1170
1171 \sa isFile(), isDir(), isShortcut(), symLinkTarget()
1172*/
1173
1174bool QFileInfo::isSymbolicLink() const
1175{
1176 Q_D(const QFileInfo);
1177 return d->checkAttribute<bool>(
1178 fsFlags: QFileSystemMetaData::LegacyLinkType,
1179 fsLambda: [d]() { return d->metaData.isLink(); },
1180 engineLambda: [d]() { return d->getFileFlags(request: QAbstractFileEngine::LinkType); });
1181}
1182
1183/*!
1184 Returns \c true if this object points to a shortcut;
1185 otherwise returns \c false.
1186
1187 Shortcuts only exist on Windows and are typically \c .lnk files.
1188 For instance, true will be returned for shortcuts (\c *.lnk files) on
1189 Windows, but false will be returned on Unix (including \macos and iOS).
1190
1191 The shortcut (.lnk) files are treated as regular files. Opening those will
1192 open the \c .lnk file itself. In order to open the file a shortcut
1193 references to, it must uses symLinkTarget() on a shortcut.
1194
1195 \note Even if a shortcut (broken shortcut) points to a non existing file,
1196 isShortcut() returns true.
1197
1198 \sa isFile(), isDir(), isSymbolicLink(), symLinkTarget()
1199*/
1200bool QFileInfo::isShortcut() const
1201{
1202 Q_D(const QFileInfo);
1203 return d->checkAttribute<bool>(
1204 fsFlags: QFileSystemMetaData::LegacyLinkType,
1205 fsLambda: [d]() { return d->metaData.isLnkFile(); },
1206 engineLambda: [d]() { return d->getFileFlags(request: QAbstractFileEngine::LinkType); });
1207}
1208
1209/*!
1210 Returns \c true if this object points to an alias;
1211 otherwise returns \c false.
1212
1213 \since 6.4
1214
1215 Aliases only exist on \macos. They are treated as regular files, so
1216 opening an alias will open the file itself. In order to open the file
1217 or directory an alias references use symLinkTarget().
1218
1219 \note Even if an alias points to a non existing file,
1220 isAlias() returns true.
1221
1222 \sa isFile(), isDir(), isSymLink(), symLinkTarget()
1223*/
1224bool QFileInfo::isAlias() const
1225{
1226 Q_D(const QFileInfo);
1227 return d->checkAttribute<bool>(
1228 fsFlags: QFileSystemMetaData::LegacyLinkType,
1229 fsLambda: [d]() { return d->metaData.isAlias(); },
1230 engineLambda: [d]() { return d->getFileFlags(request: QAbstractFileEngine::LinkType); });
1231}
1232
1233/*!
1234 \since 5.15
1235
1236 Returns \c true if the object points to a junction;
1237 otherwise returns \c false.
1238
1239 Junctions only exist on Windows' NTFS file system, and are typically
1240 created by the \c{mklink} command. They can be thought of as symlinks for
1241 directories, and can only be created for absolute paths on the local
1242 volume.
1243*/
1244bool QFileInfo::isJunction() const
1245{
1246 Q_D(const QFileInfo);
1247 return d->checkAttribute<bool>(
1248 fsFlags: QFileSystemMetaData::LegacyLinkType,
1249 fsLambda: [d]() { return d->metaData.isJunction(); },
1250 engineLambda: [d]() { return d->getFileFlags(request: QAbstractFileEngine::LinkType); });
1251}
1252
1253/*!
1254 Returns \c true if the object points to a directory or to a symbolic
1255 link to a directory, and that directory is the root directory; otherwise
1256 returns \c false.
1257*/
1258bool QFileInfo::isRoot() const
1259{
1260 Q_D(const QFileInfo);
1261 if (d->isDefaultConstructed)
1262 return false;
1263 if (d->fileEngine == nullptr) {
1264 if (d->fileEntry.isRoot()) {
1265#if defined(Q_OS_WIN)
1266 //the path is a drive root, but the drive may not exist
1267 //for backward compatibility, return true only if the drive exists
1268 if (!d->cache_enabled || !d->metaData.hasFlags(QFileSystemMetaData::ExistsAttribute))
1269 QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, QFileSystemMetaData::ExistsAttribute);
1270 return d->metaData.exists();
1271#else
1272 return true;
1273#endif
1274 }
1275 return false;
1276 }
1277 return d->getFileFlags(request: QAbstractFileEngine::RootFlag);
1278}
1279
1280/*!
1281 \since 4.2
1282
1283 Returns the absolute path to the file or directory a symbolic link
1284 points to, or an empty string if the object isn't a symbolic
1285 link.
1286
1287 This name may not represent an existing file; it is only a string.
1288
1289 \include qfileinfo.cpp symlink-target-exists-behavior
1290
1291 \sa exists(), isSymLink(), isDir(), isFile()
1292*/
1293QString QFileInfo::symLinkTarget() const
1294{
1295 Q_D(const QFileInfo);
1296 if (d->isDefaultConstructed)
1297 return ""_L1;
1298 return d->getFileName(name: QAbstractFileEngine::AbsoluteLinkTarget);
1299}
1300
1301/*!
1302 \since 6.6
1303 Read the path the symlink references.
1304
1305 Returns the raw path referenced by the symbolic link, without resolving a relative
1306 path relative to the directory containing the symbolic link. The returned string will
1307 only be an absolute path if the symbolic link actually references it as such. Returns
1308 an empty string if the object is not a symbolic link.
1309
1310 \sa symLinkTarget(), exists(), isSymLink(), isDir(), isFile()
1311*/
1312QString QFileInfo::readSymLink() const
1313{
1314 Q_D(const QFileInfo);
1315 if (d->isDefaultConstructed)
1316 return {};
1317 return d->getFileName(name: QAbstractFileEngine::RawLinkPath);
1318}
1319
1320/*!
1321 \since 6.2
1322
1323 Resolves an NTFS junction to the path it references.
1324
1325 Returns the absolute path to the directory an NTFS junction points to, or
1326 an empty string if the object is not an NTFS junction.
1327
1328 There is no guarantee that the directory named by the NTFS junction actually
1329 exists.
1330
1331 \sa isJunction(), isFile(), isDir(), isSymLink(), isSymbolicLink(),
1332 isShortcut()
1333*/
1334QString QFileInfo::junctionTarget() const
1335{
1336 Q_D(const QFileInfo);
1337 if (d->isDefaultConstructed)
1338 return ""_L1;
1339 return d->getFileName(name: QAbstractFileEngine::JunctionName);
1340}
1341
1342/*!
1343 Returns the owner of the file. On systems where files
1344 do not have owners, or if an error occurs, an empty string is
1345 returned.
1346
1347 This function can be time consuming under Unix (in the order of
1348 milliseconds). On Windows, it will return an empty string unless
1349 the \l{NTFS permissions} check has been enabled.
1350
1351 \include qfileinfo.cpp info-about-target-not-symlink
1352
1353 \sa ownerId(), group(), groupId()
1354*/
1355QString QFileInfo::owner() const
1356{
1357 Q_D(const QFileInfo);
1358 if (d->isDefaultConstructed)
1359 return ""_L1;
1360 return d->getFileOwner(own: QAbstractFileEngine::OwnerUser);
1361}
1362
1363/*!
1364 Returns the id of the owner of the file.
1365
1366 On Windows and on systems where files do not have owners this
1367 function returns ((uint) -2).
1368
1369 \include qfileinfo.cpp info-about-target-not-symlink
1370
1371 \sa owner(), group(), groupId()
1372*/
1373uint QFileInfo::ownerId() const
1374{
1375 Q_D(const QFileInfo);
1376 return d->checkAttribute(defaultValue: uint(-2),
1377 fsFlags: QFileSystemMetaData::UserId,
1378 fsLambda: [d]() { return d->metaData.userId(); },
1379 engineLambda: [d]() { return d->fileEngine->ownerId(QAbstractFileEngine::OwnerUser); });
1380}
1381
1382/*!
1383 Returns the group of the file. On Windows, on systems where files
1384 do not have groups, or if an error occurs, an empty string is
1385 returned.
1386
1387 This function can be time consuming under Unix (in the order of
1388 milliseconds).
1389
1390 \include qfileinfo.cpp info-about-target-not-symlink
1391
1392 \sa groupId(), owner(), ownerId()
1393*/
1394QString QFileInfo::group() const
1395{
1396 Q_D(const QFileInfo);
1397 if (d->isDefaultConstructed)
1398 return ""_L1;
1399 return d->getFileOwner(own: QAbstractFileEngine::OwnerGroup);
1400}
1401
1402/*!
1403 Returns the id of the group the file belongs to.
1404
1405 On Windows and on systems where files do not have groups this
1406 function always returns (uint) -2.
1407
1408 \include qfileinfo.cpp info-about-target-not-symlink
1409
1410 \sa group(), owner(), ownerId()
1411*/
1412uint QFileInfo::groupId() const
1413{
1414 Q_D(const QFileInfo);
1415 return d->checkAttribute(defaultValue: uint(-2),
1416 fsFlags: QFileSystemMetaData::GroupId,
1417 fsLambda: [d]() { return d->metaData.groupId(); },
1418 engineLambda: [d]() { return d->fileEngine->ownerId(QAbstractFileEngine::OwnerGroup); });
1419}
1420
1421/*!
1422 Tests for file permissions. The \a permissions argument can be
1423 several flags of type QFile::Permissions OR-ed together to check
1424 for permission combinations.
1425
1426 On systems where files do not have permissions this function
1427 always returns \c true.
1428
1429 \note The result might be inaccurate on Windows if the
1430 \l{NTFS permissions} check has not been enabled.
1431
1432 Example:
1433 \snippet code/src_corelib_io_qfileinfo.cpp 10
1434
1435 \include qfileinfo.cpp info-about-target-not-symlink
1436
1437 \sa isReadable(), isWritable(), isExecutable()
1438*/
1439bool QFileInfo::permission(QFile::Permissions permissions) const
1440{
1441 Q_D(const QFileInfo);
1442 // the QFileSystemMetaData::MetaDataFlag and QFile::Permissions overlap, so just cast.
1443 auto fseFlags = QFileSystemMetaData::MetaDataFlags::fromInt(i: permissions.toInt());
1444 auto feFlags = QAbstractFileEngine::FileFlags::fromInt(i: permissions.toInt());
1445 return d->checkAttribute<bool>(
1446 fsFlags: fseFlags,
1447 fsLambda: [=]() { return (d->metaData.permissions() & permissions) == permissions; },
1448 engineLambda: [=]() {
1449 return d->getFileFlags(request: feFlags) == uint(permissions.toInt());
1450 });
1451}
1452
1453/*!
1454 Returns the complete OR-ed together combination of
1455 QFile::Permissions for the file.
1456
1457 \note The result might be inaccurate on Windows if the
1458 \l{NTFS permissions} check has not been enabled.
1459
1460 \include qfileinfo.cpp info-about-target-not-symlink
1461*/
1462QFile::Permissions QFileInfo::permissions() const
1463{
1464 Q_D(const QFileInfo);
1465 return d->checkAttribute<QFile::Permissions>(
1466 fsFlags: QFileSystemMetaData::Permissions,
1467 fsLambda: [d]() { return d->metaData.permissions(); },
1468 engineLambda: [d]() {
1469 return QFile::Permissions(d->getFileFlags(request: QAbstractFileEngine::PermsMask) & QAbstractFileEngine::PermsMask);
1470 });
1471}
1472
1473
1474/*!
1475 Returns the file size in bytes. If the file does not exist or cannot be
1476 fetched, 0 is returned.
1477
1478 \include qfileinfo.cpp info-about-target-not-symlink
1479
1480 \sa exists()
1481*/
1482qint64 QFileInfo::size() const
1483{
1484 Q_D(const QFileInfo);
1485 return d->checkAttribute<qint64>(
1486 fsFlags: QFileSystemMetaData::SizeAttribute,
1487 fsLambda: [d]() { return d->metaData.size(); },
1488 engineLambda: [d]() {
1489 if (!d->getCachedFlag(c: QFileInfoPrivate::CachedSize)) {
1490 d->setCachedFlag(QFileInfoPrivate::CachedSize);
1491 d->fileSize = d->fileEngine->size();
1492 }
1493 return d->fileSize;
1494 });
1495}
1496
1497/*!
1498 \fn QDateTime QFileInfo::birthTime() const
1499
1500 Returns the date and time when the file was created (born), in local time.
1501
1502 If the file birth time is not available, this function returns an invalid QDateTime.
1503
1504 \include qfileinfo.cpp info-about-target-not-symlink
1505
1506 This function overloads QFileInfo::birthTime(const QTimeZone &tz), and
1507 returns the same as \c{birthTime(QTimeZone::LocalTime)}.
1508
1509 \since 5.10
1510 \sa lastModified(), lastRead(), metadataChangeTime(), fileTime()
1511*/
1512
1513/*!
1514 \fn QDateTime QFileInfo::birthTime(const QTimeZone &tz) const
1515
1516 Returns the date and time when the file was created (born).
1517
1518 \include qfileinfo.cpp file-times-in-time-zone
1519
1520 If the file birth time is not available, this function returns an invalid
1521 QDateTime.
1522
1523 \include qfileinfo.cpp info-about-target-not-symlink
1524
1525 \since 6.6
1526 \sa lastModified(const QTimeZone &), lastRead(const QTimeZone &),
1527 metadataChangeTime(const QTimeZone &),
1528 fileTime(QFileDevice::FileTime, const QTimeZone &)
1529*/
1530
1531/*!
1532 \fn QDateTime QFileInfo::metadataChangeTime() const
1533
1534 Returns the date and time when the file's metadata was last changed,
1535 in local time.
1536
1537 A metadata change occurs when the file is first created, but it also
1538 occurs whenever the user writes or sets inode information (for example,
1539 changing the file permissions).
1540
1541 \include qfileinfo.cpp info-about-target-not-symlink
1542
1543 This function overloads QFileInfo::metadataChangeTime(const QTimeZone &tz),
1544 and returns the same as \c{metadataChangeTime(QTimeZone::LocalTime)}.
1545
1546 \since 5.10
1547 \sa birthTime(), lastModified(), lastRead(), fileTime()
1548*/
1549
1550/*!
1551 \fn QDateTime QFileInfo::metadataChangeTime(const QTimeZone &tz) const
1552
1553 Returns the date and time when the file's metadata was last changed.
1554 A metadata change occurs when the file is first created, but it also
1555 occurs whenever the user writes or sets inode information (for example,
1556 changing the file permissions).
1557
1558 \include qfileinfo.cpp file-times-in-time-zone
1559
1560 \include qfileinfo.cpp info-about-target-not-symlink
1561
1562 \since 6.6
1563 \sa birthTime(const QTimeZone &), lastModified(const QTimeZone &),
1564 lastRead(const QTimeZone &),
1565 fileTime(QFileDevice::FileTime time, const QTimeZone &)
1566*/
1567
1568/*!
1569 \fn QDateTime QFileInfo::lastModified() const
1570
1571 Returns the date and time when the file was last modified.
1572
1573 \include qfileinfo.cpp info-about-target-not-symlink
1574
1575 This function overloads \l{QFileInfo::lastModified(const QTimeZone &)},
1576 and returns the same as \c{lastModified(QTimeZone::LocalTime)}.
1577
1578 \sa birthTime(), lastRead(), metadataChangeTime(), fileTime()
1579*/
1580
1581/*!
1582 \fn QDateTime QFileInfo::lastModified(const QTimeZone &tz) const
1583
1584 Returns the date and time when the file was last modified.
1585
1586 \include qfileinfo.cpp file-times-in-time-zone
1587
1588 \include qfileinfo.cpp info-about-target-not-symlink
1589
1590 \since 6.6
1591 \sa birthTime(const QTimeZone &), lastRead(const QTimeZone &),
1592 metadataChangeTime(const QTimeZone &),
1593 fileTime(QFileDevice::FileTime, const QTimeZone &)
1594*/
1595
1596/*!
1597 \fn QDateTime QFileInfo::lastRead() const
1598
1599 Returns the date and time when the file was last read (accessed).
1600
1601 On platforms where this information is not available, returns the same
1602 time as lastModified().
1603
1604 \include qfileinfo.cpp info-about-target-not-symlink
1605
1606 This function overloads \l{QFileInfo::lastRead(const QTimeZone &)},
1607 and returns the same as \c{lastRead(QTimeZone::LocalTime)}.
1608
1609 \sa birthTime(), lastModified(), metadataChangeTime(), fileTime()
1610*/
1611
1612/*!
1613 \fn QDateTime QFileInfo::lastRead(const QTimeZone &tz) const
1614
1615 Returns the date and time when the file was last read (accessed).
1616
1617 \include qfileinfo.cpp file-times-in-time-zone
1618
1619 On platforms where this information is not available, returns the same
1620 time as lastModified().
1621
1622 \include qfileinfo.cpp info-about-target-not-symlink
1623
1624 \since 6.6
1625 \sa birthTime(const QTimeZone &), lastModified(const QTimeZone &),
1626 metadataChangeTime(const QTimeZone &),
1627 fileTime(QFileDevice::FileTime, const QTimeZone &)
1628*/
1629
1630#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
1631/*!
1632 Returns the file time specified by \a time.
1633
1634 If the time cannot be determined, an invalid date time is returned.
1635
1636 \include qfileinfo.cpp info-about-target-not-symlink
1637
1638 This function overloads
1639 \l{QFileInfo::fileTime(QFileDevice::FileTime, const QTimeZone &)},
1640 and returns the same as \c{fileTime(time, QTimeZone::LocalTime)}.
1641
1642 \since 5.10
1643 \sa birthTime(), lastModified(), lastRead(), metadataChangeTime()
1644*/
1645QDateTime QFileInfo::fileTime(QFile::FileTime time) const {
1646 return fileTime(time, tz: QTimeZone::LocalTime);
1647}
1648#endif
1649
1650/*!
1651 Returns the file time specified by \a time.
1652
1653//! [file-times-in-time-zone]
1654 The returned time is in the time zone specified by \a tz. For example,
1655 you can use QTimeZone::LocalTime or QTimeZone::UTC to get the time in
1656 the Local time zone or UTC, respectively. Since native file system API
1657 typically uses UTC, using QTimeZone::UTC is often faster, as it does not
1658 require any conversions.
1659//! [file-times-in-time-zone]
1660
1661 If the time cannot be determined, an invalid date time is returned.
1662
1663 \include qfileinfo.cpp info-about-target-not-symlink
1664
1665 \since 6.6
1666 \sa birthTime(const QTimeZone &), lastModified(const QTimeZone &),
1667 lastRead(const QTimeZone &), metadataChangeTime(const QTimeZone &),
1668 QDateTime::isValid()
1669*/
1670QDateTime QFileInfo::fileTime(QFile::FileTime time, const QTimeZone &tz) const
1671{
1672 Q_D(const QFileInfo);
1673 QFileSystemMetaData::MetaDataFlags flag;
1674 switch (time) {
1675 case QFile::FileAccessTime:
1676 flag = QFileSystemMetaData::AccessTime;
1677 break;
1678 case QFile::FileBirthTime:
1679 flag = QFileSystemMetaData::BirthTime;
1680 break;
1681 case QFile::FileMetadataChangeTime:
1682 flag = QFileSystemMetaData::MetadataChangeTime;
1683 break;
1684 case QFile::FileModificationTime:
1685 flag = QFileSystemMetaData::ModificationTime;
1686 break;
1687 }
1688
1689 auto fsLambda = [d, time]() { return d->metaData.fileTime(time); };
1690 auto engineLambda = [d, time]() { return d->getFileTime(request: time); };
1691 const auto dt =
1692 d->checkAttribute<QDateTime>(fsFlags: flag, fsLambda: std::move(fsLambda), engineLambda: std::move(engineLambda));
1693 return dt.toTimeZone(toZone: tz);
1694}
1695
1696/*!
1697 \internal
1698*/
1699QFileInfoPrivate* QFileInfo::d_func()
1700{
1701 return d_ptr.data();
1702}
1703
1704/*!
1705 Returns \c true if caching is enabled; otherwise returns \c false.
1706
1707 \sa setCaching(), refresh()
1708*/
1709bool QFileInfo::caching() const
1710{
1711 Q_D(const QFileInfo);
1712 return d->cache_enabled;
1713}
1714
1715/*!
1716 If \a enable is true, enables caching of file information. If \a
1717 enable is false caching is disabled.
1718
1719 When caching is enabled, QFileInfo reads the file information from
1720 the file system the first time it's needed, but generally not
1721 later.
1722
1723 Caching is enabled by default.
1724
1725 \sa refresh(), caching()
1726*/
1727void QFileInfo::setCaching(bool enable)
1728{
1729 Q_D(QFileInfo);
1730 d->cache_enabled = enable;
1731}
1732
1733/*!
1734 Reads all attributes from the file system.
1735 \since 6.0
1736
1737 This is useful when information about the file system is collected in a
1738 worker thread, and then passed to the UI in the form of caching QFileInfo
1739 instances.
1740
1741 \sa setCaching(), refresh()
1742*/
1743void QFileInfo::stat()
1744{
1745 Q_D(QFileInfo);
1746 QFileSystemEngine::fillMetaData(entry: d->fileEntry, data&: d->metaData, what: QFileSystemMetaData::AllMetaDataFlags);
1747}
1748
1749/*!
1750 \typedef QFileInfoList
1751 \relates QFileInfo
1752
1753 Synonym for QList<QFileInfo>.
1754*/
1755
1756#ifndef QT_NO_DEBUG_STREAM
1757QDebug operator<<(QDebug dbg, const QFileInfo &fi)
1758{
1759 QDebugStateSaver saver(dbg);
1760 dbg.nospace();
1761 dbg.noquote();
1762 dbg << "QFileInfo(" << QDir::toNativeSeparators(pathName: fi.filePath()) << ')';
1763 return dbg;
1764}
1765#endif
1766
1767/*!
1768 \fn QFileInfo::QFileInfo(const std::filesystem::path &file)
1769 \since 6.0
1770
1771 Constructs a new QFileInfo that gives information about the given
1772 \a file.
1773
1774 \sa setFile(), isRelative(), QDir::setCurrent(), QDir::isRelativePath()
1775*/
1776/*!
1777 \fn QFileInfo::QFileInfo(const QDir &dir, const std::filesystem::path &path)
1778 \since 6.0
1779
1780 Constructs a new QFileInfo that gives information about the file system
1781 entry at \a path that is relative to the directory \a dir.
1782
1783 \include qfileinfo.cpp preserve-relative-or-absolute
1784*/
1785/*!
1786 \fn void QFileInfo::setFile(const std::filesystem::path &path)
1787 \since 6.0
1788
1789 Sets the path of file system entry that this QFileInfo provides
1790 information about to \a path.
1791
1792 \include qfileinfo.cpp preserve-relative-path
1793*/
1794/*!
1795 \fn std::filesystem::path QFileInfo::filesystemFilePath() const
1796 \since 6.0
1797
1798 Returns filePath() as a \c{std::filesystem::path}.
1799 \sa filePath()
1800*/
1801/*!
1802 \fn std::filesystem::path QFileInfo::filesystemAbsoluteFilePath() const
1803 \since 6.0
1804
1805 Returns absoluteFilePath() as a \c{std::filesystem::path}.
1806 \sa absoluteFilePath()
1807*/
1808/*!
1809 \fn std::filesystem::path QFileInfo::filesystemCanonicalFilePath() const
1810 \since 6.0
1811
1812 Returns canonicalFilePath() as a \c{std::filesystem::path}.
1813 \sa canonicalFilePath()
1814*/
1815/*!
1816 \fn std::filesystem::path QFileInfo::filesystemPath() const
1817 \since 6.0
1818
1819 Returns path() as a \c{std::filesystem::path}.
1820 \sa path()
1821*/
1822/*!
1823 \fn std::filesystem::path QFileInfo::filesystemAbsolutePath() const
1824 \since 6.0
1825
1826 Returns absolutePath() as a \c{std::filesystem::path}.
1827 \sa absolutePath()
1828*/
1829/*!
1830 \fn std::filesystem::path QFileInfo::filesystemCanonicalPath() const
1831 \since 6.0
1832
1833 Returns canonicalPath() as a \c{std::filesystem::path}.
1834 \sa canonicalPath()
1835*/
1836/*!
1837 \fn std::filesystem::path QFileInfo::filesystemSymLinkTarget() const
1838 \since 6.0
1839
1840 Returns symLinkTarget() as a \c{std::filesystem::path}.
1841 \sa symLinkTarget()
1842*/
1843/*!
1844 \fn std::filesystem::path QFileInfo::filesystemReadSymLink() const
1845 \since 6.6
1846
1847 Returns readSymLink() as a \c{std::filesystem::path}.
1848 \sa readSymLink()
1849*/
1850/*!
1851 \fn std::filesystem::path QFileInfo::filesystemJunctionTarget() const
1852 \since 6.2
1853
1854 Returns junctionTarget() as a \c{std::filesystem::path}.
1855 \sa junctionTarget()
1856*/
1857/*!
1858 \macro QT_IMPLICIT_QFILEINFO_CONSTRUCTION
1859 \since 6.0
1860 \relates QFileInfo
1861
1862 Defining this macro makes most QFileInfo constructors implicit
1863 instead of explicit. Since construction of QFileInfo objects is
1864 expensive, one should avoid accidentally creating them, especially
1865 if cheaper alternatives exist. For instance:
1866
1867 \badcode
1868
1869 QDirIterator it(dir);
1870 while (it.hasNext()) {
1871 // Implicit conversion from QString (returned by it.next()):
1872 // may create unnecessary data structures and cause additional
1873 // accesses to the file system. Unless this macro is defined,
1874 // this line does not compile.
1875
1876 QFileInfo fi = it.next();
1877
1878 ~~~
1879 }
1880
1881 \endcode
1882
1883 Instead, use the right API:
1884
1885 \code
1886
1887 QDirIterator it(dir);
1888 while (it.hasNext()) {
1889 // Extract the QFileInfo from the iterator directly:
1890 QFileInfo fi = it.nextFileInfo();
1891
1892 ~~~
1893 }
1894
1895 \endcode
1896
1897 Construction from QString, QFile, and so on is always possible by
1898 using direct initialization instead of copy initialization:
1899
1900 \code
1901
1902 QFileInfo fi1 = some_string; // Does not compile unless this macro is defined
1903 QFileInfo fi2(some_string); // OK
1904 QFileInfo fi3{some_string}; // Possibly better, avoids the risk of the Most Vexing Parse
1905 auto fi4 = QFileInfo(some_string); // OK
1906
1907 \endcode
1908
1909 This macro is provided for compatibility reason. Its usage is not
1910 recommended in new code.
1911*/
1912
1913QT_END_NAMESPACE
1914

source code of qtbase/src/corelib/io/qfileinfo.cpp