????

Your IP : 3.147.70.194


Current Path : /opt/cloudlinux/venv/lib/python3.11/site-packages/clquota/__pycache__/
Upload File :
Current File : //opt/cloudlinux/venv/lib/python3.11/site-packages/clquota/__pycache__/__init__.cpython-311.pyc

�

��f����@�ddlZddlZddlZddlZddlZddlZddlZddlm	Z	ddl
mZmZm
Z
mZmZddlmZmZmZmZddlZddlZddlmZddlmZddlmZddlmZmZm Z dd	l!m"Z"m#Z#dd
l$m%Z%m&Z&m'Z'm(Z(m)Z)ej*�+��Z,dZ-dZ.Gd
�de/��Z0Gd�de/��Z1Gd�de/��Z2Gd�de/��Z3Gd�de��Z4Gd�de/��Z5Gd�de/��Z6Gd�de6��Z7d�Z8d�Z9de:fd �Z;Gd!�d"e<��Z=dS)#�N)�defaultdict)�S_IRGRP�S_IROTH�S_IRUSR�S_IWUSR�ST_DEV)�Dict�List�Optional�Tuple)�FormattedException)�ClPwd)�check_quota_enabled)�admin_packages�
list_users�resellers_packages)�CPAPIExternalProgramFailed�
EncodingError)�ExternalProgramFailed�get_file_lines�get_filesystem_type�run_command�write_file_lines�default�
VE_DEFAULTc��eZdZd�ZdS)�NoSuchPackageExceptionc�D�t�|d|�d���dS)NzNo such package (�)��	Exception�__init__��self�packages  �G/opt/cloudlinux/venv/lib64/python3.11/site-packages/clquota/__init__.pyr"zNoSuchPackageException.__init__+s'�����4�4�7�7�7�!D�E�E�E�E�E�N��__name__�
__module__�__qualname__r"�r'r&rr*s(������F�F�F�F�Fr'rc��eZdZd�ZdS)�NoSuchUserExceptionc�D�t�|d|�d���dS)NzNo such user (rr )r$�users  r&r"zNoSuchUserException.__init__0s'�����4�4����!>�?�?�?�?�?r'Nr(r,r'r&r.r./s(������@�@�@�@�@r'r.c��eZdZd�ZdS)�InsufficientPrivilegesExceptionc�<�t�|d��dS)NzInsufficient privilegesr �r$s r&r"z(InsufficientPrivilegesException.__init__5s�����4�!:�;�;�;�;�;r'Nr(r,r'r&r2r24s#������<�<�<�<�<r'r2c��eZdZd�ZdS)�IncorrectLimitFormatExceptionc�D�t�|d|�d���dS)NzIncorrect limit format (rr �r$�limits  r&r"z&IncorrectLimitFormatException.__init__:s'�����4�4����!H�I�I�I�I�Ir'Nr(r,r'r&r6r69s(������J�J�J�J�Jr'r6c�2��eZdZdZdejf�fd�Z�xZS)�MalformedConfigExceptionz\
    Raised when config files is malformed and
    cl-quota is not able to work with it
    �errorc���tt|���dtt	|�����d���dS)Nz�cl-quota can't work because for malformed config. Please, contact CloudLinux support if you need help with resolving this issue. Details: %(error_message)s)�
error_message)�message�context)�superr;r"�dict�str)r$r<�	__class__s  �r&r"z!MalformedConfigException.__init__Cs\���
�&��-�-�6�6�-��!�%�j�j����
	8
�	8
�		�		�		�		�		r')r)r*r+�__doc__�ConfigParser�ParsingErrorr"�
__classcell__�rDs@r&r;r;>sQ���������
�l�7�
�
�
�
�
�
�
�
�
�
r'r;c��eZdZd�ZdS)�GeneralExceptionc�<�t�||��dS�Nr )r$r?s  r&r"zGeneralException.__init__Qs�����4��)�)�)�)�)r'Nr(r,r'r&rKrKPs#������*�*�*�*�*r'rKc���eZdZ�fd�Z�xZS)�QuotaDisabledExceptionc�X��tt|���d��dS)Nz&Quota disabled for all users on server)rArOr")r$rDs �r&r"zQuotaDisabledException.__init__Vs)���
�$�d�+�+�4�4�5]�^�^�^�^�^r')r)r*r+r"rHrIs@r&rOrOUsA�������_�_�_�_�_�_�_�_�_r'rOc��eZdZdZdd�ZdS)�UserQuotaDisabledExceptionz?
    Raised when quota is disabled for one particular user
    Nc�|�d}|r|d|zz
}|r|d|zz
}|r|d|zz
}t�||��dS)NzQuota disabledz for user id %sz (home directory %s)z; %sr )r$�uid�homedirr?�all_msgs     r&r"z#UserQuotaDisabledException.__init__^sj��"���	/��(�3�.�.�G��	8��-��7�7�G��	(��v��'�'�G����4��)�)�)�)�)r')NNN)r)r*r+rEr"r,r'r&rRrRZs2��������*�*�*�*�*�*r'rRc�v�|ddkr|dz
}d}|dkrdS|D]}|�|��rdS�dS)zd
    >>> _is_sys_path('/home/username')
    False
    >>> _is_sys_path('/var/davecot')
    True
    ����/)	z/root/z/usr/z/var/z/sbin/z/dev/z/bin/z/srv/z/sys/z	/etc/ntp/TN)�
startswith)�path�	sys_path_�path_s   r&�_is_sys_pathr^isf���B�x�3�������g�I��s�{�{��t������?�?�5�!�!�	��4�4�	��r'c�h��t��}|�����fd��D��}|S)z)
    Return no system users uid list
    c�^��g|])}t�|j����|j��*Sr,)r^�pw_dir�pw_uid)�.0�usr�pw_dicts  �r&�
<listcomp>z#_get_users_list.<locals>.<listcomp>�s5���a�a�a��|�G�TW�L�L_�?`�?`�a����$�a�a�ar')r�
get_user_dict)�cl_pwd�	users_uidres  @r&�_get_users_listrjzs>���
�W�W�F��"�"�$�$�G�a�a�a�a��a�a�a�I��r'�returnc�H�tjtjdd���}|S)zJ
    Check `cl_quota_inodes_inheritance` parameter in the config file
    �cl_quota_inodes_inheritanceF)�default_val)�cldetectlib�get_boolean_param�CL_CONFIG_FILE)�ress r&�is_quota_inheritance_enabledrs�s%���
