HEX
Server: Apache
System: Linux server2.voipitup.com.au 4.18.0-553.104.1.lve.el8.x86_64 #1 SMP Tue Feb 10 20:07:30 UTC 2026 x86_64
User: posscale (1027)
PHP: 8.2.29
Disabled: exec,passthru,shell_exec,system
Upload Files
File: //opt/saltstack/salt/lib/python3.10/site-packages/salt/modules/__pycache__/file.cpython-310.pyc
o

�N�g\��@sZdZddlZddlZddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlZddl
Z
ddlZddlZddlZddlZddlmZddlmZmZddlZddlZddlZddlZddlZddlZddlZddl Zddl!Zddl"Zddl#Zddl$Zddl%Zddl&Zddl'Zddl(Zddl)m*Z*m+Z+m,Z,ddl)m-Z.ddlm/Z/m0Z0ddl1m2Z2z
ddl3Z3ddl4Z4Wn	e5y�Ynwe�6e7�Z8d	d
iZ9edd�Z:d
d�Z;dd�Z<dd�Z=dd�Z>dd�Z?dd�Z@dd�ZAdd�ZBdd�ZCdd �ZD�d
d"d#�ZE�d
d$d%�ZFd&d'�ZGd(d)�ZH�d
d*d+�ZI�d
d,d-�ZJ�d
d.d/�ZKd0d1�ZLd2d3�ZMd4d5�ZNd6d7�ZOd8d9�ZPd:d;�ZQd<d=�ZR�dd?d@�ZS�ddBdC�ZT	D	D			E	!�d
dFdG�ZUdHdI�ZVdJdK�ZW�ddMdN�ZX	D	O	P	Q	L	L�ddRdS�ZY�ddTdU�ZZ	D	O	V	L	L�ddWdX�Z[e
j\e
j]e
j^e
j_e
j`e
jadY�ZbdZd[�Zc�dd]d^�Zd�dd_d`�Ze�ddadb�Zfdcdd�Zgdedf�Zh�d
dgdh�Zididj�Zj�ddldm�Zkdndo�Zldpdq�Zmdrds�Zn							!�ddtdu�Zo							!	L	L	!�ddvdw�Zp		x	k	L	L		O	L	L	!	L	!	L�ddydz�Zq	{	|	D	L	L	O	L	!	L		�dd}d~�Zr�ddd��Zs�dd�d��Ztd�d��Zu�dd�d��Zvd�d��Zwd�d��Zxd�d��Zyd�d��Zz�dd�d��Z{d�d��Z|d�d��Z}d�d��Z~d�d��Zd�d��Z�d�d��Z��dd�d��Z�d�d��Z��dd�d��Z�d�d��Z�d�d��Z��dd�d��Z��dd�d��Z�d�d��Z�d�d��Z��dd�d��Z��dd�d��Z�d�d��Z�d�d��Z�d�d��Z�d�d��Z��dd�d��Z�d�d��Z�					L�d d�d��Z�d�d„Z�d�dĄZ�	L	!	L�d!d�dƄZ�	�d"d�dȄZ�		L				�d#d�dʄZ�		L					L�d$d�d̄Z�		L	L					!	L�d%d�d΄Z�						!	L�d&d�dЄZ�	E	!	!	L		�d'd�d҄Z�	L		!			!	L	L		�					!	L�d(d�dՄZ��d)d�dׄZ��d)d�d	�Z��d*d�dۄZ�d�d݄Z�d�d߄Z��d+d�d�Z�d�d�Z��d+d�d�Z�d�d�Z��d+d�d�Z��d,d�d�Z��d-d�d�Z�ej�j���e�d�Z��d-d�d�Z�d�d�Z�d�d��Z�ej�j���e�d��Z�d�d��Z��dd�d��Z�d�d��Z�d�d��Z��d�d�Z��d�d�Z��d�d�Z��d�d�d�Z��d�d	�Z�dS(.z|
Manage information about regular files, directories,
and special files on the minion, set/read user,
group, mode, and data
�N)�
namedtuple)�Iterable�Mapping)�CommandExecutionError�MinionError�SaltInvocationError)�get_error_message)�HASHES�
HASHES_REVMAP)�Version�	makedirs_�makedirs�AttrChangesz
added,removedcCstjj��rdSdS)z)
    Only work on POSIX-like systems
    )FziThe file execution module cannot be loaded: only available on non-Windows systems - use win_file instead.T)�salt�utils�platform�
