From nobody Sun Apr 12 13:44:27 2026 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4ftsGM4jzbz6ZM6V for ; Sun, 12 Apr 2026 13:44:27 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R12" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4ftsGM2znjz3l7R for ; Sun, 12 Apr 2026 13:44:27 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1776001467; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=s3t/2VPaKQsZyxcpV1V8J9bvzq+RWd5+dhUTonEILzo=; b=RL3z8Y0C8Y2Fi/GjMR382ApAhp+gvUaWQg1uIaIEL6uHG8UX6j6CxlmAapWYfLK+SzYQ12 QpzVGbwklVpq25gPmMWcfHZ0BlkE30vciC1GMwmUimZIJgqP6ZDoTVUMM0a+fpjQs4Zyrx RU5OQn6Id7IgG3aW/8VkjOLTFpYkR64kIP19PDGfuD+qu4/L5A1gtbVkMd8pKkX773xqz1 LjVLvP1K7CPAjqJMWpc6BH7CZdQjFMaZiyw9YqnEHAnklepbdp+LeUPECxySCULAlEovNl e1tkXrt6h7qZMwwUcbFNInoQckHhwTEWwie4wADk1o8f134nzxRvZs2Z4FD2Eg== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1776001467; a=rsa-sha256; cv=none; b=VcTYRh6MmbIq3j+qUU5W48wqzpIxhBHUIXYghoXsRORdvq8P6jTo9daWjbCZNFkZQhyCM2 B8ftD7gbi8jecSTdTacxsE2ysOOeVklSopbEstMYvOWlDaviPIpErAWs0xj6I8rfzFBuX5 Owtjr8SlGSidIk/N7gNosXaLTuRrVL0v8BtB1M2JChmgdnqvaxfQ2CM7CxgkiQHheqGRDz ODFVxrH8Pqv2dLE1BfPN4dP9pDV8OqcO9H1CKhVT/StbF/aeR3PQlpeA9hB707jTM91AvA 7T1sywLqYtZ8ogLlAzJP5vz6w8FurmkvAawcIdZvvVIJZt6F8S90i/3m8o+m/w== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1776001467; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=s3t/2VPaKQsZyxcpV1V8J9bvzq+RWd5+dhUTonEILzo=; b=QILu7sM7tWG6qFXszZaGI9Od4fcgB/Mrs6A52RdETAHPE/7y12GU7vRXC7RNJcvvDYAqoI vY0rbO/qDwOF0b2R0Z6KKy0t64YGR+qMCidciV1utNvax6dxIQdGGoyJFIQWYEVP3JvfJH QYdzjT88qtxT1Z4tdjEz7N7s9B79QrrPY/ZmqnU2135Ivomu9xWPrQxQFcZ58aRgDwM2qR rjMeK6FvE9KjXIBVt2OixsXVpw/Fgp7BbRE7Zh5o22LjFvMyce8QYy0/+REJyIlgzJvRvv Qyq/CT/z+T95Grq6OVB2lGexek9PFPIhwlc489eIpB7Z5uC5zheMSIoHwN2CGQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4ftsGM2Clfz4fc for ; Sun, 12 Apr 2026 13:44:27 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 43497 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Sun, 12 Apr 2026 13:44:27 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Kyle Evans Subject: git: 6c92918fa159 - stable/14 - ls: check fts_children() for errors that may not surface otherwise List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kevans X-Git-Repository: src X-Git-Refname: refs/heads/stable/14 X-Git-Reftype: branch X-Git-Commit: 6c92918fa159e974322c5e09ac6cffa9d807b0f2 Auto-Submitted: auto-generated Date: Sun, 12 Apr 2026 13:44:27 +0000 Message-Id: <69dba1bb.43497.2a988a04@gitrepo.freebsd.org> The branch stable/14 has been updated by kevans: URL: https://cgit.FreeBSD.org/src/commit/?id=6c92918fa159e974322c5e09ac6cffa9d807b0f2 commit 6c92918fa159e974322c5e09ac6cffa9d807b0f2 Author: Kyle Evans AuthorDate: 2026-02-11 19:55:55 +0000 Commit: Kyle Evans CommitDate: 2026-04-12 13:43:45 +0000 ls: check fts_children() for errors that may not surface otherwise In particular, if one simply does a non-recursive `ls` on a directory that is not accessible, there are some classes of errors that may cause it to fail that wouldn't be surfaced unless we do an fts_read() that will recurse into the inaccessible directory. Catch those kinds of errors here since we cannot expect to an FTS_ERR/FTS_DNR entry to follow up on them. PR: 287451 Reviewed by: kib Discusssed with: des (cherry picked from commit 7bf81e39d83087dc7f984077b5eed5a48df794d4) --- bin/ls/ls.c | 17 +++++++++++++++++ bin/ls/tests/ls_tests.sh | 30 ++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/bin/ls/ls.c b/bin/ls/ls.c index 51cd45b84d63..81036f311e62 100644 --- a/bin/ls/ls.c +++ b/bin/ls/ls.c @@ -697,6 +697,23 @@ traverse(int argc, char *argv[], int options) output = 1; } chp = fts_children(ftsp, ch_options); + if (chp == NULL && errno != 0) { + warn("%s", p->fts_path); + rval = 1; + + /* + * Avoid further errors on this entry. We won't + * always get an FTS_ERR/FTS_DNR for errors + * in fts_children(), because opendir could + * have failed early on and that only flags an + * error for fts_read() when we try to recurse + * into it. We catch both the non-recursive and + * the recursive case here. + */ + (void)fts_set(ftsp, p, FTS_SKIP); + break; + } + display(p, chp, options); if (!f_recursive && chp != NULL) diff --git a/bin/ls/tests/ls_tests.sh b/bin/ls/tests/ls_tests.sh index c732b60b21a4..be662b75695d 100755 --- a/bin/ls/tests/ls_tests.sh +++ b/bin/ls/tests/ls_tests.sh @@ -476,6 +476,35 @@ b_flag_body() atf_check -e empty -o match:'y\\vz' -s exit:0 ls -b } +atf_test_case childerr +childerr_head() +{ + atf_set "descr" "Verify that fts_children() in pre-order errors are checked" + atf_set "require.user" "unprivileged" +} + +childerr_body() +{ + atf_check mkdir -p root/dir root/edir + atf_check touch root/c + + # Check that listing an empty directory hasn't regressed into being + # called an error. + atf_check -o match:"total 0" -e empty ls -l root/dir + + atf_check chmod 0 root/dir + + # If we did not abort after fts_children() properly, then stdout would + # have an output of the total files enumerated (0). Thus, assert that + # it's empty and that we see the correct error on stderr. + atf_check -s not-exit:0 -e match:"Permission denied" ls -l root/dir + + # Now ensure that we didn't just stop there, we printed out a directory + # that would've been enumerated later. + atf_check -s not-exit:0 -o match:"^root/edir" \ + -e match:"Permission denied" ls -lR root +} + atf_test_case d_flag d_flag_head() { @@ -971,6 +1000,7 @@ atf_init_test_cases() #atf_add_test_case Z_flag atf_add_test_case a_flag atf_add_test_case b_flag + atf_add_test_case childerr #atf_add_test_case c_flag atf_add_test_case d_flag atf_add_test_case f_flag