'��(B�Da�ot�
u�
u�
u�C��Jr'c�`�eZdZdZdZdZdZdZdZdZ	dZ
d	Ze	d
zZdZ
d�Zed
���Zd�Zd�Zd�Zd�Zd�Zd_d�Zd�Zd�Zd`d�Z					dadedeedeedededefd�Z				dbdedeedeededed d	fd!�Zd"�Zd#�Z dcd$efd%�Z!d&�Z"d_d'ed	zfd(�Z#d)�Z$d*�Z%	d`ded+eed,eeded e&eeeeff
d-�Z'ded+eed,eed e&eeffd.�Z(d/�Z)d0�Z*d e+j+fd1�Z,d2�Z-d3eed eefd4�Z.dddedeedeed e&eeffd5�Z/dddedeedeed e&eeffd6�Z0dededed e&eeffd7�Z1ded e&eeffd8�Z2dededed e&eeffd9�Z3ded e&eeffd:�Z4edeedeed e&eeeeffd;���Z5dededeedeed e&eeff
d<�Z6ddd=�Z7ded efd>�Z8d_d?�Z9ded@�Z:dA�Z;dB�Z<dC�Z=d_dD�Z>dE�Z?d_dF�Z@d eAeeBeffdG�ZCd eAeeBeffdH�ZDdI�ZEdJ�ZFdK�ZGdL�ZHdM�ZIdN�ZJdO�ZKd eBe&eeffdP�ZLdQ�ZMdR�ZNdS�ZOdT�ZPdU�ZQdV�ZRdW�ZSedX���ZTdY�ZUdZ�ZVd[�ZWd\�ZXd`d]�ZYd^�ZZd	S)f�QuotaWrapperaB
    Base quota class for inode quotas handling

    * Update system quotas via setquota
    * Retrieves system quotas via repquota
    * Stores current quotas in /etc/container/cl-quotas.dat file
    * Maintaines /etc/container/cl-quotas.cache file with resolved quotas. That file can be read by non-privileged users
    z/proc/mountsz/usr/bin/quotasyncz/usr/sbin/setquotaz/usr/sbin/repquotaz%/usr/bin/getcontrolpaneluserspackagesz/etc/container/cl-quotas.datz/etc/container/cl-quotas.cacheNz.lockFc�H�|�tj��|�tj��|�tj��t��|_d|_i|_i|_	i|_
i|_i|_i|_
|���|_gd�|_t#j��|_|���|_|�|j��|_d|_d|_dS)N)�
bytes_used�
bytes_soft�
bytes_hard�inodes_used�inodes_soft�inodes_hard)�_assert_file_existsru�PROC_MOUNTS�REPQUOTA�SETQUOTA�list�_quota_enabled_list�_panel_present�_grace�_quota�
_device_quota�_package_to_uids_map�_uid_to_packages_map�_uid_to_homedir_map�_get_saved_data_handler�_dh�_fields�os�geteuid�_euid�_load_quota_devices�_devices�_get_mountpoint_device_map�_mountpoint_device_mapped�_device_user_map�_all_package_listr4s r&r"zQuotaWrapper.__init__�s���� � ��!9�:�:�:�� � ��!6�7�7�7�� � ��!6�7�7�7�#'�6�6�� �"������������$&��!�$&��!�#%�� ��/�/�1�1���n�n�n����Z�\�\��
��0�0�2�2��
�)-�)H�)H���)W�)W��&� $���!%����r'c�j�tj�|��std|�d����dS)z>
        Checks if command is present and exits if no
        zNo such command (rN)r�r[�exists�RuntimeError�r[s r&r}z QuotaWrapper._assert_file_exists�s>��
�w�~�~�d�#�#�	A��,����?�@�@�@�	A�	Ar'c��|SrMr,r4s r&�	__enter__zQuotaWrapper.__enter__�s���r'c�J�|j�|j���dSdSrM)�LOCK_FD�close)r$�_type�_value�
_tracebacks    r&�__exit__zQuotaWrapper.__exit__�s,���<�#��L��� � � � � �$�#r'c�R�|�|�|����S)z9
        Returns user limits converted to tuples
        ��_convert_data_to_tuples�_get_current_quotas�r$rTs  r&�get_user_limitszQuotaWrapper.get_user_limits�s&���+�+�D�,D�,D�S�,I�,I�J�J�Jr'c�P�|�|�����S)z=
        Returns all user limits converted to tuples
        r�r4s r&�get_all_users_limitsz!QuotaWrapper.get_all_users_limits�s$���+�+�D�,D�,D�,F�,F�G�G�Gr'c�T�|�|�|�����S)z�
        :param packname: Package name for get limits. If None, returns all packages,
                          else - only supplied package
        Returns package limits converted to tuples (called only from main)
        )�packname�r��_get_package_quotasr#s  r&�get_package_limitszQuotaWrapper.get_package_limits�s)���+�+�D�,D�,D�g�,D�,V�,V�W�W�Wr'c�V�|�|�|d�����S)zY
        Returns all packages limits converted to tuples (called only from main)
        T�r��all_packagesr�r#s  r&�get_all_packages_limitsz$QuotaWrapper.get_all_packages_limits�s,���+�+�D�,D�,D�g�dh�,D�,i�,i�j�j�jr'c�H�|dkrdS|dvrdS|�|��S)z�
        Preprocessed passed limit: 'default' --> '0', 'unlimited' --> -1, else calls _check_limit
        :param limit:
        :return:
        r�0)�	unlimited�-1r�)�_check_limitr8s  r&�_preprocess_limitzQuotaWrapper._preprocess_limit�s9���I����3��'�'�'��4�� � ��'�'�'r'c�^�|j�d|���d��S)N�packages�:)r��get�splitr#s  r&�_get_package_from_dhz!QuotaWrapper._get_package_from_dh�s&���x�|�|�J��0�0�6�6�s�;�;�;r'c�l�i}i}|j�d��r�t|j�d����dkr�|���}|j�d��D]`}|r ||vr|j�d|���$|�|��}t|��dkr�M|d|df||<�a|r|���|�	��|j
���D]}||vr||||<�d||<�|S)z�
        Retrive all available packages with their limits
        :param clean_dead_packages: if True - remove all nonexistent packages from cl-quotas.dat
        :return: Dictionary: { 'package_name': (soft_limit, hard_limit) }
        r�r���r�r�)r��has_section�len�items�_get_all_package_list�options�
remove_optionr��_write_data�_get_package_to_users_mapr��keys)r$�clean_dead_packages�package_limits_dict�db_packages�list_of_packagesr%�package_limitss       r&�_get_all_packages_with_limitsz*QuotaWrapper._get_all_packages_with_limits�sj��!�����8���
�+�+�	#��D�H�N�N�:�4N�4N�0O�0O�RS�0S�0S�#�9�9�;�;���8�+�+�J�7�7�
L�
L��&��7�:J�+J�+J��H�*�*�:�w�?�?�?��!%�!:�!:�7�!C�!C���~�&�&�!�+�+��'5�a�'8�.��:K�'K��G�$�$�"�
#�� � �"�"�"��&�&�(�(�(��0�5�5�7�7�	:�	:�G��+�%�%�/:�7�/C�#�G�,�,�/9�#�G�,�,�"�"r'TrT�soft�hard�save�
force_save�
only_storec
���|���|�|��|�|��}}|�|||���\}	}
|�|	|
���\}}|�|��|}
||f|
d|
dfks|r�|dkr�|�|�|����}|rD|�d|
d�d|
d�d|�d|�d	�
}|j�|d
��|z|j|<nDtj
d||
d|
d|||g}t|��|�|��|r3|�
||||���\}}|�|||��|dkr|dks|d
kr|d
kr|�|||��|dkr|���dSdS)a6
        Set limits for users

        * Resolve limits according to those saved in cl-quota.dat
          Limits are resolved in the following order:
            user limits --> package limits --> root user (uid=0) limits
        * Apply new limits when resolved limits differ from those in cache or when `force_save` is True
        * Write updated values to cl-quota.dat if `save` is True
          Always update cl-quota.dat in case both zeroes or both unlimited are provided

        :param uid: user id
        :param soft: soft limit value
        :param hard: hard limit value
        :param save: save limits to cl-quota.dat
        :param force_save: save limits to cl-quota.dat even if they are not changed
        :param only_store: store limits in memory, but do not apply them

        :return: None
        �rTr�r��r�r�r{r|r�� rxry�
�z-u)r�r�N)�_check_adminr��_combine_user_limits�_convert_for_sys_utilityr��_get_home_device�_fetch_homedirr�r�rur�r�_sync_quota_files�_get_user_limits_to_save�_save_user_limits�_apply_all_limits)r$rTr�r�r�r�r��soft_validated�hard_validated�
soft_resolved�
hard_resolved�soft_converted�hard_converted�cached�device�stdin�cmd�
soft_user_dat�
hard_user_dats                   r&�set_user_limitzQuotaWrapper.set_user_limits_��8	
������*.�)?�)?��)E�)E�t�G]�G]�^b�Gc�Gc���(,�'@�'@�S�~�dr�'@�'s�'s�$�
�}�*.�)F�)F�M�`m�)F�)n�)n�&����)�)�#�.�.�s�3��
�N�+��}�0E�v�m�G\�/]�]�]�ak�]��c�z�z��.�.�t�/B�/B�3�/G�/G�H�H���	3�"�v�v�V�L�%9�v�v�F�<�<P�v�v�Sa�v�v�dr�v�v�v�E�15�1C�1G�1G��PR�1S�1S�V[�1[�D�&�v�.�.�%�-��c�6�,�#7���9M�~�_m�ou��C� ��$�$�$��*�*�6�2�2�2��
J�/3�/L�/L����J�0M�0P�0P�,�
�}��&�&�s�M�=�I�I�I�
�c�!�!�n��&;�&;��SW�AW�AW�\j�nr�\r�\r��"�"�3���G�G�G��#�:�:��"�"�$�$�$�$�$��:r'r%rkc
���|���|�|��|�|��}}|dura||�d���vrI||���vr3|�|||��\}}	|�|||	��dS|�|��sdS|���}
|���}|
�	��D�]!}g}
|�|��D]�}||
|vr�
|�
||||���\}}	|�||	���\}}	||d||d}}||f||fkr;|
�|�d||d	�d||d
�d|�d|��	����#t$rY��wxYwt|
��dkr>d�|
��dz}
|j�|d
��|
z|j|<��#|r1|�|||��\}}|�|||��|s|���dSdS)a,
        Sets limits for package

        :param package: package name
        :param soft: soft limit value
        :param hard: hard limit value
        :param save: save limits to cl-quota.dat
        :param only_store: store limits in memory, but do not apply them

        :return: None
        T�r�N)rTr%r�r�r�r{r|r�rxryrr�r�)r�r�r�r��!_get_saved_package_limits_if_none�_save_package_limits�_check_package_exists�_get_device_user_mapr�r��_combine_package_limitsr��append�KeyErrorr��joinr�r��_get_package_limits_to_save�_flush_device_quota)r$r%r�r�r�r�r�r�r�r��device_user_map�
cached_quotasr��std_inrTr�r��soft_cached�hard_cached�	soft_data�	hard_datas                     r&�set_package_limitzQuotaWrapper.set_package_limitZs#��(	
������*.�)?�)?��)E�)E�t�G]�G]�^b�Gc�Gc����4�<�<��t�7�7�T�7�J�J�J�J��4�#A�#A�#C�#C�C�C�+/�+Q�+Q����,9�,9�(�M�=��%�%�g�}�m�L�L�L��F��)�)�'�2�2�	��F��3�3�5�5���0�0�2�2�
�%�*�*�,�,�	Y�	Y�F��F��5�5�g�>�>�
�
���o�f�5�5�5��/3�/K�/K��W�>��0L�0X�0X�,�
�}�26�1N�1N�Ta�hu�1N�1v�1v�.���	�/<�S�/A�-�/P�R_�`c�Rd�er�Rs��K�&��7�K��;U�U�U��
�
�"�A�A�,�S�1�,�?�A�A�BO�PS�BT�Ua�Bb�A�A�-�A�A�0>�A�A������
 �����D������6�{�{�a����)�)�F�+�+�d�2��-1�-?�-C�-C�F�B�-O�-O�RX�-X��"�6�*���	E�#'�#C�#C�G�^�]k�#l�#l� �I�y��%�%�g�y�)�D�D�D��	'��$�$�&�&�&�&�&�	'�	's�A!F7�7
