The KOI8-R example wasn't quite right.
[p5sagit/p5-mst-13.2.git] / lib / File / Find.pm
index 1ebfba3..e64af10 100644 (file)
@@ -1,8 +1,9 @@
 package File::Find;
+use 5.006;
 use strict;
 use warnings;
-use 5.6.0;
-our $VERSION = '1.02';
+use warnings::register;
+our $VERSION = '1.04';
 require Exporter;
 require Cwd;
 
@@ -180,9 +181,6 @@ Notice the C<_> in the above C<int(-M _)>: the C<_> is a magical
 filehandle that caches the information from the preceding
 stat(), lstat(), or filetest.
 
-Set the variable C<$File::Find::dont_use_nlink> if you're using AFS,
-since AFS cheats.
-
 Here's another interesting wanted function.  It will find all symbolic
 links that don't resolve:
 
@@ -193,8 +191,36 @@ links that don't resolve:
 See also the script C<pfind> on CPAN for a nice application of this
 module.
 
+=head1 WARNINGS
+
+If you run your program with the C<-w> switch, or if you use the
+C<warnings> pragma, File::Find will report warnings for several weird
+situations. You can disable these warnings by putting the statement
+
+    no warnings 'File::Find';
+
+in the appropriate scope. See L<perllexwarn> for more info about lexical
+warnings.
+
 =head1 CAVEAT
 
+=over 2
+
+=item $dont_use_nlink
+
+You can set the variable C<$File::Find::dont_use_nlink> to 1, if you want to
+force File::Find to always stat directories. This was used for systems
+that do not have the correct C<nlink> count for directories. Examples are
+ISO-9660 (CD-R), AFS, and operating systems like OS/2, DOS and a couple of
+others.
+
+Since now File::Find should now detect such things on-the-fly and switch it
+self to using stat, this will probably not a problem to you.
+
+If you do set $dont_use_nlink to 1, you will notice slow-downs.
+
+=item symlinks
+
 Be aware that the option to follow symbolic links can be dangerous.
 Depending on the structure of the directory tree (including symbolic
 links to directories) you might traverse a given (physical) directory
@@ -203,6 +229,8 @@ Furthermore, deleting or changing files in a symbolically linked directory
 might cause very unpleasant surprises, since you delete or change files
 in an unknown directory.
 
+=back
+
 =head1 NOTES
 
 =over 4
@@ -436,7 +464,7 @@ sub Follow_SymLink($) {
        return undef unless defined $DEV;  #  dangling symbolic link
     }
 
