Skip to content

Commit d5feefe

Browse files
authored
chmod: symbolic file permissions (briandfoy#843)
* Sync mod() changes with bin/install * chmod would get some of the following symbolic permissions wrong... perl chmod a= ... (0000/----------) perl chmod a=rwx A ... (0777/-rwxrwxrwx) perl chmod u=rw A ... (0600/-rw-------) perl chmod u=rwx,g=w A ... (0720/-rwx-w----) perl chmod u=rx,g=r,o=r A ... (0544/-r-xr--r--)
1 parent 19934f9 commit d5feefe

File tree

1 file changed

+16
-14
lines changed

1 file changed

+16
-14
lines changed

bin/chmod

+16-14
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use constant EX_SUCCESS => 0;
1919
use constant EX_FAILURE => 1;
2020

2121
my $Program = basename($0);
22-
my $VERSION = '1.5';
22+
my $VERSION = '1.6';
2323

2424
my $rc = EX_SUCCESS;
2525

@@ -68,7 +68,7 @@ if (exists $options {R}) {
6868
}
6969
else {
7070
foreach my $file (@ARGV) {
71-
modify_file $file;
71+
modify_file($file);
7272
}
7373
}
7474
exit $rc;
@@ -134,26 +134,26 @@ sub modify_file {
134134
#
135135
#
136136

137-
sub mod ($$) {
137+
sub mod {
138138
my $symbolic = shift;
139139
my $file = shift;
140140

141-
# Initialization.
142-
# The 'user', 'group' and 'other' groups.
143-
my @ugo = qw /u g o/;
144-
# Bit masks for '[sg]uid', 'sticky', 'read', 'write' and 'execute'.
145-
# Can't use qw // cause silly Perl doesn't know '2' is a number
146-
# when dealing with &= ~$bit.
147-
my %bits = (s => 8, t => 8, r => 4, w => 2, x => 1);
148-
141+
my @ugo = qw/u g o/;
142+
my %bits = ('s' => 8, 't' => 8, 'r' => 4, 'w' => 2, 'x' => 1);
149143

150144
# For parsing.
151145
my $who_re = '[augo]*';
152146
my $action_re = '[-+=][rstwxXugo]*';
153147

154148

155149
# Find the current permissions. This is what we start with.
156-
my $mode = sprintf "%04o" => (stat $file) [2] || 0;
150+
my $mode = '000';
151+
if ($symbolic =~ m/[\-\+]/) {
152+
my @st = stat $file;
153+
if (@st) {
154+
$mode = sprintf '%04o', $st[2];
155+
}
156+
}
157157
my $current = substr $mode => -3; # rwx permissions for ugo.
158158

159159
my %perms;
@@ -237,6 +237,9 @@ sub mod ($$) {
237237
else {%perms = %umask;}
238238
next;
239239
}
240+
if ($operator eq '=') {
241+
$perms{$who} = 0;
242+
}
240243

241244
# If we arrive here, $perms is a string.
242245
# We can iterate over the characters.
@@ -297,9 +300,8 @@ sub mod ($$) {
297300

298301
# Apply.
299302
foreach my $s (@set) {
300-
do {$perms {$s} |= $bit; next} if $operator eq '+';
303+
do {$perms {$s} |= $bit; next} if ($operator eq '+' || $operator eq '=');
301304
do {$perms {$s} &= ~$bit; next} if $operator eq '-';
302-
do {$perms {$s} = $bit; next} if $operator eq '=';
303305
die "Weird operator `$operator' found\n";
304306
# Should not happen.
305307
}

0 commit comments

Comments
 (0)