summaryrefslogtreecommitdiffstats
path: root/sysif.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2020-02-07 20:36:06 -0800
committerKaz Kylheku <kaz@kylheku.com>2020-02-07 20:36:06 -0800
commit6d6bb0cae29be50cb3e69d85df6cc0b6fee1ab9d (patch)
tree5a27a7e5b9d66ba03ea55ba31a70717a177d3a76 /sysif.c
parent9dddf656328b2bcd76292aabc44112e99ad1b25a (diff)
downloadtxr-6d6bb0cae29be50cb3e69d85df6cc0b6fee1ab9d.tar.gz
txr-6d6bb0cae29be50cb3e69d85df6cc0b6fee1ab9d.tar.bz2
txr-6d6bb0cae29be50cb3e69d85df6cc0b6fee1ab9d.zip
chmod: fix broken umask application for implicit all.
* sysif.c (chmod_wrap): The umask logic is not activating after the first iteration through the loop, because when who is zero, we clobber it by adding the bits for u, g, and o. Then on subsequent iterations, who is no longer zero. Instead, let us leave the value of who alone, and in all the relevant places, check for it being zero.
Diffstat (limited to 'sysif.c')
-rw-r--r--sysif.c15
1 files changed, 6 insertions, 9 deletions
diff --git a/sysif.c b/sysif.c
index 11c07ce5..286dcca6 100644
--- a/sysif.c
+++ b/sysif.c
@@ -637,34 +637,31 @@ static val chmod_wrap(val target, val mode)
{
mode_t bits = 0;
mode_t mask = 0;
- int do_um = (who == 0);
-
- if (do_um)
- who = CHM_U | CHM_G | CHM_O;
+ int implicit_all = (who == 0);
if ((srcm & 020))
bits |= S_ISVTX;
- if ((who & CHM_U) != 0) {
+ if (implicit_all || (who & CHM_U) != 0) {
mask |= 0700;
if ((srcm & 010))
bits |= S_ISUID;
bits |= (srcm & 7) << 6;
}
- if ((who & CHM_G) != 0) {
+ if (implicit_all || (who & CHM_G) != 0) {
mask |= 0070;
if ((srcm & 010))
bits |= S_ISGID;
bits |= (srcm & 7) << 3;
}
- if ((who & CHM_O) != 0) {
+ if (implicit_all || (who & CHM_O) != 0) {
mask |= 0007;
bits |= (srcm & 7);
}
- if (do_um) {
+ if (implicit_all) {
mode_t um = umask(0777);
umask(um);
bits &= ~um;
@@ -675,7 +672,7 @@ static val chmod_wrap(val target, val mode)
case chm_sub: cmode &= ~bits; break;
case chm_set:
cmode &= ~mask;
- if ((who & CHM_O) != 0)
+ 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);