Date: Wed, 11 Jun 2025 15:32:51 +0000 From: bugzilla-noreply@freebsd.org To: bugs@FreeBSD.org Subject: [Bug 287451] [/bin/ls] readdir() errors delivered via fts_children() are silently discarded Message-ID: <bug-287451-227@https.bugs.freebsd.org/bugzilla/>
index | next in thread | raw e-mail
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=287451 Bug ID: 287451 Summary: [/bin/ls] readdir() errors delivered via fts_children() are silently discarded Product: Base System Version: 15.0-CURRENT Hardware: Any OS: Any Status: New Severity: Affects Only Me Priority: --- Component: bin Assignee: bugs@FreeBSD.org Reporter: no.spam.c@mail.ru Hello. # Problem When running the 'ls' command against an unreadable directory, its exit code is zero, and no read error is printed. Example: root@testhost:~ # mount | grep -F /mnt /dev/da1p1.eli on /mnt (ufs, local, soft-updates) root@testhost:~ # ls /mnt .snap test test2 root@testhost:~ # ls /mnt/test2 1.txt root@testhost:~ # ls /mnt/test root@testhost:~ # echo $? 0 root@testhost:~ # truss ls -l /mnt/test/ 2>&1 | tail fstat(4,{ mode=drwxr-xr-x ,inode=98304,size=26624,blksize=32768 }) = 0 (0x0) fchdir(0x4) = 0 (0x0) getdirentries(4,0x5743bd843000,4096,0x5743bd840028) ERR#97 'Integrity check failed' close(4) = 0 (0x0) fchdir(0x3) = 0 (0x0) fstat(1,{ mode=p--------- ,inode=708,size=0,blksize=4096 }) = 0 (0x0) total 0 write(1,"total 0\n",8) = 8 (0x8) exit(0x0) process exit, rval = 0 root@testhost:~ # Compare this to the 'find' command (which reports the error properly): root@testhost:~ # find /mnt/ /mnt/ /mnt/.snap /mnt/test find: /mnt/test: Integrity check failed /mnt/test2 /mnt/test2/1.txt root@testhost:~ # echo $? 1 root@testhost:~ # # Root cause The bug is in 'bin/ls/ls.c': static void traverse(int argc, char *argv[], int options) { FTS *ftsp; FTSENT *p, *chp; int ch_options; if ((ftsp = fts_open(argv, options, f_nosort ? NULL : mastercmp)) == NULL) err(1, "fts_open"); [...] chp = fts_children(ftsp, 0); if (chp != NULL) display(NULL, chp, options); if (f_listdir) { fts_close(ftsp); return; } [...] while (errno = 0, (p = fts_read(ftsp)) != NULL) switch (p->fts_info) { case FTS_DC: [...] break; case FTS_DNR: case FTS_ERR: [...] break; case FTS_D: if (p->fts_level != FTS_ROOTLEVEL && p->fts_name[0] == '.' && !f_listdot) break; [...] chp = fts_children(ftsp, ch_options); // BUG! display(p, chp, options); [...] break; default: break; } if (errno) // 'errno' is 0 after the loop! err(1, "fts_read"); fts_close(ftsp); } The second call to 'fts_children()' returns NULL and 'errno' is set to a non-zero value, but it's not checked in the code. Subsequent calls (i.e., to 'fts_read()' in the while loop) reset the 'errno' value, so it becomes zero after the loop. -- You are receiving this mail because: You are the assignee for the bug.home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?bug-287451-227>