G�Gc��|���|�d���}|���D]"\}\}}|�|||dd����#|���|���dS)zN
        Read limits from file and applies them to packages and users
        T)r�F)r�r�N)r�r�r�r�_remove_unexisting_usersr�)r$r�r%r�r�s     r&�synchronizezQuotaWrapper.synchronize�s���	
�������;�;�PT�;�U�U��%3�%9�%9�%;�%;�	U�	U�!�G�\�d�D��"�"�7�D�$�U�t�"�T�T�T�T��%�%�'�'�'�� � �"�"�"�"�"r'c���������������fd�t����t���D��}��d����tj��}tj
|tj���}|�|����
tj������dS)zF
        Caches the limits to non-privileged user to see them
        c�B���g|]��g��fd��jD��z��S)c�,��g|]}��|��Sr,r,)rc�field�current_quotas�ks  ��r&rfz;QuotaWrapper.save_user_cache.<locals>.<listcomp>.<listcomp>�s#���F�F�F��>�!�$�U�+�F�F�Fr'�r�)rcrrr$s @��r&rfz0QuotaWrapper.save_user_cache.<locals>.<listcomp>�sK����
�
�
���C�F�F�F�F�F���F�F�F�F�
�
�
r')�keyT)�quotingN)r�r��sortedr��int�_get_global_lock�_prepare_writerru�	CACHEFILE�csv�writer�
QUOTE_MINIMAL�	writerows�_end_writer�
_release_lock)r$�
cache_content�file_handler�csv_outrs`   @r&�save_user_cachezQuotaWrapper.save_user_cache�s�����	
�������1�1�3�3��
�
�
�
�
��N�/�/�1�1�s�;�;�;�
�
�
�
�
	
���d�#�#�#��+�+�L�,B�C�C���*�\�3�3D�E�E�E�����-�(�(�(�����/�0�0�0��������r'�	skip_rootc���|������D]%}|dkr|r�|�|dddd����&|���dS)z=Set limits for all users. Skip root user if skip_root is Truer�NFT)r�r�r�r�)�_get_uid_to_packages_mapr�r�r�)r$r#rTs   r&r�zQuotaWrapper._apply_all_limits�sv���0�0�2�2�7�7�9�9�	X�	X�C��c�z�z�i�z������$�T��RV��W�W�W�W�� � �"�"�"�"�"r'c���d}|j���D]/}tjd|g}t	||j|���d}�0|r|���i|_dS)zWrite all device quotas to diskFz-bu)rTN)r�r�rur�rr�)r$�quotas_writtenr�r�s    r&r�z QuotaWrapper._flush_device_quota�s~��$���(�-�-�/�/�	"�	"�F��(�%��8�C���D�$6�v�$>�?�?�?�?�!�N�N��	%��"�"�$�$�$�����r'r�c��|�8t|��}|���dkrdStj|g}ntjdg}t	|��dS)a
        In order to sync inodes limits in kernel with limits in user.quota file run `quotasync` command.
        Otherwise `repquota` called right after `setquota` may return old limits existed before `setquota` call.

        Skipped on the XFS filesystem because XFS does not require a separate quota synchronization step
        as it handles these operations in real-time. Additionally, the specific functionality required by `quotasync`
        to sync the disk quota information is not implemented, resulting in an error.
        N�xfsz-a)r�lowerru�	QUOTASYNCr)r$r��fs_typer�s    r&r�zQuotaWrapper._sync_quota_files�s_����)�&�1�1�G��}�}���%�'�'����)�6�2�C�C��)�4�0�C��C�����r'c�"�|j�d��rt|j�d��D]C}	|�|���#t$r|j�d|��Y�@wxYw|���dSdS)zARemove all records from cl-quota.dat for users which do not exist�usersN)r�r�r�r�r.r�r�r�s  r&r	z%QuotaWrapper._remove_unexisting_users�s����8����(�(�	��x�'�'��0�0�
9�
9��9��'�'��,�,�,�,��*�9�9�9��H�*�*�7�C�8�8�8�8�8�9������������	�	s�A�%A6�5A6c�T�	|�|��dS#t$rYdSwxYw)zCheck whether package existsTF)r�rr#s  r&r�z"QuotaWrapper._check_package_exists�sF��	��*�*�7�3�3�3��4��&�	�	�	��5�5�	���s��
'�'r�r�c���|�|���\}}|�|||���\}}|�|dd���\}	}
||	ks|r|�|}||
ks|r|�|}||fS)z�
        Derive package limit values to save to cl-quota.dat
        If None passed as limit to method, then replace it by the user's value from cl-quota.dat
        Update cl-quota.dat only if the derivation result changes
        �rTr�N)�_get_user_limitsr�)r$rTr�r�r�r�r�r�r��soft_none_resolved�hard_none_resolveds           r&r�z%QuotaWrapper._get_user_limits_to_saves���(,�'<�'<��'<�'E�'E�$�
�}�'+�'@�'@�S�~�dr�'@�'s�'s�$�
�}�15�1J�1J�s�Y]�dh�1J�1i�1i�.��.��.�.�.�:�.�.�B\�*�M��.�.�.�:�.�.�B\�*�M��m�+�+r'c�T�|�|���\}}|�|n|}|�|n|}||fS)z3Derive package limit values to save to cl-quota.dat�r%)�_get_package_limits)r$r%r�r��p_soft�p_hards      r&r�z(QuotaWrapper._get_package_limits_to_savesF���1�1�'�1�B�B����$2�#=���6��#1�#=���6���v�~�r'c�v�|j�,dtddg�����k|_|jS)z6
        Return True if control panel present
        N�Unknownz/usr/bin/cldetectz--detect-cp-nameonly)r�r�rstripr4s r&�_check_present_panelz!QuotaWrapper._check_present_panel$s>����&�"+�{�<O�Qg�;h�/i�/i�/p�/p�/r�/r�"r�D���"�"r'c�8�|jdkrt���dS)z2
        Raise exception if no admin user
        rN)r�r2r4s r&r�zQuotaWrapper._check_admin,s"���:��?�?�1�3�3�3��?r'c�`�|�d��tjdd���}t|_	|�t
