Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

if (open(FH, $path)) { ?

by bkiahg (Pilgrim)
on May 03, 2004 at 14:08 UTC ( [id://350010]=perlquestion: print w/replies, xml ) Need Help??

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

Hello Monks,

I am trying to test whether or not someone has permission to read a file and if they do print it out. This is how I have it so far.
if (open(FH, "C:/web/test/test.dat")) { while (<FH>) { print } close FH or die "Cannot close: $!"; } else { print "No go!!!!"; }
The above code is working but my question is, is this the best way to check?

Replies are listed 'Best First'.
Re: if (open(FH, $path)) { ?
by Ryszard (Priest) on May 03, 2004 at 14:20 UTC
    Have a look at perldoc -f -X, it has a whole bunch of tests that can be done on files: if (-r $filename) { #do something }

      Note that this is a theoretical race problem. The code could potentially run the test and determine that the file is readable, writeable, whatever.

      In the intervening period between the test and the moment you attempt to open the file, the permissions might have changed, or the file itself may no longer be around.

      It's the classic resource acquisition problem. Sometimes, no amount of testing can tell you whether something will succeed. All you can do is try it, and see what happens. So, to a certain extent, the technique shown in the OP is the best way to go.

        Yup, agreed, i would s/theoretical// as there is an actual risk, and it can happen...

        To handle the negative case, one could include a die handler in the open statement to make sure everything is nice and graceful.

      Thanks Ryszard this is a better way!
        Not really; many platforms allow additional settings to provide/forbid access not taken into account by -r, so the easiest way is actually to try the open. The problem with that is that some other error may crop up and you'll never find out about it because you are ignoring all errors; you may want to ignore only permissions errors and carp on any others:
        use Errno; if (open $fh, "<", "foo/bar/baz") { ... } elsif ($!{EPERM}) { print "no go!\n"; } else { print "error opening foo/bar/baz: $!"; }
        Of course, to be really uptight about complaining about unexpected errors but ignoring lack of read permission to the file, you should go on to make sure the EPERM didn't result from lack of access to one of the directories traversed, but I'm not going there...
      I don't see the point in testing whether a file is readable before attempting to open it for reading. It both adds unnecessary verbosity to the code and introduces the race condition as others have pointed out.
Re: if (open(FH, $path)) { ?
by jdporter (Paladin) on May 03, 2004 at 14:12 UTC
    Well, it's fine, but one tweak I would make is to add the $! variable (and maybe the filename) in the error message, e.g.
    print "Can't open $filename for reading - $!";
      I would do it that way but I don't want users who don't have access to the file to realize they don't. I'm setting up links to edit the current page.
        In that case, don't print anything if the open fails.
Re: if (open(FH, $path)) { ?
by perlinux (Deacon) on May 03, 2004 at 14:27 UTC
    Search for unary operators on files:
    • -r   File is readable
    • -w   File is writable
    • -x   File is executable
    and more...
Re: if (open(FH, $path)) { ?
by haoess (Curate) on May 03, 2004 at 14:48 UTC

    If you use -r, -w, -x etc. in your programm, be sure not to get race conditions. These are often misused functions. The right way is: Try to do what you want (= read file), and print an error message if that fails. The other way round is: Can I do this, can I do that? and then perform your action. This is the race condition, because between your tests and your action many things can change (i. e. file permissions).

    -- Frank

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://350010]
Approved by broquaint
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others avoiding work at the Monastery: (4)
As of 2024-03-28 17:13 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found