From a5fd4b908bf6ad193c5d68dfa3c0eda81aa7802a Mon Sep 17 00:00:00 2001 From: Kaz Kyheku Date: Fri, 7 Feb 2020 21:45:48 -0800 Subject: chmod: bugfix and new tests. * sysif.c (chmod_wrap): When processing set (=), only punch a hole in the target permission area once per clause, so as not to clobber previously set modes. We do this by checking for the chm_perm state. Whenever '=' is processed, the state machine enters into that state; when any permission letter is then processed, it transitions out of that state. This gets the "u=rwsx" test to pass. * tests/018/chmod.tl: New tests. --- sysif.c | 12 +++++++----- tests/018/chmod.tl | 7 +++++++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/sysif.c b/sysif.c index 286dcca6..ee219ff3 100644 --- a/sysif.c +++ b/sysif.c @@ -671,11 +671,13 @@ static val chmod_wrap(val target, val mode) case chm_add: cmode |= bits; break; case chm_sub: cmode &= ~bits; break; case chm_set: - cmode &= ~mask; - if (implicit_all || (who & CHM_O) != 0) - cmode &= ~S_ISVTX; /* GNU Coreutils 8.28 chmod behavior */ - if (!S_ISDIR(cmode)) - cmode &= ~(S_ISUID | S_ISGID); + if (cs == chm_perm) { + cmode &= ~mask; + if (implicit_all || (who & CHM_O) != 0) + cmode &= ~S_ISVTX; /* GNU Coreutils 8.28 chmod behavior */ + if (!S_ISDIR(cmode)) + cmode &= ~(S_ISUID | S_ISGID); + } cmode |= bits; break; } diff --git a/tests/018/chmod.tl b/tests/018/chmod.tl index 7ae0f9b2..16b96ad0 100644 --- a/tests/018/chmod.tl +++ b/tests/018/chmod.tl @@ -32,3 +32,10 @@ (cht "------------" "g+s" "-g----------") (cht "------------" "+t" "--t---------") (cht "sgtrwxrwxrwx" "=" "------------") +(cht "sgtrwxrwxrwx" "u=" "--t---rwxrwx") +(cht "sgtrwxrwxrwx" "g=" "--trwx---rwx") +(cht "sgtrwxrwxrwx" "o=" "---rwxrwx---") +(cht "------------" "u+s,g+s" "sg----------") +(cht "------------" "u+r,g+r,o+r,+t,+s" "sgtr--r--r--") +(cht "------------" "+rwx,g-r+w,o-r+w" "---rwx-wx-wx") +(cht "---------rwx" "u=rwsx" "s--rwx---rwx") -- cgit v1.2.3