Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

Why doesn't chmod work on this lexical filehandle?

by williff (Initiate)
on Feb 14, 2011 at 20:52 UTC ( [id://888061]=perlquestion: print w/replies, xml ) Need Help??

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

Code below works as expected except for chmod which does not make the output file read only. I changed from bareword OUT to lexical $OUT after searching thru other PerlMonk wisdom. What is wrong with my $OUT in chmod?
sub writeOutput { my $outScalarRef = shift; my $OUT; my $date = localtime(); $date =~ s/ /_/g; open ($OUT,">$$outScalarRef") or open ($OUT,">$$outScalarRef-$date") or die "Cannot open file $$outScalarRef : $!\n"; print $OUT @stuff; close $OUT; chmod 0444, $OUT; }

Replies are listed 'Best First'.
Re: Why doesn't chmod work on this lexical filehandle?
by JavaFan (Canon) on Feb 14, 2011 at 20:55 UTC
    1) your system must support fchmod for it to work. 2) you should be using globs or glob references. 3) I don't think it works with closed file handles. 4) Did you check the return value of chmod, and $! if it's false?

      Thanks for great suggestions. Moved close after chmod but it did not help.

      Working on Linux box, uname -a says: Linux ... 2.6.9-89.0.16.ELxenU #1 SMP Tue Oct 27 04:12:25 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux

      chmod returns 0 and $! returns "No such file or directory" even after moving close after chmod.

      will investigate globs, glob refs. I think those are used in main, but a scalar ref was used with this sub.

        Then it sounds like $OUT is being interpreted as a string and that that string is being interpreted as a file name: If chmod had thought that you had passed a file handle to it on a system where Perl doesn't think fchmod() is supported, then it would have died rather than returning 0. If you passed a file handle to chmod() on a system with fchmod, "No such file or directory" could not have been the failure reason.

        - tye        

Re: Why doesn't chmod work on this lexical filehandle?
by ELISHEVA (Prior) on Feb 14, 2011 at 23:01 UTC

    chmod 0444 on a file handle open for writing works for me. I'm running Linux Debian 2.6.22 (lenny) and Perl 5.10. However, I seem to recall that when I was running code on Debian Etch + 5.8.8 chmod on a file open for writing would fail. That older version of Perl (or of the operating system) didn't let you mark a file as read only when it was open for writing.

    As mentioned earlier, chmod on a file handle in Perl only works if your system supports chmod on file handles in general (i.e. it supports fchmod). I'm guessing your system does not support it or else you are using an older perl/os combination. Can you set any permissions on a file handle? Or is the problem limited to making files open for writing read only?

    In any case, your best bet is to simply call chmod on the file name rather than the file handle. I can see from your code that you have access to both so this shouldn't be a problem. Your only risk is a small chance that someone could intercept the file and modify it between the time that you close the handle and the time that you set the permissions.

    Also, as a side note, I notice you are using the two parameter open. Don't. Use the three parameter open instead. With the two parameter open there is a small chance that Perl with confuse the file name and the open instructions. With the three parameter open, this risk goes away. You may not be able to avoid the security/timing risk, but the risk of a misinterpreted is something you can eliminate entirely.

    Update: - struck out words -my recollection was faulty - looking back on my testing notes from a ways back it wasn't chmod on a file handle that failed in Etch+5.8.8 but rather 0444 passed to sysopen - system open would turn 0444 into 0644. I just brought up the Debian Etch system and chmod 0444 on a file handle does work on Etch+5.8.8. Thank-you anonymous monk below for making me double check this.

      ...only works if your system supports chmod on file handles in general (i.e. it supports fchmod).

      While this is technically correct, it's almost certainly irrelevant, as the OP is using Linux, and fchmod was introduced with kernel 0.96a almost two decades ago (when the entire kernel source tarball was just 200k).

      Rather, the problem is with older versions of Perl.  For example, when I strace a test script running under 5.8.4, I'm getting

      chmod("*main::OUT", 0444) = -1 ENOENT (No such file or d +irectory)

      for "chmod 0444, *OUT", and something like

      chmod("GLOB(0x602210)", 0444) = -1 ENOENT (No such file or d +irectory)

      for "chmod 0444, $OUT",  while newer versions of Perl in both cases correctly do

      fchmod(4, 0444) = 0

      In other words, older versions simply passed the stringified handle to the chmod system call...

      The OP's case definitely works with 5.8.8 (and newer), though.

        Yes, thank you. Changing to perl 5.10.1 (latest on our network) from 5.8.0 fixed the problem. Many thanks.

      Thank you. I changed to the three parameter open. The root problem was my version of perl. 5.8.0 is our default. After pointing to 5.10.1 the code works with the correction made moving close after chmod. Thanks again.

Re: Why doesn't chmod work on this lexical filehandle?
by Anonyrnous Monk (Hermit) on Feb 14, 2011 at 20:59 UTC

    You're calling chmod on a closed file handle. This doesn't work (it doesn't work with non-lexical file handles either).  Put the close after the chmod.

      thank you, and as promising as it seemed, it did not alter the chmod response.
Re: Why doesn't chmod work on this lexical filehandle?
by pavunkumar (Scribe) on Feb 15, 2011 at 07:23 UTC
     
     You can try this......   
    
    open ($OUT,">$$outScalarRef") or open ($OUT,">$$outScalarRef-$date") or die "Cannot open file $$outScalarRef : $!\n"; print $OUT @stuff; # chmod 0444, $OUT; my ($inode) = ((stat($OUT))[1]); my ($filename) = ` find . -inum $inode ` ; chomp $filename ; chmod 0444, $filename ; close $OUT;

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others browsing the Monastery: (8)
As of 2024-03-28 11:12 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found