1+ import  errno 
12import  sys 
23import  os 
34import  io 
@@ -3651,34 +3652,55 @@ def test_modes(self):
36513652            arc .add ('read_group_only' , mode = '?---r-----' )
36523653            arc .add ('no_bits' , mode = '?---------' )
36533654            arc .add ('dir/' , mode = '?---rwsrwt' )
3655+             arc .add ('dir_all_bits/' , mode = '?rwsrwsrwt' )
36543656
3655-         # On some systems, setting the sticky bit is a no-op. 
3656-         # Check if that's the case. 
3657+         # On some systems, setting the uid, gid, and/or sticky bit is a no-ops. 
3658+         # Check which bits we can set, so we can compare tarfile machinery to 
3659+         # a simple chmod. 
36573660        tmp_filename  =  os .path .join (TEMPDIR , "tmp.file" )
36583661        with  open (tmp_filename , 'w' ):
36593662            pass 
3660-         os .chmod (tmp_filename , os .stat (tmp_filename ).st_mode  |  stat .S_ISVTX )
3661-         have_sticky_files  =  (os .stat (tmp_filename ).st_mode  &  stat .S_ISVTX )
3662-         os .unlink (tmp_filename )
3663+         try :
3664+             new_mode  =  (os .stat (tmp_filename ).st_mode 
3665+                         |  stat .S_ISVTX  |  stat .S_ISGID  |  stat .S_ISUID )
3666+             try :
3667+                 os .chmod (tmp_filename , new_mode )
3668+             except  OSError  as  exc :
3669+                 if  exc .errno  ==  getattr (errno , "EFTYPE" , 0 ):
3670+                     # gh-108948: On FreeBSD, regular users cannot set 
3671+                     # the sticky bit. 
3672+                     self .skipTest ("chmod() failed with EFTYPE: " 
3673+                                   "regular users cannot set sticky bit" )
3674+                 else :
3675+                     raise 
3676+ 
3677+             got_mode  =  os .stat (tmp_filename ).st_mode 
3678+             _t_file  =  't'  if  (got_mode  &  stat .S_ISVTX ) else  'x' 
3679+             _suid_file  =  's'  if  (got_mode  &  stat .S_ISUID ) else  'x' 
3680+             _sgid_file  =  's'  if  (got_mode  &  stat .S_ISGID ) else  'x' 
3681+         finally :
3682+             os .unlink (tmp_filename )
36633683
36643684        os .mkdir (tmp_filename )
3665-         os .chmod (tmp_filename , os .stat (tmp_filename ).st_mode  |  stat .S_ISVTX )
3666-         have_sticky_dirs  =  (os .stat (tmp_filename ).st_mode  &  stat .S_ISVTX )
3685+         new_mode  =  (os .stat (tmp_filename ).st_mode 
3686+                     |  stat .S_ISVTX  |  stat .S_ISGID  |  stat .S_ISUID )
3687+         os .chmod (tmp_filename , new_mode )
3688+         got_mode  =  os .stat (tmp_filename ).st_mode 
3689+         _t_dir  =  't'  if  (got_mode  &  stat .S_ISVTX ) else  'x' 
3690+         _suid_dir  =  's'  if  (got_mode  &  stat .S_ISUID ) else  'x' 
3691+         _sgid_dir  =  's'  if  (got_mode  &  stat .S_ISGID ) else  'x' 
36673692        os .rmdir (tmp_filename )
36683693
36693694        with  self .check_context (arc .open (), 'fully_trusted' ):
3670-             if  have_sticky_files :
3671-                 self .expect_file ('all_bits' , mode = '?rwsrwsrwt' )
3672-             else :
3673-                 self .expect_file ('all_bits' , mode = '?rwsrwsrwx' )
3695+             self .expect_file ('all_bits' ,
3696+                              mode = f'?rw{ _suid_file } { _sgid_file } { _t_file }  )
36743697            self .expect_file ('perm_bits' , mode = '?rwxrwxrwx' )
36753698            self .expect_file ('exec_group_other' , mode = '?rw-rwxrwx' )
36763699            self .expect_file ('read_group_only' , mode = '?---r-----' )
36773700            self .expect_file ('no_bits' , mode = '?---------' )
3678-             if  have_sticky_dirs :
3679-                 self .expect_file ('dir/' , mode = '?---rwsrwt' )
3680-             else :
3681-                 self .expect_file ('dir/' , mode = '?---rwsrwx' )
3701+             self .expect_file ('dir/' , mode = f'?---rw{ _sgid_dir } { _t_dir }  )
3702+             self .expect_file ('dir_all_bits/' ,
3703+                              mode = f'?rw{ _suid_dir } { _sgid_dir } { _t_dir }  )
36823704
36833705        with  self .check_context (arc .open (), 'tar' ):
36843706            self .expect_file ('all_bits' , mode = '?rwxr-xr-x' )
@@ -3687,6 +3709,7 @@ def test_modes(self):
36873709            self .expect_file ('read_group_only' , mode = '?---r-----' )
36883710            self .expect_file ('no_bits' , mode = '?---------' )
36893711            self .expect_file ('dir/' , mode = '?---r-xr-x' )
3712+             self .expect_file ('dir_all_bits/' , mode = '?rwxr-xr-x' )
36903713
36913714        with  self .check_context (arc .open (), 'data' ):
36923715            normal_dir_mode  =  stat .filemode (stat .S_IMODE (
@@ -3697,6 +3720,7 @@ def test_modes(self):
36973720            self .expect_file ('read_group_only' , mode = '?rw-r-----' )
36983721            self .expect_file ('no_bits' , mode = '?rw-------' )
36993722            self .expect_file ('dir/' , mode = normal_dir_mode )
3723+             self .expect_file ('dir_all_bits/' , mode = normal_dir_mode )
37003724
37013725    def  test_pipe (self ):
37023726        # Test handling of a special file 
0 commit comments