@ -243,10 +243,15 @@ FILE_COMMON_ARGUMENTS = dict(
PASSWD_ARG_RE = re . compile ( r ' ^[-] { 0,2}pass[-]?(word|wd)? ' )
# Can't use 07777 on Python 3, can't use 0o7777 on Python 2.4
PERM_BITS = int ( ' 07777 ' , 8 ) # file mode permission bits
EXEC_PERM_BITS = int ( ' 00111 ' , 8 ) # execute permission bits
DEFAULT_PERM = int ( ' 0666 ' , 8 ) # default file permission bits
# Used for parsing symbolic file perms
MODE_OPERATOR_RE = re . compile ( r ' [+=-] ' )
USERS_RE = re . compile ( r ' [^ugo] ' )
PERMS_RE = re . compile ( r ' [^rwxXstugo] ' )
PERM_BITS = 0o7777 # file mode permission bits
EXEC_PERM_BITS = 0o0111 # execute permission bits
DEFAULT_PERM = 0o0666 # default file permission bits
def get_platform ( ) :
@ -1300,21 +1305,24 @@ class AnsibleModule(object):
pass
return output
def _symbolic_mode_to_octal ( self , path_stat , symbolic_mode ) :
new_mode = stat . S_IMODE ( path_stat . st_mode )
@classmethod
def _symbolic_mode_to_octal ( cls , path_stat , symbolic_mode ) :
"""
This enables symbolic chmod string parsing as stated in the chmod man - page
# Fix for issue #14634
# This enables symbolic chmod string parsing as stated in the chmod
# man-page. This includes things like: "u=rw-x+X,g=r-x+X,o=r-x+X"
This includes things like : " u=rw-x+X,g=r-x+X,o=r-x+X "
"""
new_mode = stat . S_IMODE ( path_stat . st_mode )
# Now parse all symbolic modes
for mode in symbolic_mode . split ( ' , ' ) :
# Per single mode. This always contains a '+', '-' or '='
# Split it on that
permlist = re. split ( r ' [+=-] ' , mode )
permlist = MODE_OPERATOR_RE. split ( mode )
# And find all the operators
opers = re. findall ( r ' [+=-] ' , mode )
opers = MODE_OPERATOR_RE. findall ( mode )
# The user(s) where it's all about is the first element in the
# 'permlist' list. Take that and remove it from the list.
@ -1326,23 +1334,24 @@ class AnsibleModule(object):
# Check if there are illegal characters in the user list
# They can end up in 'users' because they are not split
if re. match ( r ' [^ugo] ' , users ) :
if USERS_RE. match ( users ) :
raise ValueError ( " bad symbolic permission for mode: %s " % mode )
# Now we have two list of equal length, one contains the requested
# permissions and one with the corresponding operators.
for idx , perms in enumerate ( permlist ) :
# Check if there are illegal characters in the permissions
if re. match ( r ' [^rwxXstugo] ' , perms ) :
if PERMS_RE. match ( perms ) :
raise ValueError ( " bad symbolic permission for mode: %s " % mode )
for user in users :
mode_to_apply = self . _get_octal_mode_from_symbolic_perms ( path_stat , user , perms , use_umask )
new_mode = self . _apply_operation_to_mode ( user , opers [ idx ] , mode_to_apply , new_mode )
mode_to_apply = cl s. _get_octal_mode_from_symbolic_perms ( path_stat , user , perms , use_umask )
new_mode = cl s. _apply_operation_to_mode ( user , opers [ idx ] , mode_to_apply , new_mode )
return new_mode
def _apply_operation_to_mode ( self , user , operator , mode_to_apply , current_mode ) :
@staticmethod
def _apply_operation_to_mode ( user , operator , mode_to_apply , current_mode ) :
if operator == ' = ' :
if user == ' u ' :
mask = stat . S_IRWXU | stat . S_ISUID
@ -1360,14 +1369,8 @@ class AnsibleModule(object):
new_mode = current_mode - ( current_mode & mode_to_apply )
return new_mode
def _get_octal_mode_from_symbolic_perms ( self , path_stat , user , perms , use_umask ) :
def _apply_umask ( perm , use_umask , rev_umask ) :
""" Simple function to ' fake ' ternary if statement """
if use_umask :
return perm & rev_umask
else :
return perm
@staticmethod
def _get_octal_mode_from_symbolic_perms ( path_stat , user , perms , use_umask ) :
prev_mode = stat . S_IMODE ( path_stat . st_mode )
is_directory = stat . S_ISDIR ( path_stat . st_mode )
@ -1379,7 +1382,7 @@ class AnsibleModule(object):
# We also need the "reversed umask" for masking
umask = os . umask ( 0 )
os . umask ( umask )
rev_umask = PERM_BITS - umask
rev_umask = umask ^ PERM_BITS
# Permission bits constants documented at:
# http://docs.python.org/2/library/stat.html#stat.S_ISUID
@ -1398,27 +1401,27 @@ class AnsibleModule(object):
user_perms_to_modes = {
' u ' : {
' r ' : _apply_umask( stat . S_IRUSR , use_umask , rev_umask ) ,
' w ' : _apply_umask( stat . S_IWUSR , use_umask , rev_umask ) ,
' x ' : _apply_umask( stat . S_IXUSR , use_umask , rev_umask ) ,
' r ' : rev_umask & stat . S_IRUSR if use_umask else stat . S_IRUSR ,
' w ' : rev_umask & stat . S_IWUSR if use_umask else stat . S_IWUSR ,
' x ' : rev_umask & stat . S_IXUSR if use_umask else stat . S_IXUSR ,
' s ' : stat . S_ISUID ,
' t ' : 0 ,
' u ' : prev_mode & stat . S_IRWXU ,
' g ' : ( prev_mode & stat . S_IRWXG ) << 3 ,
' o ' : ( prev_mode & stat . S_IRWXO ) << 6 } ,
' g ' : {
' r ' : _apply_umask( stat . S_IRGRP , use_umask , rev_umask ) ,
' w ' : _apply_umask( stat . S_IWGRP , use_umask , rev_umask ) ,
' x ' : _apply_umask( stat . S_IXGRP , use_umask , rev_umask ) ,
' r ' : rev_umask & stat . S_IRGRP if use_umask else stat . S_IRGRP ,
' w ' : rev_umask & stat . S_IWGRP if use_umask else stat . S_IWGRP ,
' x ' : rev_umask & stat . S_IXGRP if use_umask else stat . S_IXGRP ,
' s ' : stat . S_ISGID ,
' t ' : 0 ,
' u ' : ( prev_mode & stat . S_IRWXU ) >> 3 ,
' g ' : prev_mode & stat . S_IRWXG ,
' o ' : ( prev_mode & stat . S_IRWXO ) << 3 } ,
' o ' : {
' r ' : _apply_umask( stat . S_IROTH , use_umask , rev_umask ) ,
' w ' : _apply_umask( stat . S_IWOTH , use_umask , rev_umask ) ,
' x ' : _apply_umask( stat . S_IXOTH , use_umask , rev_umask ) ,
' r ' : rev_umask & stat . S_IROTH if use_umask else stat . S_IROTH ,
' w ' : rev_umask & stat . S_IWOTH if use_umask else stat . S_IWOTH ,
' x ' : rev_umask & stat . S_IXOTH if use_umask else stat . S_IXOTH ,
' s ' : 0 ,
' t ' : stat . S_ISVTX ,
' u ' : ( prev_mode & stat . S_IRWXU ) >> 6 ,