diff --git a/src/allmydata/test/test_util.py b/src/allmydata/test/test_util.py index 5b9f696cc..427b67593 100644 --- a/src/allmydata/test/test_util.py +++ b/src/allmydata/test/test_util.py @@ -567,6 +567,21 @@ class FileUtil(ReallyEqualMixin, unittest.TestCase): finally: os.chdir(saved_cwd) + def test_make_dirs_with_absolute_mode(self): + workdir = u"test_make_dirs_with_absolute_mode" + fileutil.make_dirs(workdir) + fileutil.make_dirs_with_absolute_mode(workdir, os.path.join(workdir,"a/b/c/d"), 0766) + new_mode = os.stat(os.path.join(workdir,"a/b/c/d")).st_mode & 0777 + self.failUnlessEqual(new_mode, 0766) + new_mode = os.stat(os.path.join(workdir,"a/b/c")).st_mode & 0777 + self.failUnlessEqual(new_mode, 0766) + new_mode = os.stat(os.path.join(workdir,"a/b")).st_mode & 0777 + self.failUnlessEqual(new_mode, 0766) + new_mode = os.stat(os.path.join(workdir,"a")).st_mode & 0777 + self.failUnlessEqual(new_mode, 0766) + new_mode = os.stat(workdir).st_mode & 0777 + self.failIfEqual(new_mode, 0766) + def test_create_long_path(self): workdir = u"test_create_long_path" fileutil.make_dirs(workdir) diff --git a/src/allmydata/util/fileutil.py b/src/allmydata/util/fileutil.py index 0366daabf..70075bba3 100644 --- a/src/allmydata/util/fileutil.py +++ b/src/allmydata/util/fileutil.py @@ -142,6 +142,31 @@ class EncryptedTemporaryFile: old end-of-file are unspecified. The file position after this operation is unspecified.""" self.file.truncate(newsize) +def make_dirs_with_absolute_mode(parent, dirname, mode): + """ + Make directory `dirname` and chmod it to `mode` afterwards. + We chmod all parent directories of `dirname` until we reach + `parent`. + """ + precondition_abspath(parent) + precondition_abspath(dirname) + if not is_ancestor_path(parent, dirname): + raise AssertionError("dirname must be a descendant of parent") + + make_dirs(dirname) + while dirname != parent: + os.chmod(dirname, mode) + # FIXME: doesn't seem to work on Windows for long paths + old_dirname, dirname = dirname, os.path.dirname(dirname) + _assert(len(dirname) < len(old_dirname), dirname=dirname, old_dirname=old_dirname) + +def is_ancestor_path(parent, dirname): + while dirname != parent: + # FIXME: doesn't seem to work on Windows for long paths + old_dirname, dirname = dirname, os.path.dirname(dirname) + if len(dirname) >= len(old_dirname): + return False + return True def make_dirs(dirname, mode=0777): """