The KOI8-R example wasn't quite right.
[p5sagit/p5-mst-13.2.git] / lib / File / Find.pm
index 41e371e..e64af10 100644 (file)
@@ -1,8 +1,9 @@
 package File::Find;
+use 5.006;
 use strict;
 use warnings;
-use 5.6.0;
-our $VERSION = '1.01';
+use warnings::register;
+our $VERSION = '1.04';
 require Exporter;
 require Cwd;
 
@@ -135,7 +136,7 @@ not in taint-mode, C<untaint> is a no-op.
 
 See above. This should be set using the C<qr> quoting operator.
 The default is set to  C<qr|^([-+@\w./]+)$|>. 
-Note that the parantheses are vital.
+Note that the parentheses are vital.
 
 =item C<untaint_skip>
 
@@ -176,12 +177,12 @@ produces something like:
         ($File::Find::prune = 1);
     }
 
-Set the variable C<$File::Find::dont_use_nlink> if you're using AFS,
-since AFS cheats.
+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.
 
-
-Here's another interesting wanted function.  It will find all symlinks
-that don't resolve:
+Here's another interesting wanted function.  It will find all symbolic
+links that don't resolve:
 
     sub wanted {
          -l && !-e && print "bogus link: $File::Find::name\n";
@@ -190,8 +191,36 @@ 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
@@ -200,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
@@ -244,7 +275,7 @@ directories (requires Mac::Files):
  use Mac::Files;
 
  # invisible() --  returns 1 if file/directory is invisible,  
- # 0 if it's visible or undef if an error occured
+ # 0 if it's visible or undef if an error occurred
 
  sub invisible($) { 
    my $file = shift;
@@ -433,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";
        }
@@ -472,7 +503,7 @@ sub _find_opt {
        $pre_process, $post_process, $dangling_symlinks);
     local($dir, $name, $fullname, $prune);
 
-    my $cwd            = $wanted->{bydepth} ? Cwd::fastcwd() : Cwd::cwd();
+    my $cwd            = $wanted->{bydepth} ? Cwd::fastcwd() : Cwd::getcwd();
     my $cwd_untainted  = $cwd;
     my $check_t_cwd    = 1;
     $wanted_callback   = $wanted->{wanted};
@@ -488,7 +519,7 @@ sub _find_opt {
     $untaint_skip      = $wanted->{untaint_skip};
     $dangling_symlinks = $wanted->{dangling_symlinks};
 
-    # for compatability reasons (find.pl, find2perl)
+    # for compatibility reasons (find.pl, find2perl)
     local our ($topdir, $topdev, $topino, $topmode, $topnlink);
 
     # a symbolic link to a directory doesn't increase the link count
@@ -523,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;
                    }
                }
@@ -546,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;
@@ -560,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 _) {
@@ -597,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;
            }
 
@@ -638,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);
@@ -666,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;
        }
     }
@@ -709,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;
            }
@@ -727,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;
@@ -735,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;
@@ -752,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
@@ -806,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
@@ -862,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;
@@ -870,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);
@@ -897,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;
        }
     }
@@ -914,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;
                }
            }
@@ -945,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;
            }
        }
@@ -958,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;
@@ -1003,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;
                    }
                }