is_windows�rr�E/opt/saltstack/salt/lib/python3.10/site-packages/salt/modules/file.py�__virtual__Csrcsr��tj�t��tjjj	��r3t
j�t
d���}t�fdd�|D��}tj���r5|s7t���dSdSdSdS)z(
    Clean out a template temp file
    Z
file_rootsc3s�|]}��|�VqdS�N)�
startswith)�.0�root��sfnrr�	<genexpr>Zs�z__clean_tmp.<locals>.<genexpr>N)r�os�path�join�tempfile�
gettempdirrr�files�TEMPFILE_PREFIX�	itertools�chain�
from_iterable�__opts__�values�any�exists�remove)rZ	all_rootsZin_rootsrrr�__clean_tmpQs��r,cCsd|d<||d<|S)zH
    Common function for setting error information for return dicts
    F�result�commentr)�ret�err_msgrrr�_error`sr1cCsLtd|�}td|�}t||f�r$t||f�rdS|r dS|r$dSdS)ac
    This function does NOT do any diffing, it just checks the old and new files
    to see if either is binary, and provides an appropriate string noting the
    difference between the two files. If neither file is binary, an empty
    string is returned.

    This function should only be run AFTER it has been determined that the
    files differ.
    �
files.is_textzReplace binary filez"Replace binary file with text filez"Replace text file with binary file�)�	__utils__r)�all)�old�newZ	old_isbinZ	new_isbinrrr�_binary_replaceis
r8cCstj�tdd�d�S)z@
    Get the location of the backup dir in the minion cache
    z
config.get�cachedirZfile_backup)rrr�__salt__rrrr�_get_bkrootsr;cCs*|��}|�d�s|�d�r|�d�|S)a�
    Returns a list of the lines in the string, breaking at line boundaries and
    preserving a trailing newline (if present).

    Essentially, this works like ``str.striplines(False)`` but preserves an
    empty line at the end. This is equivalent to the following code:

    .. code-block:: python

        lines = str.splitlines()
        if str.endswith('
') or str.endswith('
'):
            lines.append('')
    �
�
r3)�
splitlines�endswith�append)�str�linesrrr�'_splitlines_preserving_trailing_newline�s
rCcCsntjj�d�}|rtjj��rdS|g}td|ddd�}t�dtjj	�
|��}|dur0d}|S|�d�}|S)	z0
    Return the version of chattr installed
    �tune2fsN�cmd.runTF�Zignore_retcode�python_shellztune2fs (?P<version>[0-9\.]+)�version)rrr�whichr�is_aixr:�re�search�stringutils�to_str�group)rD�cmdr-�matchrHrrr�_chattr_version�s�
�rRcCs*t�}|dur	dStd�}t|�}||kS)z|
    Return ``True`` if chattr supports extended attributes, that is,
    the version is >1.41.22. Otherwise, ``False``
    NFz1.41.12)rRr)�verZneeded_versionZchattr_versionrrr�_chattr_has_extended_attrs�srTc	Cs^zt|�}Wn
tyt|�}Ynw|dkrdSzt�|�jWSttfy.|YSw)z�
    Convert the group id to the group name on this system

    gid
        gid to convert to a group name

    CLI Example:

    .. code-block:: bash

        salt '*' file.gid_to_group 0
    r3)�int�
ValueError�group_to_gid�grp�getgrgid�gr_name�KeyError�	NameError)�gidrrr�gid_to_group�s
��r^cCs@|durdSzt|t�r|WSt�|�jWStyYdSw)z�
    Convert the group to the gid on this system

    group
        group to convert to its gid

    CLI Example:

    .. code-block:: bash

        salt '*' file.group_to_gid root
    Nr3)�
isinstancerUrX�getgrnam�gr_gidr[)rOrrrrW�s

�rWTcC�ttj�|�|d��dd�S)a]
    Return the id of the group that owns a given file

    path
        file or directory of which to get the gid

    follow_symlinks
        indicated if symlinks should be followed

    CLI Example:

    .. code-block:: bash

        salt '*' file.get_gid /etc/passwd

    .. versionchanged:: 0.16.4
        ``follow_symlinks`` option added
    ��follow_symlinksr]�����statsrr�
expanduser�get�rrdrrr�get_gid���rkcCrb)aW
    Return the group that owns a given file

    path
        file or directory of which to get the group

    follow_symlinks
        indicated if symlinks should be followed

    CLI Example:

    .. code-block:: bash

        salt '*' file.get_group /etc/passwd

    .. versionchanged:: 0.16.4
        ``follow_symlinks`` option added
    rcrOFrfrjrrr�	get_grouprlrmc	Cs*zt�|�jWSttfy|YSw)z�
    Convert a uid to a user name

    uid
        uid to convert to a username

    CLI Example:

    .. code-block:: bash

        salt '*' file.uid_to_user 0
    )�pwd�getpwuid�pw_namer[r\)�uidrrr�uid_to_user-s

�rrcCsH|dur
tjj��}zt|t�r|WSt�|�jWSt	y#YdSw)z�
    Convert user name to a uid

    user
        user name to convert to its uid

    CLI Example:

    .. code-block:: bash

        salt '*' file.user_to_uid root
    Nr3)
rr�user�get_userr_rUrn�getpwnam�pw_uidr[)rsrrr�user_to_uidAs

�rwcCrb)a\
    Return the id of the user that owns a given file

    path
        file or directory of which to get the uid

    follow_symlinks
        indicated if symlinks should be followed

    CLI Example:

    .. code-block:: bash

        salt '*' file.get_uid /etc/passwd

    .. versionchanged:: 0.16.4
        ``follow_symlinks`` option added
    rcrqrerfrjrrr�get_uidXrlrxcCrb)aT
    Return the user that owns a given file

    path
        file or directory of which to get the user

    follow_symlinks
        indicated if symlinks should be followed

    CLI Example:

    .. code-block:: bash

        salt '*' file.get_user /etc/passwd

    .. versionchanged:: 0.16.4
        ``follow_symlinks`` option added
    rcrsFrfrjrrrrtprlrtcCrb)aI
    Return the mode of a file

    path
        file or directory of which to get the mode

    follow_symlinks
        indicated if symlinks should be followed

    CLI Example:

    .. code-block:: bash

        salt '*' file.get_mode /etc/passwd

    .. versionchanged:: 2014.1.0
        ``follow_symlinks`` option added
    rc�moder3rfrjrrr�get_mode�rlrzcCsttj�|�}t|��d�}|sd}tj�|�st|�d���zt�|t|d��Wt
|�St	y9d|YSw)z�
    Set the mode of a file

    path
        file or directory of which to set the mode

    mode
        mode to set the path to

    CLI Example:

    .. code-block:: bash

        salt '*' file.set_mode /etc/passwd 0644
    �0Oo�0z: File not found�z
Invalid Mode )rrrhrA�lstripr*r�chmodrU�	Exceptionrz)rryrrr�set_mode�s��r�cCsbtj�|�}t|�}t|�}d}|dkr|r|d7}nd}|dkr*|r(|d7}nd}t�|||�S)a+
    Chown a file, pass the file the desired user and group without following
    symlinks.

    path
        path to the file or directory

    user
        user owner

    group
        group owner

    CLI Example:

    .. code-block:: bash

        salt '*' file.chown /etc/passwd root root
    r3�User does not exist
re�Group does not exist
)rrrhrwrW�lchown�rrsrOrqr]�errrrrr��s

r�cCs�tj�|�}t|�}t|�}d}|dkr|r|d7}nd}|dkr*|r(|d7}nd}tj�|�sFzt�|||�WStyAYnw|d7}|rJ|St�|||�S)a
    Chown a file, pass the file the desired user and group

    path
        path to the file or directory

    user
        user owner

    group
        group owner

    CLI Example:

    .. code-block:: bash

        salt '*' file.chown /etc/passwd root root
    r3r�rer��File not found)	rrrhrwrWr*r��OSError�chownr�rrrr��s,

�r�cCs tj�|�}t|�}t|||�S)z�
    Change the group of a file

    path
        path to the file or directory

    group
        group owner

    CLI Example:

    .. code-block:: bash

        salt '*' file.chgrp /etc/passwd root
    )rrrhrtr�)rrOrsrrr�chgrpsr�cCs�tjj��rdSz
t|��|d�}Wn
tyYdSwt|�}t|�}d|vr.|�d�t	d�
||�p7dd�
||�p?dd�S)a�
    .. versionadded:: 2018.3.0

    Compare attributes of a given file to given attributes.
    Returns a pair (list) where first item are attributes to
    add and second item are to be removed.

    Please take into account when using this function that some minions will
    not have lsattr installed.

    path
        path to file to compare attributes with.

    attrs
        string of attributes to compare against a given file
    Nr3�e)�added�removed)rrrrJ�lsattrri�AttributeError�set�addrr)r�attrsZlattrsr7r6rrr�
_cmp_attrs)s�
�r�cCs�tjj�d�r
tjj��rdStj�|�std|��d|g}t	d|ddd�}i}|�
�D]}|�d�sM|�dd	�\}}t
�rCd
}nd}t�||�||<q.|S)aV
    .. versionadded:: 2018.3.0
    .. versionchanged:: 2018.3.1
        If ``lsattr`` is not installed on the system, ``None`` is returned.
    .. versionchanged:: 2018.3.4
        If on ``AIX``, ``None`` is returned even if in filesystem as lsattr on ``AIX``
        is not the same thing as the linux version.

    Obtain the modifiable attributes of the given file. If path
    is to a directory, an empty list is returned.

    path
        path to file to obtain attributes of. File/directory must exist.

    CLI Example:

    .. code-block:: bash

        salt '*' file.lsattr foo1.txt
    r�Nz"File or directory does not exist: rETFrFzlsattr: �z[aAcCdDeijPsStTu]z[acdijstuADST])rrrrIrrJrr*rr:r>r�splitrTrK�findall)rrPr-�results�liner��file�patternrrrr�Rs 
�r�c	Os�|�dd�}|�dd�}|�dd�}|�dd�}|dus |dvr$td��|dur,td��d	g}|d
kr9d|��}n	|dkrBd
|��}|�|�|durS|�d
|���|dur^|�d|g�|�|�td|dd�}t|�rqdSdS)aI
    .. versionadded:: 2018.3.0

    Change the attributes of files. This function accepts one or more files and
    the following options:

    operator
        Can be wither ``add`` or ``remove``. Determines whether attributes
        should be added or removed from files

    attributes
        One or more of the following characters: ``aAcCdDeijPsStTu``,
        representing attributes to add to/remove from files

    version
        a version number to assign to the file(s)

    flags
        One or more of the following characters: ``RVf``, representing
        flags to assign to chattr (recurse, verbose, suppress most errors)

    CLI Example:

    .. code-block:: bash

        salt '*' file.chattr foo1.txt foo2.txt operator=add attributes=ai
        salt '*' file.chattr foo3.txt operator=remove attributes=i version=2
    �operatorN�
attributes�flagsrH)r�r+z9Need an operator: 'add' or 'remove' to modify attributes.z"Need attributes: [aAcCdDeijPsStTu]�chattrr��+r+�-z-vrEF�rGT)�poprr@�extendr:�bool)	r"�kwargsr�r�r�rHrPr�r-rrrr�}s2�


r��sha256cCs.tj�|�}tj�|�sdStjj�||d�S)aq
    Return the checksum for the given file. The following checksum algorithms
    are supported:

    * md5
    * sha1
    * sha224
    * sha256 **(default)**
    * sha384
    * sha512

    path
        path to the file or directory

    form
        desired sum format

    CLI Example:

    .. code-block:: bash

        salt '*' file.get_sum /etc/passwd sha512
    r�i)rrrh�isfilerr�	hashutils�get_hash)r�formrrr�get_sum�sr��cCstjj�tj�|�||�S)aT
    Get the hash sum of a file

    This is better than ``get_sum`` for the following reasons:
        - It does not read the entire file into memory.
        - It does not return a string on error. The returned value of
            ``get_sum`` cannot really be trusted since it is vulnerable to
            collisions: ``get_sum(..., 'xyz') == 'Hash xyz not supported'``

    path
        path to the file or directory

    form
        desired sum format

    chunk_size
        amount to sum at once

    CLI Example:

    .. code-block:: bash

        salt '*' file.get_hash /etc/shadow
    )rrr�r�rrrh)rr�Z
chunk_sizerrrr��sr�r3�basec	s��fdd�}d}tj���r�}n:z+tj���j}|tjj	j
vr4td�||d�}|s3td��d���n|dkr;|�Wnt
tfyJ|�Ynw|durht|d|||�}	|	dur^|�|	d	��|	d	<|	Si}	zd
d���dd
�D�\|	d<|	d	<Wn8t
y�|�Yn-ty�t�dtj�d���s�|��|	d	<t��}
|
tvr�t|
|	d<n|�Ynw|	dtvr�td�|	dd�t�|	d	���t|	d	�}|tvr�|�n|t|	dkr�td�||	d|	d	t|���|	d	��|	d	<|	S)a#
    .. versionadded:: 2016.11.0

    Used by :py:func:`file.get_managed <salt.modules.file.get_managed>` to
    obtain the hash and hash type from the parameters specified below.

    file_name
        Optional file name being managed, for matching with
        :py:func:`file.extract_hash <salt.modules.file.extract_hash>`.

    source
        Source file, as used in :py:mod:`file <salt.states.file>` and other
        states. If ``source_hash`` refers to a file containing hashes, then
        this filename will be used to match a filename in that file. If the
        ``source_hash`` is a hash expression, then this argument will be
        ignored.

    source_hash
        Hash file/expression, as used in :py:mod:`file <salt.states.file>` and
        other states. If this value refers to a remote URL or absolute path to
        a local file, it will be cached and :py:func:`file.extract_hash
        <salt.modules.file.extract_hash>` will be used to obtain a hash from
        it.

    source_hash_name
        Specific file name to look for when ``source_hash`` refers to a remote
        file, used to disambiguate ambiguous matches.

    saltenv: base
        Salt fileserver environment from which to retrieve the source_hash. This
        value will only be used when ``source_hash`` refers to a file on the
        Salt fileserver (i.e. one beginning with ``salt://``).

    verify_ssl
        If ``False``, remote https file sources (``https://``) and source_hash
        will not attempt to validate the servers certificate. Default is True.

        .. versionadded:: 3002

    CLI Example:

    .. code-block:: bash

        salt '*' file.get_source_sum /tmp/foo.tar.gz source=http://mydomain.tld/foo.tar.gz source_hash=499ae16dcae71eeb7c3a30c75ea7a1a6
        salt '*' file.get_source_sum /tmp/foo.tar.gz source=http://mydomain.tld/foo.tar.gz source_hash=https://mydomain.tld/hashes.md5
        salt '*' file.get_source_sum /tmp/foo.tar.gz source=http://mydomain.tld/foo.tar.gz source_hash=https://mydomain.tld/hashes.md5 source_hash_name=./dir2/foo.tar.gz
    c
s2td��d�tjjj�d�dd�tt�D�����)zD
        DRY helper for reporting invalid source_hash input
        ahSource hash {} format is invalid. The supported formats are: 1) a hash, 2) an expression in the format <hash_type>=<hash>, or 3) either a path to a local file containing hashes, or a URI of a remote hash file. Supported protocols for remote hash files are: {}. The hash may also not be of a valid length, the following are supported hash types and lengths: {}.�, cS� g|]}t|�d|�d��qS�z (�)�r
�r�xrrr�
<listcomp>?� zGget_source_sum.<locals>._invalid_source_hash_format.<locals>.<listcomp>)	r�formatrrrr"�VALID_PROTOS�sortedr
r��source_hashrr�_invalid_source_hash_format2s��z3get_source_sum.<locals>._invalid_source_hash_formatN�
cp.cache_file��
verify_sslzSource hash file z
 not foundr3�hsumcss�|]}|��VqdSr)�stripr�rrrrfs�
�z!get_source_sum.<locals>.<genexpr>�=r��	hash_typez^[z]+$z�Invalid hash type '{}'. Supported hash types are: {}. Either remove the hash type and simply use '{}' as the source_hash, or change the hash type to a supported type.r�z�Invalid length ({}) for hash type '{}'. Either remove the hash type and simply use '{}' as the source_hash, or change the hash type to '{}')rr�isabs�urllib�parse�urlparse�schemerrr"r�r:rr��	TypeError�extract_hash�lowerr�rVrKrQ�string�	hexdigits�lenr
r	r�r)�	file_name�sourcer��source_hash_name�saltenvr�r��hash_fn�protor/Zsource_hash_lenZhsum_lenrr�r�get_source_sum�s�8�
���
�
�
������r�c
Cs�tj�|�}t|t�std��dD]}||vr!|�|d�\}}n#q|}t|�}t�	|�}|durDtd�
||d�dd�tt�D�����t
||�|kS)	aI
    Check if a file matches the given hash string

    Returns ``True`` if the hash matches, otherwise ``False``.

    path
        Path to a file local to the minion.

    hash
        The hash to check against the file specified in the ``path`` argument.

        .. versionchanged:: 2016.11.4

        For this and newer versions the hash can be specified without an
        accompanying hash type (e.g. ``e138491e9d5b97023cea823fe17bac22``),
        but for earlier releases it is necessary to also specify the hash type
        in the format ``<hash_type>=<hash_value>`` (e.g.
        ``md5=e138491e9d5b97023cea823fe17bac22``).

    CLI Example:

    .. code-block:: bash

        salt '*' file.check_hash /etc/fstab e138491e9d5b97023cea823fe17bac22
        salt '*' file.check_hash /etc/fstab md5=e138491e9d5b97023cea823fe17bac22
    zhash must be a string)�:r�r�NzpHash {} (length: {}) could not be matched to a supported hash type. The supported hash types and lengths are: {}r�cSr�r�r�r�rrrr��r�zcheck_hash.<locals>.<listcomp>)rrrhr_rArr�r�r
rir�rr�r�)rZ	file_hash�sepr�Z
hash_value�hash_lenrrr�
check_hash�s.
�
���r�c
s�d|vr	d|d<nd|vrd|d<z	tjj�|��Wnty1}zd|��WYd}~Sd}~wwdd��fd	d�t�tj�|��D�D�}|�	�|S)
a�
    Approximate the Unix ``find(1)`` command and return a list of paths that
    meet the specified criteria.

    The options include match criteria:

    .. code-block:: text

        name    = path-glob                 # case sensitive
        iname   = path-glob                 # case insensitive
        regex   = path-regex                # case sensitive
        iregex  = path-regex                # case insensitive
        type    = file-types                # match any listed type
        user    = users                     # match any listed user
        group   = groups                    # match any listed group
        size    = [+-]number[size-unit]     # default unit = byte
        mtime   = interval                  # modified since date
        grep    = regex                     # search file contents

    and/or actions:

    .. code-block:: text

        delete [= file-types]               # default type = 'f'
        exec    = command [arg ...]         # where {} is replaced by pathname
        print  [= print-opts]

    and/or depth criteria:

    .. code-block:: text

        maxdepth = maximum depth to transverse in path
        mindepth = minimum depth to transverse before checking files or directories

    The default action is ``print=path``

    ``path-glob``:

    .. code-block:: text

        *                = match zero or more chars
        ?                = match any char
        [abc]            = match a, b, or c
        [!abc] or [^abc] = match anything except a, b, and c
        [x-y]            = match chars x through y
        [!x-y] or [^x-y] = match anything except chars x through y
        {a,b,c}          = match a or b or c

    ``path-regex``: a Python Regex (regular expression) pattern to match pathnames

    ``file-types``: a string of one or more of the following:

    .. code-block:: text

        a: all file types
        b: block device
        c: character device
        d: directory
        p: FIFO (named pipe)
        f: plain file
        l: symlink
        s: socket

    ``users``: a space and/or comma separated list of user names and/or uids

    ``groups``: a space and/or comma separated list of group names and/or gids

    ``size-unit``:

    .. code-block:: text

        b: bytes
        k: kilobytes
        m: megabytes
        g: gigabytes
        t: terabytes

    interval:

    .. code-block:: text

        [<num>w] [<num>d] [<num>h] [<num>m] [<num>s]

        where:
            w: week
            d: day
            h: hour
            m: minute
            s: second

    print-opts: a comma and/or space separated list of one or more of the
    following:

    .. code-block:: text

        group: group name
        md5:   MD5 digest of file contents
        mode:  file permissions (as integer)
        mtime: last modification time (as time_t)
        name:  file basename
        path:  file absolute path
        size:  file size in bytes
        type:  file type
        user:  user name

    CLI Examples:

    .. code-block:: bash

        salt '*' file.find / type=f name=\*.bak size=+10m
        salt '*' file.find /var mtime=+30d size=+10m print=path,size,mtime
        salt '*' file.find /var/log name=\*.[0-9] mtime=+30d size=+10m delete
    �delete�f�printrzerror: NcSsg|]	}|D]}|�qqSrr�r�i�itemrrrr�Fs���zfind.<locals>.<listcomp>csg|]}��|��qSr)�find)r�p��finderrrr�Hs)
rrr�ZFinderrV�globrrrh�sort)r�argsr��exr/rr�rr��sr
���r�FcCs>d}|�dd��dd�}|dur|D]
}|�|d|�}q|S)z2
    Escape single quotes and forward slashes
    z^.[$()|*+?{�'z'"'"'�/z\/T�\)�replace)r��
escape_allZ
special_chars�charrrr�_sed_escOsr��.bak�-r -e�gc	
	Cs�tj�|�}tj�|�sdSt|�}t|�}t||�}t||�}t||�}tjdkr0|�dd�}dg}	|	�	|r<d|��nd�|	�
tjj
�|��|	�	dj|rUd|�d	�nd
|rZdnd
|||d��|	�	|�td
|	dd�S)a�
    .. deprecated:: 0.17.0
       Use :py:func:`~salt.modules.file.replace` instead.

    Make a simple edit to a file

    Equivalent to:

    .. code-block:: bash

        sed <backup> <options> "/<limit>/ s/<before>/<after>/<flags> <file>"

    path
        The full path to the file to be edited
    before
        A pattern to find in order to replace with ``after``
    after
        Text that will replace ``before``
    limit: ``''``
        An initial pattern to search for before searching for ``before``
    backup: ``.bak``
        The file will be backed up before edit with this file extension;
        **WARNING:** each time ``sed``/``comment``/``uncomment`` is called will
        overwrite this backup
    options: ``-r -e``
        Options to pass to sed
    flags: ``g``
        Flags to modify the sed search; e.g., ``i`` for case-insensitive pattern
        matching
    negate_match: False
        Negate the search command (``!``)

        .. versionadded:: 0.17.0

    Forward slashes and single quotes will be escaped automatically in the
    ``before`` and ``after`` patterns.

    CLI Example:

    .. code-block:: bash

        salt '*' file.sed /etc/httpd/httpd.conf 'LogLevel warn' 'LogLevel info'
    F�darwin�-r�-E�sed�-iz/{limit}{negate_match}s/{before}/{after}/{flags}r��/ r3�!)�limit�negate_match�before�afterr��cmd.run_allr�)rrrhr*rAr��sysrr�r@r�rrr��shlex_splitr�r:)
rr�r�r��backup�optionsr�r�r�rPrrrr�[s09




��
	r�cCs�tj�|�}tj�|�sdStt|�d�}tt|�d�}d}tjdkr)|�dd�}dg}|�	t
jj�
|��|�dj|rBd|�d	�nd
|d|��d��|�|�td
|dd�}t|�S)ah
    .. deprecated:: 0.17.0
       Use :func:`search` instead.

    Return True if the file at ``path`` contains ``text``. Utilizes sed to
    perform the search (line-wise search).

    Note: the ``p`` flag will be added to any flags you pass in.

    CLI Example:

    .. code-block:: bash

        salt '*' file.contains /etc/crontab 'mymaintenance.sh'
    Fz-n -r -er�r�r�r�z{limit}s/{before}/$/{flags}r�r�r3r�)r�r�r�rEr�)rrrhr*r�rAr�rr�r�rrr�r�r@r�r:r�)r�textr�r�r�rrPr-rrr�sed_contains�s(
��
r�gMSc
Cs:tj�|�}t|�}t|�}t|�}t||�}t||�}t�||�|���tj	j
�|d��e}tj	j
�|�|��d��@}	|dur]|	��D]}
|�
tj	j�ttj	j�|
�||||���qDn|�
tj	j�ttj	j�|	���||||���Wd�n1s~wYWd�dSWd�dS1s�wYdS)a~
    .. deprecated:: 0.17.0
       Use :py:func:`~salt.modules.file.replace` instead.

    Make a simple edit to a file (pure Python version)

    Equivalent to:

    .. code-block:: bash

        sed <backup> <options> "/<limit>/ s/<before>/<after>/<flags> <file>"

    path
        The full path to the file to be edited
    before
        A pattern to find in order to replace with ``after``
    after
        Text that will replace ``before``
    limit: ``''``
        An initial pattern to search for before searching for ``before``
    backup: ``.bak``
        The file will be backed up before edit with this file extension;
        **WARNING:** each time ``sed``/``comment``/``uncomment`` is called will
        overwrite this backup
    flags: ``gMS``
        Flags to modify the search. Valid values are:
          - ``g``: Replace all occurrences of the pattern, not just the first.
          - ``I``: Ignore case.
          - ``L``: Make ``\w``, ``\W``, ``\b``, ``\B``, ``\s`` and ``\S``
            dependent on the locale.
          - ``M``: Treat multiple lines as a single line.
          - ``S``: Make `.` match all characters, including newlines.
          - ``U``: Make ``\w``, ``\W``, ``\b``, ``\B``, ``\d``, ``\D``,
            ``\s`` and ``\S`` dependent on Unicode.
          - ``X``: Verbose (whitespace is ignored).
    multi: ``False``
        If True, treat the entire file as a single line

    Forward slashes and single quotes will be escaped automatically in the
    ``before`` and ``after`` patterns.

    CLI Example:

    .. code-block:: bash

        salt '*' file.sed /etc/httpd/httpd.conf 'LogLevel warn' 'LogLevel info'
    �w�rTN)rrrhr�rAr��shutil�copy2rrr"�fopen�readline�writerMrN�_psed�
to_unicode�read)rr�r�r�rr�r�Zmulti�ofileZifiler�rrr�psed�sN=

����
������"�r)�I�L�M�S�U�Xc
Cs�|}|rt�|�}|�|�}d�|dd��}d}d|vr%d}|�dd�}d}|D]}	|t|	O}q)tj||d�}tj||||d�}|S)zS
    Does the actual work for file.psed, so that single lines can be passed in
    r3r�Nr�r�r�)�count)rK�compiler�rr��
RE_FLAG_TABLE�sub)
rr�r�r�r�Zatext�compsrZaflags�flagrrrrHs

r�#cC�t|||d|d�S)ah
    .. deprecated:: 0.17.0
       Use :py:func:`~salt.modules.file.replace` instead.

    Uncomment specified commented lines in a file

    path
        The full path to the file to be edited
    regex
        A regular expression used to find the lines that are to be uncommented.
        This regex should not include the comment character. A leading ``^``
        character will be stripped for convenience (for easily switching
        between comment() and uncomment()).
    char: ``#``
        The character to remove in order to uncomment a line
    backup: ``.bak``
        The file will be backed up before edit with this file extension;
        **WARNING:** each time ``sed``/``comment``/``uncomment`` is called will
        overwrite this backup

    CLI Example:

    .. code-block:: bash

        salt '*' file.uncomment /etc/hosts.deny 'ALL: PARANOID'
    F�r�regexr��cmntr��comment_line�rr!r�rrrr�	uncommentasr&cCr)a�
    .. deprecated:: 0.17.0
       Use :py:func:`~salt.modules.file.replace` instead.

    Comment out specified lines in a file

    path
        The full path to the file to be edited
    regex
        A regular expression used to find the lines that are to be commented;
        this pattern will be wrapped in parenthesis and will move any
        preceding/trailing ``^`` or ``$`` characters outside the parenthesis
        (e.g., the pattern ``^foo$`` will be rewritten as ``^(foo)$``)
    char: ``#``
        The character to be inserted at the beginning of a line in order to
        comment it out
    backup: ``.bak``
        The file will be backed up before edit with this file extension

        .. warning::

            This backup will be overwritten each time ``sed`` / ``comment`` /
            ``uncomment`` is called. Meaning the backup will only be useful
            after the first invocation.

    CLI Example:

    .. code-block:: bash

        salt '*' file.comment /etc/modules pcspkr
    Tr r#r%rrrr.s r.c
Cs�|rd�|�d�rdnd|�d��d�|�d�rdnd�}nd�||�d��d�|�d�r/dnd�}tj�tj�|��}tj�	|�sIt
d|����td|�sVt
d|����d	}g}g}tj�|�}zIt
jjj|d
|d��5}	|	D]*}
t
jj�|
�}
t�||
�r�|�|
�|r�|�|�|
���n|�|
�|��d}qpWd
�n1s�wYWnty�}z
td|�d|����d
}~ww|s�d	St
jj��s�t|�}t|�}
t
jj�t|��}zt|d	d�}Wnty�}ztd|����d
}~wwz�d}t
jjj|||d���}zgt
jjj|d
|d��R}	|	D]G}
t
jj�|
�}
z(t�||
��r6|�r0|�|
��}n|
�|�}n|
}t
jj�|�}|� |�W�qt�y\}z	td�|||���d
}~wwWd
�n	1�shwYWnt�y�}ztd|����d
}~wwWd
�n	1�s�wYWnt�y�}ztd|����d
}~ww|�r�|�|��}zt!�"||�Wnt�y�}z	td�|||���d
}~wwt�#|�t
jj���s�t$|d
||
|�td||�S)a�
    Comment or Uncomment a line in a text file.

    :param path: string
        The full path to the text file.

    :param regex: string
        A regex expression that begins with ``^`` that will find the line you wish
        to comment. Can be as simple as ``^color =``

    :param char: string
        The character used to comment a line in the type of file you're referencing.
        Default is ``#``

    :param cmnt: boolean
        True to comment the line. False to uncomment the line. Default is True.

    :param backup: string
        The file extension to give the backup file. Default is ``.bak``
        Set to False/None to not keep a backup.

    :return: boolean
        Returns True if successful, False if not

    CLI Example:

    The following example will comment out the ``pcspkr`` line in the
    ``/etc/modules`` file using the default ``#`` character and create a backup
    file named ``modules.bak``

    .. code-block:: bash

        salt '*' file.comment_line '/etc/modules' '^pcspkr'

    CLI Example:

    The following example will uncomment the ``log_level`` setting in ``minion``
    config file if it is set to either ``warning``, ``info``, or ``debug`` using
    the ``#`` character and create a backup file named ``minion.bk``

    .. code-block:: bash

        salt '*' file.comment_line 'C:\salt\conf\minion' '^log_level: (warning|info|debug)' '#' False '.bk'
    z{}({}){}�^r3�$z^{}\s*({}){}�File not found: r2�5Cannot perform string replacements on a binary file: F�rb�ry�	bufferingTN�Unable to open file '�'. Exception: �r�preserve_inode�Exception: r�iUnable to write file '{}'. Contents may be truncated. Temporary file contains copy at '{}'. Exception: {}�HUnable to move the temp file '{}' to the backup file '{}'. Exception: {}�stringutils.get_diff)%r�rr~�rstripr?rr�realpathrhr�rr4�getsizerrr"r	rMr
rKrQr@r�rrrrtrm�normalize_moderz�
_mkstemp_copyrNrr�mover+�check_perms)rr!r�r"r�found�	orig_file�new_file�bufsize�r_filer��exc�pre_user�	pre_group�pre_mode�	temp_filery�w_fileZwline�backup_namerrrr$�s�.� ��
����
�����
�������������
���
r$cCs�t|tj�r|St|t�rt�|�St|t�r|g}t|t�rHt|t�sHt�d�}|D]}ttjt|���d�}|sAt	d|����||O}q+|St	d|�d���)a^
    Return the names of the Regex flags that correspond to flags

    .. code-block:: python

        >>> _get_flags(['IGNORECASE', 'MULTILINE'])
        re.IGNORECASE|re.MULTILINE
        >>> _get_flags('MULTILINE')
        re.MULTILINE
        >>> _get_flags(8)
        re.MULTILINE
        >>> _get_flags(re.IGNORECASE)
        re.IGNORECASE
    rNzInvalid re flag given: zInvalid re flags: "zc", must be given either as a single flag string, a list of strings, as an integer, or as an re flag)
r_rK�	RegexFlagrUrArr�getattr�upperr)r�Z_flagsr�_flagrrr�
_get_flagsKs"





�rMcCst|�}t|�}||BS)z-
    Combine ``flags`` and ``new_flags``
    )rM)r�Z	new_flagsrrr�
_add_flagspsrNc
Cs�d}z
tjjjtjjjd�}Wnty"}ztd|����d}~ww|rDz	t�||�W|StyC}z	td�	|||���d}~wwz	t�
||�W|Styb}z	td�	|||���d}~ww)aZ
    Create a temp file and move/copy the contents of ``path`` to the temp file.
    Return the path to the temp file.

    path
        The full path to the file whose contents will be moved/copied to a temp file.
        Whether it's moved or copied depends on the value of ``preserve_inode``.
    preserve_inode
        Preserve the inode of the file, so that any hard links continue to share the
        inode with the original filename. This works by *copying* the file, reading
        from the copy, and writing to the file at the original inode. If ``False``, the
        file will be *moved* rather than copied, and a new file will be written to a
        new inode, but using the original filename. Hard links will then share an inode
        with the backup, instead (if using ``backup`` to create a backup copy).
        Default is ``True``.
    N)�prefixz'Unable to create temp file. Exception: z=Unable to copy file '{}' to the temp file '{}'. Exception: {}z=Unable to move file '{}' to the temp file '{}'. Exception: {})rrr"�mkstempr#r�rrrr�r;)rr1rFrBrrrr:ys<������������r:c
sf|r�sdSzt��tj����fdd�|D�}W|Sty2}ztt|��d��d���d}~ww)z4
    Expand regular expression to static match.
    Ncs$g|]}��|�s|���r|�qSr)rLr�rr��Zcompiledr!rrr��s$z$_regex_to_static.<locals>.<listcomp>z: 'r�)rKr�DOTALLr�r�_get_error_message)�srcr!r�rrRr�_regex_to_static�s���rVr�cCsPt|�}||krd}n||krd}n|sd}nd}|r&td|�d|�d���|S)z\
    Raise an exception, if there are different amount of specified occurrences in src.
    z	more thanz	less than�noNzFound z expected occurrences in "z" expression)r�r)Zprobe�target�amountZocc�msgrrr�_assert_occurrence�s�r[cCs>|s|Sg}|D]
}|dvrn|�|�qd�|�|��S)z/
    Indent the line with the source line.
    )�	� r3)r@rr~)rUr��indentZidt�crrr�_set_line_indent�sr`cCst�d|�}|r|��p
