diff options
-rw-r--r-- | usr.bin/find/find.1 | 4 | ||||
-rw-r--r-- | usr.bin/find/function.c | 17 |
2 files changed, 18 insertions, 3 deletions
diff --git a/usr.bin/find/find.1 b/usr.bin/find/find.1 index cffeacf..1abe825 100644 --- a/usr.bin/find/find.1 +++ b/usr.bin/find/find.1 @@ -31,7 +31,7 @@ .\" @(#)find.1 8.7 (Berkeley) 5/9/95 .\" $FreeBSD$ .\" -.Dd November 18, 2012 +.Dd January 5, 2014 .Dt FIND 1 .Os .Sh NAME @@ -520,6 +520,8 @@ Like .Ic -name , but the contents of the symbolic link are matched instead of the file name. +Note that this only matches broken symbolic links +if symbolic links are being followed. This is a GNU find extension. .It Ic -ls This primary always evaluates to true. diff --git a/usr.bin/find/function.c b/usr.bin/find/function.c index 56d361c..9f15675 100644 --- a/usr.bin/find/function.c +++ b/usr.bin/find/function.c @@ -1122,11 +1122,24 @@ f_name(PLAN *plan, FTSENT *entry) { char fn[PATH_MAX]; const char *name; + ssize_t len; if (plan->flags & F_LINK) { - name = fn; - if (readlink(entry->fts_path, fn, sizeof(fn)) == -1) + /* + * The below test both avoids obviously useless readlink() + * calls and ensures that symlinks with existent target do + * not match if symlinks are being followed. + * Assumption: fts will stat all symlinks that are to be + * followed and will return the stat information. + */ + if (entry->fts_info != FTS_NSOK && entry->fts_info != FTS_SL && + entry->fts_info != FTS_SLNONE) return 0; + len = readlink(entry->fts_accpath, fn, sizeof(fn) - 1); + if (len == -1) + return 0; + fn[len] = '\0'; + name = fn; } else name = entry->fts_name; return !fnmatch(plan->c_data, name, |