Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qfilesystemiterator_unix.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 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// Qt-Security score:significant reason:default
4
5#include "qplatformdefs.h"
7
8#ifndef QT_NO_FILESYSTEMITERATOR
9
10#include <qvarlengtharray.h>
11
12#include <memory>
13
14#include <stdlib.h>
15#include <errno.h>
16
18
19/*
20 Native filesystem iterator, which uses ::opendir()/readdir()/dirent from the system
21 libraries to iterate over the directory represented by \a entry.
22*/
23QFileSystemIterator::QFileSystemIterator(const QFileSystemEntry &entry)
24 : dirPath(entry.filePath()),
25 toUtf16(QStringDecoder::Utf8)
26{
27 dir.reset(QT_OPENDIR(entry.nativeFilePath().constData()));
28 if (!dir) {
29 lastError = errno;
30 } else {
31 if (!dirPath.endsWith(u'/'))
32 dirPath.append(u'/');
33 }
34}
35
36QFileSystemIterator::QFileSystemIterator(const QFileSystemEntry &entry, QDirListing::IteratorFlags)
37 : QFileSystemIterator(entry)
38{}
39
40QFileSystemIterator::QFileSystemIterator(const QFileSystemEntry &entry, QDir::Filters)
41 : QFileSystemIterator(entry)
42{
43}
44
45QFileSystemIterator::~QFileSystemIterator() = default;
46
47bool QFileSystemIterator::advance(QFileSystemEntry &fileEntry, QFileSystemMetaData &metaData)
48{
49 auto asFileEntry = [this](QStringView name) {
50#ifdef Q_OS_DARWIN
51 // must match QFile::decodeName
52 QString normalized = name.toString().normalized(QString::NormalizationForm_C);
53 name = normalized;
54#endif
55 return QFileSystemEntry(dirPath + name, QFileSystemEntry::FromInternalPath());
56 };
57 if (!dir)
58 return false;
59
60 for (;;) {
61 // From readdir man page:
62 // If the end of the directory stream is reached, NULL is returned and errno is
63 // not changed. If an error occurs, NULL is returned and errno is set to indicate
64 // the error. To distinguish end of stream from an error, set errno to zero before
65 // calling readdir() and then check the value of errno if NULL is returned.
66 errno = 0;
67 dirEntry = QT_READDIR(dir.get());
68
69 if (dirEntry) {
70 // POSIX allows readdir() to return a file name in struct dirent that
71 // extends past the end of the d_name array (it's a char[1] array on QNX, for
72 // example). Therefore, we *must* call strlen() on it to get the actual length
73 // of the file name. See:
74 // https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/dirent.h.html#tag_13_07_05
75 QByteArrayView name(dirEntry->d_name, strlen(dirEntry->d_name));
76 // name.size() is sufficient here, see QUtf8::convertToUnicode() for details
77 QVarLengthArray<char16_t> buffer(name.size());
78 auto *end = toUtf16.appendToBuffer(buffer.data(), name);
79 buffer.resize(end - buffer.constData());
80 if (!toUtf16.hasError()) {
81 fileEntry = asFileEntry(buffer);
82 metaData.fillFromDirEnt(*dirEntry);
83 return true;
84 } else {
85 errno = EILSEQ; // Invalid or incomplete multibyte or wide character
86 }
87 } else {
88 break;
89 }
90 }
91
92 lastError = errno;
93 return false;
94}
95
96QT_END_NAMESPACE
97
98#endif // QT_NO_FILESYSTEMITERATOR