summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--parse.c21
-rwxr-xr-xtests.sh5
-rw-r--r--tests/test_permcopy.out1
3 files changed, 22 insertions, 5 deletions
diff --git a/parse.c b/parse.c
index ed7685b..4a01467 100644
--- a/parse.c
+++ b/parse.c
@@ -1507,21 +1507,32 @@ static int parse_mode(const struct parser_state *state, const char *mode, struct
break;
case MODE_OP:
- file_change = 0;
- dir_change = 0;
-
switch (*i) {
case 'u':
+ file_change = (expr->file_mode >> 6) & 07;
+ dir_change = (expr->dir_mode >> 6) & 07;
+ break;
case 'g':
+ file_change = (expr->file_mode >> 3) & 07;
+ dir_change = (expr->dir_mode >> 3) & 07;
+ break;
case 'o':
- // PERMCOPY (e.g. u=g) has no effect for -perm
- mstate = MODE_ACTION_APPLY;
+ file_change = expr->file_mode & 07;
+ dir_change = expr->dir_mode & 07;
break;
default:
+ file_change = 0;
+ dir_change = 0;
mstate = MODE_PERM;
continue;
}
+
+ file_change |= (file_change << 6) | (file_change << 3);
+ file_change &= who;
+ dir_change |= (dir_change << 6) | (dir_change << 3);
+ dir_change &= who;
+ mstate = MODE_ACTION_APPLY;
break;
case MODE_PERM:
diff --git a/tests.sh b/tests.sh
index c518f33..2fce23b 100755
--- a/tests.sh
+++ b/tests.sh
@@ -164,6 +164,7 @@ posix_tests=(
test_perm_symbolic
test_perm_symbolic_minus
test_perm_leading_plus_symbolic_minus
+ test_permcopy
test_ok_stdin
test_parens
test_bang
@@ -833,6 +834,10 @@ function test_perm_octal_plus() {
! $BFS perms -perm +777 2>/dev/null
}
+function test_permcopy() {
+ bfs_diff perms -perm u+rw,g+u-w,o=g
+}
+
function test_ok_stdin() {
# -ok should *not* close stdin
# See https://savannah.gnu.org/bugs/?24561
diff --git a/tests/test_permcopy.out b/tests/test_permcopy.out
new file mode 100644
index 0000000..4e64e49
--- /dev/null
+++ b/tests/test_permcopy.out
@@ -0,0 +1 @@
+perms/rw