1111import os
1212import pwd
1313import shutil
14+ import stat
1415import sys
1516import unittest
1617import warnings
1718
19+ _DUMMY_SYMLINK = '%s/dummy-symlink' % os .getenv ('TMPDIR' , '/tmp' )
1820
1921warnings .filterwarnings ('ignore' , '.* potential security risk .*' ,
2022 RuntimeWarning )
@@ -25,9 +27,11 @@ def setUp(self):
2527 # create empty file
2628 fp = open (test_support .TESTFN , 'w+' )
2729 fp .close ()
30+ self .teardown_files = [ test_support .TESTFN ]
2831
2932 def tearDown (self ):
30- os .unlink (test_support .TESTFN )
33+ for teardown_file in self .teardown_files :
34+ os .unlink (teardown_file )
3135
3236 def testNoArgFunctions (self ):
3337 # test posix functions which take no arguments and have
@@ -258,7 +262,7 @@ def test_fchown(self):
258262 def test_lchown (self ):
259263 os .unlink (test_support .TESTFN )
260264 # create a symlink
261- os .symlink ('/tmp/dummy-symlink-target' , test_support .TESTFN )
265+ os .symlink (_DUMMY_SYMLINK , test_support .TESTFN )
262266 self ._test_all_chown_common (posix .lchown , test_support .TESTFN )
263267
264268 def test_chdir (self ):
@@ -315,17 +319,49 @@ def test_utime(self):
315319 posix .utime (test_support .TESTFN , (int (now ), int (now )))
316320 posix .utime (test_support .TESTFN , (now , now ))
317321
322+ def _test_chflags_regular_file (self , chflags_func , target_file ):
323+ st = os .stat (target_file )
324+ self .assertTrue (hasattr (st , 'st_flags' ))
325+ chflags_func (target_file , st .st_flags | stat .UF_IMMUTABLE )
326+ try :
327+ new_st = os .stat (target_file )
328+ self .assertEqual (st .st_flags | stat .UF_IMMUTABLE , new_st .st_flags )
329+ try :
330+ fd = open (target_file , 'w+' )
331+ except IOError as e :
332+ self .assertEqual (e .errno , errno .EPERM )
333+ finally :
334+ posix .chflags (target_file , st .st_flags )
335+
336+ @unittest .skipUnless (hasattr (posix , 'chflags' ), 'test needs os.chflags()' )
318337 def test_chflags (self ):
319- if hasattr (posix , 'chflags' ):
320- st = os .stat (test_support .TESTFN )
321- if hasattr (st , 'st_flags' ):
322- posix .chflags (test_support .TESTFN , st .st_flags )
323-
324- def test_lchflags (self ):
325- if hasattr (posix , 'lchflags' ):
326- st = os .stat (test_support .TESTFN )
327- if hasattr (st , 'st_flags' ):
328- posix .lchflags (test_support .TESTFN , st .st_flags )
338+ self ._test_chflags_regular_file (posix .chflags , test_support .TESTFN )
339+
340+ @unittest .skipUnless (hasattr (posix , 'lchflags' ), 'test needs os.lchflags()' )
341+ def test_lchflags_regular_file (self ):
342+ self ._test_chflags_regular_file (posix .lchflags , test_support .TESTFN )
343+
344+ @unittest .skipUnless (hasattr (posix , 'lchflags' ), 'test needs os.lchflags()' )
345+ def test_lchflags_symlink (self ):
346+ testfn_st = os .stat (test_support .TESTFN )
347+
348+ self .assertTrue (hasattr (testfn_st , 'st_flags' ))
349+
350+ os .symlink (test_support .TESTFN , _DUMMY_SYMLINK )
351+ self .teardown_files .append (_DUMMY_SYMLINK )
352+ dummy_symlink_st = os .lstat (_DUMMY_SYMLINK )
353+
354+ posix .lchflags (_DUMMY_SYMLINK ,
355+ dummy_symlink_st .st_flags | stat .UF_IMMUTABLE )
356+ try :
357+ new_testfn_st = os .stat (test_support .TESTFN )
358+ new_dummy_symlink_st = os .lstat (_DUMMY_SYMLINK )
359+
360+ self .assertEqual (testfn_st .st_flags , new_testfn_st .st_flags )
361+ self .assertEqual (dummy_symlink_st .st_flags | stat .UF_IMMUTABLE ,
362+ new_dummy_symlink_st .st_flags )
363+ finally :
364+ posix .lchflags (_DUMMY_SYMLINK , dummy_symlink_st .st_flags )
329365
330366 def test_getcwd_long_pathnames (self ):
331367 if hasattr (posix , 'getcwd' ):
0 commit comments