dS)Nz((?<!
)
|
(?!
)|
)$r3)rKrLrO)r�rQrrr�_get_eol�sracCst|�ptj}|��|S)z
    Add line ending
    )rar�linesepr6)rUr�Zline_endingrrr�
_set_line_eol�srccsl|dvr|durtd��td|����|dkr�durtd���s+|dur+|dur+��t||�}t||�}t|���|sJ|dvrJt�d|�g}|S|dkr[�r[�fd	d
�|D�}|S|dkry�ry|��d�}|�|�}	|�|t|	�|��|S|d
k�ra|dur�|dur�|dur�td��|r�|dkr�|r�|�t|d�|��|S|���|S|dkr�|r�|�dt	|d���|S�t
jg}|S|r�|r�t|d�t|d�|�|d�}
|�|d�}|�|t||�|��|S|�r/t|d�|�|d�}|dt
|�k�r	dn||d}|du�s|�d���d�k�r-|�|dt||�|��|S|�r]t|d�|�|d�}||d}
|
�d���d�k�r[|�|t||�|��|Std��|dk�r4|�r�|�r�t|d�t|d�|�|d�}|�|d�}t�fdd�|D��}|�s�|d|k�r�|�|dt||�|��|S|d|k�r�t||�|�||d<|Std��|S|�r�t|d�|�|d�}|dk�s�||d�d���d�k�r�|�|t||d�|��|S|�r0t|d�|�|d�}|dt
|�k}|�s ||d�d���d�k�r.|�|dt||�|��|Std��|S)a
    Take ``lines`` and insert ``content`` and the correct place. If
    ``mode`` is ``'delete'`` then delete the ``content`` line instead.
    Returns a list of modified lines.

    lines
        The original file lines to modify.

    content
        Content of the line. Allowed to be empty if ``mode='delete'``.

    match
        The regex or contents to seek for on the line.

    mode
        What to do with the matching line. One of the following options
        is required:

        - ensure
            If ``content`` does not exist, it will be added.
        - replace
            If the line already exists, it will be replaced(???? TODO WHAT DOES THIS MEAN?)
        - delete
            Delete the line, if found.
        - insert
            Insert a line if it does not already exist.

        .. note::

            If ``mode=insert`` is used, at least one of the following
            options must also be defined: ``location``, ``before``, or
            ``after``. If ``location`` is used, it takes precedence
            over the other two options

    location
        ``start`` or ``end``. Defines where to place the content in the
        lines. **Note** this option is only used when ``mode='insert`` is
        specified. If a location is passed in, it takes precedence over
        both the ``before`` and ``after`` kwargs.

        - start
            Place the ``content`` at the beginning of the lines.
        - end
            Place the ``content`` at the end of the lines.

    before
        Regular expression or an exact, case-sensitive fragment of the
        line to place the ``content`` before. This option is only used
        when either ``ensure`` or ``insert`` mode is specified.

    after
        Regular expression or an exact, case-sensitive fragment of the
        line to plaece the ``content`` after. This option is only used
        when either ``ensure`` or ``insert`` mode is specified.

    indent
        Keep indentation to match the previous line. Ignored when
        ``mode='delete'`` is specified.
    ��insert�ensurer�r�N�.Mode was not defined. How to process the file?zUnknown mode: r�z+Content can only be empty if mode is delete�r�r�z&Cannot find text to %s. File is empty.csg|]
}|�dkr|�qS)rrrQ)rQrrr�Jsz_set_line.<locals>.<listcomp>r�rrezFOn insert either "location" or "before/after" conditions are required.�endre�startr�r�r��
z)Neither before or after was found in filerfc3s�|]	}|���kVqdSr)r~rQ)�contentrrr�s�z_set_line.<locals>.<genexpr>�zAFound more than one line between boundaries "before" and "after".z\Wrong conditions? Unable to ensure line without knowing where to put it before and/or after.)rrV�log�warning�indexr�rer`r@rcrrbr[r�r6r))rBrlrQry�locationr�r�r^�idxZ
original_line�first�lastZ	next_line�	prev_lineZafter_indexZbefore_indexZ
already_thereZis_last_liner)rlrQr�	_set_line�s�F�


e�c�
_
��T
�R�O�M�

F�
"�>�
8�


�*�
�#���
����
��
��rvcCsNtj�tj�|��}tj�|�s|	std|�d���dS|r"|��p#|}|dvr8|dur0td��td|�d���d	g}||vrM|durMtd
�d�|����~|durZ|durZ|sZ|}t	j
jj|dd
��}t	j
j
�|���}
Wd�n1swwYt�t	j
j�d�|
�����}|
r�t|
d�r�|
�d�t�|�jdkr�|dvr�t�d||�g}
t|
|||||||
d�}
|
r�t|
�D]!\}}t|�s�|dt|
�kr�|r�|dp�d}t|
||�|
|<q�d|
dkr�|
��|t�t	j
j�d�|
�����k}|�r7|�r7t ddu�r7zt!|dd�}t"�#|d�|t$�%dt$�&����Wnt'�y6}ztd�||���d}~wwd}|�r�|�rkt	j
j�|d��}t	j
j
�|�(��)d��}Wd�n	1�s_wYt*d||
�}t ddu�r�d}z!d}t	j
j
j|
dd�}
t	j
j+�,||�}|�-|
�W|�r�|�.�n	|�r�|�.�ww|�r�|�p�|S)a�
    .. versionadded:: 2015.8.0

    Line-focused editing of a file.

    .. note::

        ``file.line`` exists for historic reasons, and is not
        generally recommended. It has a lot of quirks.  You may find
        ``file.replace`` to be more suitable.

    ``file.line`` is most useful if you have single lines in a file
    (potentially a config file) that you would like to manage. It can
    remove, add, and replace a single line at a time.

    path
        Filesystem path to the file to be edited.

    content
        Content of the line. Allowed to be empty if ``mode='delete'``.

    match
        Match the target line for an action by
        a fragment of a string or regular expression.

        If neither ``before`` nor ``after`` are provided, and ``match``
        is also ``None``, match falls back to the ``content`` value.

    mode
        Defines how to edit a line. One of the following options is
        required:

        - ensure
            If line does not exist, it will be added. If ``before``
            and ``after`` are specified either zero lines, or lines
            that contain the ``content`` line are allowed to be in between
            ``before`` and ``after``. If there are lines, and none of
            them match then it will produce an error.
        - replace
            If line already exists, the entire line will be replaced.
        - delete
            Delete the line, if found.
        - insert
            Nearly identical to ``ensure``. If a line does not exist,
            it will be added.

            The differences are that multiple (and non-matching) lines are
            alloweed between ``before`` and ``after``, if they are
            specified. The line will always be inserted right before
            ``before``. ``insert`` also allows the use of ``location`` to
            specify that the line should be added at the beginning or end of
            the file.

        .. note::

            If ``mode='insert'`` is used, at least one of ``location``,
            ``before``, or ``after`` is required.  If ``location`` is used,
            ``before`` and ``after`` are ignored.

    location
        In ``mode='insert'`` only, whether to place the ``content`` at the
        beginning or end of a the file. If ``location`` is provided,
        ``before`` and ``after`` are ignored. Valid locations:

        - start
            Place the content at the beginning of the file.
        - end
            Place the content at the end of the file.

    before
        Regular expression or an exact case-sensitive fragment of the string.
        Will be tried as **both** a regex **and** a part of the line.  Must
        match **exactly** one line in the file.  This value is only used in
        ``ensure`` and ``insert`` modes. The ``content`` will be inserted just
        before this line, with matching indentation unless ``indent=False``.

    after
        Regular expression or an exact case-sensitive fragment of the string.
        Will be tried as **both** a regex **and** a part of the line.  Must
        match **exactly** one line in the file.  This value is only used in
        ``ensure`` and ``insert`` modes. The ``content`` will be inserted
        directly after this line, unless ``before`` is also provided. If
        ``before`` is not provided, indentation will match this line, unless
        ``indent=False``.

    show_changes
        Output a unified diff of the old file and the new file.
        If ``False`` return a boolean if any changes were made.
        Default is ``True``

        .. note::
            Using this option will store two copies of the file in-memory
            (the original version and the edited version) in order to generate the diff.

    backup
        Create a backup of the original file with the extension:
        "Year-Month-Day-Hour-Minutes-Seconds".

    quiet
        Do not raise any exceptions. E.g. ignore the fact that the file that is
        tried to be edited does not exist and nothing really happened.

    indent
        Keep indentation with the previous line. This option is not considered when
        the ``delete`` mode is specified. Default is ``True``

    CLI Example:

    .. code-block:: bash

        salt '*' file.line /etc/nsswitch.conf "networks:	files dns" after="hosts:.*?" mode='ensure'

    .. note::

        If an equal sign (``=``) appears in an argument to a Salt command, it is
        interpreted as a keyword argument in the format of ``key=val``. That
        processing can be bypassed in order to pass an equal sign through to the
        remote shell command by manually specifying the kwarg:

        .. code-block:: bash

            salt '*' file.line /path/to/file content="CREATEMAIL_SPOOL=no" match="CREATE_MAIL_SPOOL=yes" mode="replace"

    **Examples:**

    Here's a simple config file.

    .. code-block:: ini

        [some_config]
        # Some config file
        # this line will go away

        here=False
        away=True
        goodybe=away

    .. code-block:: bash

        salt \* file.line /some/file.conf mode=delete match=away

    This will produce:

    .. code-block:: ini

        [some_config]
        # Some config file

        here=False
        away=True
        goodbye=away

    If that command is executed 2 more times, this will be the result:

    .. code-block:: ini

        [some_config]
        # Some config file

        here=False

    If we reset the file to its original state and run

    .. code-block:: bash

        salt \* file.line /some/file.conf mode=replace match=away content=here

    Three passes will this state will result in this file:

    .. code-block:: ini

        [some_config]
        # Some config file
        here

        here=False
        here
        here

    Each pass replacing the first line found.

    Given this file:

    .. code-block:: text

        insert after me
        something
        insert before me

    The following command

    .. code-block:: bash

        salt \* file.line /some/file.txt mode=insert after="insert after me" before="insert before me" content=thrice

    If that command is executed 3 times, the result will be:

    .. code-block:: text

        insert after me
        something
        thrice
        thrice
        thrice
        insert before me

    If the mode is ``ensure`` instead, it will fail each time. To succeed, we
    need to remove the incorrect line between before and after:

    .. code-block:: text

        insert after me
        insert before me

    With an ensure mode, this will insert ``thrice`` the first time and
    make no changes for subsequent calls. For something simple this is
    fine, but if you have instead blocks like this:

    .. code-block:: text

        Begin SomeBlock
            foo = bar
        End

        Begin AnotherBlock
            another = value
        End

    And you try to use ensure this way:

    .. code-block:: bash

        salt \* file.line  /tmp/fun.txt mode="ensure" content="this = should be my content" after="Begin SomeBlock" before="End"

    This will fail because there are multiple ``End`` lines. Without that
    problem, it still would fail because there is a non-matching line,
    ``foo = bar``. Ensure **only** allows either zero, or the matching
    line present to be present in between ``before`` and ``after``.
    zFile "z#" does not exists or is not a file.FrdNrgzUnknown mode: "�"r�z)Content can only be empty if mode is "{}"r�r)ryr3rerrhz+Cannot find text to %s. File '%s' is empty.)rBrlrQryrqr�r�r^r��testTr0z{}.{}z%Y-%m-%d-%H-%M-%Sz5Unable to create the backup file of {}. Exception: {}r5r)rN)/rrr7rhr�rr�r�rrrr"r	�dataZdecode_list�	readlines�hashlibr�rM�to_bytes�	hexdigestrar@�stat�st_sizernrorv�	enumerater�rcr�r'r:rr;�time�strftime�	localtimer�rr>r4�
atomicfile�atomic_open�
writelines�close)rrlrQryrqr�r��show_changesr�quietr^Zempty_content_modes�fp_�bodyZbody_beforerrr��prev�changedrFrBZchanges_diffZpath_content�fh_rrrr��s�
�������
�������������
�r�r}c+Csd}t|�rd}tjj�|�}tj�|�}tj�tj�|��}tj�|�s0|
r)dSt	d|����t
d|�s=t	d|����|rG|sC|rGt	d��|rO|rOt	d��t|�}t�
tjj�|�|�}tj�|�}|dkrj|}d}g}g}tjj��s�t|�}t|�}tjj�t|��}tjj�t|��}|r�tjj�|�}d}d	}|r�|s�|r�tjj�|�ntjj�|�}�z	z�d	}tjjj|d
|d���} z
tj| ��dtjd
�}Wnttfy�d� | �}Ynw|�r#t�!||��r	Wd	�WW|�rt"|tj��r|�#�dSdSdS	Wd	�WW|�rt"|tj��r!|�#�dSdSdSt�$||�r/|�%dd�n|||�\}!}"|"dk�rFd}||k�rDdn|}|�sL|�rctj!tjj�dt�&|��d��||d��rcd}t"|tj��rr|�'|��(d�n|�(d�}|!�(d�}||k�r�d}Wd	�n	1�s�wYWnt�y�}#z
t)d|�d|#����d	}#~#wwW|�r�t"|tj��r�|�#�n|�r�t"|tj��r�|�#�www|�r�|
�s�zt*||d�}Wnt�y�}#zt)d|#����d	}#~#wwd	}z�tjjj|d|d���}$z�z^tjjj|d|d��I} tj| ��dtjd
�}t�$||�r"|�%dd�n|||�\}!}"z|$�+tjj�,|!��Wnt�yK}#z	t)d�-|||#���d	}#~#wwWd	�n	1�sWwYWnt�yq}#zt)d|#����d	}#~#wwW|�r�t"|tj��r�|�#�n|�r�t"|tj��r�|�#�wwwWd	�n	1�s�wYWnt�y�}#zt)d|#����d	}#~#ww|�sQ|�s�|�rQ|d	u�r�|}|�r�|�.d|tjj�tj/��n0dt0|�k�r�|d�1tjj�tj/���s�|dtjj�tj/�7<|�2|tjj�tj/��d}|
�sQzt*||d�}Wnt�y,}#zt)d|#����d	}#~#wwztjj3�4|d�}%|D]
}&|%�+tjj�|&���q8W|%�#�n|%�#�w|	�r�|�r�|
�s�|�|	��}'zt5�6||'�Wnt�y~}#z	t)d�-|||#���d	}#~#ww|�r�|�|	��}(|�|	��})zt�7|)|(�WnHt�y�t�8|(�t�7|)|(�Yn4t9�y�t)d�-|(|)|#���wn"|�r�zt�8|�Wnt�y�}#z
t)d|�d|#����d	}#~#ww|
�s�tjj���s�t:|d	|||�t
d ||�}*|�r�|*S|*�sd}|S)!a~
    .. versionadded:: 0.17.0

    Replace occurrences of a pattern in a file. If ``show_changes`` is
    ``True``, then a diff of what changed will be returned, otherwise a
    ``True`` will be returned when changes are made, and ``False`` when
    no changes are made.

    This is a pure Python implementation that wraps Python's :py:func:`~re.sub`.

    path
        Filesystem path to the file to be edited. If a symlink is specified, it
        will be resolved to its target.

    pattern
        A regular expression, to be matched using Python's
        :py:func:`~re.search`.

    repl
        The replacement text

    count: 0
        Maximum number of pattern occurrences to be replaced. If count is a
        positive integer ``n``, only ``n`` occurrences will be replaced,
        otherwise all occurrences will be replaced.

    flags (list or int)
        A list of flags defined in the ``re`` module documentation from the
        Python standard library. Each list item should be a string that will
        correlate to the human-friendly flag name. E.g., ``['IGNORECASE',
        'MULTILINE']``. Optionally, ``flags`` may be an int, with a value
        corresponding to the XOR (``|``) of all the desired flags. Defaults to
        8 (which supports 'MULTILINE').

    bufsize (int or str)
        How much of the file to buffer into memory at once. The
        default value ``1`` processes one line at a time. The special value
        ``file`` may be specified which will read the entire file into memory
        before processing.

    append_if_not_found: False
        .. versionadded:: 2014.7.0

        If set to ``True``, and pattern is not found, then the content will be
        appended to the file.

    prepend_if_not_found: False
        .. versionadded:: 2014.7.0

        If set to ``True`` and pattern is not found, then the content will be
        prepended to the file.

    not_found_content
        .. versionadded:: 2014.7.0

        Content to use for append/prepend if not found. If None (default), uses
        ``repl``. Useful when ``repl`` uses references to group in pattern.

    backup: .bak
        The file extension to use for a backup of the file before editing. Set
        to ``False`` to skip making a backup.

    dry_run: False
        If set to ``True``, no changes will be made to the file, the function
        will just return the changes that would have been made (or a
        ``True``/``False`` value if ``show_changes`` is set to ``False``).

    search_only: False
        If set to true, this no changes will be performed on the file, and this
        function will simply return ``True`` if the pattern was matched, and
        ``False`` if not.

    show_changes: True
        If ``True``, return a diff of changes made. Otherwise, return ``True``
        if changes were made, and ``False`` if not.

        .. note::
            Using this option will store two copies of the file in memory (the
            original version and the edited version) in order to generate the
            diff. This may not normally be a concern, but could impact
            performance if used with large files.

    ignore_if_missing: False
        .. versionadded:: 2015.8.0

        If set to ``True``, this function will simply return ``False``
        if the file doesn't exist. Otherwise, an error will be thrown.

    preserve_inode: True
        .. versionadded:: 2015.8.0

        Preserve the inode of the file, so that any hard links continue to
        share the inode with the original filename. This works by *copying* the
        file, reading from the copy, and writing to the file at the original
        inode. If ``False``, the file will be *moved* rather than copied, and a
        new file will be written to a new inode, but using the original
        filename. Hard links will then share an inode with the backup, instead
        (if using ``backup`` to create a backup copy).

    backslash_literal: False
        .. versionadded:: 2016.11.7

        Interpret backslashes as literal backslashes for the repl and not
        escape characters.  This will help when using append/prepend so that
        the backslashes are not interpreted for the repl on the second run of
        the state.

    If an equal sign (``=``) appears in an argument to a Salt command it is
    interpreted as a keyword argument in the format ``key=val``. That
    processing can be bypassed in order to pass an equal sign through to the
    remote shell command by manually specifying the kwarg:

    .. code-block:: bash

        salt '*' file.replace /path/to/file pattern='=' repl=':'
        salt '*' file.replace /path/to/file pattern="bind-address\s*=" repl='bind-address:'

    CLI Examples:

    .. code-block:: bash

        salt '*' file.replace /etc/httpd/httpd.conf pattern='LogLevel warn' repl='LogLevel info'
        salt '*' file.replace /some/file pattern='before' repl='after' flags='[MULTILINE, IGNORECASE]'
    FTr)r2r*z;search_only cannot be used with append/prepend_if_not_foundz8Only one of append and prepend_if_not_found is permittedr�Nr+r,r)�access��\s\\r'z
($|(?=
))rr.r/r0r2rrr3re�wbr4zAUnable create backup symlink '{}'. Target was '{}'. Exception: {}zUnable to delete temp file 'r5);�is_linkrrr�readlinkrrhr7r*rr4rMrKrrMr|r8rrrtrmr"r9rzrAr
r	�mmap�filenoZACCESS_READrVr�rrLr_r��subnr��escaperr>rr:rrNr�rerbr�r?r@r�r�rr;�symlinkr+r�r<)+rr��replrr�r@�append_if_not_found�prepend_if_not_foundZnot_found_contentr�dry_run�search_onlyr��ignore_if_missingr1Zbackslash_literalr��target_pathZ
given_path�re_flagsZcpatternZfilesize�has_changesr>r?rCrDrEr=rFrlZr_datarAr-ZnreplrBrGr�r�rHZsymlink_backupZ
target_backup�differencesrrrr�	s����������4���4���
��
��

���1�����
�����
�����������
������
������
���

������r��#-- start managed zone --�#-- end managed zone --c"s�||t|
�t|�g}t|�dkrtd��tj�|�}tj�|�s'td|����ztd|�}
Wnty:d}
Ynwtd|�rJ|
sJtd|����|
sN|re|
rZt	|
t
�sYtd��n|ret	|t
�setd	���durs|�tjd
f�ssd�g�|�
d�D]}|�
d
�D]}��|�q�qzt���d
}g}g}d
}d
}d}d%�����fdd�	}z�zmtjjj|d|
dd��W}|D]L}d}|dur�|�d�r�d}n|�d
�r�d
}ntj}�|vr�d}n|r�d
}|���}|dkr�d
}d}|||d
||d�d�|�|�|�r|�|�q�Wd�n	1�s
wYWnt�y*}z
td|�d|����d}~wwW|du�r4tj}z|��Wn#t�yDYnw|du�rMtj}z|��Wwt�y]Yww|�retd��|�s�|�ry||�}|�|�|}d}n_|�r�|�r�|d�|��s�|d|7<|||d�d}n@|
�s�|�r�|
�p�|��fdd�t|�D�}|�r�|d}||�D]}|�r�|d7}|�||�|
�r�|d7}�q�d}ntd��|�r6td||�}|dk}|�r6|�s6i}t|�|d<t|�|d<tjj�t|��|d <|d
u�r6|�|��} t� || �tjj!�"��r't#| d|dd!�nt#| d|d|d|d d"�|�s=td��td||�}|dk}|�r�|�s�i}t|�|d<t|�|d<tjj�t|��|d <|d
u�r�|�|��} t� || �tjj!�"��r�t#| d|dd!�nt#| d|d|d|d �z tjj$�%|d#�}!|D]}|!�&tjj'j(||
d$���q�W|!��n|!��wtjj!�"��r�t#|d|dd!�nt#|d|d|d|d �|�r�|S|S)&a�

    .. versionadded:: 2014.1.0

    Replace content of a text block in a file, delimited by line markers

    A block of content delimited by comments can help you manage several lines
    entries without worrying about old entries removal.

    .. note::

        This function will store two copies of the file in-memory (the original
        version and the edited version) in order to detect changes and only
        edit the targeted file if necessary.

    path
        Filesystem path to the file to be edited

    marker_start
        The line content identifying a line as the start of the content block.
        Note that the whole line containing this marker will be considered, so
        whitespace or extra content before or after the marker is included in
        final output

    marker_end
        The line content identifying the end of the content block. As of
        versions 2017.7.5 and 2018.3.1, everything up to the text matching the
        marker will be replaced, so it's important to ensure that your marker
        includes the beginning of the text you wish to replace.

    content
        The content to be used between the two lines identified by marker_start
        and marker_stop.

    append_if_not_found: False
        If markers are not found and set to ``True`` then, the markers and
        content will be appended to the file.

    prepend_if_not_found: False
        If markers are not found and set to ``True`` then, the markers and
        content will be prepended to the file.

    insert_before_match
        If markers are not found, this parameter can be set to a regex which will
        insert the block before the first found occurrence in the file.

        .. versionadded:: 3001

    insert_after_match
        If markers are not found, this parameter can be set to a regex which will
        insert the block after the first found occurrence in the file.

        .. versionadded:: 3001

    backup
        The file extension to use for a backup of the file if any edit is made.
        Set to ``False`` to skip making a backup.

    dry_run: False
        If ``True``, do not make any edits to the file and simply return the
        changes that *would* be made.

    show_changes: True
        Controls how changes are presented. If ``True``, this function will
        return a unified diff of the changes made. If False, then it will
        return a boolean (``True`` if any changes were made, otherwise
        ``False``).

    append_newline: False
        Controls whether or not a newline is appended to the content block. If
        the value of this argument is ``True`` then a newline will be added to
        the content block. If it is ``False``, then a newline will *not* be
        added to the content block. If it is ``None`` then a newline will only
        be added to the content block if it does not already end in a newline.

        .. versionadded:: 2016.3.4
        .. versionchanged:: 2017.7.5,2018.3.1
            New behavior added when value is ``None``.
        .. versionchanged:: 2019.2.0
            The default value of this argument will change to ``None`` to match
            the behavior of the :py:func:`file.blockreplace state
            <salt.states.file.blockreplace>`

    CLI Example:

    .. code-block:: bash

        salt '*' file.blockreplace /etc/hosts '#-- start managed zone foobar : DO NOT EDIT --' \
        '#-- end managed zone foobar --' $'10.0.1.1 foo.foobar\n10.0.1.2 bar.foobar' True

    r�zoOnly one of append_if_not_found, prepend_if_not_found, insert_before_match, and insert_after_match is permittedr)zfiles.get_encodingNzfiles.is_binaryr*z0RegEx expected in insert_before_match parameter.z/RegEx expected in insert_after_match parameter.r<TrkFcs�|durg}d}|dur�}|�d�|}|r|��|��rNt�d�D]&\}}|�kr5|�||�q%�rD|�||�|�|�q%|�||�q%|S|�|�|S)NTrkr�)r6r@r�)rbrB�include_marker_start�end_linerp�content_line)�append_newline�
line_count�
marker_end�marker_start�
split_contentrr�_add_contentBs&
�z"blockreplace.<locals>._add_contentrr3)�encoding�newlinere)rBr�r�zFailed to read from �: zAUnterminated marked block. End of file reached before marker_end.)rBcs g|]\}}t��|�r|�qSr)rKrLr�)�match_regexrrr��s
��z blockreplace.<locals>.<listcomp>rz9Cannot edit marked block. Markers were not found in file.r5rsrOry)rr/�owner)�namer/rsrOryr�)r�)NTN))r��sumrrrrhr*r4rr_rAr?rbr�r@r�rrr"r	r�r�r�r�r�r�rertrmr9rzrrrrr<r�r�rrMr|)"rr�r�rlr�r�rr�r�r�Zinsert_before_matchZinsert_after_matchZexclusive_params�
file_encodingZwin_liner�r�r>r?Zin_blockZblock_foundrbr�Zfi_filer�Zwrite_line_to_new_fileZmarker_end_posrBZprepended_contentZ	match_idx�diff�permsZbackup_pathr�r)r�r�r�r�r�r�r�blockreplace�
sxi����
��
���



�

����,���
�
���


����
��
��r�cCsB|rt|d�}nt|�}tjj|vrd}t||d||ddd|d�	S)a�
    .. versionadded:: 0.17.0

    Search for occurrences of a pattern in a file

    Except for multiline, params are identical to
    :py:func:`~salt.modules.file.replace`.

    multiline
        If true, inserts 'MULTILINE' into ``flags`` and sets ``bufsize`` to
        'file'.

        .. versionadded:: 2015.8.0

    CLI Example:

    .. code-block:: bash

        salt '*' file.search /etc/crontab 'mymaintenance.sh'
    �	MULTILINEr�r3TF)r�r@r�r�r�r�)rNrMrKrIr�r�)rr�r�r@r�Z	multiliner�rrrrLs �rLc	Cs0tjj�d�}|s
td��|g}|�tjj�|��|r-tddvr(|�	d�n|�	d�d|vr:d|vr:|�	d�d	}|D]}|d
ksN|�
d�sN|�
d�rRd
}nq>|sZ|�	d�|�d|g�tj�|�r�|�d|g�d	}|D]}|�
d�s~|�
d�r�d
}nqr|s�|�	d�n|�	|�t
d|d	d�S)a!
    .. versionadded:: 0.10.4

    Apply a patch to a file or directory.

    Equivalent to:

    .. code-block:: bash

        patch <options> -i <patchfile> <originalfile>

    Or, when a directory is patched:

    .. code-block:: bash

        patch <options> -i <patchfile> -d <originalfile> -p0

    originalfile
        The full path to the file or directory to be patched
    patchfile
        A patch file to apply to ``originalfile``
    options
        Options to pass to patch.

    .. note::
        Windows now supports using patch as of 3004.

        In order to use this function in Windows, please install the
        patch binary through your own means and ensure it's found
        in the system Path. If installing through git-for-windows,
        please select the optional "Use Git and optional Unix tools
        from the Command Prompt" option when installing Git.

    CLI Example:

    .. code-block:: bash

        salt '*' file.patch /opt/file.txt /tmp/file.txt.patch

        salt '*' file.patch C:\file1.txt C:\file3.patch
    �patchzJpatch executable not found. Is the distribution's patch package installed?Zkernel)ZFreeBSDZOpenBSDz-Cz	--dry-runz-Nz	--forwardFr�z-r z
--reject-fileTz--reject-file=-r�z-dz-pz--strip=z	--strip=0r�r�)rrrrIrr�r�r�Z
__grains__r@rr�isdirr:)	ZoriginalfileZ	patchfilerr�Z	patchpathrPZhas_rejectfile_option�optionZhas_strip_optionrrrr�FsN*�

���	
�
�
r�cCs�tj�|�}tj�|�sdSt|���}z/tjj�	|��}|D]}||vr/Wd�WdSqWd�WdS1s<wYWdSt
yMYdSw)z�
    .. deprecated:: 0.17.0
       Use :func:`search` instead.

    Return ``True`` if the file at ``path`` contains ``text``

    CLI Example:

    .. code-block:: bash

        salt '*' file.contains /etc/crontab 'mymaintenance.sh'
    FNT)rrrhr*rAr�rr�
filebuffer�BufferedReaderr�)rrZ
stripped_text�breader�chunkrrr�contains�s&
��
���r�cCs�tj�|�}tj�|�sdSzAtjj�|d��.}|D] }tjj�	|�}|r*|�
|�}t�||�r:Wd�WdSq	Wd�WdS1sHwYWdSt
yYYdSw)a�
    .. deprecated:: 0.17.0
       Use :func:`search` instead.

    Return True if the given regular expression matches on any line in the text
    of a given file.

    If the lchar argument (leading char) is specified, it
    will strip `lchar` from the left side of each line before trying to match

    CLI Example:

    .. code-block:: bash

        salt '*' file.contains_regex /etc/crontab
    FrNT)rrrhr*rrr"r	rMr
r~rKrLr�)rr!ZlcharrXr�rrr�contains_regex�s$
�(��r�cCs�tj�|�}tj�|�sdSz2tjj�|�� }|D]}t�||�r+Wd�WdSq	Wd�WdS1s9wYWdSt	yJYdSw)z�
    .. deprecated:: 0.17.0
       Use :func:`search` instead.

    Return ``True`` if the given glob matches a string in the named file

    CLI Example:

    .. code-block:: bash

        salt '*' file.contains_glob /etc/foobar '*cheese*'
    FNT)
rrrhr*rrr�r��fnmatchr�)rZ	glob_exprr�r�rrr�
contains_glob�s
�(��r�cOsbtj�|�}d|vrt|dt�r|d}n|dg}tjj�|d��O}tjj	�
tj�}z|�t
|�tj�WntyU}z|jtjtjfvrJn�WYd}~nd}~ww|�t
|��|krk|�dtj�|�|�Wd�n1suwYtjj�|d��}|D]}|�tjj	�|�tj����q�Wd�n1s�wYdt
|��d|�d�S)	a�
    .. versionadded:: 0.9.5

    Append text to the end of a file

    path
        path to file

    `*args`
        strings to append to file

    CLI Example:

    .. code-block:: bash

        salt '*' file.append /etc/motd \
                "With all thine offerings thou shalt offer salt." \
                "Salt is what makes things taste bad when it isn't in them."

    .. admonition:: Attention

        If you need to pass a string to append and that string contains
        an equal sign, you **must** include the argument name, args.
        For example:

        .. code-block:: bash

            salt '*' file.append /etc/motd args='cheese=spam'

            salt '*' file.append /etc/motd args="['cheese=spam','spam=cheese']"

    r��rb+Nr�a�Wrote � lines to "rw)rrrhr_�listrrr"r	rMr|rb�seekr��SEEK_ENDr��errno�EINVALZESPIPErrrN)rr�r�rrbrBZnew_linerrrr@
s6!

���
�� ��r@cOstj�|�}d|vrt|dt�r|d}n|dg}z"tjj�|��}dd�|�	�D�}Wd�n1s7wYWnt
yHg}Ynwg}|D]
}|�|�d��qMtjj�|d��}||}|�tjj
�d�|���Wd�n1s|wYdt|��d	|�d
�S)a�
    .. versionadded:: 2014.7.0

    Prepend text to the beginning of a file

    path
        path to file

    `*args`
        strings to prepend to the file

    CLI Example:

    .. code-block:: bash

        salt '*' file.prepend /etc/motd \
                "With all thine offerings thou shalt offer salt." \
                "Salt is what makes things taste bad when it isn't in them."

    .. admonition:: Attention

        If you need to pass a string to append and that string contains
        an equal sign, you **must** include the argument name, args.
        For example:

        .. code-block:: bash

            salt '*' file.prepend /etc/motd args='cheese=spam'

            salt '*' file.prepend /etc/motd args="['cheese=spam','spam=cheese']"

    r�cSsg|]	}tjj�|��qSr)rrrMr
rQrrrr�p
s�zprepend.<locals>.<listcomp>Nr<rr3z
Prepended r�rw)rrrhr_r�rrr"r	rzr�r@rrMrNrr�)rr�r�Zfhr�contentsZprefacer�rrrr�prependE
s.!

�����r�cOs�tj�|�}d|vrt|dt�r|d}n|dg}g}|D]
}|�|�d��qtjj�	|d��}|�
tjj�d�
|���Wd�n1sJwYdt|��d|�d�S)	a�
    .. versionadded:: 2014.7.0

    Write text to a file, overwriting any existing contents.

    path
        path to file

    `*args`
        strings to write to the file

    CLI Example:

    .. code-block:: bash

        salt '*' file.write /etc/motd \
                "With all thine offerings thou shalt offer salt."

    .. admonition:: Attention

        If you need to pass a string to append and that string contains
        an equal sign, you **must** include the argument name, args.
        For example:

        .. code-block:: bash

            salt '*' file.write /etc/motd args='cheese=spam'

            salt '*' file.write /etc/motd args="['cheese=spam','spam=cheese']"

    r�r<rr3Nr�r�rw)rrrhr_r�r@rrr"r	rrMrNrr�)rr�r�r�r�rrrrr�
s 

�rc
Cs&tj�|�}|rt|���rt|�}|rt|���rt|�}zStj�|�s=tjj	�
|d��Wd�n1s8wY|durH|durHd}n"|durW|durW|t��f}n|durf|durft��|f}n||f}t�||�Wnt
y|td��ty�}zt|j��d}~wwtj�|�S)a�
    .. versionadded:: 0.9.5

    Just like the ``touch`` command, create a file if it doesn't exist or
    simply update the atime and mtime if it already does.

    atime:
        Access time in Unix epoch time. Set it to 0 to set atime of the
        file with Unix date of birth. If this parameter isn't set, atime
        will be set with current time.
    mtime:
        Last modification in Unix epoch time. Set it to 0 to set mtime of
        the file with Unix date of birth. If this parameter isn't set,
        mtime will be set with current time.

    CLI Example:

    .. code-block:: bash

        salt '*' file.touch /var/log/emptyfile
    r�Nz atime and mtime must be integers)rrrhrA�isdigitrUr*rrr"r	r��utimer�rr�r�strerror)r��atime�mtime�timesrBrrr�touch�
s2�
��r�c	CsZtj�|�}t�|tj�}zt�|t|�d�t�|t|��}Wt�|�|St�|�w)a.
    .. versionadded:: 2014.1.0

    Seek to a position on a file and read it

    path
        path to file

    seek
        amount to read at once

    offset
        offset to start into the file

    CLI Example:

    .. code-block:: bash

        salt '*' file.seek_read /path/to/file 4096 0
    r)	rrrh�open�O_RDONLY�lseekrUrr�)r�size�offset�seek_fhryrrr�	seek_read�
s
�r�c	Cs`tj�|�}t�|tj�}zt�|t|�d�t�||�}t�|�Wt�	|�|St�	|�w)a@
    .. versionadded:: 2014.1.0

    Seek to a position on a file and write to it

    path
        path to file

    data
        data to write to file

    offset
        position in file to start writing

    CLI Example:

    .. code-block:: bash

        salt '*' file.seek_write /path/to/file 'some data' 4096
    r)
