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

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