9e<,ddlZddlZddlZddlZddlZddlZddlZddlm Z ddl m Z ddl m Z mZmZmZmZddlZddlZddlmZddlmZddlmZddlmZmZmZdd lmZm Z dd l!m"Z"m#Z#m$Z$m%Z%ej&'Z(d Z)Gd d e*Z+Gdde*Z,Gdde*Z-Gdde*Z.GddeZ/Gdde*Z0Gdde*Z1Gdde1Z2dZ3dZ4de5fdZ6Gd d!e7Z8dS)"N)map) defaultdict)S_IRGRPS_IROTHS_IRUSRS_IWUSRST_DEV)FormattedException)ClPwd)check_quota_enabled)admin_packages list_usersresellers_packages)CPAPIExternalProgramFailed EncodingError)ExternalProgramFailedget_file_lines run_commandwrite_file_linesdefaultceZdZdZdS)NoSuchPackageExceptioncDt|d|ddS)NzNo such package () Exception__init__selfpackages G/opt/cloudlinux/venv/lib64/python3.11/site-packages/clquota/__init__.pyrzNoSuchPackageException.__init__$s'44777!DEEEEEN__name__ __module__ __qualname__rr"r!rr#s(FFFFFr"rceZdZdZdS)NoSuchUserExceptioncDt|d|ddS)NzNo such user (rr)rusers r!rzNoSuchUserException.__init__)s'44!>?????r"Nr#r'r"r!r)r)(s(@@@@@r"r)ceZdZdZdS)InsufficientPrivilegesExceptionc<t|ddS)NzInsufficient privilegesrrs r!rz(InsufficientPrivilegesException.__init__.s4!:;;;;;r"Nr#r'r"r!r-r--s#<<<<>> _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_pathrYbsf Bx3  gI s{{t ??5 ! ! 44 r"cht}|fdD}|S)z) Return no system users uid list c^g|])}t|j|j*Sr')rYpw_dirpw_uid).0usrpw_dicts r! z#_get_users_list..zs5aaa|GTWLL_?`?`a$aaar")r get_user_dict)cl_pwd users_uidr`s @r!_get_users_listress> WWF""$$GaaaaaaaI r"returncHtjtjdd}|S)zJ Check `cl_quota_inodes_inheritance` parameter in the config file cl_quota_inodes_inheritanceF) default_val) cldetectlibget_boolean_paramCL_CONFIG_FILE)ress r!is_quota_inheritance_enabledrns%  ' (BDaot u u uC Jr"ceZdZdZdZdZdZdZdZdZ dZ ed zZ d Z d Z ed Zd ZdZdZdZdZdHdZdZdIdZ dJdZdKdZdZdZdZdZdZdZdZ edZ!dLd Z"dLd!Z#dLd"Z$dLd#Z%dLd$Z&dLd%Z'dLd&Z(dLd'Z)dHd(Z*dMd)Z+d*Z,d+Z-d,Z.dHd-Z/d.Z0dHd/Z1d0Z2d1Z3d2Z4d3Z5d4Z6d5Z7d6Z8d7Z9d8Z:d9Z;d:Zd=Z?d>Z@d?ZAd@ZBedAZCdBZDdCZEdDZFdEZGdIdFZHdGZIdS)N QuotaWrapperz4 Base quota class for inode quotas handling z /proc/mountsz/usr/sbin/setquotaz/usr/sbin/repquotaz%/usr/bin/getcontrolpaneluserspackagesz/etc/container/cl-quotas.datz/etc/container/cl-quotas.cacheNz.lockFcH|tj|tj|tjt |_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_existsrp PROC_MOUNTSREPQUOTASETQUOTAlist_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_fieldsosgeteuid_euid_load_quota_devices_devices_get_mountpoint_device_map_mountpoint_device_mapped_device_user_map_all_package_listr/s r!rzQuotaWrapper.__init__s   !9:::   !6777   !6777#'66 "  $&!$&!#% //11nnn Z\\ 0022 )-)H)H)W)W& $!%r"cjtj|std|ddS)z> Checks if command is present and exits if no zNo such command (rN)rrVexists RuntimeErrorrVs r!rxz QuotaWrapper._assert_file_existss> w~~d## A,?@@ @ A Ar"c|SrHr'r/s r! __enter__zQuotaWrapper.__enter__s r"c8|jdSrH)LOCK_FDclose)rtypevalue tracebacks r!__exit__zQuotaWrapper.__exit__s r"cR|||S)z9 Returns user limits converted to tuples _convert_data_to_tuples_get_current_quotasrrOs r!get_user_limitszQuotaWrapper.get_user_limitss&++D,D,DS,I,IJJJr"cP||S)z= Returns all user limits converted to tuples rr/s r!get_all_users_limitsz!QuotaWrapper.get_all_users_limitss$++D,D,D,F,FGGGr"cT|||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) )packnamer_get_package_quotasrs r!get_package_limitszQuotaWrapper.get_package_limitss) ++D,D,Dg,D,V,VWWWr"cV|||dS)zY Returns all packages limits converted to tuples (called only from main) T)r all_packagesrrs r!get_all_packages_limitsz$QuotaWrapper.get_all_packages_limitss,++D,D,Dgdh,D,i,ijjjr"cH|dkrdS|dvrdS||S)z Preprocessed passed limit: 'default' --> '0', 'unlimited' --> -1, else calls _check_limit :param limit: :return: r0) unlimited-1r) _check_limitr3s r!_preprocess_limitzQuotaWrapper._preprocess_limits9 I  3 ' ' '4  '''r"ci}i}|jdrt|jddkr|}|jdD]y}|r ||vr|jd|$|jd|d}t|dkrf|d|df||<z|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) } packagesr:rr) r has_sectionlenitems_get_all_package_listoptions remove_optiongetsplit _write_data_get_package_to_users_maprkeys)rclean_dead_packagespackage_limits_dict db_packageslist_of_packagesr package_limitss r!_get_all_packages_with_limitsz*QuotaWrapper._get_all_packages_with_limitssz! 8   + + #DHNN:4N4N0O0ORS0S0S#99;; 8++J77 L L&7:J+J+JH**:w???!%j'!B!B!H!H!M!M~&&!++'5a'8.:K'K G$$" #  """ &&(((05577 : :G+%%/:7/C#G,,/9#G,,""r"Tc |s||dS||}|} ||}|| }|dkr$|dkrd}|dkrd}|jdr^|jddrC|jddd} |p| d} |p| d} n|pd} |pd} || | |r.|d vrd}n|| }| d vrd}n|| }|d|| | } | D]4}| |\}}|dks|dkr| |||||| 5dS|r| ||| \}}nd \}}||}}|dks|dkrd}|dks|dkrd}| |}||}|d |ks|d|ks|r7| |d}|tkr|jdrZ|jd|r?|jd|d} | d} | d} nd} d} |p| }|p| }n|}|}tjd||d|d|||||g}t'||r5|dkrd}n|dvr|}|dkrd}n|dvr|}|||||dkr|dks |dkr|dkr||||dSdSdS)z= Sets limits for users :return: None Nrrusersrrr)softhard)rrrOrr only_storerrwrvz-ursrt)rr) _check_adminrrr has_optionrr_apply_to_all_if_not_set_save_user_limitsrset_package_limit_combine_user_limitsr_get_uid_to_packages_mapDEFAULT_PACKAGErpr{_get_home_device_fetch_homedirr)rrOrrsavesync force_saversoft_arghard_arglimits cache_soft cache_hardrr p_softp_harduser_combine_softuser_combine_hard user_soft user_hard saved_quotascached user_package soft_limit hard_limitcmds r!set_user_limitzQuotaWrapper.set_user_limitsh  F %%h//%%h// #::t||t||x##G,, )1D1DWc1R1R )gs3399#>>!.VAY !.VAY ![S ![S  ) )z ) K K K F222DD\%D222DD\%D&&3T&EEE#'"D"D"F"F . g g!4W!=S==FcMM**7FFD$[e*fff F  <373L3LQT[_fj3L3k3k 0 003; 0 002C9 4<<,44I 4<<,44I//44 c" - I - - 1F)1S1SWa1S88==a@L..8''00%TX5H5HRU5V5V%!X\\'377==cBBF!'J!'JJ"%J!$J&4* &4* ' & %c|$|$%%d&9&9#&>&>??C     D$,,!%JJ{**%) $,,!%JJ{**%) &&sJ CCC CKKDCKKTT\\ddll  " "3d 3 3 3 3 3.:\llr"c t}|tkrdS|s||dS|||}||}g}|r||||\}}|rG||dvr/||vr||||dS ||n#t$r|rYdSYnwxYw| } | } | D]} ||D]k} | | | vr| t| d} trntr`t!j}|| }||kr2||d}||d}||d}|| ||}|s|dkrd }n |dpd }|dkrd }n |d pd } || | d| | df||fs;|| d | | d d | | d d |d | \#t,$rYiwxYwt/|dkrd|dz}|r,| |jvr d|j| <|j| |z|j| <n t4jd| g}t9||g}|r||||dSdS)z? Sets limits for package :rtype : None NTrrrvrwrrrr rsrt -bustd_in)r rrr!_get_saved_package_limits_if_nonerr_save_package_limitsr_get_device_user_maprr get_namesintIS_DArn clcontrollib DirectAdmin_get_user_package_combine_package_limitslimits_are_equalappendKeyErrorrjoinrrpr{r)rr rrrrrclpwdrdevice_user_maprdevicerO_userpanel _real_package _real_quotasdatarrrs r!rzQuotaWrapper.set_package_limitvs  o % % F  F %%d++%%d++  U??tTTJD$  Gt77T7JJJJt==????  % %gtT : : : F   * *7 3 3 3 3%       3355//11 %**,,- - F55g>>! ! of555C11!4J9;;J(466E%*$;$;E$B$BM$//'+'?'? t'T'T +M:=I+M:=I33$T3RR4< ? ? ? ? ? @ @s$AD;D%EEc |g}|ttt D]?|gttfd|jz@| d| tj }tj|tj}|||tj |dS)zF Caches the limits to non-privileged user to see them )keyc |SrHr')xcurrent_quotasks r!z.QuotaWrapper.save_user_cache..s>!;LQ;Or"T)quotingN)rrsortedr|rrrrr_get_global_lock_prepare_writerrp CACHEFILEcsvwriter QUOTE_MINIMAL writerows _end_writer _release_lock)r cache_content file_handlercsv_outrrs @@r!save_user_cachezQuotaWrapper.save_user_caches%  1133^002233=== b bA  !tC1O1O1O1O1ORVR^,_,_'`'`!` a a a a d###++L,BCC *\33DEEE-((( /000 r"cv|j,dtddgk|_|jS)z6 Return True if control panel present NUnknownz/usr/bin/cldetectz--detect-cp-nameonly)r~rrstripr/s r!_check_present_panelz!QuotaWrapper._check_present_panels>   &"+{ optionxformreadrpDATAFILErBr6r")rdhes r!rz$QuotaWrapper._get_saved_data_handlers d###  &T% H H H ! GGL) * * * *( . . .*1-- - . +    D    s)ABA<(A77A<<BB+c|j|jSi}g}|D]P} |||||fA#t $rYMwxYw|D]>}|d|vr g||d<||d|d?||_|jS)zF Returns dictionary mapping devices to lists of users Nrr)r_get_list_of_uidsrrrr)r devices_mapdevice_user_pairsrOpairs r!rz!QuotaWrapper._get_device_user_maps  ,( ( ))++  C !(($*?*?@S@STW@X@X*Y*Y[^)_````    % 1 1DAwk))') DG$ Q ' 'Q 0 0 0 0 +$$s=A(( A54A5c||dkr|Stjd}||}|st||dS)Nrz(\d+)r)recompilesearchr1group)rr4 limit_pattern pattern_matchs r!rzQuotaWrapper._check_limit+s` =ETMML 8,, %,,U33  7/66 6""1%%%r"c||krdSdS)z Compare tuples :param limits1: tuple :param limits2: tuple :return: True of tuple 1 equal to tuple 2 TFr')limits1limits2s r!rzQuotaWrapper.limits_are_equal4s g  4ur"cg}|}|}|D]%}tjd|g}|D]}|||vst ||vr)||||} | sD| ||d||df| sK| |d||dd||dd| dpd d| d pd  t|dkrd |d z}t|| g}'d S)zr Applies limits to all users if no other (user or package) ones has not been set for them rrrvrwrrsrtrrrrrN)rrrrpr{r5rr_combine_default_limitsrrrrr) rrrrrrr rrOrs r!rz%QuotaWrapper._apply_to_all_if_not_set@s 3355//11 %**,,  F(%8C--// ) )of555PTPmPmnqPrPr9r9r33$T3RR,,l3.? .NP\]`PaboPp-qswxx)MM$S),777$S),777Q3Q3 #())) 6{{aii''$.F F + + + +FF)  r"c||||\}}d\}}||D]}||||\}}|d||\} } | d} | d} | | fS)zc Determines user limits taking into account saved package and default ones rNN)r rrr)_get_saved_user_limits_if_noner*_get_saved_package_limits_if_none_or_unlim'_get_saved_user_limits_if_none_or_unlim) rrOrru_softu_hardrrr d_softd_hards r!rz!QuotaWrapper._combine_user_limits^s <<4VZ<[[#44S99 x xG!LLU\cipvLwwNFFFEE#TZagEhh >F >Fv~r"c||\}}|r|rdS||}||}|d||S)zc Determines package limits taking into account saved user and default ones rOr'Nrr)rGrIrrOrrt_softt_hards r!rz$QuotaWrapper._combine_package_limitspsb <<<EE  f 2 >F >F;;&W];^^^r"cl||\}}||}||}|dkrd}|dkrd}||fS)z Determines default limits taking into account saved user and package ones :param soft: soft limit from uid=0 :param hard: hard limit from uid=0 rONrr)rGrPs r!rDz$QuotaWrapper._combine_default_limitssZ<<<EE  D  D 4<<D 4<<DTzr"c. |jd|d\}}||dkr|}||dkr|}n!#tjtjf$rYnwxYw||}||}||fS)z? Retrives saved user limits if none has passed rrNrrrrrANoSectionError NoOptionErrorrrrOrrrrs r!rGz+QuotaWrapper._get_saved_user_limits_if_nones #'8<<#=#=#C#CC#H#H Iy| S 0 0 | S 0 0 +\-GH    D   &&  &&TzsAAA&%A&cf |jd|d\}}|dkrd}|dkrd}||dkr|dkr|}||dkr|dkr|}n!#tjtjf$rYnwxYw||}||}||fS)zN Applies saved user limits if none or unlimit has been passed rrrrrUrXs r!rIz4QuotaWrapper._get_saved_user_limits_if_none_or_unlims #'8<<#=#=#C#CC#H#H IyD   D     c1A1A   c1A1A +\-GH    D   &&  &&TzsA!A$$BBcD|tkrh |jd|d\}}||dkr|}||dkr|}n!#tjtjf$rYnwxYw||}||}||fS)zA Applies saved package limits if none has passed rrNrrrrrrArVrWrrr rr pack_soft pack_hards r!rz.QuotaWrapper._get_saved_package_limits_if_nones o % % '+x||J'H'H'N'Ns'S'S$ 9.s!d1Q4j/Ar")r=r|r enumerater)ritemrs `r!rizQuotaWrapper._populatesHd4%A%A%A%AIdl[\[][]N^D_D_ ` `aabbccr"cht|SrH)r|rrr/s r!rfz"QuotaWrapper._get_list_of_packagess(D224499;;<<#tttf$r$}t dt |zd}~wwxYwt t}t t|_| D]f\}}t |}|d|dnt}|| ||j| |g td}n8#ttf$r$}t dt |zd}~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)rOSErrorrrrr>rr|rrrrr setdefault) rusers_packagesr3packages_usersrOuid_datas_uidr admin_pkgss r!_get_packages_uids_from_cpapiz*QuotaWrapper._get_packages_uids_from_cpapiAs L'\\NN3]C L L L'(?3q66(JKK K L%T**$/$5$5!+1133 = =MCHHE-5i-@-Lhy))RaG 7 # * *5 1 1 1  %e , 3 3G < < < < U'$777JJ34 U U U'(HCPQFF(STT T U" _ _G  % %1Dgg/[] ^ ^ ^ ^!!/2666s,A AA 8D D>D99D>c2i}|jdkr|S|satttt |t <td|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']} rc3(K|] }|tfVdSrH)r)r^is r! z7QuotaWrapper._load_package_uids_data..zs',e,eaa-A,e,e,e,e,e,er") rr*r|rr>rerr=rr)rrs r!ruz$QuotaWrapper._load_package_uids_datals :??O((** (,So6G6G-H-H(I(IH_ %(,,e,e8TcKd,e,e,e(e(eD %O11333r"cf|jr|jS g|_td}|D]}|j|n8#ttf$r$}t dt |zd}~wwxYw td}|D]!}|D]}|j|"n8#ttf$r$}t dt |zd}~wwxYwt|jvr|jt|jS)zm Retrives all (root and resellers) panel package list :return: List of package names Tr|r~Nz!%s. Can not get reseller packages) rr rrrrr>rrkr)rlist_admin_packagesr r3dict_resellers_packages packages_lists r!rz"QuotaWrapper._get_all_package_lists  ! *) ) U%'D ""04"@"@"@ . 7 7&--g6666 734 U U U'(HCPQFF(STT T U X&84&H&H&H #!8!?!?!A!A ; ; ,;;G*11'::::; ;34 X X X'(KsSTvv(VWW W X $"8 8 8  " ) )/ : : :%%s06AA<A77A<ACC<C77C<c D]F ttfd|jdd}|<7#t$rYCwxYwS)zI Convert dict to tuples for passing to printing routines c$||fSrHr')rrrs r!rz6QuotaWrapper._convert_data_to_tuples..sac1->r"roN)rtuplerrr)rrentryrs ` @r!rz$QuotaWrapper._convert_data_to_tupless99;;  C c#>#>#>#>#>L$&&''!S      s3A AAc i}d}j}tjdg}t|}t jdtj}|D]}|dr|s| }t|dkr |}|ddd} | dkro ||vr |}||vrn | |rEtt!t#fd t%|d d|| <#t&t(t*f$rYwxYw|d r1||d d}`d |vrZ||} | rCjtt!t#d| ||S)zZ Gets current quota settings from repqouta utility for further processing Nz-unaz2(block|inode)\sgrace\stime:?\s(\d[\w:]+)(?:;|$|\s)#rrrc:j|d|dfSNrrr)rrs r!rz3QuotaWrapper._load_current_quotas..s4<!;MqQRt:Tr"rz***z/devgracecF|d|dfSr)lower)rs r!rz3QuotaWrapper._load_current_quotas..s1qQRt@Tr")rrprzrr:r; IGNORECASE splitlinesrUrr#_remove_redundant_fields_from_input_find_unknown_device_is_home_devicerr=r|rrpr IndexErrorr)findstripfindallrrh _add_default) rrjr devicesrrgrace_regex_patternlinepartsrOfounds ` r!rbz!QuotaWrapper._load_current_quotassJ -$f-3 j)^`b`mnnOO%% a aDs## a u::?? DDUKKEAhqrrl#::W,,!%!:!:6!B!B((T-A-A$BUBUVYBZBZ\b-c-c(!%d30T0T0T0TW`afghgigiajWkWk+l+l&m&m!n!n# *.ABH'' adii//0017799D+33D99aK&&tD6T6TW\1]1],^,^'_'_``` ""$$%%%s B EE43E4c|dd}tjd|fd|ddD|S)Nrz^\d+$c>g|]}||Sr')r<)r^fieldis_digit_patterns r!razDQuotaWrapper._remove_redundant_fields_from_input..s- L L Lu-=-D-DU-K-K LU L L Lr")r:r;rg)rrstripped_partsrs @r!rz0QuotaWrapper._remove_redundant_fields_from_inputs`rrH-- L L L Labb L L L N N Nr"c t|jdkrB|jtdt jD |j|S#t $rt|wxYw)Nrc3LK|]}t|j|jfV dSrH)r>r]r\)r^rs r!rz.QuotaWrapper._fetch_homedir..sG55!%,''6555555r")rrrhr=pwdgetpwallrr)rs r!rzQuotaWrapper._fetch_homedirs t' ( (A - -  $ + +55%(\^^55566 7 7 7 ++C0 0 + + +%c** * +s  A))Bci}ttj}tjd}|D]}|dr||}|d}d|di}|D]~}|ds|dr|dd|d <K|d r|dd|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 mountpointrz usrquota=zusruota== quota_filezjqfmt= quota_type) openrpryr:r;rUrrrrrJ) rrproc_mounts_stream split_pattr line_splitedr mountpoint_dataline_splited_elements r!rz QuotaWrapper._load_quota_devicessy!,":;;Z'' & 4 4Dz** %++D11L!!_F+l1o>O(4 W W$'22;??WCWCbCbcmCnCnW4H4N4Ns4S4STU4VOL11)44X>>W4H4N4Ns4S4STU4VOL1  &&7777#2"3  """ w<<1  (** *r"c>i} ttj}t j|d}n_#t tf$rKtj t j dicY SwxYw n# wxYwtj }|D]xd|krj|dttt!fdt#t%j iny|s4tj t j diS|S)zJ For non-privileged user we outputting data from the file ,) delimiterrrc4j||dzfS)Nrr)rrowrs r!rz/QuotaWrapper._load_user_cache..s Q #AaC *r")rrrprrreaderrIOErrorr>rr=fromkeysrr"rhr|rranger)rrjfocvs_inrOrs` @r!razQuotaWrapper._load_user_caches  !  ! ! # # #l,--BZc222FF! G G G OOT]]4<%E%EF F F     G     D   $*oo  C1v}}#a&$tC*****#dl++,,-.-.(/(/#0#01222  G OOT]]4<%E%EF Fs+AA B? AB&B?%B&&B??Ccd}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')] cZ|ddkrd}n|dd}|S)NrrT)count)device_mountpoint deep_paths r!sort_by_deep_pathzBQuotaWrapper._get_mountpoint_device_map..sort_by_deep_path%s7 #s** -a066s;;  r"rT)rreverse)rrsort)rrrmountpoint_device_mapr mountpoint_data_listrmountpoint_paths r!rz'QuotaWrapper._get_mountpoint_device_map s     !#,3MMOO H H (F(#7 H H"1,"?%,,ov-FGGGG H ""'8$"GGG$$r"cd}|tj|}|jD]'\}}|||r|cS(dS)z3 Returns device user homedir is on c,|r|ddkr|dz }|S)NrSrTr'rs r! _add_slashz1QuotaWrapper._get_home_device.._add_slash7s$ RC Kr"N)rrVdirnamerrU)rhomerrmounpoint_pathr s r!rzQuotaWrapper._get_home_device3s   *RW__T2233&*&D   "NF!!**^"<"<==     r"c4|||kS)z; Checks if a device is user homedir device )r)rrr s r!rzQuotaWrapper._is_home_device@s$$T**f44r"c tj|t}tj|tj|f}|jD]Q}tj|t}|tj|tj|fkr|cSRdS#t$r|cYSwxYwrH)rstatr majorminorrrr)rr dev dev_to_findcurrent_devices r!rz!QuotaWrapper._find_unknown_deviceFs '&//&)C8C=="(3--8K"&-"4"4"6"6 * *gn--f528C=="(3--"@@@))))A * *   MMM sB0B63B66 CCc gd |jddd\}}|dkrd}|dkrd}||gn8#tjtjf$rddgYnwxYwdtttfdt|j iS)zw Insert 'default' quota. Calls only from _load_current_quotas, after parsing repquota's output )rerrrerrrrc0|d|dfSrnr')rrks r!rz+QuotaWrapper._add_default..asqtVAaD\.Br") rrrrgrArVrWr=r|rrpr)rrrrks @r!rzQuotaWrapper._add_defaultQs &%% &#'8<<#=#=#C#CC#H#H IyD   D   MM9i0 1 1 1 1+\-GH & & & MM3* % % % % % &T$s$B$B$B$BYt|E\E\]]^^__``sAA 2BBc|d}|d}||||\}}||dkr>| |dkr6|jdr|jd|nU|jds|jd|jd||d||dS)z# Saves user limits Nrrr)rGrrr add_sectionsetr)rrOrrs r!rzQuotaWrapper._save_user_limitscs <D <D88dDII d LDCKK1E1Eg1N1N H " "7C 0 0 0 08''00 .$$W--- HLL#$$$'= > > > r"c|d}|d}||||\}}||dkr>| |dkr6|jdr|jd|nU|jds|jd|jd||d||||dS)z& Saves package limits Nrrr)rrrrrrr_copy_package_limits_to_cpanel)rr rrs r!rz!QuotaWrapper._save_package_limitsus <D <D;;GT4PP d LDCKKdldckkH((44?J H " ":w 7 7 7 78'' 33 1$$Z000 HLLWtt.D E E E  ++G44444r"ctjsdSd|}t|}t|dkrdS||\}}||dS||d|}|D]\}}|dkrd||<||dd |d d f|d|d frdSd D]E} d t| zd zt|| zdz} | | Ft||ddS)zV Copy package quota limits from cl-quotas.dat to cpanel packages data Nz/var/cpanel/packages/rTrrerrvrrwrvrwlve_rrw) rj is_cpanelrr_parse_cpanel_package_datarrrrr>rr) rr package_pathcpanel_package_linesold_cpanel_datamodified_cpanel_lines quotas_datarr limit_type limit_strings r!rz+QuotaWrapper._copy_package_limits_to_cpanels$&&  F8w88 -l;; # $ $ ) ) F151P1PQe1f1f..  "'<'D F..wT.JJ7S &++-- ( (JC||#' C  /"5"5mS"I"I"1"5"5mS"I"I"K"-m"X!Y [ [  F8 7 7J!C OO3c9C J@W>DDFF a=I--2>>455 "%t:K:K!zz ===r"cT|dkr8|dkr2 |j||nj#tj$rYnYwxYw|j|s|j||j|||d||dS)z& Saves data to a file rrN)rrrArVrrrr)rrrrq item_types r! _save_datazQuotaWrapper._save_datas 3;;43;; &&y$7777.    8'' 22 0$$Y/// HLLDTTT44*@ A A A s *<<c^tj|} tjd|\}}tj|d}||_|S#ttf$rCtj |rtj |tdwxYw)zH Open temporary file for writing and return file object lvetmp_)prefixdirrzCould not save data) rrVrtempfilemkstempfdopen_tmprrrunlinkrF)rfilepathrVfd temp_pathr$s r!rzQuotaWrapper._prepare_writerswx(( :$,I4HHHMB 9R--L!DI ! : : :w~~i(( % )$$$"#899 9 :s 6AAB,c ttztztz}t j|j|t j||dS#t$rYdSwxYw)z0 Routines after writing to file N) rrrrrrenamer chmodr)rrVmasks r!r!zQuotaWrapper._end_writersi W$w.8D Idi & & & HT4     DD sAA A A c|d|tj}|j||tj|dS)z7 Actual place of saving data to a file TN)rrrpr1rwriter!r")rr$s r!rzQuotaWrapper._write_datasq d###++L,ABB  |$$$ ./// r"c|r dt_tj ttjdt_n$#t t f$rtdwxYw tj tj tj dS#t $rtdwxYwdS)NTrz Can't open lock file for readingzCan't get lock) rp LOCK_WRITErr LOCK_FILErrrFfcntlflockfilenoLOCK_EX)rrs r!rzQuotaWrapper._get_global_locks  +&*L #   ' K'+L,BC'H'H $$W% K K K&'IJJJ K 9 L077995=IIIII 9 9 9&'7888 9 ( 's$A!A"&;B##B=ctjs8tj.tjdt_dSdSdSrH)rprrrr/s r!r"zQuotaWrapper._release_locksH' (l.B.N  & & ( ( (#'L  ( (.N.Nr"rH)F)NNTTFF)NNTTFrF)NF)Jr$r%r&r@ryr{rzGETPACKSr1rrrrr staticmethodrxrrrrrrrrrrrr&r*rrrrrrrrrDrGrIrrHrrrirfr5rrcrrrurrrbrrrrarrrrrrrrrrrr!rrr"r'r"r!rprps!K$H$H7H.H0IG7"IJ&&&,AA\AKKK HHH XXXkkkk ( ( ( # # # #DIM49q4q4q4q4fQ;Q;Q;Q;f@@@>"###444   %%%(&&&  \ <$____$$ *""$++++Zddd===<<<))))111)))))))V444&&&&6   """H + + +%%%N8%%%&   555   aaa$$555&CCC:>>\>&    : : :    9 9 9 9(((((r"rp)9 configparserrArrrrr:rbuiltinsr collectionsrrrrrrr rrjclcommonr clcommon.clpwdr clcommon.clquotar clcommon.cpapir rrclcommon.cpapi.cpapiexceptionsrrclcommon.utilsrrrrdetectis_darrrrr)r-r1r6rFrJrMrYreboolrnobjectrpr'r"r!r-sC$### ######;;;;;;;;;;;;;;'''''' 000000IIIIIIIIIITTTTTTTT____________ !!##FFFFFYFFF @@@@@)@@@ <<<<