rrrhr��O_WRONLYr�rUr�fsyncr�)rryr�r�r/rrr�
seek_writes
�r�cCsPtj�|�}tjj�|d��}|�t|��Wd�dS1s!wYdS)a
    .. versionadded:: 2014.1.0

    Seek to a position on a file and delete everything after that point

    path
        path to file

    length
        offset into file to truncate

    CLI Example:

    .. code-block:: bash

        salt '*' file.truncate /path/to/file 512
    r�N)	rrrhrrr"r	�truncaterU)r�lengthr�rrrr�"s"�r�c
Cs`tj�|�}tj�|�std��z	t�||�WdSty/}z
td|�d|����d}~ww)z�
    .. versionadded:: 2014.1.0

    Create a hard link to a file

    CLI Example:

    .. code-block:: bash

        salt '*' file.link /path/to/file /path/to/link
    �File path must be absolute.T�Could not create '�': N)rrrhr�r�linkr�r)rUr�Errrr�9s��r�cCs ttj�|��}|o|ddkS)z�
    Check if the path is a hard link by verifying that the number of links
    is larger than 1

    CLI Example:

    .. code-block:: bash

       salt '*' file.is_hardlink /path/to/link
    �st_nlinkr�)�lstatrrrh)r�resrrr�is_hardlinkRsr�cC�tj�tj�|��S)z�
    Check if the path is a symbolic link

    CLI Example:

    .. code-block:: bash

       salt '*' file.is_link /path/to/link
    )rr�islinkrh�rrrrr�dsr�cCs�tj�|�}tj�|�std|����tj�|�rMztj�tjj�	|��tj�|�kr5t
�d||�WdSWn	ty?Ynw|sM|sMd|��}t
|��tj�|�r`|s`|s`d|��}t
|��tj�|�sltj�|�rv|rv|svt�|�nL|r�tj�|�}d}|dkr�tj|d�}zt�||�Wnty�|d	7}Ynw|dks�z	t�||�WdSty�t�|�t
d
|�d���wz	t�||�WdSty�t
d
|�d���w)ay
    Create a symbolic link (symlink, soft link) to a file

    Args:

        src (str): The path to a file or directory

        path (str): The path to the link. Must be an absolute path

        force (bool):
            Overwrite an existing symlink with the same name
            .. versionadded:: 3005

        atomic (bool):
            Use atomic file operations to create the symlink
            .. versionadded:: 3006.0

    Returns:
        bool: ``True`` if successful, otherwise raises ``CommandExecutionError``

    CLI Example:

    .. code-block:: bash

        salt '*' file.symlink /path/to/file /path/to/link
    zLink path must be absolute: z'link already in correct state: %s -> %sTzFound existing symlink: z Existing path is not a symlink: r�)�dirr�r�r�)rrrhr�rr��normpathrrr�rn�debugr�rr*�unlink�dirnamer Zmktempr��FileExistsErrorr�r+)rUr�forceZatomicrZZlink_dirZretryZ	temp_linkrrrr�vs^���

 ��
