summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorConrad E. Kimball <cek@tblv021.ca.boeing.com>1997-08-07 00:00:00 +0000
committerTim Bunce <Tim.Bunce@ig.co.uk>1997-08-07 00:00:00 +1200
commitd0e28714d06a28aece55f6d80cabd610184a6bd0 (patch)
treec16de7fb00fb4ef6409a9195938adad24367f515 /lib
parent5f6761f91ec05d535baaab2c6bf33877a80d1dda (diff)
downloadperl-d0e28714d06a28aece55f6d80cabd610184a6bd0.tar.gz
(3) File::Find::find()/finddepth() bugs with toplevel paths
The File::Find module exhibits the following defects: 1) If the top-level directory is a symbolic link to another directory, the find() and finddepth() functions follow that symbolic link and traverse that directory. This behavior is both contrary to the way the real find command works and contrary to the way find() and finddepth() treat symbolic links that occur lower down in the directory hierarchy (which aren't followed). Example: $ cd $HOME $ mkdir findbug; cd findbug $ ln -s /usr usr $ find usr -print usr $ find2perl usr -print | perl usr usr/lost+found usr/tmp usr/tmp/.zma25637cbbb ... 2) If the wanted() function sets $prune = 1 for a toplevel directory, the find() function ignores it. It honors $prune for all lower level directories, but not the toplevel ones. This, too, is contrary to the way the real find command works. Example: $ find /usr -print -prune /usr $ find2perl /usr -print -prune | perl /usr /usr/lost+found /usr/tmp /usr/bin /usr/man /usr/etc /usr/lib /usr/netdemo /usr/include /usr/adm ... 3) If finddepth() is passed a toplevel path that is not a directory, it fails to set $name before calling the wanted() function. This, too, is contrary to the way the real find command works. Example: $ cd $HOME $ find /dev/null -depth -print /dev/null $ find2perl /dev/null -depth -print | perl $ The following patch corrects all three defects: p5p-msgid: 199707040045.RAA24459@mailgate2.boeing.com
Diffstat (limited to 'lib')
-rw-r--r--lib/File/Find.pm20
1 files changed, 13 insertions, 7 deletions
diff --git a/lib/File/Find.pm b/lib/File/Find.pm
index 1faea50158..1d565f2871 100644
--- a/lib/File/Find.pm
+++ b/lib/File/Find.pm
@@ -78,18 +78,22 @@ sub find {
# compatibility.
local($topdir,$topdev,$topino,$topmode,$topnlink);
foreach $topdir (@_) {
- (($topdev,$topino,$topmode,$topnlink) = stat($topdir))
+ (($topdev,$topino,$topmode,$topnlink) =
+ ($Is_VMS ? stat($topdir) : lstat($topdir)))
|| (warn("Can't stat $topdir: $!\n"), next);
if (-d _) {
if (chdir($topdir)) {
($dir,$_) = ($topdir,'.');
$name = $topdir;
+ $prune = 0;
&$wanted;
- my $fixtopdir = $topdir;
- $fixtopdir =~ s,/$,, ;
- $fixtopdir =~ s/\.dir$// if $Is_VMS;
- $fixtopdir =~ s/\\dir$// if $Is_NT;
- &finddir($wanted,$fixtopdir,$topnlink);
+ if (!$prune) {
+ my $fixtopdir = $topdir;
+ $fixtopdir =~ s,/$,, ;
+ $fixtopdir =~ s/\.dir$// if $Is_VMS;
+ $fixtopdir =~ s/\\dir$// if $Is_NT;
+ &finddir($wanted,$fixtopdir,$topnlink);
+ }
}
else {
warn "Can't cd to $topdir: $!\n";
@@ -169,7 +173,8 @@ sub finddepth {
# compatibility.
local($topdir, $topdev, $topino, $topmode, $topnlink);
foreach $topdir (@_) {
- (($topdev,$topino,$topmode,$topnlink) = stat($topdir))
+ (($topdev,$topino,$topmode,$topnlink) =
+ ($Is_VMS ? stat($topdir) : lstat($topdir)))
|| (warn("Can't stat $topdir: $!\n"), next);
if (-d _) {
if (chdir($topdir)) {
@@ -190,6 +195,7 @@ sub finddepth {
unless (($_,$dir) = File::Basename::fileparse($topdir)) {
($dir,$_) = ('.', $topdir);
}
+ $name = $topdir;
chdir $dir && &$wanted;
}
chdir $cwd;