From: Tavian Barnes <taviana...@tavianator.com>

About -H/-L, POSIX says

> If the referenced file does not exist, the file information and type
> shall be for the link itself.

so we need to fall back from stat() to lstat() if errno indicates a
broken link.
---
 find.c | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/find.c b/find.c
index f96c05b..d907594 100644
--- a/find.c
+++ b/find.c
@@ -223,6 +223,19 @@ static struct {
        char print; /* whether we will need -print when parsing           */
 } gflags;
 
+static int
+find_stat(const char *path, int is_root, struct stat *st)
+{
+       if (gflags.l || (gflags.h && is_root)) {
+               int ret = stat(path, st);
+               if (ret == 0 || (errno != ENOENT && errno != ENOTDIR)) {
+                       return ret;
+               }
+       }
+
+       return lstat(path, st);
+}
+
 /*
  * Primaries
  */
@@ -660,7 +673,7 @@ get_newer_arg(char *argv[], union extra *extra)
 {
        struct stat st;
 
-       if (stat(*argv, &st))
+       if (find_stat(*argv, 1, &st))
                eprintf("failed to stat '%s':", *argv);
 
        extra->i = st.st_mtime;
@@ -944,7 +957,7 @@ find(char *path, struct findhist *hist)
 
        len = strlen(path) + 2; /* \0 and '/' */
 
-       if ((gflags.l || (gflags.h && !hist) ? stat(path, &st) : lstat(path, 
&st)) < 0) {
+       if (find_stat(path, !hist, &st) < 0) {
                weprintf("failed to stat %s:", path);
                return;
        }
-- 
2.19.1


Reply via email to