j��n&#tj$r}t|���d}~wwxYw	|�	��n#|�	��wxYw|S)z|
        Gets ConfigParser handler for future use
        Loads saved quotas from /etc/container/cl-quotas.dat file
        TNF)�
interpolation�strict)
rrFrC�optionxform�readru�DATAFILErGr;r)r$�dh�es   r&r�z$QuotaWrapper._get_saved_data_handler3s���
	
���d�#�#�#�
�
&�T�%�
H�
H�
H�����	!��G�G�L�)�*�*�*�*���(�	.�	.�	.�*�1�-�-�-�����	.����
+�
��� � � � ��D��� � � � �����	s)�A�B�A<�(A7�7A<�<B�B+c��|j�|jSi}g}|���D]P}	|�|�|�|����|f���A#t
$rY�MwxYw|D]>}|d|vrg||d<||d�|d���?||_|jS)zF
        Returns dictionary mapping devices to lists of users
        Nrr�)r��_get_list_of_uidsr�r�r�r�)r$�devices_map�device_user_pairsrT�pairs     r&r�z!QuotaWrapper._get_device_user_mapCs���� �,��(�(������)�)�+�+�	�	�C�
�!�(�(�$�*?�*?��@S�@S�TW�@X�@X�*Y�*Y�[^�)_�`�`�`�`���
�
�
���
����%�	1�	1�D��A�w�k�)�)�')��D��G�$���Q�� �'�'��Q��0�0�0�0� +����$�$s�=A(�(
A5�4A5r9c��|�|dkr|Stjd��}|�|��}|st|���|�d��S)Nr�z(\d+)r�)�re�compile�searchr6�group)r$r9�
limit_pattern�
pattern_matchs    r&r�zQuotaWrapper._check_limitWs`���=�E�T�M�M��L��
�8�,�,�
�%�,�,�U�3�3�
��	7�/��6�6�6��"�"�1�%�%�%r'c�v�|dkr3|�|||���\}}|dkr|nd|dkr|nd}}||fS|�|||���\}}|�|��D]}|�|||���\}}�|�d||���\}}|dkr|nd|dkr|nd}}||fS)a
        Determines user limits by resolving them according to the limits inheritance rule:
            user limits ---(overridden by provided as method param if provided not None)--->
                ---> package limits ---> root user (uid=0) limits

        uid: user id
        soft: Optional[str] = None: limit value, can be:
            * None -- value not passed
            * "-1" -- unlimited
            * "0" -- default (next value from hierarchy should be considered)
            * "1", "2", ... -- precice limit values
        hard: soft: Optional[str] = None: limit value, values range the same as for soft

        return: Tuple[str, str]: (soft_limit, hard_limit), they can be:
            * "-1" -- unlimited
            * "1", "2", ... -- precice limit values
        r�r�r�)r%r�r�)�_get_user_limits_override_noner%�$_get_package_limits_override_default�!_get_user_limits_override_default)r$rTr�r�r%s     r&r�z!QuotaWrapper._combine_user_limits`s��$�#�:�:��<�<��4�VZ�<�[�[�J�D�$�"&�#�+�+�$�$�4�������RV�$�D���:���8�8�S�t�RV�8�W�W�
��d��4�4�S�9�9�	j�	j�G��B�B�7�Y]�dh�B�i�i�J�D�$�$��;�;��$�UY�;�Z�Z�
��d�"�c�k�k�d�d�t�T�S�[�[�T�T�d�d���T�z�r'c��|�|���\}}|�|�|n|���}|�|�|n|���}||fS)aGet user limits from cl-quota.dat. If limit is None, then override it by user's limit

        :param str uid: user id
        :param Optional[str] soft: limit value, can be:
            * None -- value not passed, should be overridden by user's limit
            * "-1" -- unlimited
            * "0" -- default (next value from hierarchy should be taken)
            * "1", "2", ... -- values
        :param Optional[str] hard: limit values same as for soft
        :return Tuple[str, str]: derived limits
        r1N�r9�r2r��r$rTr�r��	user_soft�	user_hards      r&rTz+QuotaWrapper._get_user_limits_override_none�sg�� $�4�4��4�=�=��	�9�� � �t�/?�t�t�Y� �O�O��� � �t�/?�t�t�Y� �O�O���T�z�r'c��|�|���\}}|�|dkr|n|���}|�|dkr|n|���}||fS)a�Get user limits from cl-quota.dat. If limit is default, then override it by user's limit

        :param str uid: user id
        :param Optional[str] soft: limit value, can be:
            * "-1" -- unlimited
            * "0" -- default (next value from hierarchy should be taken)
            * "1", "2", ... -- values
        :param Optional[str] hard: limit values same as for soft
        :return Tuple[str, str]: derived limits
        r1r�rXrYrZs      r&rVz.QuotaWrapper._get_user_limits_override_default�sm�� $�4�4��4�=�=��	�9�� � �t�s�{�{�t�t�	� �J�J��� � �t�s�{�{�t�t�	� �J�J���T�z�r'c��	|j�d|���d��\}}n&#tjtjf$rd\}}YnwxYw||fS)z*Try to get user's limits from cl-quota.datr.r�r�)r�r�r�rF�NoSectionError�
NoOptionError)r$rTr[r\s    r&r2zQuotaWrapper._get_user_limits�sp��	,�#'�8�<�<���#=�#=�#C�#C�C�#H�#H� �I�y�y���+�\�-G�H�	,�	,�	,�#+� �I�y�y�y�	,�����)�#�#s�14� A�Ac��|�|���\}}|�|dkr|n|���}|�|dkr|n|���}||fS)zeGet package limits from cl-quota.dat. If passed limit is default, then override it by package's limitr6r�rX)r7r��r$r%r�r��	pack_soft�	pack_hards      r&rUz1QuotaWrapper._get_package_limits_override_default�sk��#�7�7��7�H�H��	�9�� � �D�C�K�K�y�y�T� �J�J��� � �D�C�K�K�y�y�T� �J�J���T�z�r'c��	|�|��\}}n&#tjtjf$rd\}}YnwxYw||fS)z-Try to get package's limits from cl-quota.datr�)r�rFr_r`�r$r%r�r�s    r&r7z QuotaWrapper._get_package_limits�s]��	"��2�2�7�;�;�J�D�$�$���+�\�-G�H�	"�	"�	"�!�J�D�$�$�$�	"�����T�z�s�� >�>c�*�|dkrd}|dkrd}||fS)zAConverts limits for setquota utility which threats 0 as unlimitedr�r�r,r�s  r&r�z%QuotaWrapper._convert_for_sys_utility�s*���4�<�<��D��4�<�<��D��T�z�r'c�
�|�|���\}}tr|t��rn|�|���}||kr8|�|d���}||dx}}	||dx}}
n3|�|���\}	}
n|�|���\}	}
|dkr|n|�|n|	}|dkr|n|�|n|
}|�d||�	��\}}|dkr|nd
|dkr|nd
}}||fS)z[
        Determines package limits taking into account saved user and default ones
        r1Tr�r{r|r6r�Nr�r�)r2�IS_DArs�_get_da_real_packager�r7rV)r$r%rTr�r��u_soft�u_hard�da_real_package�da_real_quotasr8r9s           r&r�z$QuotaWrapper._combine_package_limits�sT��
�.�.�3�.�7�7�����	G�1�3�3�	G�#�7�7�C�7�@�@�O��'�)�)�!%�!9�!9�?�ae�!9�!f�!f�� .�� ?�
� N�N��v� .�� ?�
� N�N��v�v�!%�!9�!9�'�!9�!J�!J�����!�5�5�g�5�F�F�N�F�F�
 �3���v�v�T�5E�T�T�6���3���v�v�T�5E�T�T�6���;�;��$�UY�;�Z�Z�
��d�"�c�k�k�d�d�t�T�S�[�[�T�T�d�d���T�z�r'c��	|�|��\}}|�|dkr|}|�|dkr|}n!#tjtjf$rYnwxYw|�|��}|�|��}||fS)zF
        Applies saved package limits if none has been passed
        Nr�)r�rFr_r`r�rbs      r&r�z.QuotaWrapper._get_saved_package_limits_if_none�s���	�#'�#<�#<�W�#E�#E� �I�y��|�	�S� 0� 0� ���|�	�S� 0� 0� �����+�\�-G�H�	�	�	��D�	����� � ��&�&��� � ��&�&���T�z�s�,/�A
�A
c��t���t|����d}tj���|��S)z�
        Get real package name for DA user

        :param str uid: user id
        :return str: retrieved package name
        r)r�	get_namesr�clcontrollib�DirectAdmin�_get_user_package)r$rT�usernames   r&rjz!QuotaWrapper._get_da_real_package�sC���7�7�$�$�S��X�X�.�.�q�1���'�)�)�;�;�H�E�E�Er'c��|jdkr|���S|js|���|_|rB	||j|iS#t$r%|�|��t
|���wxYw|jS)z�
        Retrieves current quotas.
        If euid == 0, use data from repquota utility, else from /etc/container/cl-quotas.cache file
        r)r��_load_user_cacher��_load_current_quotasr��_check_if_quota_enabledr.r�s  r&r�z QuotaWrapper._get_current_quotas�s���
�:��?�?��(�(�*�*�*��{�	6��3�3�5�5�D�K��	/�
/��T�[��-�.�.���
/�
/�
/��,�,�S�1�1�1�)�#�.�.�.�
/�����{�s�A�/Bc��i}|r|���}n|���}|D�](}dg}	|tkr2|j�dd���d��\}}n1|j�d|���d��\}}|�|��}|�|��}|dkrd}|dkrd}|�||g��n8#tj	tj
f$r|�ddg��YnwxYw|�|�||������*|r(	|||iS#t$rt|���wxYw|S)ab
        Prepares package limits data for outputting
        (call only from get_package_limits/get_all_packages_limits - main)

        :param packname: Package name for get limits. If present, function returns
                            limits only for this package, else - all packages
        :param all_packages: If False reads only used and admin's packages, True - all packages
                                (including reseller packages without users)
        :return Dictionary of package limits:
            {package_name: {'inodes_used': 'xxx', 'inodes_soft': 'yyy', 'inodes_hard': 'zzz'}
        �-r.r�r�r�r�)r��_get_list_of_packages�VE_DEFAULT_PACKAGEr�r�r�r��extendrFr_r`�update�	_populater�r)	r$r�r��qr�r%�valuesr�r�s	         r&r�z QuotaWrapper._get_package_quotass���
���	<�#�9�9�;�;��� $�9�9�;�;��'�	6�	6�G��U�F�
*��0�0�0�"&����g�s�!;�!;�!A�!A�#�!F�!F�J�D�$�$�!%����j�'�!B�!B�!H�!H��!M�!M�J�D�$��(�(��.�.���(�(��.�.���4�<�<��D��4�<�<��D��
�
�t�T�l�+�+�+�+�� �/��1K�L�
*�
*�
*��
�
�s�C�j�)�)�)�)�)�
*����
�H�H�T�^�^�G�V�4�4�5�5�5�5��	7�
7� �!�H�+�.�.���
7�
7�
7�,�X�6�6�6�
7�����s�B?C7�72D,�+D,�	E'�'Fc
���|ttt�fd�t|jdd���������iS)Nc�0��|d�|dfS�Nr�rr,)�x�datas �r&�<lambda>z(QuotaWrapper._populate.<locals>.<lambda>=s����!��d�1�Q�4�j�/A�r'�)rBr��map�	enumerater�)r$�itemr�s  `r&r�zQuotaWrapper._populate<sH����d�4��%A�%A�%A�%A�I�d�l�[\�[]�[]�N^�D_�D_� `� `�a�a�b�b�c�cr'c�h�t|��������SrM)r�r�r�r4s r&r|z"QuotaWrapper._get_list_of_packages?s(���D�2�2�4�4�9�9�;�;�<�<�<r'c�h�t|��������SrM)r�r%r�r4s r&rHzQuotaWrapper._get_list_of_uidsBs(���D�1�1�3�3�8�8�:�:�;�;�;r'c��|js|���|_|r+	|j|S#t$rt|���wxYw|jSrM)r��_load_package_uids_datar�rr#s  r&r�z&QuotaWrapper._get_package_to_users_mapEso���(�	G�(,�(D�(D�(F�(F�D�%��	6�
6��0��9�9���
6�
6�
6�,�W�5�5�5�
6�����(�(�	�1�Ac���||jvrdS|�|��}t|���}|rt|||����|j�|��dS)Nr�)rTrUr?)r�r�rrRr�)r$rT�home_dir�quota_disabled_messages    r&ryz$QuotaWrapper._check_if_quota_enabledOst���$�*�*�*��F��&�&�s�+�+��!4�(�!C�!C�!C��!�	1�,��h�Pf�g�g�g�g��$�+�+�C�0�0�0�0�0r'c��|js|���|_|r+	|j|S#t$rt	|���wxYw|jSrM)r�r�r�r�r.r�s  r&r%z%QuotaWrapper._get_uid_to_packages_mapYso���(�	G�(,�(D�(D�(F�(F�D�%��	/�
/��0��5�5���
/�
/�
/�)�#�.�.�.�
/�����(�(r�c��	t��}n>#tttf$r$}t	dt|��z���d}~wwxYwt
t��}t
t��|_|�	��D]f\}}t|��}|d�|dnt}||�|��|j|�|���g	td���}n8#ttf$r$}t	dt|��z���d}~wwxYw|D]!}|�
|�|ntg���"|�
tg��|S)a
        Retrieve package-uids map from cpapi. Only for custom panels. See LU-610 for details.
        Null packages coming from cpapi are considered to be 'default' package.

        :return: Dictionary with data.
        Example response:
            {'default': ['1038', '1043', '1046'], 'res1_pack1': ['1044'], 'pack1': ['1042']}
        Coorresponding self._uid_to_packages_map value:
            {'1038': ['default'], '1042': ['pack1'], '1043': ['default'], '1044': ['res1_pack1'], '1046': ['default']}
        z%s. Can not get usersNr%T��	raise_exc�%s. Can not get admin packages)r�OSErrorrrrrCrr�r�r�r}r�r�
setdefault)	r$�users_packagesrF�packages_usersrT�uid_data�s_uidr%�
admin_pkgss	         r&�_get_packages_uids_from_cpapiz*QuotaWrapper._get_packages_uids_from_cpapics���	L�'�\�\�N�N���3�]�C�	L�	L�	L�'�(?�3�q�6�6�(J�K�K�K�����	L����%�T�*�*��$/��$5�$5��!�+�1�1�3�3�	=�	=�M�C����H�H�E�-5�i�-@�-L�h�y�)�)�Rd�G��7�#�*�*�5�1�1�1��%�e�,�3�3�G�<�<�<�<�	U�'�$�7�7�7�J�J���3�4�	U�	U�	U�'�(H�C�PQ�F�F�(S�T�T�T�����	U����"�	b�	b�G��%�%��1D�g�g�J\�^`�a�a�a�a��!�!�"4�b�9�9�9��s,��A�A�A�8D	�	D>�D9�9D>c��i}|jdkr|S|���sTtttt������|t<d�|tD��|_|S|���S)z�
        Gets map of packages and users
        :rtype dict
        :return Dictionary with data. Example:
            {'default': ['1038', '1043', '1046'], 'res1_pack1': ['1044'], 'pack1': ['1042']}
        rc� �i|]}|tg��Sr,)r})rc�is  r&�
<dictcomp>z8QuotaWrapper._load_package_uids_data.<locals>.<dictcomp>�s��(g�(g�(g�Q��-?�,@�(g�(g�(gr')	r�r=r�r�rCrjr}r�r�)r$r�s  r&r�z$QuotaWrapper._load_package_uids_data�s������:��?�?��O��(�(�*�*�	�+/��C��9J�9J�0K�0K�+L�+L�H�'�(�(g�(g�(�Se�Jf�(g�(g�(g�D�%��O��1�1�3�3�3r'c�f�|jr|jS	g|_td���}|D]}|j�|���n8#ttf$r$}tdt
|��z���d}~wwxYw	td���}|���D]!}|D]}|j�|����"n8#ttf$r$}tdt
|��z���d}~wwxYwt|jvr|j�t��|jS)zm
        Retrives all (root and resellers) panel package list
        :return: List of package names
        Tr�r�Nz!%s. Can not get reseller packages)
r�rr�r�rrrCrr�r})r$�list_admin_packagesr%rF�dict_resellers_packages�
packages_lists      r&r�z"QuotaWrapper._get_all_package_list�s����!�	*��)�)�	U�%'�D�"�"0�4�"@�"@�"@��.�
7�
7���&�-�-�g�6�6�6�6�
7���3�4�	U�	U�	U�'�(H�C�PQ�F�F�(S�T�T�T�����	U����	X�&8�4�&H�&H�&H�#�!8�!?�!?�!A�!A�
;�
;�
�,�;�;�G��*�1�1�'�:�:�:�:�;�
;���3�4�	X�	X�	X�'�(K�s�ST�v�v�(V�W�W�W�����	X�����T�%;�;�;��"�)�)�*<�=�=�=��%�%s0�6A�A<�A7�7A<�AC�C<�C7�7C<c	��������D]F�	tt��fd�|jdd�����}|��<�7#t$rY�CwxYw�S)zI
        Convert dict to tuples for passing to printing routines
        c�$��|��|fSrMr,)r�r�rs ��r&r�z6QuotaWrapper._convert_data_to_tuples.<locals>.<lambda>�s���a��c��1��->�r'r�N)r��tupler�r�r�)r$r��entryrs ` @r&r�z$QuotaWrapper._convert_data_to_tuples�s������9�9�;�;�	�	�C�
��c�#>�#>�#>�#>�#>���a�b�b�AQ�R�R�S�S��!��S�	�	���
�
�
���
�����s�3A�
A�Ac
���i}d}�j}tjdg}t|��}t	jdtj��}|���D�]�}|�d���r|s�|�	��}t|��dkr��|��}|ddd�}	|	dkr�o	||vr��|��}||vrn��
��|	��|��rEtt!t#�fd	�t%|d
d���������||	<��#t&t(t*f$rY��wxYw|�d��r1||�d��d����}��`d
|vrZ|�|��}
|
rC�j�tt!t#d�|
�����������|�������|S)zZ
        Gets current quota settings from repqouta utility for further processing
        Nz-unaz2(block|inode)\sgrace\stime:?\s(\d[\w:]+)(?:;|$|\s)�#�rr�r�c�:���j|d|dfS�Nrr�r)r�r$s �r&r�z3QuotaWrapper._load_current_quotas.<locals>.<lambda>�s���4�<��!��;M�q�QR�t�:T�r'r�z***z/dev�gracec�F�|d���|dfSr�)r*)r�s r&r�z3QuotaWrapper._load_current_quotas.<locals>.<lambda>�s���1������q�QR�t�@T�r')r�rurrrMrN�
IGNORECASE�
splitlinesrZr�r��#_remove_redundant_fields_from_input�_find_unknown_device�_is_home_devicer�rBr�r�r�r��
IndexErrorr.�find�strip�findallr�r�_add_default)r$r�r��devicesr�r��grace_regex_pattern�line�partsrT�founds`          r&rxz!QuotaWrapper._load_current_quotas�sJ���
�����-���$�f�-���3���� �j�)^�`b�`m�n�n���O�O�%�%�	a�	a�D����s�#�#�
a�����
�
�����u�:�:��?�?� �D�D�U�K�K�E��A�h�q�r�r�l���#�:�:����W�,�,�!%�!:�!:�6�!B�!B����(�(�T�-A�-A�$�BU�BU�VY�BZ�BZ�\b�-c�-c�(�!%�d�3�0T�0T�0T�0T�W`�af�gh�gi�gi�aj�Wk�Wk�+l�+l�&m�&m�!n�!n��#���� �*�.A�B�����H���������'�'�
a��d�i�i��/�/�0�0�1�7�7�9�9����D���+�3�3�D�9�9���a��K�&�&�t�D��6T�6T�W\�1]�1]�,^�,^�'_�'_�`�`�`��	����"�"�$�$�%�%�%��s�
BE�E4�3E4c���|dd�}tjd���|��fd�|dd�D����|S)Nr�z^\d+$c�>��g|]}��|���|��Sr,)rO)rcr�is_digit_patterns  �r&rfzDQuotaWrapper._remove_redundant_fields_from_input.<locals>.<listcomp>�s-���L�L�L�u�-=�-D�-D�U�-K�-K�L�U�L�L�Lr')rMrNr~)r$r��stripped_partsr�s   @r&r�z0QuotaWrapper._remove_redundant_fields_from_input�s`����r��r����:�h�/�/�����L�L�L�L��a�b�b�	�L�L�L�	N�	N�	N��r'c���t|j��dkr5|j�d�tj��D����	|j|S#t
$rt
|���wxYw)Nrc�B�i|]}t|j��|j��Sr,)rCrbra)rcr�s  r&r�z/QuotaWrapper._fetch_homedir.<locals>.<dictcomp>�s'��,i�,i�,i�QV�S���->�->���,i�,i�,ir')r�r�r�pwd�getpwallr�r.r�s  r&r�zQuotaWrapper._fetch_homedir�s����t�'�(�(�A�-�-��$�+�+�,i�,i�Z]�Zf�Zh�Zh�,i�,i�,i�j�j�j�	+��+�C�0�0���	+�	+�	+�%�c�*�*�*�	+���s�A�A6c��i}ttj��}tjd��}|D]�}|�d��r�|�|��}|d}d|di}|D]~}|�d��s|�d��r|�d��d|d	<�K|�d
��r|�d��d|d<�||vr||�|����|g||<��|���t|��dkrt���|S)aj
        Gets mounted filesystems list and picks ones with quota on

        Example of returned data structure:
            {'/dev/mapper/VolGroup-lv_root': [
                {'mountpoint': '/', 'quota_file': 'quota.user', 'quota_type': 'vfsv0'},
                {'mountpoint': '/var', 'quota_file': 'quota.user', 'quota_type': 'vfsv0'}
                ],
            '/dev/mapper/VolGroup-lv_root2': [
                {'mountpoint': '/', 'quota_file': 'quota.user', 'quota_type': 'vfsv0'},
                {'mountpoint': '/var', 'quota_file': 'quota.user', 'quota_type': 'vfsv0'}
            ]
            }
        z |,zrootfs /r�
