From def2b7c13cc31df9ed53e768d59d0442dc5d48af Mon Sep 17 00:00:00 2001 From: gongheng Date: Mon, 2 Mar 2026 16:41:31 +0800 Subject: [PATCH] Fix: [file-enumerator] use g_file_enumerator_next_file() --Replace use of g_file_enumerator_iterate() with g_file_enumerator_next_file() in DEnumerator::hasNext() so the enumerator's internal cursor is advanced by GIO and error/end conditions are handled unambiguously. --Using g_file_enumerator_next_file() yields clearer semantics: non-NULL -> next entry, NULL + NULL error -> end, NULL + non-NULL error -> error. This avoids premature termination caused by backend-specific iterate() quirks. --Construct next entry URL via the existing buildUrl(...) helper and preserve existing logic that creates the DFileInfo from the returned GFileInfo. Preserve existing error handling and d->checkFilter() behavior and recursive skipping of filtered entries. --Fix URL construction so joining directory path and filename does not introduce an extra '/' (previously produced e.g. .../vault_unlocked//file). The logic now concatenates carefully (handles root path and trailing slashes) to avoid duplicate separators. Log: fix issue Bug: https://pms.uniontech.com//bug-view-351177.html --- src/dfm-io/dfm-io/denumerator.cpp | 46 +++++++++++++------------------ 1 file changed, 19 insertions(+), 27 deletions(-) diff --git a/src/dfm-io/dfm-io/denumerator.cpp b/src/dfm-io/dfm-io/denumerator.cpp index 48dafe8..8c6d40a 100644 --- a/src/dfm-io/dfm-io/denumerator.cpp +++ b/src/dfm-io/dfm-io/denumerator.cpp @@ -446,9 +446,13 @@ char *DEnumeratorPrivate::filePath(const QUrl &url) QUrl DEnumeratorPrivate::buildUrl(const QUrl &url, const char *fileName) { - auto path = url.path() == "/" ? - "/" + QString(fileName) : - url.path() + "/" + QString(fileName); + QString path; + if (url.path() == "/") { + path = "/" + QString(fileName); + } else { + QString dirPath = url.path(); + path = dirPath.endsWith('/') ? dirPath + QString(fileName) : dirPath + "/" + QString(fileName); + } QUrl nextUrl = QUrl::fromLocalFile(path); if (url.userInfo().startsWith("originPath::")) { @@ -674,34 +678,19 @@ bool DEnumerator::hasNext() const while (!d->stackEnumerator.isEmpty()) { GFileEnumerator *enumerator = d->stackEnumerator.top(); - GFileInfo *gfileInfo = nullptr; - GFile *gfile = nullptr; g_autoptr(GError) gerror = nullptr; d->checkAndResetCancel(); - bool hasNext = g_file_enumerator_iterate(enumerator, &gfileInfo, &gfile, d->cancellable, &gerror); + // Use g_file_enumerator_next_file() which returns a GFileInfo* for the next + // entry (or NULL). This avoids ambiguous iterate() behavior across backends. + GFileInfo *nextInfo = g_file_enumerator_next_file(enumerator, d->cancellable, &gerror); + if (nextInfo) { + d->nextUrl = d->buildUrl(d->uri, g_file_info_get_name(nextInfo)); + d->dfileInfoNext = DLocalHelper::createFileInfoByUri(d->nextUrl, g_file_info_dup(nextInfo), FILE_DEFAULT_ATTRIBUTES, + d->enumLinks ? DFileInfo::FileQueryInfoFlags::kTypeNone : DFileInfo::FileQueryInfoFlags::kTypeNoFollowSymlinks); - if (hasNext) { - if (!gfileInfo || !gfile) { - // 当前枚举器已完成,弹出并继续下一个 - GFileEnumerator *enumeratorPop = d->stackEnumerator.pop(); - g_object_unref(enumeratorPop); - continue; - } - g_autofree gchar *path = g_file_get_path(gfile); - if (path) { - d->nextUrl = QUrl::fromLocalFile(QString::fromLocal8Bit(path)); - if (DFMUtils::isInvalidCodecByPath(path)) - d->nextUrl.setUserInfo(QString::fromLatin1("originPath::") + QString::fromLatin1(path)); - } else { - g_autofree gchar *uri = g_file_get_uri(gfile); - d->nextUrl = QUrl(QString::fromLocal8Bit(uri)); - if (DFMUtils::isInvalidCodecByPath(uri)) - d->nextUrl.setUserInfo(QString::fromLatin1("originPath::") + QString::fromLatin1(path)); - } - d->dfileInfoNext = DLocalHelper::createFileInfoByUri(d->nextUrl, g_file_info_dup(gfileInfo), FILE_DEFAULT_ATTRIBUTES, - d->enumLinks ? DFileInfo::FileQueryInfoFlags::kTypeNone : DFileInfo::FileQueryInfoFlags::kTypeNoFollowSymlinks); + g_object_unref(nextInfo); // 如果是目录且需要遍历子目录 if (d->enumSubDir && d->dfileInfoNext && d->dfileInfoNext->attribute(DFileInfo::AttributeID::kStandardIsDir).toBool()) { @@ -720,9 +709,12 @@ bool DEnumerator::hasNext() const return true; } + // nextInfo == NULL: either finished or an error occurred if (gerror) { d->setErrorFromGError(gerror); - return false; + d->nextUrl = QUrl(); + d->dfileInfoNext.reset(); + return true; } // 当前枚举器已完成,弹出并继续下一个