��r�c	Csdtj�|�}tj�|�}tj�|�std��z	t�||�WdSty1td|�d|�d���w)z�
    Rename a file or directory

    CLI Example:

    .. code-block:: bash

        salt '*' file.rename /path/to/src /path/to/dst
    r�TzCould not rename '�' to 'r�)rrrhr�r�renamer�r)rU�dstrrrr��s
�r�c	Cs6tj�|�}tj�|�}tj�|�std��tj�|�s$td|�d���tjj	�
�s;t|�}t|�}tjj
�t|��}z=tj�|�rHtj�|�sNtj�|�rq|sTtd��|rhtj�|�rat�|�t�||�ntjj
�||�nt�||�Wnty�td|�d|�d���wtjj	�
�s�t|d|||�dS)	a�
    Copy a file or directory from source to dst

    In order to copy a directory, the recurse flag is required, and
    will by default overwrite files in the destination with the same path,
    and retain all other existing files. (similar to cp -r on unix)

    remove_existing will remove all files in the target directory,
    and then copy files from the source.

    .. note::
        The copy function accepts paths that are local to the Salt minion.
        This function does not support salt://, http://, or the other
        additional file paths that are supported by :mod:`states.file.managed
        <salt.states.file.managed>` and :mod:`states.file.recurse
        <salt.states.file.recurse>`.

    CLI Example:

    .. code-block:: bash

        salt '*' file.copy /path/to/src /path/to/dst
        salt '*' file.copy /path/to/src_dir /path/to/dst_dir recurse=True
        salt '*' file.copy /path/to/src_dir /path/to/dst_dir recurse=True remove_existing=True

    r�zNo such file or directory 'r�zECannot copy overwriting a directory without recurse flag set to true!zCould not copy 'r�NT)rrrhr�rr*rrrrrrtrmr"r9rzr�r�rmtree�copytreeZrecursive_copy�copyfiler�r<)rUr��recurseZremove_existingrCrDrErrr�copy�s:$�
��r�csVtj�|�}tj�|�std��zt�|���fdd�dD�WSty*iYSw)z�
    .. versionadded:: 2014.1.0

    Returns the lstat attributes for the given file or dir. Does not support
    symbolic links.

    CLI Example:

    .. code-block:: bash

        salt '*' file.lstat /path/to/file
    zPath to file must be absolute.c�i|]}|t�|��qSr�rJ�r�key��lstrr�
<dictcomp>.�
��zlstat.<locals>.<dictcomp>)�st_atime�st_ctime�st_gid�st_mode�st_mtimer�r�st_uid)rrrhr�rr�r�r�rrrr�s


�
�r�cCsntj�|�}tj�|�std��tjtjtjtjd�}||vr't�	|||�S||�
�vr3t�	||�Std��)a�
    .. versionadded:: 2014.1.0

    Test whether the Salt process has the specified access to the file. One of
    the following modes must be specified:

    .. code-block:: text

        f: Test the existence of the path
        r: Test the readability of the path
        w: Test the writability of the path
        x: Test whether the path can be executed

    CLI Example:

    .. code-block:: bash

        salt '*' file.access /path/to/file f
        salt '*' file.access /path/to/file x
    zPath to link must be absolute.)r�rrr�zInvalid mode specified.)rrrhr�r�F_OK�R_OK�W_OK�X_OKr�r()rry�modesrrrr�?sr�cCsxd}|dur
|d7}tjj�||�� }|dur"|��Wd�Stjj�|���Wd�S1s5wYdS)z�
    .. versionadded:: 2017.7.0

    Return the content of the file.

    :param bool binary:
        Whether to read and return binary data

    CLI Example:

    .. code-block:: bash

        salt '*' file.read /path/to/file
    rT�bN)rrr"r	rrMr
)r�binaryZaccess_modeZfile_objrrrrcs�$�rc
Cs�tj�|�}tj�|�}tj�|�std|����tj�|�s&td|����|r.tj�|�Sztj	j�
|�WStyU}z|jtj
krKtd|����tt|���d}~ww)ae
    .. versionadded:: 2014.1.0

    Return the path that a symlink points to

    Args:

        path (str):
            The path to the symlink

        canonicalize (bool):
            Get the canonical path eliminating any symbolic links encountered in
            the path

    Returns:

        str: The path that the symlink points to

    Raises:

        SaltInvocationError: path is not absolute

        SaltInvocationError: path is not a link

        CommandExecutionError: error reading the symbolic link

    CLI Example:

    .. code-block:: bash

        salt '*' file.readlink /path/to/link
    zPath to link must be absolute: z A valid link was not specified: zNot a symbolic link: N)rrrh�
expandvarsr�rr�r7rrr�r�r�r�rrA)rZcanonicalizerBrrrr�|s !��r�cCsPtj�|�}tj�|�std��tj�|�std��ddg}|�t�|��|S)z�
    .. versionadded:: 2014.1.0

    Return a list containing the contents of a directory

    CLI Example:

    .. code-block:: bash

        salt '*' file.readdir /path/to/dir/
    zDir path must be absolute.�$A valid directory was not specified.�.z..)rrrhr�rr�r��listdir)rZdirentsrrr�readdir�srcs^tj�|�}tj�|�std��zt�|���fdd�dD�WSty.td|�d���w)z�
    .. versionadded:: 2014.1.0

    Perform a statvfs call against the filesystem that the file resides on

    CLI Example:

    .. code-block:: bash

        salt '*' file.statvfs /path/to/file
    r�crrrr�Zstvrrr�rzstatvfs.<locals>.<dictcomp>)
�f_bavail�f_bfree�f_blocks�f_bsize�f_favail�f_ffree�f_files�f_flag�f_frsize�	f_namemaxzCould not statvfs 'r�)rrrhr�r�statvfsr�rr�rrrr%�s

��r%cCs�tj�|�}i}tj�|�s$zt�|�}Wnty#td|����w|r,t�|�}nt�|�}|j|d<|j	|d<|j
|d<t|j
�|d<t|j	�|d<|j
|d<|j|d<|j|d	<|j|d
<tjj�tt�|j���|d<|rzt||�|d<d
|d<t�|j�r�d|d<t�|j�r�d|d<t�|j�r�d|d<t�|j�r�d
|d<t�|j�r�d|d<t�|j�r�d|d<t�|j�r�d|d<tj� |�|d<|S)z�
    Return a dict containing the stats for a given file

    CLI Example:

    .. code-block:: bash

        salt '*' file.stats /etc/passwd
    zPath not found: �inoderqr]rOrsr�r��ctimer�ryr�r��typer�r��blockr��pipe�socketrX)!rrrhr*r�r�rr~�st_inor
r
r^rrrrr	rrrr"r9�oct�S_IMODErr��S_ISDIR�S_ISCHR�S_ISBLK�S_ISREG�S_ISLNK�S_ISFIFO�S_ISSOCKr7)rr�rdr/Zpstatrrrrg�sP
�







rgcCsd}g}g}tj�|�}tj�|�std��tj�|�s td��|rTt��}z|t|�d}t�	d||�Wnt
tfyS}zd}t�d|�WYd}~nd}~ww|r�tj
|dd	�D]R\}	}
}|
D]J}tj�|	|�}
|rwtj�|
�|ksy|s�zt�	d
|
�t�|
�|�|
�Wqdty�}z|�|
t|�g�t�d|
|�WYd}~qdd}~wwqdq]|}|r�tj�|�|ks�|s�zt�	d
|�t�|�|�|�|s�|s�dnd}Wn$ty�}zd}|�|t|�g�t�d||�WYd}~nd}~ww|�r|||d
�S|S)a�
    .. versionadded:: 2014.1.0
    .. versionchanged:: 3006.0
        Changed return value for failure to a boolean.

    Remove the specified directory. Fails if a directory is not empty.

    recurse
        When ``recurse`` is set to ``True``, all empty directories
        within the path are pruned.

        .. versionadded:: 3006.0

    verbose
        When ``verbose`` is set to ``True``, a dictionary is returned
        which contains more information about the removal process.

        .. versionadded:: 3006.0

    older_than
        When ``older_than`` is set to a number, it is used to determine the
        **number of days** which must have passed since the last modification
        timestamp before a directory will be allowed to be removed. Setting
        the value to 0 is equivalent to leaving it at the default of ``None``.

        .. versionadded:: 3006.0

    CLI Example:

    .. code-block:: bash

        salt '*' file.rmdir /tmp/foo/
    Fr�ri�Qz.Now (%s) looking for directories older than %srz6Unable to set 'older_than'. Defaulting to 0 days. (%s)N)�topdownz
Removing '%s'zCould not remove '%s': %sT)�deleted�errorsr-)rrrhr�rr�r�rUrnr�r�rV�error�walkr�getmtime�rmdirr@r�rA)rr��verboseZ
older_thanr/r7r8�nowrBr�dirs�_ZsubdirZsubdir_pathrrrr<.sl"����
����

��r<c
Ks�tj�|�}tj�|�std|����z+tj�|�s&tj�|�r.tj�|�s.t�|�WdStj�|�r<t	�
|�WdSWdStyT}z
td|�d|����d}~ww)aE
    Remove the named file. If a directory is supplied, it will be recursively
    deleted.

    CLI Example:

    .. code-block:: bash

        salt '*' file.remove /tmp/foo

    .. versionchanged:: 3000
        The method now works on all types of file system entries, not just
        files, directories and symlinks.
    zFile path must be absolute: TzCould not remove 'r�NF)
rrrhr�rr�r*r�r+rr�r�r)rr�rBrrrr+�s $

����r+cCr�)z�
    Tests to see if path is a valid directory.  Returns True/False.

    CLI Example:

    .. code-block:: bash

        salt '*' file.directory_exists /etc

    )rrr�rhr�rrr�directory_exists��rAcCr�)z�
    Tests to see if path is a valid file.  Returns True/False.

    CLI Example:

    .. code-block:: bash

        salt '*' file.file_exists /etc/passwd

    )rrr�rhr�rrr�file_exists�rBrCcCst�tj�|��rdSdS)aM
    Tests to see if path after expansion is a valid path (file or directory).
    Expansion allows usage of ? * and character ranges []. Tilde expansion
    is not supported. Returns True/False.

    .. versionadded:: 2014.7.0

    CLI Example:

    .. code-block:: bash

        salt '*' file.path_exists_glob /etc/pam*/pass*

    TF)r�rrrhr�rrr�path_exists_glob�srDcCs,|rdd|g}ndd|g}td|dd�S)z�
    Reset the SELinux context on a given path

    CLI Example:

    .. code-block:: bash

         salt '*' file.restorecon /home/user/.ssh/authorized_keys
    �
restoreconz-FRz-F�cmd.retcodeFr��r:)r�	recursiverPrrrrE�s

rEcCs>tdddd|gdd�}|ddkr|d	}|Sd
|��}|S)z�
    Get an SELinux context from a given path

    CLI Example:

    .. code-block:: bash

        salt '*' file.get_selinux_context /etc/hosts
    r�r~z-cz%CFr��retcoder�stdoutz0No selinux context information is available for rG)rZcmd_retr/rrr�get_selinux_context�s

