Perl / perl5

🐪 The Perl programming language
https://dev.perl.org/perl5/
Other
1.85k stars 527 forks source link

find2perl and File::Find doesn't emulate find when path is a symlink (with proposed patch) #4043

Closed p5pRT closed 20 years ago

p5pRT commented 22 years ago

Migrated from rt.perl.org#7056 (status was 'resolved')

Searchable as RT7056$

p5pRT commented 22 years ago

From dcd@tc.fluke.com

find2perl doesn's call &wanted with correct arguments in some cases

Given the environment

mkdir /tmp/testfind2perl cd /tmp/testfind2perl

Please consider the following where find and find2perl agree​: touch f ln -s f q find q -type l -print q # prints q

find2perl q -type l -print > qf perl qf ./q # prints ./q (but close enough for my purposed this time)

Now observe this case using symbolic links to directories mkdir d ln -s d qd find qd -type l -print qd # prints qd as desired

find2perl qd -type l -print > qdf perl qdf

prints nothing

I added the following line my the sub wanted in qdf print "\$dir=$dir\, \$name=$name\, \$_=$_\n";

so now wanted looks like​: sub wanted {   my ($dev\,$ino\,$mode\,$nlink\,$uid\,$gid); print "\$dir=$dir\, \$name=$name\, \$_=$_\n";

  (($dev\,$ino\,$mode\,$nlink\,$uid\,$gid) = lstat($_)) &&   -l _ &&   print("$name\n"); }

This seems to show that wanted is not called with the correct arguments

$dir=qd\, $name=qd\, $_=.

At least the lstat of $_ doesn't stat the file "qd" that I desire that it should.

According to the documentation

  The wanted() function does whatever verifications you want.   `$File​::Find​::dir' contains the current directory name\, and   `$_' the current filename within that directory.   `$File​::Find​::name' contains the complete pathname to the   file. You are chdir()'d to `$File​::Find​::dir' when the   function is called\, unless `no_chdir' was specified. When   \ or \<follow_fast> are in effect there is also a   `$File​::Find​::fullname'. The function may set

and find2perl inserted the aliases into the script it generates *name = *File​::Find​::name; *dir = *File​::Find​::dir;

$dir=qd\, $name=qd\, $_=.

When $_ is "."\, the -l _ test fails\, even though the argument File​::Find​::find({wanted => \&wanted}\, 'qd'); explicitly list 'qd' as the file to be tested.

If I apply the following patch to File​::Find\, so the non -follow path does an lstat instead of a stat\, then the symbolic link to directory finds and prints the desired information like find does.

