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