Skip to content

Commit 14b99ef

Browse files
committed
flesh out duplicate code from mkdir and create_unused_dir functions into set_gid_sticky_bits
1 parent ed0d6ae commit 14b99ef

File tree

2 files changed

+98
-26
lines changed

2 files changed

+98
-26
lines changed

easybuild/tools/filetools.py

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1667,6 +1667,25 @@ def patch_perl_script_autoflush(path):
16671667
write_file(path, newtxt)
16681668

16691669

1670+
def set_gid_sticky_bits(path, set_gid=None, sticky=None, recursive=False):
1671+
"""Set GID/sticky bits on specified path."""
1672+
if set_gid is None:
1673+
set_gid = build_option('set_gid_bit')
1674+
if sticky is None:
1675+
sticky = build_option('sticky_bit')
1676+
1677+
bits = 0
1678+
if set_gid:
1679+
bits |= stat.S_ISGID
1680+
if sticky:
1681+
bits |= stat.S_ISVTX
1682+
if bits:
1683+
try:
1684+
adjust_permissions(path, bits, add=True, relative=True, recursive=recursive, onlydirs=True)
1685+
except OSError as err:
1686+
raise EasyBuildError("Failed to set groud ID/sticky bit: %s", err)
1687+
1688+
16701689
def mkdir(path, parents=False, set_gid=None, sticky=None):
16711690
"""
16721691
Create a directory
@@ -1702,18 +1721,9 @@ def mkdir(path, parents=False, set_gid=None, sticky=None):
17021721
raise EasyBuildError("Failed to create directory %s: %s", path, err)
17031722

17041723
# set group ID and sticky bits, if desired
1705-
bits = 0
1706-
if set_gid:
1707-
bits |= stat.S_ISGID
1708-
if sticky:
1709-
bits |= stat.S_ISVTX
1710-
if bits:
1711-
try:
1712-
new_subdir = path[len(existing_parent_path):].lstrip(os.path.sep)
1713-
new_path = os.path.join(existing_parent_path, new_subdir.split(os.path.sep)[0])
1714-
adjust_permissions(new_path, bits, add=True, relative=True, recursive=True, onlydirs=True)
1715-
except OSError as err:
1716-
raise EasyBuildError("Failed to set groud ID/sticky bit: %s", err)
1724+
new_subdir = path[len(existing_parent_path):].lstrip(os.path.sep)
1725+
new_path = os.path.join(existing_parent_path, new_subdir.split(os.path.sep)[0])
1726+
set_gid_sticky_bits(new_path, set_gid, sticky, recursive=True)
17171727
else:
17181728
_log.debug("Not creating existing path %s" % path)
17191729

@@ -2614,14 +2624,6 @@ def create_unused_dir(parent_folder, name):
26142624
raise EasyBuildError("Failed to create directory %s: %s", path, err)
26152625

26162626
# set group ID and sticky bits, if desired
2617-
bits = 0
2618-
if build_option('set_gid_bit'):
2619-
bits |= stat.S_ISGID
2620-
if build_option('sticky_bit'):
2621-
bits |= stat.S_ISVTX
2622-
if bits:
2623-
try:
2624-
adjust_permissions(path, bits, add=True, relative=True, recursive=True, onlydirs=True)
2625-
except OSError as err:
2626-
raise EasyBuildError("Failed to set group ID/sticky bit: %s", err)
2627+
set_gid_sticky_bits(path, recursive=True)
2628+
26272629
return path

test/framework/filetools.py

Lines changed: 74 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2947,16 +2947,84 @@ def test_locate_files(self):
29472947
error_pattern = r"One or more files not found: 2\.txt \(search paths: \)"
29482948
self.assertErrorRegex(EasyBuildError, error_pattern, ft.locate_files, ['2.txt'], [])
29492949

2950+
def test_set_gid_sticky_bits(self):
2951+
"""Test for set_gid_sticky_bits function."""
2952+
test_dir = os.path.join(self.test_prefix, 'test_dir')
2953+
test_subdir = os.path.join(test_dir, 'subdir')
2954+
2955+
ft.mkdir(test_subdir, parents=True)
2956+
dir_perms = os.lstat(test_dir)[stat.ST_MODE]
2957+
self.assertEqual(dir_perms & stat.S_ISGID, 0)
2958+
self.assertEqual(dir_perms & stat.S_ISVTX, 0)
2959+
dir_perms = os.lstat(test_subdir)[stat.ST_MODE]
2960+
self.assertEqual(dir_perms & stat.S_ISGID, 0)
2961+
self.assertEqual(dir_perms & stat.S_ISVTX, 0)
2962+
2963+
# by default, GID & sticky bits are not set
2964+
ft.set_gid_sticky_bits(test_dir)
2965+
dir_perms = os.lstat(test_dir)[stat.ST_MODE]
2966+
self.assertEqual(dir_perms & stat.S_ISGID, 0)
2967+
self.assertEqual(dir_perms & stat.S_ISVTX, 0)
2968+
2969+
ft.set_gid_sticky_bits(test_dir, set_gid=True)
2970+
dir_perms = os.lstat(test_dir)[stat.ST_MODE]
2971+
self.assertEqual(dir_perms & stat.S_ISGID, stat.S_ISGID)
2972+
self.assertEqual(dir_perms & stat.S_ISVTX, 0)
2973+
ft.remove_dir(test_dir)
2974+
ft.mkdir(test_subdir, parents=True)
2975+
2976+
ft.set_gid_sticky_bits(test_dir, sticky=True)
2977+
dir_perms = os.lstat(test_dir)[stat.ST_MODE]
2978+
self.assertEqual(dir_perms & stat.S_ISGID, 0)
2979+
self.assertEqual(dir_perms & stat.S_ISVTX, stat.S_ISVTX)
2980+
ft.remove_dir(test_dir)
2981+
ft.mkdir(test_subdir, parents=True)
2982+
2983+
ft.set_gid_sticky_bits(test_dir, set_gid=True, sticky=True)
2984+
dir_perms = os.lstat(test_dir)[stat.ST_MODE]
2985+
self.assertEqual(dir_perms & stat.S_ISGID, stat.S_ISGID)
2986+
self.assertEqual(dir_perms & stat.S_ISVTX, stat.S_ISVTX)
2987+
# no recursion by default
2988+
dir_perms = os.lstat(test_subdir)[stat.ST_MODE]
2989+
self.assertEqual(dir_perms & stat.S_ISGID, 0)
2990+
self.assertEqual(dir_perms & stat.S_ISVTX, 0)
2991+
2992+
ft.remove_dir(test_dir)
2993+
ft.mkdir(test_subdir, parents=True)
2994+
2995+
ft.set_gid_sticky_bits(test_dir, set_gid=True, sticky=True, recursive=True)
2996+
dir_perms = os.lstat(test_dir)[stat.ST_MODE]
2997+
self.assertEqual(dir_perms & stat.S_ISGID, stat.S_ISGID)
2998+
self.assertEqual(dir_perms & stat.S_ISVTX, stat.S_ISVTX)
2999+
dir_perms = os.lstat(test_subdir)[stat.ST_MODE]
3000+
self.assertEqual(dir_perms & stat.S_ISGID, stat.S_ISGID)
3001+
self.assertEqual(dir_perms & stat.S_ISVTX, stat.S_ISVTX)
3002+
3003+
ft.remove_dir(test_dir)
3004+
ft.mkdir(test_subdir, parents=True)
3005+
3006+
# set_gid_sticky_bits honors relevant build options
3007+
init_config(build_options={'set_gid_bit': True, 'sticky_bit': True})
3008+
ft.set_gid_sticky_bits(test_dir, recursive=True)
3009+
dir_perms = os.lstat(test_dir)[stat.ST_MODE]
3010+
self.assertEqual(dir_perms & stat.S_ISGID, stat.S_ISGID)
3011+
self.assertEqual(dir_perms & stat.S_ISVTX, stat.S_ISVTX)
3012+
dir_perms = os.lstat(test_subdir)[stat.ST_MODE]
3013+
self.assertEqual(dir_perms & stat.S_ISGID, stat.S_ISGID)
3014+
self.assertEqual(dir_perms & stat.S_ISVTX, stat.S_ISVTX)
3015+
29503016
def test_create_unused_dir(self):
29513017
"""Test create_unused_dir function."""
29523018
path = ft.create_unused_dir(self.test_prefix, 'folder')
29533019
self.assertEqual(path, os.path.join(self.test_prefix, 'folder'))
29543020
self.assertTrue(os.path.exists(path))
3021+
29553022
# Repeat with existing folder(s) should create new ones
29563023
for i in range(10):
29573024
path = ft.create_unused_dir(self.test_prefix, 'folder')
29583025
self.assertEqual(path, os.path.join(self.test_prefix, 'folder_%s' % i))
29593026
self.assertTrue(os.path.exists(path))
3027+
29603028
# Not influenced by similar folder
29613029
path = ft.create_unused_dir(self.test_prefix, 'folder2')
29623030
self.assertEqual(path, os.path.join(self.test_prefix, 'folder2'))
@@ -2965,18 +3033,20 @@ def test_create_unused_dir(self):
29653033
path = ft.create_unused_dir(self.test_prefix, 'folder2')
29663034
self.assertEqual(path, os.path.join(self.test_prefix, 'folder2_%s' % i))
29673035
self.assertTrue(os.path.exists(path))
3036+
29683037
# Fail cleanly if passed a readonly folder
29693038
readonly_dir = os.path.join(self.test_prefix, 'ro_folder')
2970-
os.mkdir(readonly_dir)
3039+
ft.mkdir(readonly_dir)
29713040
old_perms = os.lstat(readonly_dir)[stat.ST_MODE]
2972-
os.chmod(readonly_dir, stat.S_IREAD | stat.S_IEXEC)
3041+
ft.adjust_permissions(readonly_dir, stat.S_IREAD | stat.S_IEXEC, relative=False)
29733042
try:
29743043
self.assertErrorRegex(EasyBuildError, 'Failed to create directory',
29753044
ft.create_unused_dir, readonly_dir, 'new_folder')
29763045
finally:
2977-
os.chmod(readonly_dir, old_perms)
3046+
ft.adjust_permissions(readonly_dir, old_perms, relative=False)
3047+
29783048
# Ignore files same as folders. So first just create a file with no contents
2979-
open(os.path.join(self.test_prefix, 'file'), 'w').close()
3049+
ft.write_file(os.path.join(self.test_prefix, 'file'), '')
29803050
path = ft.create_unused_dir(self.test_prefix, 'file')
29813051
self.assertEqual(path, os.path.join(self.test_prefix, 'file_0'))
29823052
self.assertTrue(os.path.exists(path))

0 commit comments

Comments
 (0)