summaryrefslogtreecommitdiffstats
path: root/Lib/os.py
diff options
context:
space:
mode:
authorGregory P. Smith <greg@krypto.org>2012-06-03 21:30:44 (GMT)
committerGregory P. Smith <greg@krypto.org>2012-06-03 21:30:44 (GMT)
commita81c8564365d4485bcf1d413b92fb275c091831d (patch)
tree31f166723bf72d1cd61a1bba318a82f5472e1a65 /Lib/os.py
parent9f44a66abc476a6aa57238c005253242b45f827e (diff)
downloadcpython-a81c8564365d4485bcf1d413b92fb275c091831d.zip
cpython-a81c8564365d4485bcf1d413b92fb275c091831d.tar.gz
cpython-a81c8564365d4485bcf1d413b92fb275c091831d.tar.bz2
Fixes Issue #14992: os.makedirs(path, exist_ok=True) would raise an OSError
when the path existed and had the S_ISGID mode bit set when it was not explicitly asked for. This is no longer an exception as mkdir cannot control if the OS sets that bit for it or not.
Diffstat (limited to 'Lib/os.py')
-rw-r--r--Lib/os.py16
1 files changed, 14 insertions, 2 deletions
diff --git a/Lib/os.py b/Lib/os.py
index 5862383..864edfd 100644
--- a/Lib/os.py
+++ b/Lib/os.py
@@ -152,8 +152,20 @@ def makedirs(name, mode=0o777, exist_ok=False):
mkdir(name, mode)
except OSError as e:
import stat as st
- if not (e.errno == errno.EEXIST and exist_ok and path.isdir(name) and
- st.S_IMODE(lstat(name).st_mode) == _get_masked_mode(mode)):
+ dir_exists = path.isdir(name)
+ expected_mode = _get_masked_mode(mode)
+ if dir_exists:
+ # S_ISGID is automatically copied by the OS from parent to child
+ # directories on mkdir. Don't consider it being set to be a mode
+ # mismatch as mkdir does not unset it when not specified in mode.
+ actual_mode = st.S_IMODE(lstat(name).st_mode) & ~st.S_ISGID
+ else:
+ actual_mode = -1
+ if not (e.errno == errno.EEXIST and exist_ok and dir_exists and
+ actual_mode == expected_mode):
+ if dir_exists and actual_mode != expected_mode:
+ e.strerror += ' (mode %o != expected mode %o)' % (
+ actual_mode, expected_mode)
raise
def removedirs(name):