fish-shell/share/functions/umask.fish
ridiculousfish a5fd0b317e Revert "Switch to bare vars in our math invocations"
This reverts commit bd18736ee5.

Bare variables should only be used in commands that must
manipulate the variable stack, such as `set`.
2017-09-09 23:35:47 -07:00

185 lines
5.4 KiB
Fish

# Support the usual (i.e., bash compatible) `umask` UI. This reports or modifies the magic global
# `umask` variable which is monitored by the fish process.
# This table is indexed by the base umask value to be modified. Each digit represents the new umask
# value when the permissions to add are applied to the base umask value.
set __fish_umask_add_table 0101010 2002200 2103210 4440000 4541010 6442200 6543210
function __fish_umask_add
set -l mask_digit $argv[1]
set -l to_add $argv[2]
set -l mask_table 0000000
if test $mask_digit -gt 0
set mask_table $__fish_umask_add_table[$mask_digit]
end
set -l new_vals (string split '' $mask_table)
echo $new_vals[$to_add]
end
# This table is indexed by the base umask value to be modified. Each digit represents the new umask
# value when the permissions to remove are applied to the base umask value.
set __fish_umask_remove_table 1335577 3236767 3337777 5674567 5775577 7676767 7777777
function __fish_umask_remove
set -l mask_digit $argv[1]
set -l to_remove $argv[2]
set -l mask_table 1234567
if test $mask_digit -gt 0
set mask_table $__fish_umask_remove_table[$mask_digit]
end
set -l new_vals (string split '' $mask_table)
echo $new_vals[$to_remove]
end
# This returns the mask corresponding to allowing the permissions to allow. In other words it
# returns the inverse of the mask passed in.
set __fish_umask_set_table 6 5 4 3 2 1 0
function __fish_umask_set
set -l to_set $argv[1]
if test $to_set -eq 0
return 7
end
echo $__fish_umask_set_table[$to_set]
end
# Given a umask string, possibly in symbolic mode, return an octal value with leading zeros.
# This function expects to be called with a single value.
function __fish_umask_parse
# Test if already a valid octal mask. If so pad it with zeros and return it.
# Note that umask values are always base 8 so they don't require a leading zero.
if string match -qr '^0?[0-7]{1,3}$' -- $argv
string sub -s -4 0000$argv
return 0
end
# Test if argument is a valid symbolic mask. Note that the basic pattern allows one illegal
# pattern: who and perms without a mode such as "urw". We test for that below after using the
# pattern to split the rights then testing for that invalid combination.
set -l basic_pattern '([ugoa]*)([=+-]?)([rwx]*)'
if not string match -qr "^$basic_pattern(,$basic_pattern)*\$" -- $argv
printf (_ "%s: Invalid mask '%s'\n") umask $argv >&2
return 1
end
# Split umask into individual digits. We erase the first one because it should always be zero.
set -l res (string split '' $umask)
set -e res[1]
for rights in (string split , $argv)
set -l match (string match -r "^$basic_pattern\$" $rights)
set -l scope $match[2]
set -l mode $match[3]
set -l perms $match[4]
if test -n "$scope" -a -z "$mode"
printf (_ "%s: Invalid mask '%s'\n") umask $argv >&2
return 1
end
if test -z "$scope"
set scope a
end
if test -z "$mode"
set mode =
end
set -l scopes_to_modify
string match -q '*u*' $scope
and set scopes_to_modify 1
string match -q '*g*' $scope
and set -a scopes_to_modify 2
string match -q '*o*' $scope
and set -a scopes_to_modify 3
string match -q '*a*' $scope
and set scopes_to_modify 1 2 3
set -l val 0
if string match -q '*r*' $perms
set val 4
end
if string match -q '*w*' $perms
set val (math $val + 2)
end
if string match -q '*x*' $perms
set val (math $val + 1)
end
for j in $scopes_to_modify
switch $mode
case '='
set res[$j] (__fish_umask_set $val)
case '+'
set res[$j] (__fish_umask_add $res[$j] $val)
case '-'
set res[$j] (__fish_umask_remove $res[$j] $val)
end
end
end
echo 0$res[1]$res[2]$res[3]
return 0
end
function __fish_umask_print_symbolic
set -l val
set -l res ""
set -l letter a u g o
for i in 2 3 4
set res $res,$letter[$i]=
set val (echo $umask|cut -c $i)
if contains $val 0 1 2 3
set res {$res}r
end
if contains $val 0 1 4 5
set res {$res}w
end
if contains $val 0 2 4 6
set res {$res}x
end
end
echo (string split -m 1 '' -- $res)[2]
end
function umask --description "Set default file permission mask"
set -l options 'h/help' 'p/as-command' 'S/symbolic'
argparse -n umask $options -- $argv
or return
if set -q _flag_help
__fish_print_help umask
return 0
end
switch (count $argv)
case 0
set -q umask
or set -g umask 113
if set -q _flag_as_command
echo umask $umask
else if set -q _flag_symbolic
__fish_umask_print_symbolic $umask
else
echo $umask
end
case 1
if set -l parsed (__fish_umask_parse $argv)
set -g umask $parsed
return 0
end
return 1
case '*'
printf (_ '%s: Too many arguments\n') umask >&2
return 1
end
end