-    if ($full_check && $SLnkSeen{$DEV, $INO}++) {
+    if ($full_check && defined $DEV && $SLnkSeen{$DEV, $INO}++) {
        if ( ($follow_skip < 1) || ((-d _) && ($follow_skip < 2)) ) {
            die "$AbsName encountered a second time";
        }
@@ -526,7 +554,7 @@ sub _find_opt {
                else {
                    $abs_dir = contract_name_Mac($cwd, $top_item);
                    unless (defined $abs_dir) {
-                       warn "Can't determine absolute path for $top_item (No such file or directory)\n" if $^W;
+                       warnings::warnif "Can't determine absolute path for $top_item (No such file or directory)\n";
                        next Proc_Top_Item;
                    }
                }
@@ -549,7 +577,7 @@ sub _find_opt {
                    if (ref $dangling_symlinks eq 'CODE') {
                        $dangling_symlinks->($top_item, $cwd);
                    } else {
-                       warn "$top_item is a dangling symbolic link\n" if $^W;
+                       warnings::warnif "$top_item is a dangling symbolic link\n";
                    }
                }
                next Proc_Top_Item;
@@ -563,7 +591,7 @@ sub _find_opt {
        else { # no follow
            $topdir = $top_item;
            unless (defined $topnlink) {
-               warn "Can't stat $top_item: $!\n" if $^W;
+               warnings::warnif "Can't stat $top_item: $!\n";
                next Proc_Top_Item;
            }
            if (-d _) {
@@ -600,7 +628,7 @@ sub _find_opt {
            }
 
            unless ($no_chdir || chdir $abs_dir) {
-               warn "Couldn't chdir $abs_dir: $!\n" if $^W;
+               warnings::warnif "Couldn't chdir $abs_dir: $!\n";
                next Proc_Top_Item;
            }
 
@@ -641,16 +669,15 @@ sub _find_dir($$$) {
     my $SE= [];
     my $dir_name= $p_dir;
     my $dir_pref;
-    my $dir_rel;
+    my $dir_rel = $File::Find::current_dir;
     my $tainted = 0;
+    my $no_nlink;
 
     if ($Is_MacOS) {
        $dir_pref= ($p_dir =~ /:$/) ? $p_dir : "$p_dir:"; # preface
-       $dir_rel= ':'; # directory name relative to current directory
     }
     else {
        $dir_pref= ( $p_dir eq '/' ? '/' : "$p_dir/" );
-       $dir_rel= '.'; # directory name relative to current directory
     }
 
     local ($dir, $name, $prune, *DIR);
@@ -669,7 +696,7 @@ sub _find_dir($$$) {
            }
        }
        unless (chdir $udir) {
-           warn "Can't cd to $udir: $!\n" if $^W;
+           warnings::warnif "Can't cd to $udir: $!\n";
            return;
        }
     }
@@ -712,10 +739,11 @@ sub _find_dir($$$) {
            }
            unless (chdir $udir) {
                if ($Is_MacOS) {
-                   warn "Can't cd to ($p_dir) $udir: $!\n" if $^W;
+                   warnings::warnif "Can't cd to ($p_dir) $udir: $!\n";
                }
                else {
-                   warn "Can't cd to (" . ($p_dir ne '/' ? $p_dir : '') . "/) $udir: $!\n" if $^W;
+                   warnings::warnif "Can't cd to (" .
+                       ($p_dir ne '/' ? $p_dir : '') . "/) $udir: $!\n";
                }
                next;
            }
@@ -730,7 +758,7 @@ sub _find_dir($$$) {
 
        # Get the list of files in the current directory.
        unless (opendir DIR, ($no_chdir ? $dir_name : $File::Find::current_dir)) {
-           warn "Can't opendir($dir_name): $!\n" if $^W;
+           warnings::warnif "Can't opendir($dir_name): $!\n";
            next;
        }
        @filenames = readdir DIR;
@@ -738,7 +766,13 @@ sub _find_dir($$$) {
        @filenames = &$pre_process(@filenames) if $pre_process;
        push @Stack,[$CdLvl,$dir_name,"",-2]   if $post_process;
 
-       if ($nlink == 2 && !$avoid_nlink) {
+       # default: use whatever was specifid
+        # (if $nlink >= 2, and $avoid_nlink == 0, this will switch back)
+        $no_nlink = $avoid_nlink;
+        # if dir has wrong nlink count, force switch to slower stat method
+        $no_nlink = 1 if ($nlink < 2);
+
+       if ($nlink == 2 && !$no_nlink) {
            # This dir has no subdirectories.
            for my $FN (@filenames) {
                next if $FN =~ $File::Find::skip_pattern;
@@ -755,7 +789,7 @@ sub _find_dir($$$) {
 
            for my $FN (@filenames) {
                next if $FN =~ $File::Find::skip_pattern;
-               if ($subcount > 0 || $avoid_nlink) {
+               if ($subcount > 0 || $no_nlink) {
                    # Seen all the subdirs?
                    # check for directoriness.
                    # stat is faster for a file in the current directory
@@ -809,12 +843,7 @@ sub _find_dir($$$) {
 
            if ( $nlink == -2 ) {
                $name = $dir = $p_dir; # $File::Find::name / dir
-               if ($Is_MacOS) {
-                   $_ = ':'; # $_
-               }
-               else {
-                   $_ = '.';
-               }
+                $_ = $File::Find::current_dir;
                &$post_process;         # End-of-directory processing
            }
            elsif ( $nlink < 0 ) {  # must be finddepth, report dirname now
@@ -865,7 +894,7 @@ sub _find_dir_symlnk($$$) {
     my $dir_name = $p_dir;
     my $dir_pref;
     my $loc_pref;
-    my $dir_rel;
+    my $dir_rel = $File::Find::current_dir;
     my $byd_flag; # flag for pending stack entry if $bydepth
     my $tainted = 0;
     my $ok = 1;
@@ -873,11 +902,9 @@ sub _find_dir_symlnk($$$) {
     if ($Is_MacOS) {
        $dir_pref = ($p_dir =~ /:$/) ? "$p_dir" : "$p_dir:";
        $loc_pref = ($dir_loc =~ /:$/) ? "$dir_loc" : "$dir_loc:";
-       $dir_rel  = ':'; # directory name relative to current directory
     } else {
        $dir_pref = ( $p_dir   eq '/' ? '/' : "$p_dir/" );
        $loc_pref = ( $dir_loc eq '/' ? '/' : "$dir_loc/" );
-       $dir_rel  = '.'; # directory name relative to current directory
     }
 
     local ($dir, $name, $fullname, $prune, *DIR);
@@ -900,7 +927,7 @@ sub _find_dir_symlnk($$$) {
        }
        $ok = chdir($updir_loc) unless ($p_dir eq $File::Find::current_dir);
        unless ($ok) {
-           warn "Can't cd to $updir_loc: $!\n" if $^W;
+           warnings::warnif "Can't cd to $updir_loc: $!\n";
            return;
        }
     }
@@ -917,7 +944,7 @@ sub _find_dir_symlnk($$$) {
            # change (back) to parent directory (always untainted)
            unless ($no_chdir) {
                unless (chdir $updir_loc) {
-                   warn "Can't cd to $updir_loc: $!\n" if $^W;
+                   warnings::warnif "Can't cd to $updir_loc: $!\n";
                    next;
                }
            }
@@ -948,7 +975,7 @@ sub _find_dir_symlnk($$$) {
                }
            }
            unless (chdir $updir_loc) {
-               warn "Can't cd to $updir_loc: $!\n" if $^W;
+               warnings::warnif "Can't cd to $updir_loc: $!\n";
                next;
            }
        }
@@ -961,7 +988,7 @@ sub _find_dir_symlnk($$$) {
 
        # Get the list of files in the current directory.
        unless (opendir DIR, ($no_chdir ? $dir_loc : $File::Find::current_dir)) {
-           warn "Can't opendir($dir_loc): $!\n" if $^W;
+           warnings::warnif "Can't opendir($dir_loc): $!\n";
            next;
        }
        @filenames = readdir DIR;
@@ -1006,7 +1033,7 @@ sub _find_dir_symlnk($$$) {
            if ( $byd_flag < 0 ) {  # must be finddepth, report dirname now
                unless ($no_chdir || ($dir_rel eq $File::Find::current_dir)) {
                    unless (chdir $updir_loc) { # $updir_loc (parent dir) is always untainted 
-                       warn "Can't cd to $updir_loc: $!\n" if $^W;
+                       warnings::warnif "Can't cd to $updir_loc: $!\n";
                        next;
                    }
                }