�rKc	Cs�t||||f�s
dS|r%td||||d�}|�dd�dkr%td|����dg}|r1|�d	|g�|r:|�d
|g�|rC|�d|g�|rL|�d|g�|�|�td
|dd�}|r`t|�S|S)aS
    .. versionchanged:: 3001

        Added persist option

    Set a specific SELinux label on a given path

    CLI Example:

    .. code-block:: bash

        salt '*' file.set_selinux_context path <user> <role> <type> <range>
        salt '*' file.set_selinux_context /etc/yum.repos.d/epel.repo system_u object_r system_conf_t s0
    Fzselinux.fcontext_add_policy)Zsel_typeZsel_userZ	sel_levelrINrzProblem setting fcontext: Zchconz-ur�z-tz-lrFr�)r)r:rirr�r@rK)	rrs�roler(�range�persistZfcontext_resultrPr/rrr�set_selinux_context�s,�
rOcs�|�d|�d���}|tvrt|St|t��r�fdd�td��D�}�fdd�td��D�}|D]6}t|t�rAtt|��}tjj	�
|�\}��rj|�fdd�td��D�7}|�fdd�td��D�7}q4d	}|D�]f}t|t��r/t|�d
krqott|��}	||	r�||	n|}
tj
�
|	�}tjj��r�|j��tjvr�tj
�
d|	�}|j}|dkr�tjj	�
|	�\}��s���|�f|vs�|�f|vr�|	|
f}�nqo|�d
�s�|dkr�tjjj|	ddd�}
d|
vr�|	|
f}n�qo|dk�rtj�|j��stj�|j��stj�tj�|j|j���r|	|
f}n�|	�tj��r.tj�|	��r.|	|
f}n�qot|t��r�tjj	�
|�\}���sC��|�f|v�sQ|�f|v�rW||f}n�tj
�
|�}tjj���ru|j��tjv�rutj
�
d|�}|j}|dk�r�tj�|j��s�tj�|j��s�tj�tj�|j|j���r�||f}n6|�d
��s�|dk�r�tjjj|ddd�}
d|
v�r�||f}nqo|�tj��r�tj�|��r�||f}nqo|d	u�r�td��n||f}|t|<|S)z�
    Check the source list and return the source to use

    CLI Example:

    .. code-block:: bash

        salt '*' file.source_list salt://http/httpd.conf '{hash_type: 'md5', 'hsum': <md5sum>}' base
    z_|-c�g|]}|�f�qSrr�rr��r�rrr�;�zsource_list.<locals>.<listcomp>zcp.list_mastercrPrr�r�drRrrr�<rSzcp.list_master_dirscrPrrrQ��senvrrr�CrScrPrrrTrVrrr�DrSNr�zfile://r�http�ftp�HEADF)�methodZdecode_bodyr9r�z(none of the specified sources were found)�__context__r_r�r:�dict�next�iterrr�urlr�r�r�r�rrr�r�r��ascii_lowercaserrX�queryrrr*�netlocrr�rAr)r�r�r�Z
contextkeyZmfilesZmdirsZsinglerr/Z
single_srcZsingle_hashZurlparsed_single_srcr�Z	query_resZ
urlparsed_srcr)r�rWr�source_list+s�

�
����
�����	�
�����
��
�rdcCs�|tjjjvr6|r|ni}|r|�|�tjjj||dd||tdtttd�	d}t|t	�r4|�
d�}|Si}d|d<d�|�|d	<|S)
a(
    Return the contents after applying the templating engine

    contents
        template string

    template
        template format

    context
        Overrides default context variables passed to the template.

    defaults
        Default context passed to the template.

    CLI Example:

    .. code-block:: bash

        salt '*' file.apply_template_on_contents \
            contents='This is a {{ template }} string.' \
            template=jinja \
            "context={}" "defaults={'template': 'cool'}" \
            saltenv=base
    T�grains)Zfrom_strrN�contextr�re�pillarr�optsryzutf-8Fr-z-Specified template format {} is not supportedr.)rr�	templates�TEMPLATE_REGISTRY�updater'�
__pillar__r:r_�bytes�decoder�)r��templaterf�defaultsr��context_dictr/rrr�apply_template_on_contents�s4
�
�

��rrc!Ks�d}i}dd�}|r�tj�|�}|jtjjjvr|j}nd}tj	�
|j|j	��tj
�}|dv}|dkrI|}}tj	�|�sHd|�d�}di|fSn|dkr`|}tj	�|�s`d|�d�}di|fS|rr|��tjvrrd�
||g�}d}|d	kr�td
||	�}|s�did|�d|	�d
�fSnP|s�|r�||�}nG|s�|�tj
�r�||�}n:|s�|r�zt|||||	|
d�}Wn)ty�}zdi|jfWYd}~Sd}~ww|s�d�tjj�|��}di|fS|�r�|s�|tjjjv�r�d}td||	�}|�r&|s�|s�|�r&|�dd�}t||d�}|�r|}||d�}n|�s!||�dtd�k�r$d}n|}|�r,|�rbztd||	|�d�|
|d�}Wn%t�ya}ztjj�|�}did|�d|��fWYd}~Sd}~ww|�rltj	�|��s|tjj�|�}|id|�d�fS||k�r�td��|�r�|tjj j!v�r�|�r�|ni}|
�r�|�"|
�tjj j!||f|||||||	|tt#td td!�|��}n	|id"|�d#�fS|d$�r�|d%}t|dd�} d| d&�}nt$|�|i|d%fS||dfS)'a�
    Return the managed file data for file.managed

    name
        location where the file lives on the server

    template
        template format

    source
        managed source file

    source_hash
        hash of the source file

    source_hash_name
        When ``source_hash`` refers to a remote file, this specifies the
        filename to look for in that file.

        .. versionadded:: 2016.3.5

    user
        Owner of file

    group
        Group owner of file

    mode
        Permissions of file

    attrs
        Attributes of file

        .. versionadded:: 2018.3.0

    context
        Variables to add to the template context

    defaults
        Default values of for context_dict

    skip_verify
        If ``True``, hash verification of remote file sources (``http://``,
        ``https://``, ``ftp://``) will be skipped, and the ``source_hash``
        argument will be ignored.

        .. versionadded:: 2016.3.0

    verify_ssl
        If ``False``, remote https file sources (``https://``) and source_hash
        will not attempt to validate the servers certificate. Default is True.

        .. versionadded:: 3002

    use_etag
        If ``True``, remote http/https file sources will attempt to use the
        ETag header to determine if the remote file needs to be downloaded.
        This provides a lightweight mechanism for promptly refreshing files
        changed on a web server without requiring a full hash comparison via
        the ``source_hash`` parameter.

        .. versionadded:: 3005

    CLI Example:

    .. code-block:: bash

        salt '*' file.get_managed /etc/httpd/conf.d/httpd.conf jinja salt://http/httpd.conf '{hash_type: 'md5', 'hsum': <md5sum>}' None root root '755' base None None
    r3cSst|dd�dd�S)za
        DRY helper for getting the source_sum value from a locally cached
        path.
        r��r��r�r�)r�r�rrr�_get_local_file_source_sum7sz/get_managed.<locals>._get_local_file_source_sum)r�r3zLocal file source z does not existr�r�rzcp.hash_filezSource file z not found in saltenv 'r�r�NzcUnable to verify upstream hash of source file {}, please set source_hash or set skip_verify to TrueFzcp.is_cachedr�r�rsrtr�Tr�)r�r��use_etagzFailed to cache r��
Source file '�' not foundz-Source file cannot be the same as destinationre)r�r�rsrOryr�r�rfrrgrerhzSpecified template format z is not supportedr-ry�r�r�)%r�r�r�r�rrr"r�rrrrcr6r�r*r�r�rar:rr�rr�r�r`Zredact_http_basic_authZ
REMOTE_PROTOSrir�r'r�rrirjrkrlr,)!r�ror�r�r�rsrOryr�r�rfrp�skip_verifyr�rvr�r�
source_sumru�urlparsed_sourceZ
parsed_schemeZparsed_pathZunix_local_sourcerZrBZ
cache_refetchZcached_dest�htypeZ
cached_sumZ_sourcerqryr�rrr�get_managed�sX��
�
��


�����
�
�"��

���
�

r~cCs�t�|�}|dur|rt�d|�d}tt��dtt���}nt|�}tj	d}|rFt
|t�s3t|�}t|�dd}t�d|sBd	n||�|r_t
|t�sQt|�}t
j�|�}	t|	�dd}
|r�t
|t�sjt|�}tj�|�}t
j�|jpx|j�}t|�dd}
d
d�||fD�}|r�t�d|r�d
nd|s�d	n|t|�dkr�dndd�|��d}i}tjj�|d���*}|D�]}tjj�|���}d|d}t�||�}d}|r�|�d�}|dur�t�t|��}|dur�d}n||d�}|du�rt�d||s�dn|d�q�|du�r|}dd�}d}|�rO|�|��r9z||tj	v�r-|||d||�d}Wn t �y8Ynwt�!t�"|�d|��rO|||d||�d}|�r�|�|	��rvz||
|v�rj|||d||�d}Wn t �yuYnwt�!t�"|�d|��r�|||d||�d}|�r�|�|��r�z||
|v�r�|||d||�d}Wn t �y�Ynwt�!t�"|�d|��r�|||d||�d}|�s�t�d||d |d!�q�Wd�n	1�s�wYd|fd|fd|ffD];\}}||v�r.t||�dk�rt�d"||d�d#d�||D���||d$}t�d%|d |d!|�|S�q�|�r@t�d&|d |d!�|St�d'�dS)(a0	
    .. versionchanged:: 2016.3.5
        Prior to this version, only the ``file_name`` argument was considered
        for filename matches in the hash file. This would be problematic for
        cases in which the user was relying on a remote checksum file that they
        do not control, and they wished to use a different name for that file
        on the minion from the filename on the remote server (and in the
        checksum file). For example, managing ``/tmp/myfile.tar.gz`` when the
        remote file was at ``https://mydomain.tld/different_name.tar.gz``. The
        :py:func:`file.managed <salt.states.file.managed>` state now also
        passes this function the source URI as well as the ``source_hash_name``
        (if specified). In cases where ``source_hash_name`` is specified, it
        takes precedence over both the ``file_name`` and ``source``. When it is
        not specified, ``file_name`` takes precedence over ``source``. This
        allows for better capability for matching hashes.
    .. versionchanged:: 2016.11.0
        File name and source URI matches are no longer disregarded when
        ``source_hash_name`` is specified. They will be used as fallback
        matches if there is no match to the ``source_hash_name`` value.

    This routine is called from the :mod:`file.managed
    <salt.states.file.managed>` state to pull a hash from a remote file.
    Regular expressions are used line by line on the ``source_hash`` file, to
    find a potential candidate of the indicated hash type. This avoids many
    problems of arbitrary file layout rules. It specifically permits pulling
    hash codes from debian ``*.dsc`` files.

    If no exact match of a hash and filename are found, then the first hash
    found (if any) will be returned. If no hashes at all are found, then
    ``None`` will be returned.

    For example:

    .. code-block:: yaml

        openerp_7.0-latest-1.tar.gz:
          file.managed:
            - name: /tmp/openerp_7.0-20121227-075624-1_all.deb
            - source: http://nightly.openerp.com/7.0/nightly/deb/openerp_7.0-20121227-075624-1.tar.gz
            - source_hash: http://nightly.openerp.com/7.0/nightly/deb/openerp_7.0-20121227-075624-1.dsc

    CLI Example:

    .. code-block:: bash

        salt '*' file.extract_hash /path/to/hash/file sha512 /etc/foo
    Nz_file.extract_hash: Unsupported hash_type '%s', falling back to matching any supported hash_typer3�,z\/*r�rezMfile.extract_hash: Extracting %s hash for file matching source_hash_name '%s'z
any supportedcSsg|]}|r|�qSrrr�rrrr�)rSz extract_hash.<locals>.<listcomp>z5file.extract_hash: %s %s hash for file matching%s: %sz0If no source_hash_name match found, will extractZ
Extractingz either of the followingr�rz(?i)(?<![a-z0-9])([a-f0-9]{z})(?![a-z0-9])rtz0file.extract_hash: In line '%s', no %shash foundr]cSs&t�d|||�|�|g��|�dS)Nz,file.extract_hash: Line '%s' matches %s '%s')rnr��
setdefaultr@)r=r�Z
match_type�value�matchedrrr�_add_to_matchesVs�z%extract_hash.<locals>._add_to_matchesFr�Tz\s+r�r�z]file.extract_hash: Line '%s' contains %s hash '%s', but line did not meet the search criteriar�r�z1file.extract_hash: Multiple %s matches for %s: %scSs g|]}d�|d|d��qS)z{} ({})r�r�)r�r�rrrr��s��rz:file.extract_hash: Returning %s hash '%s' as a match of %szBfile.extract_hash: Returning the partially identified %s hash '%s'z-file.extract_hash: No matches, returning None)#r	rirnro�minr
�maxrAr��
whitespacer_r�r�rr�basenamer�r�r�rcrrrr"r	rMr
r�rKrLrOr?�
IndexErrorrQr�)r�r�r�r�r�r�Z
hash_len_exprZfilename_separatorsZsource_hash_name_idxZfile_name_basenameZ
file_name_idxr|Zsource_basenameZ
source_idxZbasename_searches�partialr=r�r�Zhash_reZ
hash_matchr�Zmatched_hsumZmatched_typer�Zhash_matchedZ
found_typeZ	found_strr/rrrr��sF
2�


�


��
�



�
	���
�
���������e�
������
r�c"Cs�tj�|�}tjj�|�}|s|igdd�}d}n|d}g|d<t||d�}i}
t|t	�r2|dn|d|
d<t|t	�rA|d	n|d
|
d<|d|
d
<tj�
|�}tj�|�}|rtjj�
�rit|�|dkr{tjj�
�s||dks||dks||
d<|r�tjj�
�r�t|�|d	kr�tjj�
�s�||d
ks�||d	ks�||
d<d|
vs�d|
vr�tds�|r�|s�t}nt}|dur�|d}|dur�|d
}z||||�}|r�d|d<|d�|�n	|s�t||d�Wn
ty�d|d<Ynw|du�rtddu�r|�r	|�r||dk�s||
d<t||�t||d�}|�rotjj�
��r2t|�|dk�rGtjj�
��sd||dk�sd||dk�sdtddu�rU||dd<nd|d<|d�d|���nd|
v�ro||dd<|�r�tjj�
��r�t|�|d	k�r�tjj�
��s�||d
k�s�||d	k�s�tddu�r�||dd
<nd|d<|d�d|���nd|
v�r�||dd
<|du�r�|�r�|�r�||dk�s�tddu�r�||dd<nd|d<|d�d|���nd|
v�r�||dd<|du�r�|�s�|�r|�r�t||�}|�r�tdd�|D���r�d�t|�|�dd�}tddu�r1||d<nE|j�r=t|d|jd�|j�rIt|d|jd�t||�}td d�|D���rrd|d<|d�d!|���d�t|�|�|d<n||d<|d"|dk�r�||dd#<tjj���r'|�s�|�s�|	�s�|
�r'd}zt|��d$�\}}}}t �!d%||||�Wnt"�y�t �#d&�d|d<|d�d'�d}Ynw|�s'd}d}d}d}|�r�||k�r�|}|�r�||k�r�|}|	�r�|	|k�r�|	}|
�r|
|k�r|
}|�s|�s|�s|�r'd}d} |�r#|d(|�d)�7}| d(|�d)�7} |�r6|d*|�d)�7}| d*|�d)�7} |�rI|d+|�d)�7}| d+|�d)�7} |�r\|d,|�d)�7}| d,|�d)�7} td�rzd-�$|�|d<d|d<| �%�|�%�d.�|dd/<n�z)|�s�|�s�|�r�|�s�|}t&|||||dd0�}!t �!d1|!�|!�d$�\}}}}Wnt"�y�t �#d2�d|d<|d�d3�d}Ynw|�s'|d�d4|�d5��|�r�||k�r�|d�d6�d|d<|�r�||k�r�|d�d7�d|d<|�r||k�r|d�d8�d|d<|�r||k�r|d�d9�d|d<| �%�|�%�d.�|dd/<t|t'��rA|�r8|d�(d:|�d;�|d�|d<tddu�rQ|d�rQd|d<||
fS)<a�
    .. versionchanged:: 3001

        Added selinux options

    Check the permissions on files, modify attributes and chown if needed. File
    attributes are only verified if lsattr(1) is installed.

    CLI Example:

    .. code-block:: bash

        salt '*' file.check_perms /etc/sudoers '{}' root root 400 ai

    .. versionchanged:: 2014.1.3
        ``follow_symlinks`` option added
    T�r��changesr.r-r3r.rcrqrsZluserr]rOZlgroupryZlmodeZcuserZcgrouprxNFr-Zcmoder�zFailed to change user to zFailed to change group to zFailed to change mode to cs��|]}|VqdSrr�r�attrrrrrd��zcheck_perms.<locals>.<genexpr>)r6r7r7r�)r�r�r+csr�rrr�rrrryr�zFailed to change attributes to r6r�r��8Current selinux context user:%s role:%s type:%s range:%s�(Unable to get current selinux attributesz Failed to get selinux attributeszUser: r]zRole: zType: zRange: z%File {} selinux context to be updated)ZOldZNew�selinux)rsrLr(rMrNzselinux set result: %sz(Unable to set current selinux attributesz Failed to set selinux attributes�	The file z is set to be changedzUnable to update seuser contextzUnable to update serole contextzUnable to update setype contextz Unable to update serange contextrz; ))rrrhrrr"r9rgr_rUr�r�rrrwrWr'r�r�r@r�r�r�r)rr�r�r�r�Zis_linuxrKr�rnr�rVr9r�r�rOrAre)"r�r/rsrOryr�rd�seuser�serole�setype�serangeZorig_commentZcurr��is_dirr�Z
chown_funcr�Zpost�
diff_attrsr�Z	cmp_attrsZ
selinux_error�current_seuser�current_serole�current_setype�current_serangeZrequested_seuserZrequested_seroleZrequested_setypeZrequested_serangeZselinux_change_newZselinux_change_origr-rrrr<�s�
�
�
�
���


�
�

�
�



�
��
&��
�����
��������
�



��r<cKs�t|||�\}}d}d}|dur1t|||||||||||	|
|
f
i|��\}}}|r1t|�d|fSt|||||||||||||||d�}|�t���rVdD]}|�|d�qMt|�|rwt�	|�dg}|�
dd�|��D��dd�|�fSd	d
|�d�fS)a�
    Check to see what changes need to be made for a file

    follow_symlinks
        If the desired path is a symlink, follow it and check the permissions
        of the file to which the symlink points.

        .. versionadded:: 3005

    CLI Example:

    .. code-block:: bash

        salt '*' file.check_managed /etc/httpd/conf.d/httpd.conf salt://http/httpd.conf '{hash_type: 'md5', 'hsum': <md5sum>}' root, root, '755' jinja True None None base
    r3NF�r�r�r�r�rd�rsrOryz,The following values are set to be changed:
css$�|]
\}}|�d|�d�VqdS)r�r<Nr)rr�valrrrrhs�"z check_managed.<locals>.<genexpr>Tr�� is in the correct state)
rdr~r,�check_file_metarr r!r�rn�infor��itemsr)r�r�r�r�rsrOryr�rorfrpr�r�rzr�r�r�r�rdr�rr{�commentsr�rrrr�
check_managedsj&����
r�cKs&t|||�\}}d}d}|durzt|||||||||||	|
|
f
d|i|��\}}}|r7d|vr7|d��|d<|rAt|�d|fS|rz|rz|rztj�|�jdvsU|�d�rzzt	d||d	d
�}Wnt
yy}z
t�d||�WYd}~nd}~wwt
|||||||||||||||d�}t|�|S)
a�
    Return a dictionary of what changes need to be made for a file

    .. versionchanged:: 3001

        selinux attributes added

    verify_ssl
        If ``False``, remote https file sources (``https://``) and source_hash
        will not attempt to validate the servers certificate. Default is True.

        .. versionadded:: 3002

    follow_symlinks
        If the desired path is a symlink, follow it and check the permissions
        of the file to which the symlink points.

        .. versionadded:: 3005

    CLI Example:

    .. code-block:: bash

        salt '*' file.check_managed_changes /etc/httpd/conf.d/httpd.conf salt://http/httpd.conf '{hash_type: 'md5', 'hsum': <md5sum>}' root, root, '755' jinja True None None base
    r3Nr�r�F)rr�r��cp.stat_fileT�r�Zoctal�Unable to stat %s: %sr�)rdr~r�r,r�r�r�r�rr:r�rnror�)r�r�r�r�rsrOryr�rorfrpr�r�rz�	keep_moder�r�r�r�r�rdr�rr{r�rBr�rrr�check_managed_changesmsv2��������r�c
Csi}|st�}z
t||�dd�|d�}Wntyi}Ynw|s(||d<|Sd|vrn|d|dkrn|sD|rDtd|||d|d�}|rjzt||d	d
d�|d<Wntyi}z|j|d<WYd}~n	d}~wwd
|d<|	du�rt|	t�r�t	j
jjt	j
jj
d
d�}t	j
j�|d��
}|�|	�Wd�n1s�wYn<t	j
jjt	j
jj
d	d�}t	j
j��r�tj�t|	��}	t	j
j�|d��}|�t	j
j�|	��Wd�n1s�wYz	t||d
d�}Wnt�y}zt�d|�|j}WYd}~nd}~wwt|�|�rtdd��rd|d<n||d<t	j
j���s
|du�r9||dk�r9||dk�r9||d<|du�rP||dk�rP||dk�rP||d<t	j
j�|d�}t	j
j�|�}|du�rn||k�rn||d<|�r�t||�}|du�r�|du�r�|ddu�s�|ddu�r�||d<|
�s�|�s�|�s�|
�r
zt|��d�\}}}}t�d||||�Wnt �y�}zt�d �|j|d!<WYd}~nd}~ww|
�r�|
|k�r�d|
i|d!<|�r�||k�r�d"|i|d!<|�r�||k�r�d#|i|d!<|
�r
|
|k�r
d$|
i|d!<|S)%as
    Check for the changes in the file metadata.

    CLI Example:

    .. code-block:: bash

        salt '*' file.check_file_meta /etc/httpd/conf.d/httpd.conf None salt://http/httpd.conf '{hash_type: 'md5', 'hsum': <md5sum>}' root root '755' None base

    .. note::

        Supported hash types include sha512, sha384, sha256, sha224, sha1, and
        md5.

    name
        Path to file destination

    sfn
        Template-processed source file contents

    source
        URL to file source

    source_sum
        File checksum information as a dictionary

        .. code-block:: yaml

            {hash_type: md5, hsum: <md5sum>}

    user
        Destination file user owner

    group
        Destination file group owner

    mode
        Destination file permissions mode

    attrs
        Destination file attributes

        .. versionadded:: 2018.3.0

    saltenv
        Salt environment used to resolve source files

    contents
        File contents

    seuser
        selinux user attribute

        .. versionadded:: 3001

    serole
        selinux role attribute

        .. versionadded:: 3001

    setype
        selinux type attribute

        .. versionadded:: 3001

    serange
        selinux range attribute

        .. versionadded:: 3001

    verify_ssl
        If ``False``, remote https file sources (``https://``)
        will not attempt to validate the servers certificate. Default is True.

        .. versionadded:: 3002

    follow_symlinks
        If the desired path is a symlink, follow it and check the permissions
        of the file to which the symlink points.

        .. versionadded:: 3005
    r�N)r�rdZnewfiler�r�r�)r�r�TF)ro�show_filenamesr�zChecksum differs�rOrr�r�r�zFailed to diff files: %s�
config.option�obfuscate_templates�<Obfuscated Template>rsrqrOr]ryrr�r�r�r�r�r�rLr(rM)!r]rgrirr:�get_diffr�r_rmrrr"rPr#r	rrrrrbrrCrMrNrnr9r,r9r�rKr�r�rV)r�rr�r{rsrOryr�r�r�r�r�r�r�r�rdr�ZlstatsrB�tmp�tmp_r�Zsmoder�r�r�r�r�rrrr��s�d

������


���
�����
&&


��
��r�cCs�||f}||f}	g}
g}t||	�D]E\}}
z#td|||
d�}|dur2|�d�tjj�|���Wq|
�|�WqtyV}z|�tjj�t	|���WYd}~qd}~ww|r_t
d|d��g}|
D]=}z!tjj�|d��}|�|�
��Wd�n1s�wYWqcty�}zt
d	�tjj�|�|j���d}~ww|d
|dkr�|r�tdd
�r�d}|S|s�d}|St|
�}|r�|}|S|r�|�|
�td|�}|SdS)aU
    Return unified diff of two files

    file1
        The first file to feed into the diff utility

        .. versionchanged:: 2018.3.0
            Can now be either a local or remote file. In earlier releases,
            thuis had to be a file local to the minion.

    file2
        The second file to feed into the diff utility

        .. versionchanged:: 2018.3.0
            Can now be either a local or remote file. In earlier releases, this
            had to be a file on the salt fileserver (i.e.
            ``salt://somefile.txt``)

    show_filenames: True
        Set to ``False`` to hide the filenames in the top two lines of the
        diff.

    show_changes: True
        If set to ``False``, and there are differences, then instead of a diff
        a simple message stating that show_changes is set to ``False`` will be
        returned.

    template: False
        Set to ``True`` if two templates are being compared. This is not useful
        except for within states, with the ``obfuscate_templates`` option set
        to ``True``.

        .. versionadded:: 2018.3.0

    source_hash_file1
        If ``file1`` is an http(s)/ftp URL and the file exists in the minion's
        file cache, this option can be passed to keep the minion from
        re-downloading the archive if the cached copy matches the specified
        hash.

        .. versionadded:: 2018.3.0

    source_hash_file2
        If ``file2`` is an http(s)/ftp URL and the file exists in the minion's
        file cache, this option can be passed to keep the minion from
        re-downloading the archive if the cached copy matches the specified
        hash.

        .. versionadded:: 2018.3.0

    CLI Examples:

    .. code-block:: bash

        salt '*' file.get_diff /home/fred/.vimrc salt://users/fred/.vimrc
        salt '*' file.get_diff /tmp/foo.txt /tmp/bar.txt
    r�r�FzFile {} not foundNz!Failed to cache one or more files)r�r+zFailed to read {}: {}rr�r�r�r��<show_changes=False>r5r3)�zipr:r@r�rrrMr
rrArr"r	rzr�r�r8r�r4)Zfile1Zfile2r�r�r�roZsource_hash_file1Zsource_hash_file2r"Z
source_hashes�pathsr8�filenamer�Zcached_pathrBr�r�r/Zbdiffrrrr��snC������������	��
r��strictc+
s~
tj�|�}t|otj�|�jdko|o|�}�s"|iddd��|r0d|vr0|d��|d<|r��sYt	d||	|d���sHt
�d|�d	��S|�d
td
�}|t
�|d�d�}|r�tj�|�jd
vr�zt	d||	dd�}Wnty�}z
t�d�|�WYd}~nd}~wwtj�|�s�tj�|��r.tj�|�r�|r�tj�|�}n|}|r�|s�tj�|�s�t
||�d
td
��} nd} |�r�| dus�|�dtd
�| k�r��s�t	d||	||d���s�t
�d|�d	��S|�r
t
�|d
�}!|!|dk�r
d�|d
||d|!��d<d�d<�St	dd��rd�dd<n7|
�s%d�dd<n-zt|�dd�}"|"�r6|"�dd<Wnt�yQ}z
|j�dd<WYd}~nd}~wwztjj��|t	d|
�td�Wnt�y�}#zt��t
�d |#���WYd}#~#Sd}#~#ww|du�rHtjjjtjjjdd!�}$tjj� |$d"��5}%|�r�tjj!�"��r�tj#�$t%|��}t�&d#|�|%�'|j(||d$��n
|%�'tjj)�*|��Wd�n	1�s�wYzt||$d|
dd%�}&Wn"t�y}z��+d&g��,d'|j���d}&WYd}~nd}~ww|&�rD|&�dd<ztjj�|$|t	d|
�td�Wnt�yC}#zt|$�t
�d |#���WYd}#~#Sd}#~#wwt|$�tj�|��r�|�sLj�s^t	d||	|d����sjt
�d|�d	��S|�r�t
�|d
�}!|!|dk�r�d(�|d
||d|!��d<d�d<�Sztjj��|t	d|
�td�Wnt�y�}#zt��t
�d |#���WYd}#~#Sd}#~#wwd)�dd<tjj!�"��r�t-|���d*���d+���d,���d-d���d.d�d/��nt-|�|||||||||d0�\�}'�d�rd1tjj.�/|��d2��d<n�d�s%�d�r%d3�tjj.�/|���d<��r,t���Stj�0|�}(���fd4d5�})|�r���sKt	d||	|d����sWt
�d|�d	��S|�r|t
�|d
�}!|!|dk�r|d(�|d
||d|!��d<d�d<�Sd6�dd<tj�1|(��s�|�r�|)|||||�n�t���d�2dd�t
�d7�Sn�tj�1|(��s�|�r�|)|||||�nt���d�2dd�t
�d7�Stjj�3|�r�d8nd��X|du�rtd9�st4|��r�d:|�d;��dd<<d=�d<n2t
�d>|�d?��Wd�Sn!td9�s(t4|��rd6�dd<nt
�d1|�d?��Wd�SWd�n	1�s3wY|du�r�tjjjtjjjdd!�}$tjj� |$d"��5}%|�rutjj!�"��rdtj#�$t%|��}t�&d#|�|%�'|j(||d$��n
|%�'tjj)�*|��Wd�n	1�s�wYtjj�|$|t	d|
�td�t|$�n��r�tjj��|t	d|
�td�t��|du�r�tjj!�"��s�tjj�5�}*t6d@|*AdA@�}tjj!�"��r�t-|���d*���d+���d,���d-d���d.d�d/��nt-|�||||||||d0�
\�}'�d�sd1|d2�d<td9�r$d1|dB�d<n�d�s6�d�r6d1|dC�d<��r=t���S)Da&
    Checks the destination against what was retrieved with get_managed and
    makes the appropriate modifications (if necessary).

    name
        location to place the file

    sfn
        location of cached file on the minion

        This is the path to the file stored on the minion. This file is placed
        on the minion using cp.cache_file.  If the hash sum of that file
        matches the source_sum, we do not transfer the file to the minion
        again.

        This file is then grabbed and if it has template set, it renders the
        file to be placed into the correct place on the system using
        salt.files.utils.copyfile()

    ret
        The initial state return data structure. Pass in ``None`` to use the
        default structure.

    source
        file reference on the master

    source_sum
        sum hash for source

    user
        user owner

    group
        group owner

    backup
        backup_mode

    attrs
        attributes to be set on file: '' means remove all of them

        .. versionadded:: 2018.3.0

    makedirs
        make directories if they do not exist

    template
        format of templating

    show_changes
        Include diff in state return

    contents:
        contents to be placed in the file

    dir_mode
        mode for directories created with makedirs

    skip_verify: False
        If ``True``, hash verification of remote file sources (``http://``,
        ``https://``, ``ftp://``) will be skipped, and the ``source_hash``
        argument will be ignored.

        .. versionadded:: 2016.3.0

    keep_mode: False
        If ``True``, and the ``source`` is a file from the Salt fileserver (or
        a local file on the minion), the mode of the destination file will be
        set to the mode of the source file.

        .. note:: keep_mode does not work with salt-ssh.

            As a consequence of how the files are transferred to the minion, and
            the inability to connect back to the master with salt-ssh, salt is
            unable to stat the file as it exists on the fileserver and thus
            cannot mirror the mode on the salt-ssh minion

    encoding
        If specified, then the specified encoding will be used. Otherwise, the
        file will be encoded using the system locale (usually UTF-8). See
        https://docs.python.org/3/library/codecs.html#standard-encodings for
        the list of available encodings.

        .. versionadded:: 2017.7.0

    encoding_errors: 'strict'
        Default is ```'strict'```.
        See https://docs.python.org/2/library/codecs.html#codec-base-classes
        for the error handling schemes.

        .. versionadded:: 2017.7.0

    seuser
        selinux user attribute

        .. versionadded:: 3001

    serange
        selinux range attribute

        .. versionadded:: 3001

    setype
        selinux type attribute

        .. versionadded:: 3001

    serange
        selinux range attribute

        .. versionadded:: 3001

    verify_ssl
        If ``False``, remote https file sources (``https://``)
        will not attempt to validate the servers certificate. Default is True.

        .. versionadded:: 3002

    use_etag
        If ``True``, remote http/https file sources will attempt to use the
        ETag header to determine if the remote file needs to be downloaded.
        This provides a lightweight mechanism for promptly refreshing files
        changed on a web server without requiring a full hash comparison via
        the ``source_hash`` parameter.

        .. versionadded:: 3005

    CLI Example:

    .. code-block:: bash

        salt '*' file.manage_file /etc/httpd/conf.d/httpd.conf '' '{}' salt://http/httpd.conf '{hash_type: 'md5', 'hsum': <md5sum>}' root root '755' '' base ''

    .. versionchanged:: 2014.7.0
        ``follow_symlinks`` option added

    rr3Tr�r�r�r�rwrxr�rsry)rr�r3r�r�r�N)r�rvz�Specified {} checksum for {} ({}) does not match actual checksum ({}). If the 'source_hash' value refers to a remote file with multiple possible matches, then it may be necessary to set 'source_hash_name'.r.Fr-r�r�r�r�r�r�r�zconfig.backup_moder9zFailed to commit change: r�r�zFile will be encoded with %s)r�r8)r�r�ro�warningsz"Failed to detect changes to file: zESpecified {} checksum for {} ({}) does not match actual checksum ({})z'Replace symbolic link with regular file�	win_owner�	win_perms�win_deny_perms�win_inheritance�win_perms_reset)rr/r��grant_perms�
deny_perms�inheritance�reset)r�r�r�r��File z updatedzFile {} is in the correct statec

stjj��r"tj�|�\}}|r"tj�|�s"t��t	�|�d��S|durS|durSdd�t
|�D�dd�}t|�D]\}}	|	dkrMt
t|	�dB�||<q;d�
|�}tjj��rvt|��d���d	���d
���dd���d
d�d�dSt||||d�dS)Nz drive not presentcSsg|]}|�qSrrr�rrrr��sz@manage_file.<locals>._set_mode_and_make_dirs.<locals>.<listcomp>���r|r�r3r�r�r�r�Tr�F)rr�r�r�r�r�r�)rrrrrr�
splitdriver*r,r1rAr�rUrrri)
r��dir_moderyrsrO�driver@Z	mode_listrr�part�r�r/rrr�_set_mode_and_make_dirs�s,�



�
z,manage_file.<locals>._set_mode_and_make_dirszNew filezParent directory not present�?rxzfile z createdr7z
Empty filezEmpty file z not createdi�i�z not updatedr�)7rrrhr�r�r�r�r�r�r:r1rir'r�r�rnror�r�r7r�r�rr�rrr"r�r�r,rPr#r	rrrbrrCr�r�encoderMr|r�r@r<ryrnr�r�r�Z	set_umaskr�Z	get_umaskr-)+r�rr/r�r{rsrOryr�r�rr
ror�r�r�rdrzr�r�Zencoding_errorsr�r�r�r�r�rvr�Zcheck_web_source_hashr}rBZ	real_nameZname_sumZdl_sumZ	file_diffZio_errorr�r�r�r@Zcontain_dirr��maskrr�r�manage_file8sP(���������	���
���

�����

�
���
�����
���

�
�
�"��
�	




�

��

������
�

�
�


r�cCs6tj�|�}tj�|�}tj�|�st||||�dS)z�
    Ensure that a directory is available.

    CLI Example:

    .. code-block:: bash

        salt '*' file.mkdir /opt/jetty/context
    T)rrrhr�r��makedirs_perms)Zdir_pathrsrOry�	directoryrrr�mkdiris

r�c	Cs�tj�|�}|rtjj�|�}tj�tj�|��}tj�	|�r,d|�d�}t
�|�|Stj�|�r?d|�d�}t
�|�|Sg}	tj�	|�rIn|�
|�|}tj�|�}||kratd�|���qB|��|D]}t
�d|�t||||d�qhd	S)
a
    Ensure that the directory containing this path is available.

    .. note::

        The path must end with a trailing slash otherwise the directory/directories
        will be created up to the parent directory. For example if path is
        ``/opt/code``, then it would be treated as ``/opt/`` but if the path
        ends with a trailing slash like ``/opt/code/``, then it would be
        treated as ``/opt/code/``.

    CLI Example:

    .. code-block:: bash

        salt '*' file.makedirs /opt/code/
    zDirectory 'z' already existsz
The path 'z'' already exists and is not a directoryTz_Recursive creation for path '{}' would result in an infinite loop. Please use an absolute path.zCreating directory: %sr�N)rrrhrrr"r9r�r�r�rnr�r*r@rr��reverser�)	rrsrOryr�rZZdirectories_to_createZcurrent_dirnameZdirectory_to_createrrrr�s<


����0755c
Cs�tj�|�}tj}|�|�\}}|s|�|�\}}|rL|rL|�|�sLz	t||||�WntyD}z
|jtjkr:�WYd}~nd}~ww|tj	krLdSt�
|�t|d|||r`t|���dSd�dS)z�
    Taken and modified from os.makedirs to set user, group and mode for each
    directory created.

    CLI Example:

    .. code-block:: bash

        salt '*' file.makedirs_perms /opt/code
    N)
rrrhr�r*r�r�r��EEXIST�curdirr�r<rU)r�rsrOryr�head�tailrBrrrr��s$���

(r�cCsBtj�|�}t|�st|�rt�|�}t�|j�t�|j�fSdS)z�
    Get major/minor info from a device

    CLI Example:

    .. code-block:: bash

       salt '*' file.get_devmm /dev/chr
    )rr)	rrrh�	is_chrdev�	is_blkdevr~�major�st_rdev�minor)r��stat_structurerrr�	get_devmm�s


r�c
C�`tj�|�}d}zt�|�}Wnty)}z|jtjkr$WYd}~dS�d}~wwt�|j�S)z�
    Check if a file exists and is a character device.

    CLI Example:

    .. code-block:: bash

       salt '*' file.is_chrdev /dev/chr
    NF)	rrrhr~r�r��ENOENTr0r�r�r�rBrrrr���
��r��0660c
C�tj�|�}|iddd�}t�d||||�z;tdr*dd|�d�i|d	<d
|d<n&t�|tt|��	d�d
�t
jBt�||��d
urPdd|�d�i|d	<d|d<Wn!t
yr}z|jtjkr`�d|�d�|d<WYd
}~nd
}~wwt|d
|||r�t|���|Sd
�|S)z�
    .. versionadded:: 0.17.0

    Create a character device.

    CLI Example:

    .. code-block:: bash

       salt '*' file.mknod_chrdev /dev/chr 180 31
    r3Fr�z;Creating character device name:%s major:%s minor:%s mode:%srxr7zCharacter device �	 created.r�Nr-r{r}Tr��! exists and cannot be overwrittenr.)rrrhrnr�r'�mknodrUrAr~r~�S_IFCHR�makedevr�r�r�r<�r�r�r�rsrOryr/rBrrr�mknod_chrdev�B�

������r�c
Cr�)z�
    Check if a file exists and is a block device.

    CLI Example:

    .. code-block:: bash

       salt '*' file.is_blkdev /dev/blk
    NF)	rrrhr~r�r�r�r1rr�rrrr�7r�r�c
Cr�)z�
    .. versionadded:: 0.17.0

    Create a block device.

    CLI Example:

    .. code-block:: bash

       salt '*' file.mknod_blkdev /dev/blk 8 999
    r3Fr�z7Creating block device name:%s major:%s minor:%s mode:%srxr7z
Block device r�r�Nr-r{r}Tr�r�r.)rrrhrnr�r'r�rUrAr~r~�S_IFBLKr�r�r�r�r<r�rrr�mknod_blkdevOr�r�c
Cr�)z�
    Check if a file exists and is a FIFO.

    CLI Example:

    .. code-block:: bash

       salt '*' file.is_fifo /dev/fifo
    NF)	rrrhr~r�r�r�r4rr�rrr�is_fifo�r�r�c
Cs�tj�|�}|iddd�}t�d|�z3tdr'dd|�d�i|d	<d
|d<nt�|tt|��	d�d
��d
urEdd|�d�i|d	<d|d<Wn!t
yg}z|jtjkrU�d|�d�|d<WYd
}~nd
}~wwt
|d
|||rwt|���|Sd
�|S)z�
    .. versionadded:: 0.17.0

    Create a FIFO pipe.

    CLI Example:

    .. code-block:: bash

       salt '*' file.mknod_fifo /dev/fifo
    r3Fr�zCreating FIFO name: %srxr7z
Fifo pipe r�r�Nr-r{r}Tr�r�r.)rrrhrnr�r'�mkfiforUrAr~r�r�r�r<)r�rsrOryr/rBrrr�
mknod_fifo�s*
 ����r��0600cCstd}t|||�|dkrt||||||�}|S|dkr&t||||||�}|S|dkr3t||||�}|Std�|���)a/
    .. versionadded:: 0.17.0

    Create a block device, character device, or fifo pipe.
    Identical to the gnu mknod.

    CLI Examples:

    .. code-block:: bash

        salt '*' file.mknod /dev/chr c 180 31
        salt '*' file.mknod /dev/blk b 8 999
        salt '*' file.nknod /dev/fifo p
    Fr_rr�zcNode type unavailable: '{}'. Available node types are character ('c'), block ('b'), and pipe ('p').)rr�r�r�rr�)r�Zntyper�r�rsrOryr/rrrr��s
����r�c	s�tj�|�}zt|�}WntyYnty$t�d�d}Ynwt�}tj�	|�\}}t
jj�
�r=|�dd�}n|dd�}tj�||��tj���sRiSi��fdd�t���D�D]S}t
jj�
�rn|�d�}n|�d	�}z	tj�||�}Wn	ty�Yq`wt
jj�
�r�d
}	nd}	|�|	���|i�d<tj��|�}
t�|
�j�|d
<|
�|d<q`tttttt�����fdd�t�dd�d|�D����S)a�
    .. versionadded:: 0.17.0

    Lists the previous versions of a file backed up using Salt's :ref:`file
    state backup <file-state-backups>` system.

    path
        The path on the minion to check for backups
    limit
        Limit the number of results to the most recent N backups

    CLI Example:

    .. code-block:: bash

        salt '*' file.list_backups /foo/bar/baz.txt
    z0file.list_backups: 'limit' value must be numericNr�r@r�cs&g|]}tj�tj��|��r|�qSr)rrr�rr�)�bkdirrrr�s
��z list_backups.<locals>.<listcomp>z_%a_%b_%d_%H-%M-%S_%f_%Y�_%a_%b_%d_%H:%M:%S_%f_%Yz%a %b %d %Y %H-%M-%S.%f�%a %b %d %Y %H:%M:%S.%f�Backup Time�Size�Locationc�g|]}�|�qSrrr�)r"rrr�rST�r�)rrrhrUr�rVrnr9r;r�rrrrr�rr�r�datetime�strptimer�r�r~rr]r�r�rMr�r�)rr��bkroot�
parent_dirr�Zsrc_dir�fname�strpfmt�	timestampZ
str_formatrqr)r�r"r�list_backups�sX
�

�
� ���r�list_backupc
s�tj�|�}zt|�}WntyYnty$t�d�d}Ynwt�}tj�	|�\}}tj�
||dd��}tj�|�sCiSi}dd�t�
dd�tt�|��D��D�}t�|�}|��D]w\}	}
i�t|�D]G}|�	d�d	}|	|kr�|�d
�}z	tj�||�}
Wn	ty�Yqlw|
�d���|
i�d<tj�
||�}t�|�j�|
d
<|�|
d<qlttttt|
���fdd�t�dd�d|�D����}|	|i}|�|�qb|S)au
    Lists the previous versions of a directory backed up using Salt's :ref:`file
    state backup <file-state-backups>` system.

    path
        The directory on the minion to check for backups
    limit
        Limit the number of results to the most recent N backups

    CLI Example:

    .. code-block:: bash

        salt '*' file.list_backups_dir /foo/bar/baz/
    z4file.list_backups_dir: 'limit' value must be numericNr�cSsi|]\}}|tt|���qSr)r�r�)rr��nrrrrKs��z$list_backups_dir.<locals>.<dictcomp>cSsg|]	}|�d�d�qS)r@r)r�r�rrrr�Nsz$list_backups_dir.<locals>.<listcomp>r@rr�r�r�r�r�cr�rrr��Zssfilerrr�irSTr�)rrrhrUr�rVrnr9r;r�rr�r$�groupbyr�rr�r�r�r�r�r~rr]r�r�rMrk)rr�r�r�r�r�r"r�Zffr�rr�rrrqZsfilesZsefilesrrr�list_backups_dir(sd
���

���
 ���rc
Csntj�|�}dd|�d�d�}ztt|��ttt|���kr't|�t|�}n|WSWnty6|YStyJd|�d|��|d<|YSwt	j
j�|t
��z
t�|d|�Wnty}}zd	�|d||�|d<|WYd
}~Sd
}~wwd|d<d
�|d|�|d<t	j
j��s�zt�|�}Wnty�|dd7<Y|Swt�||j|j�|S)a�
    .. versionadded:: 0.17.0

    Restore a previous version of a file that was backed up using Salt's
    :ref:`file state backup <file-state-backups>` system.

    path
        The path on the minion to check for backups
    backup_id
        The numeric id for the backup you wish to restore, as found using
        :mod:`file.list_backups <salt.modules.file.list_backups>`

    CLI Example:

    .. code-block:: bash

        salt '*' file.restore_backup /foo/bar/baz.txt 0
    F�Invalid backup_id 'r��r-r.�backup_id '�' does not exist for r.r�zUnable to restore {} to {}: {}NTr-zSuccessfully restored {} to {}z!, but was unable to set ownership)rrrhr�rArUrrVr[rrr"Z
backup_minionr;rr�r�r�rrr~r�r
r
)r�	backup_idr/rrB�fstatrrr�restore_backuprsH��
�����rc
Cstj�|�}dd|�d�d�}ztt|��ttt|���kr't|�t|�}n|WSWnty6|YStyJd|�d|��|d<|YSwz	t�	|d�Wnt
yq}zd	�|d|�|d<WYd
}~|Sd
}~wwd|d<d
�|d�|d<|S)a
    .. versionadded:: 0.17.0

    Delete a previous version of a file that was backed up using Salt's
    :ref:`file state backup <file-state-backups>` system.

    path
        The path on the minion to check for backups
    backup_id
        The numeric id for the backup you wish to delete, as found using
        :mod:`file.list_backups <salt.modules.file.list_backups>`

    CLI Example:

    .. code-block:: bash

        salt '*' file.delete_backup /var/cache/salt/minion/file_backup/home/foo/bar/baz.txt 0
    Fr	r�r
rrr.r�zUnable to remove {}: {}NTr-zSuccessfully removed {})rrrhr�rArUrrVr[r+r�r�)rr
r/rrBrrr�
delete_backup�s.����r�
remove_backupc

Gs�tj�|�}|}t�|�}|s|}g}|D]0}z	tjj�|�}Wnty2tjj�t	|��}Ynwt
|�dkr@td�|���|�
|�qt|t�rVdg||g|}n	dg|||g}ztd|dd�}W|Sty{}	zt|	j��d}	~	ww)a�
    Grep for a string in the specified file

    .. note::
        This function's return value is slated for refinement in future
        versions of Salt

        Windows does not support the ``grep`` functionality.

    path
        Path to the file to be searched

        .. note::
            Globbing is supported (i.e. ``/var/log/foo/*.log``, but if globbing
            is being used then the path should be quoted to keep the shell from
            attempting to expand the glob expression.

    pattern
        Pattern to match. For example: ``test``, or ``a[0-5]``

    opts
        Additional command-line flags to pass to the grep command. For example:
        ``-v``, or ``-i -B2``

        .. note::
            The options should come after a double-dash (as shown in the
            examples below) to keep Salt's own argument parser from
            interpreting them.

    CLI Example:

    .. code-block:: bash

        salt '*' file.grep /etc/passwd nobody
        salt '*' file.grep /etc/sysconfig/network-scripts/ifcfg-eth0 ipaddr -- -i
        salt '*' file.grep /etc/sysconfig/network-scripts/ifcfg-eth0 ipaddr -- -i -B2
        salt '*' file.grep "/etc/sysconfig/network-scripts/*" ipaddr -- -i -l
    r�zPassing multiple command line arguments in a single string is not supported, please pass the following arguments separately: {}�grepr�Fr�N)rrrhr�rrr�r�r�rAr�rr�r�r_r�r:r�rr�)
rr�rh�_pathZ
split_opts�optr�rPr/rBrrrr�s8'
��
�
��rc
Cs�i}t�d�}|D]}zg|t|�<Wq	tyYq	wi}|D]�}d|��}z
t�|�d��}Wn	ty;Yq!wg}t�|�d��D]}	|�|�d|	���qF|D]8}
z|�tj�|�d|
�d���Wn	tyqYqUwt�|�d|
�d��D]}|�|�d|
�d|���q}qUtt	|��}|D]E}z
tj�|�}
t�
|
�Wn	ty�Yq�w|
|vr�|g||
<n||
�|�tt	||
��||
<||�|
�tt	||��||<q�q!|r�|S|S)z�
    Return a list of all physical open files on the system.

    CLI Examples:

    .. code-block:: bash

        salt '*' file.open_files
        salt '*' file.open_files by_pid=True
    z/proc/z/taskz/fdz/fd/z/task/z/exe)rrrUrVr�r@rr7r�r�r~)Zby_pidZpidsZprocfsZpfiler"�pidZppathZtidsZfd_Zfpath�tidZtpathZfdpathr�rrr�
open_files+s\
�
�"����rcCstjjS)a�
    Return the relative parent directory path symbol for underlying OS

    .. versionadded:: 2014.7.0

    This can be useful when constructing Salt Formulas.

    .. code-block:: jinja

        {% set pardir = salt['file.pardir']() %}
        {% set final_path = salt['file.join']('subdir', pardir, 'confdir') %}

    CLI Example:

    .. code-block:: bash

        salt '*' file.pardir
    )rr�pardirrrrrrysrcC�tj�|�S)ay
    Returns Normalize path, eliminating double slashes, etc.

    .. versionadded:: 2015.5.0

    This can be useful at the CLI but is frequently useful when scripting.

    .. code-block:: jinja

        {%- from salt['file.normpath'](tpldir + '/../vars.jinja') import parent_vars %}

    CLI Example:

    .. code-block:: bash

        salt '*' file.normpath 'a/b/c/..'
    )rrr�r�rrrr���r�cCr)a[
    Returns the final component of a pathname

    .. versionadded:: 2015.5.0

    This can be useful at the CLI but is frequently useful when scripting.

    .. code-block:: jinja

        {%- set filename = salt['file.basename'](source_file) %}

    CLI Example:

    .. code-block:: bash

        salt '*' file.basename 'test/test.config'
    )rrr�r�rrrr��rr�cCr)az
    Returns the directory component of a pathname

    .. versionadded:: 2015.5.0

    This can be useful at the CLI but is frequently useful when scripting.

    .. code-block:: jinja

        {%- from salt['file.dirname'](tpldir) + '/vars.jinja' import parent_vars %}

    CLI Example:

    .. code-block:: bash

        salt '*' file.dirname 'test/path/filename.config'
    )rrr�r�rrrr��rr�cGstjj|�S)a
    Return a normalized file system path for the underlying OS

    .. versionadded:: 2014.7.0

    This can be useful at the CLI but is frequently useful when scripting
    combining path variables:

    .. code-block:: jinja

        {% set www_root = '/var' %}
        {% set app_dir = 'myapp' %}

        myapp_config:
          file:
            - managed
            - name: {{ salt['file.join'](www_root, app_dir, 'config.yaml') }}

    CLI Example:

    .. code-block:: bash

        salt '*' file.join '/' 'usr' 'local' 'bin'
    )rrr)r�rrrr�src
Cs�|rt||�Stj�|�}tj�|�}tj�|�std��tj�|�s'td��dd|�d|�d�d�}z	t�||�W|StyU}z
t	d|�d|�d	|����d
}~ww)al
    Move a file or directory

    disallow_copy_and_unlink
        If ``True``, the operation is offloaded to the ``file.rename`` execution
        module function. This will use ``os.rename`` underneath, which will fail
        in the event that ``src`` and ``dst`` are on different filesystems. If
        ``False`` (the default), ``shutil.move`` will be used in order to fall
        back on a "copy then unlink" approach, which is required for moving
        across filesystems.

        .. versionadded:: 3006.0

    CLI Example:

    .. code-block:: bash

        salt '*' file.move /path/to/src /path/to/dst
    zSource path must be absolute.z"Destination path must be absolute.Tr�z' moved to 'r
zUnable to move 'r�r�N)
r�rrrhr�rrr;r�r)rUr�Zdisallow_copy_and_unlinkr/rBrrrr;�s$
����r;c

Cs�d}t�}tj�|�rt�|�}|j}|Stjj�|�D]3\}}}|D]+}tj�	||�}	zt�|	�}Wn	t
y<Yq#w|j|vrCq#|�|j�||j7}q#q|}|S)z�
    Recursively calculate disk usage of path and return it
    in bytes

    CLI Example:

    .. code-block:: bash

        salt '*' file.diskusage /path/to/check
    r)
r�rrr�r~rrrZos_walkrr�r,r�)
rZ
total_size�seenr�r/�dirpath�dirnames�	filenamesr��fprrr�	diskusages*
�
�r )T)r�)r�r�)r3r3NNr�T)F)r3r�r�r�FF)r3r�)r3r�rFF)rr�)rTr�)r�)NNNNNNT)
NNNNNNTFFT)
rr}r�FFNr�FFTFTF)r�r�r3FFr�FTFNN)r}r�FF)r3F)r3)NN)FF)NT)FFN)NNNNF)FTF)r�r3r3N)NFNNNN)NFNNNNF)	NFFNNNNTF)NNNNNTF)r�TTFNN)FNTNNTFFNr�NNNNTF)NNN)NNr�)NNr�)rrNNr�r)��__doc__r�r�r�r�r{r$�loggingr�rrKrr~r�r�r r��urllib.parser��collectionsr�collections.abcrrZsalt.utils.argsrZsalt.utils.atomicfileZsalt.utils.dataZsalt.utils.filebufferZsalt.utils.filesZsalt.utils.findZsalt.utils.functoolsZsalt.utils.hashutilsZsalt.utils.httpZsalt.utils.itertoolsZsalt.utils.pathZsalt.utils.platformZsalt.utils.stringutilsZsalt.utils.templatesZsalt.utils.urlZsalt.utils.userZsalt.exceptionsrrrrrTr	r
Zsalt.utils.versionsrrXrn�ImportError�	getLogger�__name__rnZ__func_alias__rrr,r1r8r;rCrRrTr^rWrkrmrrrwrxrtrzr�r�r�r�r�r�r�r�r�r�r�r�r�r�rrrrrrrrrrr&r.r$rMrNr:rVr[r`rarcrvr�r�r�rLr�r�r�r�r@r�rr�r�r�r�r�r�r�r�r�r�r�r�rr�rr%rgr<r+rArCrDrErKrOrdrrr~r�r<r�r�r�r�r�r�rr�r�r�r�r�r�r�r�r�rr�	functoolsZalias_functionrrrrrrrrr�r�r�rr;r rrrr�<module>sf
�

	'.)+B�8�X0�f#*%	2
�E�q��}-_#D;03 L@%$5'=W �3zD�v�|�V�n�|�b��5=11#KJ=,MN-