Inline Patch ```diff --- lib/File/Find.pm.dist Wed Mar 28 17:35:47 2001 +++ lib/File/Find.pm Mon May 21 10:22:17 2001 @@ -330,9 +330,8 @@ $top_item =~ s|/\z|| unless $top_item eq '/'; $Is_Dir= 0; - ($topdev,$topino,$topmode,$topnlink) = stat $top_item; - if ($follow) { + ($topdev,$topino,$topmode,$topnlink) = stat $top_item; if (substr($top_item,0,1) eq '/') { $abs_dir = $top_item; } @@ -353,6 +352,7 @@ } } else { # no follow + ($topdev,$topino,$topmode,$topnlink) = lstat $top_item; $topdir = $top_item; unless (defined $topnlink) { warn "Can't stat $top_item: $!\n"; ```
Perl Info ``` Flags: category=utilities severity=medium Site configuration information for perl v5.6.0: Configured by wjones at Fri Mar 24 11:42:06 PST 2000. Summary of my perl5 (revision 5.0 version 6 subversion 0) configuration: Platform: osname=solaris, osvers=2.5, archname=sun4-solaris uname='sunos tekoa 5.5 generic_103093-26 sun4u sparc sunw,ultra-1 ' config_args='-Dcf_email=wjones@tc.fluke.com -Dprefix=/usr/applocal/sweng/perl/5.6.0 -Dstartperl=#!/usr/local/bin/perl -Dmake=gmake -Dcc=gcc -Dloclibpth=/apps/sweng/lib -Dlocincpth=/apps/sweng/include' hint=recommended, useposix=true, d_sigaction=define usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef useperlio=undef d_sfio=undef uselargefiles=define use64bitint=undef use64bitall=undef uselongdouble=undef usesocks=undef Compiler: cc='gcc', optimize='-O', gccversion=cygnus-2.7-96q4 cppflags='-I/apps/sweng/include' ccflags ='-I/apps/sweng/include ' stdchar='unsigned char', d_stdstdio=define, usevfork=false intsize=4, longsize=4, ptrsize=4, doublesize=8 d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16 ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=4 alignbytes=8, usemymalloc=y, prototype=define Linker and Libraries: ld='gcc', ldflags =' -L/apps/sweng/lib ' libpth=/apps/sweng/lib /lib /usr/lib /usr/ccs/lib /usr/local/lib libs=-lsocket -lnsl -lgdbm -ldb -ldl -lm -lc -lcrypt -lsec libc=/lib/libc.so, so=so, useshrplib=false, libperl=libperl.a Dynamic Linking: dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags=' ' cccdlflags='-fPIC', lddlflags='-G -L/apps/sweng/lib' Locally applied patches: @INC for perl v5.6.0: /apps/ecad/lib/perl /usr/applocal/sweng/perl/5.6.0/lib/5.6.0/sun4-solaris /usr/applocal/sweng/perl/5.6.0/lib/5.6.0 /usr/applocal/sweng/perl/5.6.0/lib/site_perl/5.6.0/sun4-solaris /usr/applocal/sweng/perl/5.6.0/lib/site_perl/5.6.0 /usr/applocal/sweng/perl/5.6.0/lib/site_perl . Environment for perl v5.6.0: HOME=/evtfs/home/dcd LANG=C LANGUAGE (unset) LD_LIBRARY_PATH=/usr/openwin/lib:/usr/motif/lib:/usr/dt/lib:/apps/sybase/lib LOGDIR (unset) PATH=/usr/local/sys:/usr/openwin/bin:/usr/motif/bin/X11:/usr/bin:/usr/ccs/bin:/etc:/usr/local/bin:/usr/local:/usr0/dcd/bin:/usr0/dcd/sys/sparc.sunos5:/home/hobbes/tools/scripts:/home/hobbes/tools/sun4:/usr/sbin:/usr/ucb:/apps/gnu/bin:/usr/applocal/emacs/bin_v19.29:/apps/sweng/bin:/apps/general/bin:/apps/ecad/bin:/usr0/cae/sun4/bin:/apps/ecad/wbin:/apps/sybase/bin:/usr/public PERL5LIB=/apps/ecad/lib/perl PERL_BADLANG (unset) SHELL=/bin/ksh ```
p5pRT commented 22 years ago

From @jhi

Thanks\, applied.

Maybe add the test case to t/lib/filefind.t (only if symlinks are supported\, of course?)

p5pRT commented 22 years ago

From [Unknown Contact. See original ticket]

Maybe add the test case to t/lib/filefind.t (only if symlinks are supported\, of course?)

This will pass when Change 10308 has been applied\, and it will fail appropriately when 10308 is not applied if symlinks are available​:

Inline Patch ```diff --- t/lib/filefind.t.dist Tue May 29 21:06:52 2001 +++ t/lib/filefind.t Tue May 29 21:59:14 2001 @@ -9,7 +9,7 @@ @INC = '../lib'; } -if ( $symlink_exists ) { print "1..117\n"; } +if ( $symlink_exists ) { print "1..119\n"; } else { print "1..61\n"; } use File::Find; @@ -203,6 +203,15 @@ File::Find::finddepth( {wanted => \&d_wanted, follow_fast => 1, no_chdir => 1},'fa' ); Check( scalar(keys %Expect) == 0 ); + + # Verify that File::Find::find will call wanted even if the topdir of + # is a symlink to a directory, and it shouldn't follow the link + # unless follow is set, which it isn't in this case + %Expect = ('fsl' => 1); + %Expect_Dir = (); + File::Find::find( {wanted => \&wanted, },'fa/fsl' ); + Check( scalar(keys %Expect) == 0 ); + } print "# of cases: $case\n"; ```