tags:

views:

81

answers:

3

I need help with this program. As a part of my project I need to create a directory. I was using the system function to do this, but later was told that Perl has a builtin called mkdir.

I'm on Ubuntu 10.04. The problem is mkdir does not seem to work as needed.

It creates the directory but the permissions are different. Here is my function that creates the directory:

sub createDir {
       my ($dir,$perm) = @_;
       unless(-d $dir) {
               mkdir $dir,$perm or die "$!";
       }
}

and I call it in many parts of my program as:

createDir('.today','0755');

the directory .today gets created but the problem is with permissions, it does not have the 0755 permission.

What am I doing wrong?

My Perl details are:

$perl -v

This is perl, v5.8.8 built for x86_64-linux-thread-multi
+8  A: 

You are passing the permission as a string. mkdir expects it to be numeric. But an octal number inside a string is interpreted as a decimal. So '0755' is being interpreted as decimal 755 and is being used by mkdir.

To fix this you can call the subroutine passing it numeric permission:

createDir('.today',0755);

Alternatively you can use make use of the oct function to convert the octal string into a numeric value.

Subroutine call remains the same:

createDir('.today','0755');

but its definition changes to use the oct function as:

mkdir $dir,oct($perm) or die "$!";
codaddict
That would be more clearly written as `mkdir($dir, oct($mask)) || die "cannot mkdir $dir: $!";`.
tchrist
+3  A: 

The second argument to mkdir is not the creation mode. It is a mask which will be &ed with ~umask to determine the creation mode. If you specify an argument of 0755 and your umask is 027, then 0755 &~ 0027 == 0750. Make sure to keep everything in octal, not decimal.

There are also constants for these things available via use POSIX qw[ :sys_stat_h ], such as S_IRWXU, S_IWGRP, and S_ISVTX, but those may be more trouble than they're worth.

tchrist
+1  A: 

After you fix codeaddict's string versus number issue and note tchrist's umask issue you should call chmod on the new directory after creating it if you need specific permissions.

I usually call mkdir without the mask and then chmod the directory to the permissions I want.

Check these from the shell:

$ perldoc -f mkdir
$ perldoc -f chmod
$ perldoc -f unmask

You can also set the umask to zero before calling mkdir, you'd need to do it this way if you need to create the directory with the correct permissions atomically. Something like this is probably what you're looking for:

sub createDir {
        my ($dir, $perm) = @_;
        if(!-d $dir) {
                my $old = umask(0);
                mkdir($dir, $perm) or die "$!";
                umask($old);
        }
        else {
                chmod($dir, $perm);
        }
}
mu is too short
+1 That's my most complete solution, too. To get it done, just `chmod` it.
Axeman