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