mountpointr�z	usrquota=zusruota=�=�
quota_filezjqfmt=�
quota_type)�openrur~rMrNrZr�r�r�r�rO)	r$r��proc_mounts_stream�
split_pattr��line_splitedr��mountpoint_data�line_splited_elements	         r&r�z QuotaWrapper._load_quota_devices�sy����!�,�":�;�;���Z��'�'�
�&�	4�	4�D����z�*�*�
��%�+�+�D�1�1�L�!�!�_�F�+�l�1�o�>�O�(4�
W�
W�$�'�2�2�;�?�?�W�CW�Cb�Cb�cm�Cn�Cn�W�4H�4N�4N�s�4S�4S�TU�4V�O�L�1�1�)�4�4�X�>�>�W�4H�4N�4N�s�4S�4S�TU�4V�O�L�1���� � ����&�&��7�7�7�7�#2�"3������ � �"�"�"��w�<�<�1���(�*�*�*��r'c�>���i}	����ttj��}t	j|d���}n_#ttf$rKt�j	��t��jd��icY��
��SwxYw	��
��n#��
��wxYwt�j	��}|D]x��d|krj|��dttt!��fd�t#t%�j����������i��n�y|s4t�j	��t��jd��iS|S)zJ
        For non-privileged user we outputting data from the file
        �,)�	delimiterr�rc�4���j|�|dzfS)Nr�r)r��rowr$s ��r&r�z/QuotaWrapper._load_user_cache.<locals>.<lambda>4s�����Q�� #�A�a�C�� *�r')rr�rurr�readerr��IOErrorrCr�rB�fromkeysr�rrr�r��ranger�)r$r��fo�cvs_inrTr�s`    @r&rwzQuotaWrapper._load_user_cache!s�����
��		!��!�!�#�#�#��l�,�-�-�B��Z��c�2�2�2�F�F����!�	G�	G�	G���
�O�O�T�]�]�4�<��%E�%E�F�F�F���� � � � �	G����
�
��� � � � ��D��� � � � �����$�*�o�o���	�	�C��1�v��}�}����#�a�&�$�t�C�*�*�*�*�*��#�d�l�+�+�,�,�-.�-.�(/�(/�#0�#0�1�2�2�2�����	G���
�O�O�T�]�]�4�<��%E�%E�F�F��s+�AA
�	B?�
AB&�B?�%B&�&B?�?Cc��d�}g}|���D])\}}|D]!}|d}|�||f���"�*|�|d���|S)z�
        return list tuple ('mountpoin tpath', 'device') reverse sorted by deep mountpoint path
        [('/mountpoint_path/path', '/device'), ('/mountpoint_path', '/device')]
        c�Z�|ddkrd}n|d�d��}|S)NrrY)�count)�device_mountpoint�	deep_paths  r&�sort_by_deep_pathzBQuotaWrapper._get_mountpoint_device_map.<locals>.sort_by_deep_pathBs7�� ��#�s�*�*��	�	�-�a�0�6�6�s�;�;�	��r'r�T)r�reverse)r�r��sort)r$r�r��mountpoint_device_mapr��mountpoint_data_listr��mountpoint_paths        r&r�z'QuotaWrapper._get_mountpoint_device_map=s���
	�	�	�!#��,3�M�M�O�O�	H�	H�(�F�(�#7�
H�
H��"1�,�"?��%�,�,�o�v�-F�G�G�G�G�
H�	�"�"�'8�$�"�G�G�G�$�$r'c��d�}|tj�|����}|jD]'\}}|�||����r|cS�(dS)z3
        Returns device user homedir is on
        c�,�|r|ddkr|dz
}|S)NrXrYr,r�s r&�
_add_slashz1QuotaWrapper._get_home_device.<locals>._add_slashTs$���
��R��C��������Kr'N)r�r[�dirnamer�rZ)r$�homer�r��mounpoint_pathr�s      r&r�zQuotaWrapper._get_home_devicePs��	�	�	��*�R�W�_�_�T�2�2�3�3��&*�&D�	�	�"�N�F��!�!�*�*�^�"<�"<�=�=�
��
�
�
�
�	�	r'c�4�|�|��|kS)z;
        Checks if a device is user homedir device
        )r�)r$r�r�s   r&r�zQuotaWrapper._is_home_device]s���$�$�T�*�*�f�4�4r'c��	tj|��t}tj|��tj|��f}|j���D]Q}tj|��t}|tj|��tj|��fkr|cS�RdS#t$r|cYSwxYwrM)r��statr�major�minorr�r�r�)r$r��dev�dev_to_find�current_devices     r&r�z!QuotaWrapper._find_unknown_devicecs���	��'�&�/�/�&�)�C��8�C�=�=�"�(�3�-�-�8�K�"&�-�"4�"4�"6�"6�
*�
*���g�n�-�-�f�5���2�8�C�=�=�"�(�3�-�-�"@�@�@�)�)�)�)�A�
*�
*���	�	�	��M�M�M�	���s�B0B6�3B6�6C�Cc���gd��	|j�dd���d��\}}|dkrd}|dkrd}��||g��n8#tjtjf$r��ddg��YnwxYwdttt�fd�t|j��������iS)zw
        Insert 'default' quota.
        Calls only from _load_current_quotas, after parsing repquota's output
        )r{r�r�r{r.r�r�r�c�0��|d�|dfSr�r,)r�r�s �r&r�z+QuotaWrapper._add_default.<locals>.<lambda>~s���q��t�V�A�a�D�\�.B�r')r�r�r�r~rFr_r`rBr�r�r�r�)r$r[r\r�s   @r&r�zQuotaWrapper._add_defaultns����
&�%�%��		&�#'�8�<�<���#=�#=�#C�#C�C�#H�#H� �I�y��D� � ��	��D� � ��	��M�M�9�i�0�1�1�1�1���+�\�-G�H�	&�	&�	&��M�M�3��*�%�%�%�%�%�	&�����T�$�s�$B�$B�$B�$B�Y�t�|�E\�E\�]�]�^�^�_�_�`�`s�AA � 2B�Bc�l�|�d}|�d}|dkr<|dkr6|j�d��r|j�d|��nU|j�d��s|j�d��|j�d||�d|����|���dS)z#
        Saves user limits
        Nr�r.r�)r�r�r��add_section�setr�)r$rTr�r�s    r&r�zQuotaWrapper._save_user_limits�s����<��D��<��D��3�;�;�4�3�;�;�4�8�+?�+?��+H�+H�;��H�"�"�7�C�0�0�0�0��8�'�'��0�0�
.���$�$�W�-�-�-��H�L�L��#�$�$�$���'=�>�>�>��������r'c��|�d}|�d}|dkr<|dkr6|j�d��r|j�d|��nU|j�d��s|j�d��|j�d||�d|����|���|�|��dS)z&
        Saves package limits
        Nr�r�r�)r�r�r�r�r�r��_copy_package_limits_to_cpanelrfs    r&r�z!QuotaWrapper._save_package_limits�s����<��D��<��D��3�;�;�4�3�;�;�4�8�+?�+?�
�+K�+K�;��H�"�"�:�w�7�7�7�7��8�'�'�
�3�3�
1���$�$�Z�0�0�0��H�L�L��W����t�t�.D�E�E�E��������+�+�G�4�4�4�4�4r'c�|�tj��sdSd|��}t|��}t|��dkrdS|�|��\}}|�|�dS|�|d���|}|���D]\}}|dkrd||<�|�dd	��|�d
d	��f}	|d|d
f}
|	|
krdSdD]E}dt|��zd
zt||��zdz}|�	|���Ft||d��dS)zV
        Copy package quota limits from cl-quotas.dat to cpanel packages data
        Nz/var/cpanel/packages/rTr�r{r�r{r�r|�r{r|�lve_r�r��w)ro�	is_cpanelrr��_parse_cpanel_package_datar�r�r�rCr�r)
r$r%�package_path�cpanel_package_lines�old_cpanel_data�modified_cpanel_lines�quotas_datar�value�old_cpanel_limits�current_quota_limits�
limit_type�limit_strings
             r&rz+QuotaWrapper._copy_package_limits_to_cpanel�s����$�&�&�	��F�8�w�8�8��-�l�;�;���#�$�$��)�)��F�15�1P�1P�Qe�1f�1f�.��.��"�'<�'D��F��.�.�w�T�.�J�J�7�S��&�+�+�-�-�	(�	(�J�C����|�|�#'��C� ��,�0�0���D�D�o�FY�FY�Zg�il�Fm�Fm�n�� +�M� :�K�
�<V�W��� 4�4�4��F�8�	7�	7�J�!�C�
�O�O�3�c�9�C��J�@W�<X�<X�X�[_�_�L�!�(�(��6�6�6�6���'<�c�B�B�B�B�Br'c��|dd�}i}|D]�}|�d��r�|����d��}|d�dd�����}|ddkr|d||<|dvr|�|��|�d	��rd
|vrdS��||fS)z�
        Process cpanel_package_lines - get values of all old lve_ limits
        and remove lines with limits that would be changed
        Nrr�rr�r��DEFAULTr�_PACKAGE_EXTENSIONS�lve�NN)rZr�r��replace�remove)r	�cpanel_package_lines_modifiedr
