skerr1 has asked for the wisdom of the Perl Monks concerning the following question:

Unix SunOS 5.6 environment and Perl 5.005_02.

According to the man page for the File::Path module, when using rmtree I should be able to catch warnings with rmtree. Will this catch warnings when rmtree fails to remove a file with the following usage:
rmtree("/tmp/tempdir",0,1);

Let's say I don't have permission to remove the file "foo" in the tempdir directory. I would then be unable to remove the tempdir directory. Will I get a warning with this? I have tried to setup the following to catch a warning:
$SIG{'__WARN__'} = sub { die $_[0] }; rmtree("/tmp/tempdir",0,1); $SIG{'__WARN__'} = 'DEFAULT';

But I am not catching a warning for failure to remove the directory or it's contents.

Any help with this would be great. For now I am just verifying that the directory is gone with a (-d <dir>) and, while that works, I don't get details about the failure. I was under the impression that because the return value from rmtree is the number of files removed that I had to catch the __WARN__ signal to know that it failed and to get the details.

All help is greatly appreciated.

Shannon

Replies are listed 'Best First'.
Re: rmtree __WARN__
by rjray (Chaplain) on Jul 31, 2002 at 20:23 UTC

    The online docs for File::Path only go as far back as 5.005_03. Is there a specific reason why you are using an older version of Perl? I would have to dig up the source for 5.005_02 to look at the module in order to answer this, but it may be that the warn-handler for File::Path was only introduced in a later version of Perl.

    --rjray

      I use Perl 5.005_02 because that is what my office currently has at multiple sites (our tools are multisited and have to be able to function at all sites). I have looked into getting my office to use 5.6.0 (or 5.6.1) but so far that is not going to work out.

      I tried to find the source for 5.005_02's version (I am not sure which version is used; 1.03 perhaps?) but I have only been able to find for 5.005 the 03 patch level or higher.

      Any help in figuring this out would be greatly appreciated.

      Thanks,

      Shannon (skerr1)
      According to "perldoc -m File::Path" for the module at location: /opt/gnu/lib/perl5/5.00502/File/Path.pm (on my system) The version is: $VERSION = "1.0401"; (taken from the code).

      Also in the code I see:
      It returns the number of files successfully deleted. Symlinks are treated as ordinary files. B<NOTE:> If the third parameter is not TRUE, C<rmtree> is B<unsecure> in the face of failure or interruption. Files and directories which were not deleted may be left with permissions reset to allow world read and write access. Note also that the occurrence of errors in rmtree can be determined I<only> by trapping diagnostic messages using C<$SIG{__WARN__}>; it is not apparent from the return value. Therefore, you must be extremely careful about using C<rmtree($foo,$ba +r,0> in situations where security is an issue.
      This tells me that this is a version that should be signalling the the __WARN__ for failures. I see that when a file cannot be unlinked it uses carp to throw a warning:(Snippet from File::Path 1.0401)
      unless (unlink $root) { carp "Can't unlink file $root: $!"; if ($force_writeable) { chmod $rp, $root or carp("and can't restore permissions to " . sprintf("0%o",$rp) . "\n"); } last; }
      But my code is not catching the __WARN__ signal.
      $SIG{'__WARN__'} = sub { die $_[0] }; rmtree("/tmp/tempdir",0,1); $SIG{'__WARN__'} = 'DEFAULT';
      Thanks for continuing to help with this.

      -Shannon
        I dont know for sure but it would seem that you are calling rmtree() incorrectly. You are doing
        rmtree("/tmp/tempdir",0,1);
        But the docs say

          NOTE: If the third parameter is not TRUE, rmtree is unsecure in the face of failure or interruption. Files and directories which were not deleted may be left with permissions reset to allow world read and write access. Note also that the occurrence of errors in rmtree can be determined only by trapping diagnostic messages using $SIG{__WARN__}; it is not apparent from the return value. Therefore, you must be extremely careful about using rmtree($foo,$bar,0) in situations where security is an issue.
        Which suggests to me that your problem is because the third parameter is TRUE where it should really be FALSE.

        Yves / DeMerphq
        ---
        Writing a good benchmark isnt as easy as it might look.

        I just tested and I am getting the same results with Perl 5.6.1. Same simple code and call to 5.6.1's File::Path::rmtree.

        Thanks,

        Shannon