#!/usr/bin/perl -w # # Perl Power Tools - mkdir - make directories # James Wetterau, Jr. # 1999-03-06 use strict; use File::Basename; use vars qw($opt_m $opt_p $user_bits $group_bits $other_bits); my $ILLEGAL = 100000; # outside the range for any acceptable mode my $mode = oct(777) - umask; my $orig_mode = $mode | oct(300); # intermediate dirs need u+wx perms my $error = 0; umask 0000; # umask already incorporated into mode $0 = basename $0; # check for @ARGV to make sure $ARGV[0] exists, required by -w while (@ARGV && $ARGV[0] =~ /^-/) { my $opt = shift; if ($opt =~ /^-m(.*)/) { my $mode_opt = $1 || shift; if (! $mode_opt) { ErrorUsage("option requires an argument -- m"); } elsif (($mode = ParseMode($mode_opt)) == $ILLEGAL) { ErrorUsage ("invalid file mode: $mode_opt"); } else { $mode = oct($mode); $opt_m = 1; } } elsif ($opt =~ /^-p$/) { $opt_p = 1; } else { $opt =~ s/^-//; ErrorUsage("illegal option -- $opt"); } } ErrorUsage() unless @ARGV; foreach (@ARGV) { if (MakeDirectory($_, $mode)) { print STDERR "$0: $_: $!\n"; $error = 1; } } exit $error; sub ParseMode { my $parse_mode = $_[0]; my $bits = 0; local ($user_bits, $group_bits, $other_bits) = (7,7,7); if ($parse_mode =~ /^0*[0-7]{1,4}$/) { if ($parse_mode =~ /^[^0]/) { $parse_mode = 0 . $parse_mode; } return $parse_mode; } else { my %who_bits = ('a' => 7, 'u' => 4, 'g' => 2, 'o' => 1); my %perm_bits = ('r' => \4, 's' => \0, 't' => \0, 'w' => \2, 'x' => \1, 'X' => \1, 'u' => *user_bits, 'g' => *group_bits, 'o' => *other_bits); foreach (split (/,/, $parse_mode, -1)) { # don't trim trailing nulls my ($who, $op, $perm) = (0,'',0); if (/^([augo]*)([+-=])([rstwxXugo]*)$/) { foreach (split (//, $1)) { $who = $who | $who_bits{$_}; # use | or to create user mask $who } $op = $2; foreach (split (//, $3)) { $perm = $perm | ${$perm_bits{$_}}; } if ($op eq "+") { # add permissions if ($perm) { if ($who & 4) { $user_bits = $user_bits | $perm; # | or operation sets unset bits, adding perms } if ($who & 2) { $group_bits = $group_bits | $perm; } if ($who & 1) { $other_bits = $other_bits | $perm; } } } elsif ($op eq "-") { # subtract permissions if ($perm) { # only act if there is a permission set if ($who & 4) { $user_bits = $user_bits & (7 - $perm); # 7 - $perm = bits to leave as they are, others # are zero and get cleared by & and operation } if ($who & 2) { $group_bits = $group_bits & (7 - $perm); } if ($who & 1) { $other_bits = $other_bits & (7 - $perm); } } } else { if (! $who) { $who = 7; } if ($who & 4) { $user_bits = $perm; } if ($who & 2) { $group_bits = $perm; } if ($who & 1) { $other_bits = $perm; } } } else { return $ILLEGAL; } } } return (0 . $user_bits . $group_bits . $other_bits); } sub ErrorUsage { if ($_[0]) { print STDERR "$0 (Perl Power Tools): $_[0]\n"; } print STDERR "usage: $0 [-p] [-m mode] dirname ...\n"; exit 1; } sub MakeDirectory { my ($dir,$mode) = @_[0,1]; if (! basename($dir)) { $dir .= "x"; $dir = dirname($dir); } if ($opt_p) { if (! -e dirname($dir)) { if (MakeDirectory(dirname($dir),$orig_mode)) { return $!; } } } mkdir ($dir, $mode) or return $!; return 0; } __END__ =pod =head1 NAME B -- make directories =head1 SYNOPSIS B [-B

] [-B I] I =head1 DESCRIPTION B creates the directories names as operands, in the order specified, using mode rwxrwxrwx (0777) as modified by the current umask. =head2 OPTIONS B accepts the following options: =over 4 =item -m Set the file permission bits of the final created directory to the specified mode. The mode argument can be in any of the formats specified to the chmod utility, though they are I all implemented. (See B.) If a symbolic mode is specified, the operation characters ``+'' and ``-'' are interpreted relative to an initial mode of ``a=rwx''. =item -p Create intermediate directories as required. If this option is not specified, the full path prefix of each operand must already exist. Intermediate directories are created with permission bits of rwxrwxrwx (0777) as modified by the current umask, plus write and search permission for the owner. Do not consider it an error if the argument directory already exists. =back The user must have write permission in the parent directory. mkdir exits 0 if successful, and >0 if an error occurred. =head1 ENVIRONMENT The mode used by B in creating directories is affected by the umask. =head1 BUGS B depends on the underlying Perl mkdir function. On systems without proper support for mode setting, or without POSIX modes, it does not set the modes specified. This B implementation is modelled on the B and B variants. It accepts permission options, as they do, which it does not implement: specifically it ignores the set user id, set group id, and sticky bit flags. B collapses the ``X'' and ``x'' options. =head1 STANDARDS This B implementation is compatible with the B implementation. This implementation has also been based on the B manual description. The B implementation is expected to be compliant with the B specification, also known as B, so this implementation may be, as well. =head1 AUTHOR The Perl implementation of B was written by James Wetterau, Jr., I. =head1 COPYRIGHT and LICENSE This program is copyright by James Wetterau, Jr., 1999. This program is free and open software. You may use, copy, modify, distribute and sell this program (and any modified variants) in any way you wish, provided you do not restrict others to do the same. =cut