PNG  IHDRQgAMA a cHRMz&u0`:pQ<bKGDgmIDATxwUﹻ& ^CX(J I@ "% (** BX +*i"]j(IH{~R)[~>h{}gy)I$Ij .I$I$ʊy@}x.: $I$Ii}VZPC)I$IF ^0ʐJ$I$Q^}{"r=OzI$gRZeC.IOvH eKX $IMpxsk.쒷/&r[޳<v| .I~)@$updYRa$I |M.e JaֶpSYR6j>h%IRز if&uJ)M$I vLi=H;7UJ,],X$I1AҒJ$ XY XzI@GNҥRT)E@;]K*Mw;#5_wOn~\ DC&$(A5 RRFkvIR}l!RytRl;~^ǷJj اy뷦BZJr&ӥ8Pjw~vnv X^(I;4R=P[3]J,]ȏ~:3?[ a&e)`e*P[4]T=Cq6R[ ~ޤrXR Հg(t_HZ-Hg M$ãmL5R uk*`%C-E6/%[t X.{8P9Z.vkXŐKjgKZHg(aK9ڦmKjѺm_ \#$5,)-  61eJ,5m| r'= &ڡd%-]J on Xm|{ RҞe $eڧY XYrԮ-a7RK6h>n$5AVڴi*ֆK)mѦtmr1p| q:흺,)Oi*ֺK)ܬ֦K-5r3>0ԔHjJئEZj,%re~/z%jVMڸmrt)3]J,T K֦OvԒgii*bKiNO~%PW0=dii2tJ9Jݕ{7"I P9JKTbu,%r"6RKU}Ij2HKZXJ,妝 XYrP ެ24c%i^IK|.H,%rb:XRl1X4Pe/`x&P8Pj28Mzsx2r\zRPz4J}yP[g=L) .Q[6RjWgp FIH*-`IMRaK9TXcq*I y[jE>cw%gLRԕiFCj-ďa`#e~I j,%r,)?[gp FI˨mnWX#>mʔ XA DZf9,nKҲzIZXJ,L#kiPz4JZF,I,`61%2s $,VOϚ2/UFJfy7K> X+6 STXIeJILzMfKm LRaK9%|4p9LwJI!`NsiazĔ)%- XMq>pk$-$Q2x#N ؎-QR}ᶦHZډ)J,l#i@yn3LN`;nڔ XuX5pF)m|^0(>BHF9(cզEerJI rg7 4I@z0\JIi䵙RR0s;$s6eJ,`n 䂦0a)S)A 1eJ,堌#635RIgpNHuTH_SԕqVe ` &S)>p;S$魁eKIuX`I4춒o}`m$1":PI<[v9^\pTJjriRŭ P{#{R2,`)e-`mgj~1ϣLKam7&U\j/3mJ,`F;M'䱀 .KR#)yhTq;pcK9(q!w?uRR,n.yw*UXj#\]ɱ(qv2=RqfB#iJmmL<]Y͙#$5 uTU7ӦXR+q,`I}qL'`6Kͷ6r,]0S$- [RKR3oiRE|nӦXR.(i:LDLTJjY%o:)6rxzҒqTJjh㞦I.$YR.ʼnGZ\ֿf:%55 I˼!6dKxm4E"mG_ s? .e*?LRfK9%q#uh$)i3ULRfK9yxm܌bj84$i1U^@Wbm4uJ,ҪA>_Ij?1v32[gLRD96oTaR׿N7%L2 NT,`)7&ƝL*꽙yp_$M2#AS,`)7$rkTA29_Iye"|/0t)$n XT2`YJ;6Jx".e<`$) PI$5V4]29SRI>~=@j]lp2`K9Jaai^" Ԋ29ORI%:XV5]JmN9]H;1UC39NI%Xe78t)a;Oi Ҙ>Xt"~G>_mn:%|~ޅ_+]$o)@ǀ{hgN;IK6G&rp)T2i୦KJuv*T=TOSV>(~D>dm,I*Ɛ:R#ۙNI%D>G.n$o;+#RR!.eU˽TRI28t)1LWϚ>IJa3oFbu&:tJ*(F7y0ZR ^p'Ii L24x| XRI%ۄ>S1]Jy[zL$adB7.eh4%%누>WETf+3IR:I3Xה)3אOۦSRO'ٺ)S}"qOr[B7ϙ.edG)^ETR"RtRݜh0}LFVӦDB^k_JDj\=LS(Iv─aTeZ%eUAM-0;~˃@i|l @S4y72>sX-vA}ϛBI!ݎߨWl*)3{'Y|iSlEڻ(5KtSI$Uv02,~ԩ~x;P4ցCrO%tyn425:KMlD ^4JRxSهF_}شJTS6uj+ﷸk$eZO%G*^V2u3EMj3k%)okI]dT)URKDS 7~m@TJR~荪fT"֛L \sM -0T KfJz+nإKr L&j()[E&I ߴ>e FW_kJR|!O:5/2跌3T-'|zX ryp0JS ~^F>-2< `*%ZFP)bSn"L :)+pʷf(pO3TMW$~>@~ū:TAIsV1}S2<%ޟM?@iT ,Eūoz%i~g|`wS(]oȤ8)$ ntu`өe`6yPl IzMI{ʣzʨ )IZ2= ld:5+請M$-ї;U>_gsY$ÁN5WzWfIZ)-yuXIfp~S*IZdt;t>KūKR|$#LcԀ+2\;kJ`]YǔM1B)UbG"IRߊ<xܾӔJ0Z='Y嵤 Leveg)$znV-º^3Ւof#0Tfk^Zs[*I꯳3{)ˬW4Ւ4 OdpbZRS|*I 55#"&-IvT&/윚Ye:i$ 9{LkuRe[I~_\ؠ%>GL$iY8 9ܕ"S`kS.IlC;Ҏ4x&>u_0JLr<J2(^$5L s=MgV ~,Iju> 7r2)^=G$1:3G< `J3~&IR% 6Tx/rIj3O< ʔ&#f_yXJiގNSz; Tx(i8%#4 ~AS+IjerIUrIj362v885+IjAhK__5X%nV%Iͳ-y|7XV2v4fzo_68"S/I-qbf; LkF)KSM$ Ms>K WNV}^`-큧32ŒVؙGdu,^^m%6~Nn&͓3ŒVZMsRpfEW%IwdǀLm[7W&bIRL@Q|)* i ImsIMmKmyV`i$G+R 0tV'!V)֏28vU7͒vHꦼtxꗞT ;S}7Mf+fIRHNZUkUx5SAJㄌ9MqμAIRi|j5)o*^'<$TwI1hEU^c_j?Е$%d`z cyf,XO IJnTgA UXRD }{H}^S,P5V2\Xx`pZ|Yk:$e ~ @nWL.j+ϝYb퇪bZ BVu)u/IJ_ 1[p.p60bC >|X91P:N\!5qUB}5a5ja `ubcVxYt1N0Zzl4]7­gKj]?4ϻ *[bg$)+À*x쳀ogO$~,5 زUS9 lq3+5mgw@np1sso Ӻ=|N6 /g(Wv7U;zωM=wk,0uTg_`_P`uz?2yI!b`kĸSo+Qx%!\οe|އԁKS-s6pu_(ֿ$i++T8=eY; צP+phxWQv*|p1. ά. XRkIQYP,drZ | B%wP|S5`~́@i޾ E;Չaw{o'Q?%iL{u D?N1BD!owPHReFZ* k_-~{E9b-~P`fE{AܶBJAFO wx6Rox5 K5=WwehS8 (JClJ~ p+Fi;ŗo+:bD#g(C"wA^ r.F8L;dzdIHUX݆ϞXg )IFqem%I4dj&ppT{'{HOx( Rk6^C٫O.)3:s(۳(Z?~ٻ89zmT"PLtw䥈5&b<8GZ-Y&K?e8,`I6e(֍xb83 `rzXj)F=l($Ij 2*(F?h(/9ik:I`m#p3MgLaKjc/U#n5S# m(^)=y=đx8ŬI[U]~SцA4p$-F i(R,7Cx;X=cI>{Km\ o(Tv2vx2qiiDJN,Ҏ!1f 5quBj1!8 rDFd(!WQl,gSkL1Bxg''՞^ǘ;pQ P(c_ IRujg(Wz bs#P­rz> k c&nB=q+ؔXn#r5)co*Ũ+G?7< |PQӣ'G`uOd>%Mctz# Ԫڞ&7CaQ~N'-P.W`Oedp03C!IZcIAMPUۀ5J<\u~+{9(FbbyAeBhOSܳ1 bÈT#ŠyDžs,`5}DC-`̞%r&ڙa87QWWp6e7 Rϫ/oY ꇅ Nܶըtc!LA T7V4Jsū I-0Pxz7QNF_iZgúWkG83 0eWr9 X]㾮݁#Jˢ C}0=3ݱtBi]_ &{{[/o[~ \q鯜00٩|cD3=4B_b RYb$óBRsf&lLX#M*C_L܄:gx)WΘsGSbuL rF$9';\4Ɍq'n[%p.Q`u hNb`eCQyQ|l_C>Lb꟟3hSb #xNxSs^ 88|Mz)}:](vbۢamŖ࿥ 0)Q7@0=?^k(*J}3ibkFn HjB׻NO z x}7p 0tfDX.lwgȔhԾŲ }6g E |LkLZteu+=q\Iv0쮑)QٵpH8/2?Σo>Jvppho~f>%bMM}\//":PTc(v9v!gոQ )UfVG+! 35{=x\2+ki,y$~A1iC6#)vC5^>+gǵ@1Hy٪7u;p psϰu/S <aʸGu'tD1ԝI<pg|6j'p:tպhX{o(7v],*}6a_ wXRk,O]Lܳ~Vo45rp"N5k;m{rZbΦ${#)`(Ŵg,;j%6j.pyYT?}-kBDc3qA`NWQū20/^AZW%NQ MI.X#P#,^Ebc&?XR tAV|Y.1!؅⨉ccww>ivl(JT~ u`ٵDm q)+Ri x/x8cyFO!/*!/&,7<.N,YDŽ&ܑQF1Bz)FPʛ?5d 6`kQձ λc؎%582Y&nD_$Je4>a?! ͨ|ȎWZSsv8 j(I&yj Jb5m?HWp=g}G3#|I,5v珿] H~R3@B[☉9Ox~oMy=J;xUVoj bUsl_35t-(ՃɼRB7U!qc+x4H_Qo֮$[GO<4`&č\GOc[.[*Af%mG/ ňM/r W/Nw~B1U3J?P&Y )`ѓZ1p]^l“W#)lWZilUQu`-m|xĐ,_ƪ|9i:_{*(3Gѧ}UoD+>m_?VPۅ15&}2|/pIOʵ> GZ9cmíتmnz)yߐbD >e}:) r|@R5qVSA10C%E_'^8cR7O;6[eKePGϦX7jb}OTGO^jn*媓7nGMC t,k31Rb (vyܴʭ!iTh8~ZYZp(qsRL ?b}cŨʊGO^!rPJO15MJ[c&~Z`"ѓޔH1C&^|Ш|rʼ,AwĴ?b5)tLU)F| &g٣O]oqSUjy(x<Ϳ3 .FSkoYg2 \_#wj{u'rQ>o;%n|F*O_L"e9umDds?.fuuQbIWz |4\0 sb;OvxOSs; G%T4gFRurj(֍ڑb uԖKDu1MK{1^ q; C=6\8FR艇!%\YÔU| 88m)֓NcLve C6z;o&X x59:q61Z(T7>C?gcļxѐ Z oo-08jہ x,`' ҔOcRlf~`jj".Nv+sM_]Zk g( UOPyεx%pUh2(@il0ݽQXxppx-NS( WO+轾 nFߢ3M<;z)FBZjciu/QoF 7R¥ ZFLF~#ȣߨ^<쩡ݛкvџ))ME>ώx4m#!-m!L;vv#~Y[đKmx9.[,UFS CVkZ +ߟrY٧IZd/ioi$%͝ب_ֶX3ܫhNU ZZgk=]=bbJS[wjU()*I =ώ:}-蹞lUj:1}MWm=̛ _ ¾,8{__m{_PVK^n3esw5ӫh#$-q=A̟> ,^I}P^J$qY~Q[ Xq9{#&T.^GVj__RKpn,b=`żY@^՝;z{paVKkQXj/)y TIc&F;FBG7wg ZZDG!x r_tƢ!}i/V=M/#nB8 XxЫ ^@CR<{䤭YCN)eKOSƟa $&g[i3.C6xrOc8TI;o hH6P&L{@q6[ Gzp^71j(l`J}]e6X☉#͕ ׈$AB1Vjh㭦IRsqFBjwQ_7Xk>y"N=MB0 ,C #o6MRc0|$)ف"1!ixY<B9mx `,tA>)5ػQ?jQ?cn>YZe Tisvh# GMމȇp:ԴVuږ8ɼH]C.5C!UV;F`mbBk LTMvPʍϤj?ԯ/Qr1NB`9s"s TYsz &9S%U԰> {<ؿSMxB|H\3@!U| k']$U+> |HHMLޢ?V9iD!-@x TIî%6Z*9X@HMW#?nN ,oe6?tQwڱ.]-y':mW0#!J82qFjH -`ѓ&M0u Uγmxϵ^-_\])@0Rt.8/?ٰCY]x}=sD3ojަЫNuS%U}ԤwHH>ڗjܷ_3gN q7[q2la*ArǓԖ+p8/RGM ]jacd(JhWko6ڎbj]i5Bj3+3!\j1UZLsLTv8HHmup<>gKMJj0@H%,W΃7R) ">c, xixј^ aܖ>H[i.UIHc U1=yW\=S*GR~)AF=`&2h`DzT󑓶J+?W+}C%P:|0H܆}-<;OC[~o.$~i}~HQ TvXΈr=b}$vizL4:ȰT|4~*!oXQR6Lk+#t/g lԁߖ[Jڶ_N$k*". xsxX7jRVbAAʯKҎU3)zSNN _'s?f)6X!%ssAkʱ>qƷb hg %n ~p1REGMHH=BJiy[<5 ǁJҖgKR*倳e~HUy)Ag,K)`Vw6bRR:qL#\rclK/$sh*$ 6덤 KԖc 3Z9=Ɣ=o>X Ώ"1 )a`SJJ6k(<c e{%kϊP+SL'TcMJWRm ŏ"w)qc ef꒵i?b7b('"2r%~HUS1\<(`1Wx9=8HY9m:X18bgD1u ~|H;K-Uep,, C1 RV.MR5άh,tWO8WC$ XRVsQS]3GJ|12 [vM :k#~tH30Rf-HYݺ-`I9%lIDTm\ S{]9gOڒMNCV\G*2JRŨ;Rҏ^ڽ̱mq1Eu?To3I)y^#jJw^Ńj^vvlB_⋌P4x>0$c>K†Aļ9s_VjTt0l#m>E-,,x,-W)سo&96RE XR.6bXw+)GAEvL)͞K4$p=Ũi_ѱOjb HY/+@θH9޼]Nԥ%n{ &zjT? Ty) s^ULlb,PiTf^<À] 62R^V7)S!nllS6~͝V}-=%* ʻ>G DnK<y&>LPy7'r=Hj 9V`[c"*^8HpcO8bnU`4JȪAƋ#1_\ XϘHPRgik(~G~0DAA_2p|J묭a2\NCr]M_0 ^T%e#vD^%xy-n}-E\3aS%yN!r_{ )sAw ڼp1pEAk~v<:`'ӭ^5 ArXOI驻T (dk)_\ PuA*BY]yB"l\ey hH*tbK)3 IKZ򹞋XjN n *n>k]X_d!ryBH ]*R 0(#'7 %es9??ښFC,ՁQPjARJ\Ρw K#jahgw;2$l*) %Xq5!U᢯6Re] |0[__64ch&_}iL8KEgҎ7 M/\`|.p,~`a=BR?xܐrQ8K XR2M8f ?`sgWS%" Ԉ 7R%$ N}?QL1|-эټwIZ%pvL3Hk>,ImgW7{E xPHx73RA @RS CC !\ȟ5IXR^ZxHл$Q[ŝ40 (>+ _C >BRt<,TrT {O/H+˟Pl6 I B)/VC<6a2~(XwV4gnXR ϱ5ǀHٻ?tw똤Eyxp{#WK qG%5],(0ӈH HZ])ג=K1j&G(FbM@)%I` XRg ʔ KZG(vP,<`[ Kn^ SJRsAʠ5xՅF`0&RbV tx:EaUE/{fi2;.IAwW8/tTxAGOoN?G}l L(n`Zv?pB8K_gI+ܗ #i?ޙ.) p$utc ~DžfՈEo3l/)I-U?aԅ^jxArA ΧX}DmZ@QLےbTXGd.^|xKHR{|ΕW_h] IJ`[G9{).y) 0X YA1]qp?p_k+J*Y@HI>^?gt.06Rn ,` ?);p pSF9ZXLBJPWjgQ|&)7! HjQt<| ؅W5 x W HIzYoVMGP Hjn`+\(dNW)F+IrS[|/a`K|ͻ0Hj{R,Q=\ (F}\WR)AgSG`IsnAR=|8$}G(vC$)s FBJ?]_u XRvύ6z ŨG[36-T9HzpW̞ú Xg큽=7CufzI$)ki^qk-) 0H*N` QZkk]/tnnsI^Gu't=7$ Z;{8^jB% IItRQS7[ϭ3 $_OQJ`7!]W"W,)Iy W AJA;KWG`IY{8k$I$^%9.^(`N|LJ%@$I}ֽp=FB*xN=gI?Q{٥4B)mw $Igc~dZ@G9K X?7)aK%݅K$IZ-`IpC U6$I\0>!9k} Xa IIS0H$I H ?1R.Чj:4~Rw@p$IrA*u}WjWFPJ$I➓/6#! LӾ+ X36x8J |+L;v$Io4301R20M I$-E}@,pS^ޟR[/s¹'0H$IKyfŸfVOπFT*a$I>He~VY/3R/)>d$I>28`Cjw,n@FU*9ttf$I~<;=/4RD~@ X-ѕzἱI$: ԍR a@b X{+Qxuq$IЛzo /~3\8ڒ4BN7$IҀj V]n18H$IYFBj3̵̚ja pp $Is/3R Ӻ-Yj+L;.0ŔI$Av? #!5"aʄj}UKmɽH$IjCYs?h$IDl843.v}m7UiI=&=0Lg0$I4: embe` eQbm0u? $IT!Sƍ'-sv)s#C0:XB2a w I$zbww{."pPzO =Ɔ\[ o($Iaw]`E).Kvi:L*#gР7[$IyGPI=@R 4yR~̮´cg I$I/<tPͽ hDgo 94Z^k盇΄8I56^W$I^0̜N?4*H`237}g+hxoq)SJ@p|` $I%>-hO0eO>\ԣNߌZD6R=K ~n($I$y3D>o4b#px2$yڪtzW~a $I~?x'BwwpH$IZݑnC㧄Pc_9sO gwJ=l1:mKB>Ab<4Lp$Ib o1ZQ@85b̍ S'F,Fe,^I$IjEdù{l4 8Ys_s Z8.x m"+{~?q,Z D!I$ϻ'|XhB)=…']M>5 rgotԎ 獽PH$IjIPhh)n#cÔqA'ug5qwU&rF|1E%I$%]!'3AFD/;Ck_`9 v!ٴtPV;x`'*bQa w I$Ix5 FC3D_~A_#O݆DvV?<qw+I$I{=Z8".#RIYyjǪ=fDl9%M,a8$I$Ywi[7ݍFe$s1ՋBVA?`]#!oz4zjLJo8$I$%@3jAa4(o ;p,,dya=F9ً[LSPH$IJYЉ+3> 5"39aZ<ñh!{TpBGkj}Sp $IlvF.F$I z< '\K*qq.f<2Y!S"-\I$IYwčjF$ w9 \ߪB.1v!Ʊ?+r:^!I$BϹB H"B;L'G[ 4U#5>੐)|#o0aڱ$I>}k&1`U#V?YsV x>{t1[I~D&(I$I/{H0fw"q"y%4 IXyE~M3 8XψL}qE$I[> nD?~sf ]o΁ cT6"?'_Ἣ $I>~.f|'!N?⟩0G KkXZE]ޡ;/&?k OۘH$IRۀwXӨ<7@PnS04aӶp.:@\IWQJ6sS%I$e5ڑv`3:x';wq_vpgHyXZ 3gЂ7{{EuԹn±}$I$8t;b|591nءQ"P6O5i }iR̈́%Q̄p!I䮢]O{H$IRϻ9s֧ a=`- aB\X0"+5"C1Hb?߮3x3&gşggl_hZ^,`5?ߎvĸ%̀M!OZC2#0x LJ0 Gw$I$I}<{Eb+y;iI,`ܚF:5ܛA8-O-|8K7s|#Z8a&><a&/VtbtLʌI$I$I$I$I$I$IRjDD%tEXtdate:create2022-05-31T04:40:26+00:00!Î%tEXtdate:modify2022-05-31T04:40:26+00:00|{2IENDB`Mini Shell

HOME


Mini Shell 1.0
DIR:/proc/thread-self/root/scripts/
Upload File :
Current File : //proc/thread-self/root/scripts/cpanelsync
#!/usr/local/cpanel/3rdparty/bin/perl

# cpanel - scripts/cpanelsync                      Copyright 2022 cPanel, L.L.C.
#                                                           All rights reserved.
# copyright@cpanel.net                                         http://cpanel.net
# This code is subject to the cPanel license. Unauthorized copying is prohibited

package Scripts::cpanelsync;

## "grep '###' cpanelsync" gives an overview of the logic and files downloaded

BEGIN {
    my $running_in_debugger = exists $INC{'perl5db.pl'};
    if ($running_in_debugger) {
        $ENV{'LANG'} = 'C';
    }

    if ( defined $ENV{'LANG'} && $ENV{'LANG'} ne 'C' && !$^C ) {
        $ENV{'LANG'} = 'C';
        exec $0, @ARGV;
        die 'Failed to recreate self in a sane env';
    }
}

use strict;
use warnings;

use Socket;
use Cpanel::Tar                  ();
use Cpanel::HttpRequest          ();
use Cpanel::SafeDir::MK          ();
use Cpanel::Sync::Common         ();
use Cpanel::Sync::Digest         ();
use Cpanel::Usage                ();
use Cpanel::Crypt::GPG::Settings ();

exit __PACKAGE__->script(@ARGV) unless caller();

sub script {
    my ( $package, @argv ) = @_;

    local $| = 1;
    $SIG{'INT'} = 'IGNORE';

    my ( $exit_code, $options, $host, $url, $root ) = _parse_argv( \@argv );

    if ( defined $exit_code ) {
        return $exit_code;
    }
    else {
        $exit_code = 0;
    }

    eval {
        no warnings;
        local $SIG{'__DIE__'};
        local $SIG{'__WARN__'};
        require Cpanel::Carp;
        local $SIG{'__DIE__'};
        local $SIG{'__WARN__'};
        Cpanel::Carp::enable();
        $Cpanel::Carp::OUTPUT_FORMAT = 'suppress';
    };

    # setup httpclient with keyring
    my $httpClient = Cpanel::HttpRequest->new(
        categories => $options->{categories},
        vendor     => $options->{vendor},
        hideOutput => $options->{quiet},
    );

    if ( !-d $root ) {
        Cpanel::SafeDir::MK::safemkdir( $root, '0755', 2 );
        if ( !-d $root ) {
            die "Unable to create directory $root";
        }
    }

    _wait_for_mirror_lock( $httpClient, $host, $url, $options );

    ### "$url/.cpanelsync.version",
    if ( $options->{repo} ) {

        # The intent with the unchecked exit code is apparently that the repo version needs to
        # be updated at the start of the cpanelsync run so that it can be compared to the state
        # at the end of the cpanelsync run.
        $exit_code = check_repo_version( $options->{repo}, $httpClient, $host, $url );
    }

    my $dotcpanelsync = "$root/.cpanelsync";

    my %OLDFILES;
    my %NEWFILES;
    if ( !-e $dotcpanelsync ) {    ###
        ## if .cpanelsync does not exist, download/extract the .tar.bz2
        my $basedir = $root;
        my @DIRS    = split m{ [/] }xms, $basedir;
        pop @DIRS;
        $basedir = join '/', @DIRS;

        my $basename = $url;
        my @BDIR     = split m{ [/] }xms, $basename;
        $basename = pop @BDIR;

        if ( $basedir eq '' ) { $basedir = '/'; }

        my $tarball = "$basedir/$basename.tar";
        my $bz2     = "$tarball.bz2";
        unlink $bz2;

        ### "http://${host}${url}.tar.bz2"

        if ( eval { downloadfile( $httpClient, "http://${host}${url}.tar.bz2", $bz2, $options->{signed} ) } ) {
            my $tarcfg = Cpanel::Tar::load_tarcfg();
            system( $tarcfg->{'bin'}, '-x', '-p', $tarcfg->{'no_same_owner'}, '-j', '-v', '-C', $basedir, '-f', $bz2 );
            unlink $bz2;
        }

        ## TODO?: take the md5sums of the new files, and manipulate %OLDFILES (or %MD5LIST?)
    }
    else {
        if ( open my $cpsync_fh, '<', $dotcpanelsync ) {
            no warnings;    # we will discard undef in our delete
            local $/;
            %OLDFILES = map { reverse( ( split( /===/, $_ ) )[ 0, 1 ] ) } split( /\n/, readline($cpsync_fh) );
            delete @OLDFILES{''};
            $OLDFILES{'.'} = 'd';
            close $cpsync_fh;
        }
    }

    my @FILELIST;
    my $trycount = 0;
    my $usebz2   = 1;
    my $skipbz2  = 0;

    # Download file list to sync
    while (1) {    ###
        $trycount++;

        if   ( $trycount % 2 == 0 ) { $usebz2 = 0; }
        else                        { $usebz2 = 1; }

        my $target_url        = "${url}/.cpanelsync";
        my $staged_destfile   = "${dotcpanelsync}.staged";
        my $download_destfile = $staged_destfile;

        if ( !$skipbz2 && $usebz2 ) {
            $target_url        .= '.bz2';
            $download_destfile .= '.bz2';
        }

        eval { $httpClient->request( 'host' => $host, 'url' => $target_url, 'protocol' => 1, 'destfile' => $download_destfile, 'signed' => $options->{signed} ); };

        # Note: signed requests will automatically unbzip the target to verify signatures
        if ( !$@ && -e $staged_destfile ) {
            if ( rename( $staged_destfile, $dotcpanelsync ) ) {
                if ( open( my $cpanelsync_fh, $dotcpanelsync ) ) {
                    local $/;
                    @FILELIST = split( /\n/, readline($cpanelsync_fh) );
                    close($cpanelsync_fh);
                }
            }
            else {
                print "Failed to overwrite $dotcpanelsync: $!\n";
            }
        }

        if ( -e "$dotcpanelsync.bz2" ) {
            unlink "$dotcpanelsync.bz2";
            $skipbz2 = 1;
        }

        last if ( @FILELIST && $FILELIST[-1] eq '.' );

        if ( $trycount > 1 ) {
            if ( $trycount == 10 ) {
                print "Tried to download the sync file 10 times and failed!\n";
                return 1;
            }
            downloadfailed($httpClient);
        }
    }

    # Global excludes for handling excluded files from update or permission checks
    my @excludes       = Cpanel::Sync::Common::get_excludes($Cpanel::Sync::Common::cpanelsync_excludes);
    my @chmod_excludes = Cpanel::Sync::Common::get_excludes($Cpanel::Sync::Common::cpanelsync_chmod_excludes);

    my %MD5LIST;
    loadmd5s( \%MD5LIST, $root ) if -e "$dotcpanelsync.md5s";
    my @allowed_digests = Cpanel::Crypt::GPG::Settings::allowed_digest_algorithms();

    foreach my $fileinfo (@FILELIST) {    ###
        chomp $fileinfo;
        next if ( $fileinfo eq '.' );

        ## note: appending 'r' to these vars to denote that they represent info on the
        ##   remote (incoming) resource. Ideally, they should be packaged in a hash,
        ##   similar to how $target is handled.
        ## $rextra is either an md5 for 'file' $ftype, or symlink destination
        ## $rsha is only valid for 'file' types, and will contain a SHA512 digest for the file.

        my ( $rtype, $rfile, $rperm, $rextra, $rsha ) = split( /===/, $fileinfo );

        my $target_info = lstat_target( $root, $rfile );

        ## using %04d as $rperm is a string (comes from the .cpanelsync file)
        $rperm = sprintf( "%04d", $rperm );

        prune_OLDFILES( \%OLDFILES, $rfile, $rtype );

        next if ( @excludes && is_excluded( \@excludes, $root, $rfile ) );

        if ( $rtype eq 'f' ) {
            $exit_code = handle_file( $target_info, \%MD5LIST, $root, $rfile, $rextra, $rsha, \@allowed_digests, $skipbz2, $httpClient, $host, $url, $Cpanel::Sync::Common::hasbzip2, $exit_code, $options->{repo}, \@chmod_excludes, $rperm, \%NEWFILES );
            return $exit_code if ( $exit_code != 0 );
        }
        elsif ( $rtype eq 'd' ) {
            handle_dir( $target_info, \@chmod_excludes, $root, $rfile, $rperm );
        }
        elsif ( $rtype eq 'l' ) {
            handle_symlink( $target_info, $rextra );
        }
    }

    my $saferoot = $root;
    $saferoot =~ s/\.\///g;

    handle_deletes( \@FILELIST, \%OLDFILES, $saferoot );

    write_newlist( \%NEWFILES, $saferoot );

    writemd5s( \%MD5LIST, $saferoot );

    ### "$url/.cpanelsync.version",
    if ( $exit_code == 0 && $options->{repo} ) {
        $exit_code = check_repo_version( $options->{repo}, 0, $httpClient, $host, $url );
    }

    if ( -x '/usr/local/cpanel/scripts/cpanelsync_postprocessor' ) {
        system '/usr/local/cpanel/scripts/cpanelsync_postprocessor', $saferoot;
    }
    if ( -x '/usr/local/cpanel/scripts/cpanelsync_postprocessor.custom' ) {
        system '/usr/local/cpanel/scripts/cpanelsync_postprocessor.custom', $saferoot;
    }

    return $exit_code;
}

sub downloadfile {
    my ( $httpClient, $file, $where, $signed ) = @_;

    $file =~ m!http://([^/]+)(.*)!;

    my $host = $1;
    my $url  = $2;

    $httpClient->request(
        'host'     => $1,
        'url'      => $2,
        'protocol' => 1,
        'destfile' => $where,
        'signed'   => $signed,
    );

}

sub loadmd5s {
    my ( $hr_MD5LIST, $dir ) = @_;

    if ( open( my $md5_fh, '<', $dir . '/.cpanelsync.md5s' ) ) {
        local $/;
        %{$hr_MD5LIST} = map { $_ = [ split( /:::/, $_, 4 ) ]; $_->[0] => { 'size' => $_->[1], 'mtime' => $_->[2], 'md5' => $_->[3] } } split( /\n/, readline($md5_fh) );
        close($md5_fh);
    }

    return;
}

sub write_newlist {
    my ( $hr_NEWFILES, $dir ) = @_;

    $dir =~ s/\/$//g;
    open( my $new_fh, '>', $dir . '/.cpanelsync.new' ) || do {
        warn "Could not write new list: " . $dir . '/.cpanelsync.new';
        return;
    };
    print {$new_fh} join( "\n", keys %$hr_NEWFILES ) . ( scalar keys %$hr_NEWFILES ? "\n" : '' );    # as we did before
    close($new_fh);
}

sub writemd5s {
    my ( $hr_MD5LIST, $dir ) = @_;

    $dir =~ s/\/$//g;
    open( MD5, '>', $dir . '/.cpanelsync.md5s' ) || do {
        warn "Could not write md5 cache: " . $dir . '/.cpanelsync.md5s';
        return;
    };
    foreach my $filename ( keys %$hr_MD5LIST ) {
        next if ( !$hr_MD5LIST->{$filename}{'used'} || substr( $filename, 0, 1 ) eq '/' );
        print MD5 join( ':::', $filename, $hr_MD5LIST->{$filename}{'size'}, $hr_MD5LIST->{$filename}{'mtime'}, $hr_MD5LIST->{$filename}{'md5'} ) . "\n";
    }
    close(MD5);
}

sub downloadfailed {
    my ($httpClient) = @_;
    print 'Download Failed... trying again...in..';
    if ($httpClient) {
        $httpClient->disconnect();
    }
    my $sleepsecs = 60;
    for ( my $i = $sleepsecs; $i > 0; $i-- ) {
        print '..' . $i . '..';
        sleep 1;
    }
}

sub check_repo_version {
    my ( $repo, $httpClient, $host, $url ) = @_;
    my $local_repo_v;
    if ( !-e '/var/cpanel' )            { mkdir( '/var/cpanel',            0755 ); }
    if ( !-e '/var/cpanel/cpanelsync' ) { mkdir( '/var/cpanel/cpanelsync', 0755 ); }
    if ( !-e '/var/cpanel/cpanelsync/repoversions' ) {
        mkdir( '/var/cpanel/cpanelsync/repoversions', 0755 );
    }
    my $repo_fh;
    open( $repo_fh, '<', '/var/cpanel/cpanelsync/repoversions/' . $repo ) && do {
        $local_repo_v = readline($repo_fh);
        chomp($local_repo_v);
        close($repo_fh);
    };
    my ( $remote_repo_v, $status ) = $httpClient->request(
        'exitOn404' => 0,
        'host'      => $host,
        'url'       => "$url/.cpanelsync.version",
        'protocol'  => 1,
    );
    if ($remote_repo_v) {
        if ( !$local_repo_v || $remote_repo_v ne $local_repo_v ) {
            open( my $repo_fh, '>', '/var/cpanel/cpanelsync/repoversions/' . $repo );
            print {$repo_fh} $remote_repo_v;
            close($repo_fh);
            if ($local_repo_v) {
                print "Repo: $repo : version changed from $local_repo_v to $remote_repo_v in mid sync.  Sync needs to be restarted.\n";
                return 16;
            }
            else {
                print "Repo: $repo : learned new version: $remote_repo_v\n";
            }
        }
        else {
            print "Repo: $repo : check passed : local=$local_repo_v & remote=$remote_repo_v\n";
        }
    }
    return 0;
}

sub is_excluded {
    my ( $ar_excludes, $root, $rfile ) = @_;

    if ( @{$ar_excludes} ) {
        my $clean_rfile = $rfile;
        $clean_rfile =~ s!^\./!!;
        my $absfile = $root . '/' . $clean_rfile;
        $absfile =~ tr{/}{}s;
        $absfile =~ s{ [/] \z }{}xmsg;

        ## Note: to take advantage of the "implicit" exclusion of a directory's contents, as written
        ##   the explicitly listed exclude directory must exist at the installation site.
        if ( grep { $_ eq $absfile || ( -d $_ && $absfile =~ m/^\Q$_\E\// ) } @{$ar_excludes} ) {
            print "Skipping sync of $absfile (check /etc/cpanelsync.exclude)\n";
            return 1;
        }

        ## Maintain support for old broken behavior --------------
        $absfile = $root . '/' . $rfile;
        $absfile =~ tr{/}{}s;
        $absfile =~ s{ [/] \z }{}xmsg;
        if ( grep { $_ eq $absfile } @{$ar_excludes} ) {
            print "Skipping sync of $absfile (check /etc/cpanelsync.exclude)\n";
            return 1;
        }
        ## -------------------------------------------------------
    }
    return;
}

sub in_chmod_excludes {
    my ( $ar_chmod_excludes, $root, $rfile ) = @_;
    if (@$ar_chmod_excludes) {
        my $clean_rfile = $rfile;
        $clean_rfile =~ s/^\.\///;
        my $absfile = $root . '/' . $clean_rfile;
        $absfile =~ tr{/}{}s;
        $absfile =~ s{ [/] \z }{}xmsg;
        return 1 if ( grep { $_ eq $absfile } @$ar_chmod_excludes );
    }
    return;
}

sub handle_symlink {
    my ( $target, $rextra ) = @_;

    my $dolink = 0;
    if ( !$target->{'exists'} ) {
        $dolink = 1;
    }
    elsif ( $target->{'islnk'} ) {
        if ( readlink $target->{'path'} ne $rextra ) {
            unlink $target->{'path'};
            $dolink = 1;
        }
    }
    elsif ( $target->{'isnormfile'} ) {
        unlink $target->{'path'};
        $dolink = 1;
    }
    elsif ( $target->{'isdir'} ) {
        system 'rm', '-rf', '--', $target->{'path'};
        $dolink = 1;
    }

    if ($dolink) {
        if ( symlink( $rextra, $target->{'path'} ) ) {
            print "Created symlink $target->{'path'} -> $rextra successfully\n";
        }
        else {
            print "Failed to create symlink $target->{'path'} -> $rextra: $!\n";
        }
    }

    return;
}

sub handle_dir {
    my ( $target, $ar_chmod_excludes, $root, $rfile, $rperm ) = @_;
    ## note: $rperm is an octal string (e.g. '0751')

    if ( $target->{'islnk'} || $target->{'isnormfile'} ) {
        unlink $target->{'path'};
        $target->{'exists'} = 0;
    }

    if ( !$target->{'exists'} ) {
        ## FIX: used to be created with a hardcoded mode of '0755'. The only case this
        ##   will not account for is a new directory that is also in chmod_excludes. I believe
        ##   this to be a very edge case.
        if ( Cpanel::SafeDir::MK::safemkdir( $target->{'path'}, $rperm, 2 ) ) {
            print "Created directory $target->{'path'} successfully\n";
        }
    }
    elsif ( ( !@$ar_chmod_excludes || !in_chmod_excludes( $ar_chmod_excludes, $root, $rfile ) )
        && sprintf( "%04o", ( $target->{'perm'} & 07777 ) ) ne $rperm ) {
        if ( chmod( oct($rperm), $target->{'path'} ) ) {
            print "Directory $target->{'path'} verified\n";
        }
        else {
            print "Failed to update permissions on directory $target->{'path'}: $!";
        }
    }
}

sub handle_file {    ###
    my ( $target, $hr_MD5LIST, $root, $rfile, $rextra, $rsha, $allowed_digests_ar, $skipbz2, $httpClient, $host, $url, $hasbzip2, $exit_code, $repo, $ar_chmod_excludes, $rperm, $newfiles_ref ) = @_;

    if ( $target->{'isdir'} ) {
        system 'rm', '-rf', '--', $target->{'path'};
    }
    elsif ( $target->{'islnk'} ) {
        unlink $target->{'path'};
    }

    my $local_digest = Cpanel::Sync::Common::get_digest_from_cache( $hr_MD5LIST, $target );
    $local_digest ||= Cpanel::Sync::Digest::digest( $target->{'path'} );

    if ( ( $target->{'isdir'} || $target->{'islnk'} || !$target->{'exists'} ) || ( $local_digest ne $rextra ) ) {
        my $dfile = $rfile;
        $dfile =~ s/^\.//g;

        my $trycount = 0;
        my $goodfile = 1;
        my $usebz2   = 1;
        my $pathtemp = $target->{'path'} . '-cpanelsync';

      DOWNLOAD:
        while (1) {    ###
            $trycount++;
            if   ( $trycount % 2 == 0 ) { $usebz2 = 0; }
            else                        { $usebz2 = 1; }

            unlink($pathtemp);
            ### "http://${host}${url}${dfile}.bz2"  -or-
            ### "http://${host}${url}${dfile}"
            if ( !$skipbz2 && $usebz2 && $dfile !~ m/\.bz2$/ ) {
                downloadfile( $httpClient, "http://${host}${url}${dfile}.bz2", "$pathtemp.bz2" );
                my $size = ( stat("$pathtemp.bz2") )[7];
                if ( $size && $size > 0 ) {
                    Cpanel::Sync::Common::unbzip2("$pathtemp.bz2");
                }
                if ( -e "$pathtemp.bz2" ) {
                    ## TODO: meaning what exactly? test with dashk
                    ### TODO: I have no idea myself. Maybe someone else will figure it out.
                    print "$pathtemp.bz2 still exists\n";
                    unlink "$pathtemp.bz2";
                    $skipbz2 = 1;
                    next;
                }
            }
            else {
                downloadfile( $httpClient, "http://${host}${url}${dfile}", $pathtemp );
            }

            my $size = ( stat( $rfile . '-cpanelsync' ) )[7] || 0;

            my %expected_digests = (
                'md5'    => $rextra,
                'sha512' => $rsha,
            );

            for my $algo (@$allowed_digests_ar) {
                my $expected_digest = $expected_digests{$algo};
                my $real_digest     = Cpanel::Sync::Digest::digest( $target->{'path'} . '-cpanelsync', { algo => $algo } );

                if ( $real_digest && $expected_digest ) {
                    if ( $real_digest eq $expected_digest ) {
                        last DOWNLOAD;
                    }
                    else {
                        print "Digest mismatch (actual: $real_digest) (expected: $expected_digest) (size: $size)\n";
                    }
                }
            }

            print "No valid digest found\n";

            if ( $trycount > 1 ) {
                if ( $trycount % 3 == 0 ) { $httpClient->skiphost(); }
                if ( $trycount == 10 ) {
                    print "Tried to download the file $rfile 10 times and failed!\n";
                    if ($repo) {
                        return 16;
                    }
                    $goodfile = 0;
                    last;
                }

                ### "$url/.cpanelsync.version",
                if ($repo) {
                    $exit_code = check_repo_version( $repo, 0, $httpClient, $host, $url );
                    if ( $exit_code != 0 ) {
                        return $exit_code;
                    }
                }

                downloadfailed($httpClient);
            }
        }
        if ($goodfile) {
            print "Got file $rfile ok (digest matched)\n";
            _goodfile_handle_chmod(
                $ar_chmod_excludes, $root, $rfile, $target->{'perm'},
                $pathtemp,          $rperm
            );
            _goodfile_handle_rename( $target->{'path'} );
            $newfiles_ref->{ $target->{'path'} } = 1;
            $hr_MD5LIST->{$rfile} = $hr_MD5LIST->{ $rfile . '-cpanelsync' };
            delete $hr_MD5LIST->{ $rfile . '-cpanelsync' };
        }
        else {
            unlink $pathtemp;
        }
    }
    else {
        if (   ( !@$ar_chmod_excludes || !in_chmod_excludes( $ar_chmod_excludes, $root, $rfile ) )
            && $target->{'exists'}
            && ( sprintf( "%04o", ( $target->{'perm'} & 07777 ) ) ne $rperm ) ) {
            chmod( oct($rperm), $target->{'path'} );
        }
    }
    return 0;
}

sub _goodfile_handle_chmod {
    my ( $ar_chmod_excludes, $root, $rfile, $origperm, $pathtemp, $rperm ) = @_;
    ## if file matches the chmod exclude list, chmod the new temp file with
    ##   the mode from the old file
    if ( @$ar_chmod_excludes && in_chmod_excludes( $ar_chmod_excludes, $root, $rfile ) && $origperm ) {
        my $real_origperm = sprintf( "%04o", ( $origperm & 07777 ) );
        chmod( oct($real_origperm), $pathtemp );
    }
    else {
        chmod( oct($rperm), $pathtemp );
    }
}

sub _goodfile_handle_rename {
    my ($path) = @_;
    unlink $path;
    if ( -e $path ) {
        if ( rename( $path, $path . '.unlink' ) ) {
            unlink $path . '.unlink';
        }
        else {
            unlink $path;
        }
    }
    ## the "rename || unlink" clause ideally should warn the user that the file did not make it to
    ##   its production location. but this, as this runs as root, is hard-to-replicate.
    rename( $path . '-cpanelsync', $path ) || unlink( $path . '-cpanelsync' );
    return;
}

sub prune_OLDFILES {
    my ( $hr_OLDFILES, $rfile, $rtype ) = @_;
    if ( exists $hr_OLDFILES->{$rfile} ) {

        # Handle transition from directory to a symlink
        if ( $rtype eq 'l' && $hr_OLDFILES->{$rfile} ne 'l' ) {
            foreach my $old_file ( keys %$hr_OLDFILES ) {
                ## delete from hash all subdirs of $rfile, which is becoming a link
                if ( $old_file =~ m/^\Q$rfile\E\// ) {
                    delete $hr_OLDFILES->{$old_file};
                }
            }
        }
        delete $hr_OLDFILES->{$rfile};
    }
    return;
}

sub handle_deletes {
    my ( $ar_FILELIST, $hr_OLDFILES, $saferoot ) = @_;
    my @olddirectories;
    my %EXCLUDE_DELETE;

    if ( -e $saferoot . '/.cpanelsync.delete.exclude' && open( my $exc_fh, '<', $saferoot . '/.cpanelsync.delete.exclude' ) ) {
        %EXCLUDE_DELETE = map { chomp($_); $_ => undef } (<$exc_fh>);
        close($exc_fh);
    }

    ## note: loop on @FILELIST to prevent mass deletion on an inadvertantly empty .cpanelsync
    if ( scalar @$ar_FILELIST ) {
        ## adding 'sort' to guarantee an order for keys()
        foreach my $oldfile ( sort keys %$hr_OLDFILES ) {
            $oldfile =~ s/^\.\///g;

            my @BASEDIR = split( /\//, $saferoot . '/' . $oldfile );
            pop(@BASEDIR);
            my $basedir = join( '/', @BASEDIR );

            if ( -l $basedir ) {
                print "Skipping cleanse of $saferoot/$oldfile (within symlinked directory)\n";
                next;
            }

            if ( exists $EXCLUDE_DELETE{ $saferoot . '/' . $oldfile } ) {
                print "Excluding file removal from previous tree: $saferoot/$oldfile\n";
                next;
            }

            if ( -l $saferoot . '/' . $oldfile ) {
                ## ???: what sets the .keep files?
                next if -e $saferoot . '/' . $oldfile . '.keep';
                print "Removing symlink from previous tree: $saferoot/$oldfile\n";
                unlink $saferoot . '/' . $oldfile or print "Unable to remove deprecated symlink $saferoot/$oldfile: $!\n";
            }
            elsif ( -d $saferoot . '/' . $oldfile ) {
                push @olddirectories, $saferoot . '/' . $oldfile;
            }
            elsif ( -e _ ) {
                ## ???: what sets the .keep files?
                next if -e $saferoot . '/' . $oldfile . '.keep';
                print "Removing file from previous tree: $saferoot/$oldfile\n";
                unlink $saferoot . '/' . $oldfile or print "Unable to remove deprecated file $saferoot/$oldfile: $!\n";
            }
        }
    }
    foreach my $dir ( reverse sort @olddirectories ) {
        print "Removing directory from previous tree: $dir\n";
        rmdir $dir or print "Unable to remove deprecated directory $dir: $!\n";
    }

    return;
}

sub lstat_target {
    my ( $root, $rfile ) = @_;
    my %target;

    $target{'path'} = $root . '/' . $rfile;
    $target{'path'} =~ s/^\.\///;
    $target{'path'} =~ s/\/(?:\.\/)+/\//g;
    $target{'path'} =~ s/\/{2,}/\//g;

    my @_lstat = lstat( $target{'path'} );
    ## two slices to assign @_lstat indexes into %target

    #'S_IFDIR', 0040000 == Directory
    #'S_IFREG', 0100000 == Regular file
    #'S_IFLNK', 0120000 == Symbolic link

    @target{ 'perm', 'size', 'mtime', 'isdir', 'exists', 'isnormfile', 'islnk' } = (
        @_lstat[ 2, 7, 9 ],                                                   #perm,size,mtime
        ( defined $_lstat[2] && $_lstat[2] & 0170000 ) == 0040000 ? 1 : 0,    #isdir
        defined $_lstat[2]                                        ? 1 : 0,    #exists
        ( defined $_lstat[2] && $_lstat[2] & 0170000 ) == 0100000 ? 1 : 0,    #isnormfile
        ( defined $_lstat[2] && $_lstat[2] & 0170000 ) == 0120000 ? 1 : 0     #islnk
    );

    return \%target;
}

sub _usage {
    print <<EO_USAGE;
Usage: cpanelsync [options] <host> [url] [root]

    Options:
      --help              Brief help message
      --nfok=[1|0]        Exit on a 404 response from the mirror. Defaults off.
      --repo=<name>       Treats the sync source as a named repo that supports versioning.
      --signed=[1|0]      Enforce GPG signature verificaiton for the .cpanelsync files.
      --vendor=<name>     Specifies the vendor to use with GPG signature verification.
                          Defaults to 'cpanel'
      --categories=<name> Specifies the vendor keyring to use with GPG signature verification.
                          Defaults based on the globally configured TweakSetting.
      --quiet=1           Suppress HttpRequest output.

    Arguments:
      host                The mirror to download from. Normally httpupdate.cpanel.net
      url                 The mirror URL that represents the base of the cpanelsync repo.
                          Defaults to '/'
      root                The local directory that is being synced. Defaults to '/'.

    Notes:

      This script no longer supports syncing directly against named cPanel tier targets
      such as RELEASE or STABLE. The cPanel update system in all releases after 11.30
      uses a separate cpanelsync v2 system and should be updated using upcp or updatenow.

EO_USAGE
    return 1;
}

sub _parse_argv {
    my $argv_ar = shift;
    my %options = (
        nfok       => 0,
        repo       => undef,
        signed     => 0,
        categories => undef,
        vendor     => undef,
        help       => 0,
        quiet      => 0,
    );

    my $usage_flags = {};
    foreach my $option_name ( keys %options ) {
        $usage_flags->{$option_name} = \$options{$option_name};
    }

    my $help_called = 0;
    my $usage_cr    = sub { $help_called = 1; _usage(); };

    Cpanel::Usage::wrap_options( { remove => 1 }, $argv_ar, $usage_cr, $usage_flags );
    return 0 if ($help_called);

    if ( $argv_ar->[0] && $argv_ar->[0] =~ m/404/ ) {
        $options{nfok} = 1;
        shift @$argv_ar;
    }
    my $host = $argv_ar->[0] || '';
    my $url  = $argv_ar->[1] || '/';
    my $root = $argv_ar->[2] || '/';

    if ( !$host || $host eq '' ) {
        return _usage();
    }

    # Block accidental legacy use of cpanelsync to sync /scripts /usr/local/cpanel paths
    # Only block if coming from cpanel servers so we don't break 3rd party addons
    if (   $host =~ m{^httpupdate\w*.cpanel.net$}i
        && $url =~ m{^/cpanelsync/(BETA|CURRENT|DEMO|DNSONLY|EDGE|RELEASE|STABLE)} ) {
        print "The use of cpanelsync to sync /scripts and/or most /usr/local/cpanel trees is unsupported in 11.30+\n";
        print "Please run /usr/local/cpanel/scripts/upcp --force instead.\n";
        return 1;
    }
    return ( undef, \%options, $host, $url, $root );
}

sub _wait_for_mirror_lock {
    my ( $httpClient, $host, $url, $options ) = @_;
    my $lock = 'locked';

    my $sleep      = 30;
    my $lock_count = 0;
    my $trycount   = 0;

    # Check for Locked file
    ### "$url/.cpanelsync.lock",
    while ( $lock =~ m/locked/i ) {

        # Unsigned request: no trust anchor, content is not sensitive
        my ( $lock, $status ) = $httpClient->request(
            'exitOn404' => $options->{nfok},
            'host'      => $host,
            'url'       => "$url/.cpanelsync.lock",

            #http 1.1 on the first request, but drop the connection on the
            #second one to not tie up the server
            'protocol' => ( $lock_count == 0 ? 1 : 0 )
        );
        return 0 if ( $status == 0 );
        last     if ( !$lock || $lock !~ m/locked/i );
        $lock_count++;
        if ( $lock_count > 20 ) {
            $sleep += 30;
        }
        elsif ( $lock_count == 20 ) {
            $sleep = 120;
        }

        print "The update server is currently updating its files.\n";
        print "It may take up to 30 minutes before access can be obtained.\n";
        print "Waiting $sleep seconds for access to the update server......\n";

        $httpClient->disconnect();    #do not leave the connection open

        if ( ++$trycount % 30 == 0 ) { $httpClient->skiphost(); }
        sleep $sleep;
        print "Checking again....\n";

    }
    return;
}

1;