r��
line_parts�
limit_names      r&rz'QuotaWrapper._parse_cpanel_package_data�s���)=�Q�Q�Q�(?�%���(�		"�		"�D����v�&�&�
?�!�Z�Z�\�\�/�/��4�4�
�'��]�2�2�6�2�>�>�D�D�F�F�
��a�=�I�-�-�2<�Q�-�O�J�/��!?�?�?�1�8�8��>�>�>����4�5�5�
"�%�t�:K�:K�!�z�z��� =�=�=r'c�T�|dkr8|dkr2	|j�||��nj#tj$rYnYwxYw|j�|��s|j�|��|j�|||�d|����|���dS)z&
        Saves data to a file
        r�r�N)r�r�rFr_r�r�r�r�)r$r�r�r��	item_types     r&�
_save_datazQuotaWrapper._save_data�s����3�;�;�4�3�;�;�
���&�&�y�$�7�7�7�7���.�
�
�
���
�����8�'�'�	�2�2�
0���$�$�Y�/�/�/��H�L�L��D�T�T�T�4�4�*@�A�A�A��������s�*�<�<c�^�tj�|��}	tjd|���\}}tj|d��}||_|S#ttf$rCtj�	|��rtj
|��td���wxYw)zH
        Open temporary file for writing and return file object
        �lvetmp_)�prefix�dirrzCould not save data)r�r[r��tempfile�mkstemp�fdopen�_tmpr�r�r��unlinkrK)r$�filepathr[�fd�	temp_pathr s      r&rzQuotaWrapper._prepare_writer�s����w���x�(�(��	:�$�,�I�4�H�H�H�M�B�	��9�R��-�-�L�!�D�I������!�	:�	:�	:��w�~�~�i�(�(�
%��	�)�$�$�$�"�#8�9�9�9�	:���s�6A�AB,c���	ttztztz}t	j|j|��t	j||��dS#t$rYdSwxYw)z0
        Routines after writing to file
        N)	rrrrr��renamer&�chmodr�)r$r[�masks   r&rzQuotaWrapper._end_writer�si��	��W�$�w�.��8�D��I�d�i��&�&�&��H�T�4� � � � � ���	�	�	��D�D�	���s�AA�
A �A c��|�d��|�tj��}|j�|��|�tj��|���dS)z7
        Actual place of saving data to a file
        TN)rrrurDr��writerr)r$r s  r&r�zQuotaWrapper._write_data�sq��	
���d�#�#�#��+�+�L�,A�B�B������|�$�$�$�����.�/�/�/��������r'c��|rdt_tj��	ttjd��t_n$#t
tf$rtd���wxYw	tj	tj�
��tj��dS#t
$rtd���wxYwdS)NT�rz Can't open lock file for readingzCan't get lock)ru�
LOCK_WRITEr�r��	LOCK_FILEr�r�rK�fcntl�flock�fileno�LOCK_EX)r$r0s  r&rzQuotaWrapper._get_global_lock
s����	+�&*�L�#���'�
K�'+�L�,B�C�'H�'H��$�$���W�%�
K�
K�
K�&�'I�J�J�J�
K����
9���L�0�7�7�9�9�5�=�I�I�I�I�I���
9�
9�
9�&�'7�8�8�8�
9����(�'s�$A�!A"�&;B#�#B=c��tjs8tj�.tj���dt_dSdSdSrM)rur3r�r�r4s r&rzQuotaWrapper._release_locksH���'�	(�l�.B�.N�� �&�&�(�(�(�#'�L� � � �	(�	(�.N�.Nr'rM)F)NNTFF)NNTF)Tr)NF)[r)r*r+rEr~r+r�r�GETPACKSrDrr�r4r3r"�staticmethodr}r�r�r�r�r�r�r�r�r�rCr�boolr�rr
r"r�r�r�r	r�rr�r�r=r�rFr�r�r�r�rTrVr2rUr7r�r�r�rjr�r�r�r|rHr�ryr%r	r
r�r�r�r�rxr�r�r�rwr�r�r�r�r�r�r�rrrrrr�rrr,r'r&ruru�sw��������!�K�%�I�$�H�$�H�7�H�.�H�0�I��G��7�"�I��J�&�&�&�,�A�A��\�A����!�!�!�K�K�K�H�H�H�X�X�X�k�k�k�k�
(�
(�
(�<�<�<� #� #� #� #�J#'�"&��$�$�E%�E%��E%��3�-�E%��3�-�	E%�
�E%��
E%��E%�E%�E%�E%�T#'�"&��$�
G'�G'��G'��3�-�G'��3�-�	G'�
�G'��
G'�
�G'�G'�G'�G'�R#�#�#����,#�#�4�#�#�#�#� � � ����d�
�����$	�	�	���� %�,�,��,�%�S�M�,�%�S�M�	,�
�,�
�x��}�h�s�m�+�	,�
,�,�,�,�0���08��
��OW�X[�}��af�gj�lo�go�ap�����#�#�#�4�4�4���)B����� %�%�%�(&�(�3�-�&�H�S�M�&�&�&�&�����8�C�=��x�X[�}��hm�nq�sv�nv�hw�����@��#��X�c�]��Ya�be�Yf��rw�x{�~A�yA�sB�����$�S����3��SX�Y\�^a�Ya�Sb�����"$�C�$�E�#�s�(�O�$�$�$�$��C��s��RU��Z_�`c�eh�`h�Zi������3��5��c��?�������x��}��H�S�M��e�T\�]`�Ta�ck�lo�cp�Tp�Nq�����\�����%(��08��
��EM�c�]��W\�]`�be�]e�Wf�����>���� F��F��F�F�F�F�����$,�,�,�,�\d�d�d�=�=�=�<�<�<�)�)�)�)�1�1�1�)�)�)�)�)�t�C��c��N�/C�)�)�)�)�V4��c�4��9�n�)=�4�4�4�4�$&�&�&�6
�
�
�"�"�"�H���+�+�+�%�%�%�N���8%�T�%��S��/�5J�%�%�%�%�&���5�5�5�	�	�	�a�a�a�$���$5�5�5�$C�C�C�:�>�>��\�>�&
�
�
�
:�
:�
:�	�	�	����9�9�9�9�(�(�(�(�(r'ru)>�configparserrFrr5r�r�rMr#�collectionsrr�rrrrr�typingr	r
rrrrro�clcommonr
�clcommon.clpwdr�clcommon.clquotar�clcommon.cpapirrr�clcommon.cpapi.cpapiexceptionsrr�clcommon.utilsrrrrr�detect�is_dari�DEFAULT_PACKAGEr}r!rr.r2r6r;rKrOrRr^rjr<rs�objectrur,r'r&�<module>rJs}��$�#�#�#�
�
�
�
�����	�	�	�	�
�
�
�
�	�	�	�	�����#�#�#�#�#�#�;�;�;�;�;�;�;�;�;�;�;�;�;�;�.�.�.�.�.�.�.�.�.�.�.�.���������'�'�'�'�'�'� � � � � � �0�0�0�0�0�0�I�I�I�I�I�I�I�I�I�I�T�T�T�T�T�T�T�T���������������	��!�!�#�#����!��F�F�F�F�F�Y�F�F�F�
@�@�@�@�@�)�@�@�@�
<�<�<�<�<�i�<�<�<�
J�J�J�J�J�I�J�J�J�
�����1����$*�*�*�*�*�y�*�*�*�
_�_�_�_�_�Y�_�_�_�
*�*�*�*�*�!7�*�*�*����"	�	�	��d�����L(�L(�L(�L(�L(�6�L(�L(�L(�L(�L(r'