Wed, 01 Mar 2006

IO::File->open() is broken

So you read the documentation for IO::File and see:

open( FILENAME [,MODE [,PERMS]] )
open( FILENAME, IOLAYERS )

so you write:

my $rules = new IO::File('debian/rules','w', 0755);

and wonder why it hasn't changed the permissions from 0666. Stracing confirms it is opened 0666:

open("./debian/rules", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE, 0666) = 4

A bit further reading of the documentation you discover:

If IO::File::open receives a Perl mode string (">", "+<", etc.) or an ANSI C fopen() mode string ("w", "r+", etc.), it uses the basic Perl open operator (but protects any special characters).

If IO::File::open is given a numeric mode, it passes that mode and the optional permissions value to the Perl sysopen operator. The permissions default to 0666.

If IO::File::open is given a mode that includes the : character, it passes all the three arguments to the three-argument open operator.

For convenience, IO::File exports the O_XXX constants from the Fcntl module, if this module is available.

and the correct way to write this is

my $rules = new IO::File('debian/rules',O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE, 0755)

Thank you very much perl for ignoring the permission parameter when you feel like it.

Update:Steinar, yes sorry, I did have 0755 rather than "0755" originally, but changed it just to check that didn't make a difference and copied the wrong version. I've changed the post to have the right thing.

% strace -eopen perl -MIO::File \
   -e 'my $rules = new IO::File("foo","w", 0755);' 2>&1 | grep foo
open("./foo", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE, 0666) = 3
% strace -eopen perl -MIO::File \
   -e 'my $rules = new IO::File("foo","w", "0755");' 2>&1 | grep foo
open("./foo", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE, 0666) = 3

Incidentally, 0755 and "0755" are different:

 perl -e 'printf("%d %d\n", 0755, "0755");'
493 755
[, , ] | # Read Comments (1) |

Related Products

Comments

Sure 0755 and "0755" are different. 0755 is an octal number and you're printing decimal numbers. Although I'm surprised that passing a string to printf worked when it was expected a decimal number, or more accurately it generated the correct decimal number. Maybe I've been working with strongly typed languages too long.

What happens if you try:


perl -e 'printf("%o %o\n", 0755, "0755");'


?
Posted by Miles Barr at Wed Mar 1 23:23:13 2006

Name:


E-mail:


URL:


Comment:


Please enter "fudge" to prove you are a human