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

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