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

I wrote a wrapper sub for creating a new directory using make_path. When I pass this sub the octal mode value in different manners I am unable to get make_path happy. I do more than make_path but that is where my problem is so I am simplifying. I am unable to copy and paste so hand typed code follows (please pardon my typos):

#!/usr/bin/perl # # Many comments # use warnings; use strict; use lib'./'; use File::Path qw(make_path remove_tree); use Getopt::Std; use Data::Dumper; use POSIX; use constant ( FALSE => 0, TRUE => 1); sub usage { print STDERR "SetPermissions -d <directory path name> -m <mode i.e. +0777>\n"; } # Get any command line parameters. my %options = (); getopts("d:m:", \%options); # Get the directory path name. my $dirPathName = ""; if (defined($options{d})) { $dirPathName = $options{d}; } else { usage; die "ERROR: the directory path name must be supplied."; } # Get the directory mode. my $dirMode = ""; if (defined($options{m})) { $dirMode = $options{m}; } else { usage; die "ERROR: the directory mode must be supplied."; } ############################################# # Create a directory if it is not already there. # Parameters: # 1) String : The directory path name. # 2) String : The directory mode. # sub smoothMakeDir { my ($dirPathName, $mode) = @_; if ( ! -e $dirPathName ) { my $err; my $saveUmask = umask(); print STDERR "MODE: " . $mode . "\n"; my $usedMode = oct($Mode); umask(0); print STDERR "usedMode: " . $usedMode . "\n"; make_path( $dirPathName, { mode => $usedMode, error => \$err ) ); print STDERR Dumper($err); if ( @$err ) { print STDERR "$!\n"; print STDERR "ERROR: Failed to create the directory: " . $dirPat +hName . "\n"; umask($saveUmask); die "Failed to create a directory"; } umask($saveUmask); } return 0; } print STDERR "\n"; smoothMakeDir( $dirPathName . "1", $dirMode ); print STDERR "\n"; smoothMakeDir( $dirPathName . "2", 0777 ); print STDERR "\n"; smoothMakeDir( $dirPathName . "3", "0777" ); RESULTS: MODE: 0777 usedMode: 511 $VAR1 = []; MODE: 511 usedMode: 329 $VAR1 = []; MODE: 0777 usedMode: 511 $VAR1 = []; ls -al dr----x--t 2 myuserid mygroup 0 Oct 22 11:22 david1 drwxrwxrwx 2 myuserid mygroup 0 Oct 22 11:22 david2 dr----x--t 2 myuserid mygroup 0 Oct 22 11:22 david3

No matter what I try, I am unable to adjust the mode within the sub so that make_path works correctly. I want to pass a variable to the sub with the user's input but it "always" fails. Only the hard coded value works.

I just tried using chmod --> chmod($mode, $dirpathName); <-- while not setting a mode in the make_path call. I get the same results both ways.

It MUST be something in the pass by value to the sub because the print in the sub will print different values depending on what it was passed.

UPDATE:

Using --> $val = oct($val) if $val =~ /^0/; <-- from the oct() Perldoc page flipped the result! At least I can get a value passed by a variable to work correctly now. I still think that there should be a way to handle all value types passed in this "typeless" language!!!!

Replies are listed 'Best First'.
Re: Automatic type conversion in a sub parameter causing a problem
by stevieb (Canon) on Oct 22, 2015 at 17:07 UTC

    Welcome to the Monastery, davebock!

    I can get it to work after making a couple of slight changes (moving the oct() call to inside of the call to make_path(), and fixing your compile-time errors). First, replace:

    my $usedMode = oct($Mode);

    with:

    my $usedMode = $mode;

    then, replace:

    make_path( $dirPathName, { mode => $usedMode, error => \$err ) );

    with:

    make_path( $dirPathName, { mode => oct($usedMode), error => \$err +} );

    Note that you don't need the intermediary $usedMode variable... it can be refactored out, and you can simply use $mode instead.

    -stevieb

      It still does not work for me. The existence of the extraneous variables is because I have been experimenting with moving the oct() around and add things like $mode . " " or $mode + 0 to see if I can affect the value. I am starting to suspect that I have an old, and buggy, module somewhere. I am unable to update my modules at all, short of hand typing them myself and putting them locally. My File::Path module is version 5.005_04

        Could you try the builtin mkdir instead as a test? Although you're setting permissions as you create, chmod might be worth a look too.