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

I'm attempting to port my diffdel.pl script for use on Windows. In this case on Windows 7 inside 64 bit Strawberry Perl.

I want something simple like this to actually work on Windows:

if ( ! -r "$File1" ) { $Debug && print "File $File1 is not readable!\n"; return 1; }

Unfortunately this doesn't work on Windows resulting in my script crashing due to Permission Denied trying to read a protected file.

Would someone please show me a code fragment on how to do this on Windows? I suspect it is going to be some kind of a Win32 ACL test but the details are evading me...

An example path with unreadable files where this keeps failing on Windows: C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys\*

Edit: I may have figured a way around the need for this test. I'm simply going to blindly assume any error returned by the diff binary means the file is different. Ugly solution but it should work...

Replies are listed 'Best First'.
Re: How to test if a file is readable on Win64?
by Anonymous Monk on Mar 09, 2014 at 23:29 UTC

    Hi , I have some ideas :)

    Unfortunately this doesn't work on Windows resulting in my script crashing due to Permission Denied trying to read a protected file.

    Try Win32API::File , for example

    sub is_readable { use Win32API::File (); my $oldMode = Win32API::File::SetErrorMode(2); my $readable = -r $_[0]; Win32API::File::SetErrorMode( $oldMode ); return $readable; }

    Also try cacls.exe for changing permissions ...

    Also, I remember hearing about starting win32 programs with "dropped privileges" (psexec.exe -d -l ) ... so the program doesn't use all the permissions you have ... :)

    Thats my ideas

      Unfortunately this did not seem to work. I implemented your suggestions but my script fails in the exact same way i.e. it gets to a file which it cannot read but the is_readable function returns that it is readable and my program proceeds to try and execute code which can't possibly succeed i.e. diffing two files, one of which it can't read.
Re: How to test if a file is readable on Win64?
by Discipulus (Canon) on Mar 10, 2014 at 08:00 UTC
    Hello,
    you have to be sure you are not falled in such type of pit.
    The  -e test is passing?
    Are file that you are testing inside some system dir? or fake ones?

    HtH
    L*
    There are no rules, there are no thumbs..
    Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
Re: How to test if a file is readable on Win64?
by jellisii2 (Hermit) on Mar 10, 2014 at 14:48 UTC
    eval the test:
    eval {-r "$File1"}; if ($@) { $Debug && print "File $File1 is not readable! Return was $@.\n"; return 1; }
      I'm puzzled. Why would an eval make any difference?

        No, eval wouldn't make any difference

        If the -r test is causing the popup Win32API::File::SetErrorMode(2); should silence it

        It's my understanding that wrapping code in an eval will effectively fork and return the result code, setting $@ on an error. It should sidestep the crash nicely allowing for the catch that the OP appears to be digging for.

        That said, I could be answering the wrong question.

Re: How to test if a file is readable on Win64?
by locked_user sundialsvc4 (Abbot) on Mar 11, 2014 at 13:46 UTC

    In my experience, there are so many possible factors that could influence “the ability to access a file,” and so many ways for the system to (rudely) inform you that you can’t, that you’re going to have to use logic that can handle the possibility that an exception might be thrown.   The simplest way to do that in Perl is with the eval { ... } construct.   Wrap the entire thing up in a subroutine which will always survive and which will return True or False.   Within that subroutine, do this ... attempt the test, and if the test succeeds without an exception, use the result that it obtained.   If it does not, catch the exception, squash it, and say that access is denied.   Don’t attempt to write logic that avoids the possibility of an exception being thrown, because that probably can’t be avoided in the general case.

    Many CPAN modules already incorporate this kind of logic.

      In my experience,...

      Do you own a windows operating system?

      Since when does eval handle errors generated by microsoft c runtime?

      sundialsvc4 stop that

      there are so many possible factors that could influence “the ability to access a file,” and so many ways for the system to (rudely) inform you that you can’t, you’re going to have to use logic that can handle the possibility that an exception might be thrown
      Really? In Perl? Which Perl file handling functions or operators might throw an exception? I'm not aware of any (unless, of course, you are using autodie).