From 7b7a19c95f236cd18f48e44b7cc6794d21c0369f Mon Sep 17 00:00:00 2001 From: Bernhard Voelker Date: Fri, 20 Jul 2018 10:07:13 +0200 Subject: [PATCH 181/224] find: fix -printf %Y output to 'N' for broken links The format %Y shall output 'N' for broken links (ENOENT), 'L' for ELOOP, and '?' for any other error when stat()ing the symlink target. The %Y implementation implicitly fell back to lstat(); therefore it output 'l' for dangling symlinks. $ ln -s ENOENT DANGLE $ find -D stat DANGLE -printf '%y %Y %p\n' fallback_stat(): stat(DANGLE) failed; falling back on lstat() l l DANGLE * find/print.c (do_fprintf): For %Y, always follow links to determine the type of the symlink target. * find/testsuite/find.gnu/printf-symlink.exp: Add a test case for broken links and the ELOOP case ... * find/testsuite/find.gnu/printf-symlink.xo: ... with the expected output. * NEWS (Bug fixes): Mention the fix. Bug introduced in version v4.5.8 with commit '25e7c5fbf9'. --- NEWS | 4 ++++ find/print.c | 9 +++++---- find/testsuite/find.gnu/printf-symlink.exp | 5 ++++- find/testsuite/find.gnu/printf-symlink.xo | 4 ++++ 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/find/print.c b/find/print.c index 3af3e91d..545df96a 100644 --- a/find/print.c +++ b/find/print.c @@ -1175,11 +1175,12 @@ do_fprintf (struct format_val *dest, if (S_ISLNK (stat_buf->st_mode)) { struct stat sbuf; - /* If we would normally follow links, do not do so. - * If we would normally not follow links, do so. + /* %Y needs to stat the symlink target regardless of + * whether we would normally follow symbolic links or not. + * (Actually we do not even come here when following_links() + * other than the ENOENT case.) */ - if ((following_links () ? optionp_stat : optionl_stat) - (state.rel_pathname, &sbuf) != 0) + if (fstatat (state.cwd_dir_fd, state.rel_pathname, &sbuf, 0) != 0) { if ( errno == ENOENT ) { diff --git a/find/testsuite/find.gnu/printf-symlink.exp b/find/testsuite/find.gnu/printf-symlink.exp index 6acc3e68..453f07fc 100644 --- a/find/testsuite/find.gnu/printf-symlink.exp +++ b/find/testsuite/find.gnu/printf-symlink.exp @@ -2,5 +2,8 @@ exec rm -rf tmp exec mkdir tmp exec touch tmp/file exec ln -s file tmp/LINK -find_start p {tmp/LINK -printf "RESULT: %y %Y %p\n" -printf "RESULT2: %Y %y %p\n" } +exec ln -s ENOENT tmp/DANGLE +exec ln -s SELF tmp/SELF +exec ls -ls tmp +find_start p {tmp/LINK tmp/DANGLE tmp/SELF -printf "RESULT: %y %Y %p\n" -printf "RESULT2: %Y %y %p\n" } exec rm -rf tmp diff --git a/find/testsuite/find.gnu/printf-symlink.xo b/find/testsuite/find.gnu/printf-symlink.xo index cc2b69c4..08eb83c6 100644 --- a/find/testsuite/find.gnu/printf-symlink.xo +++ b/find/testsuite/find.gnu/printf-symlink.xo @@ -1,2 +1,6 @@ RESULT: l f tmp/LINK RESULT2: f l tmp/LINK +RESULT: l N tmp/DANGLE +RESULT2: N l tmp/DANGLE +RESULT: l L tmp/SELF +RESULT2: L l tmp/SELF -- 2.19.1