From a7980f3dc4617cab82a0194c386fa464e01d5670 Mon Sep 17 00:00:00 2001 From: atomicbit <63680982+atomicbitty@users.noreply.github.com> Date: Wed, 16 Sep 2020 14:21:47 -0400 Subject: [PATCH] Some fixes and tweaks in the Ext2 filesystem (#25) * Some fixes and tweaks in the Ext2 filesystem * revert my .gitignore shit Co-authored-by: atomicbit --- limine.bin | Bin 32768 -> 32768 bytes stage2/fs/ext2.c | 81 +++++++++++++++++++++++++++++------------------ 2 files changed, 50 insertions(+), 31 deletions(-) diff --git a/limine.bin b/limine.bin index 9026b15d645acba042a99bce46213a6ff30ac6a4..220dc3c5251e74fe31576401f49d4d9def8b1302 100644 GIT binary patch delta 18083 zcmV(N#zHi*o+WhS|PHD9~CNF zZyYQ9SV1)2|D1c@41?P4{{HMbbKkk=o_o%@=bm%!$D6KA@O*6C&2iQBtsGbEf5YO% z_kFRmInGM{AqjdZt`aIpv?Lg$xE-{ZS*KR%T+i&}xXm22xgNH)6=9pUz*kw^wOt%n zTCOP?$kjP#bi)JZFwm-oA_T6gtJ(-(WznVO&nSwLG-Km$26AF2YghFrcqol-NK%YW zIc$dVCRSl*&U1Rnte5`?EmTYne~2`2#!`#M=?PPblpJtGHHKqf_;Sha*Qpy zI>>Qb(N(>e<~qQa6aicE=3Yf{`ojFrrKj&fK1maBdeJ{JFnLTZWp|dGaNN19C#pIMNOhgk^rZ0n z4my1k$U*Pb5t^nU$NeW4KlL<|nRrc}vf-L(!^0c~euIbK<#EsE6n`X;&?fo+Ve$ZR zjTd^+nmn{YS^Tuy`=J_=W&yGeP&z0!*>Ca`O%LO+eV59Z^W1PEe{_%|#C#HrRXzr4 zAl^+I(X54b;94nqkaJ`ba~li}>69g?cX=dpn<%(r6N;t}o*_o(1c@-IH|CsR5v2IZ1(LMD7q()DDjAA8U}Fwfe)wn-)&M{<$0tV}dN+Mxpn$iI?{r>=h zi=PT09+aYruk-@O8om2@4VhRvTrb_ypoFo!9%Qj(YOQy5$YQSIxXCVZPhxo zbJ(N52V(%EBMRp2v=DUdXfqvV)-u|k?7JH^kPh4tJE5e>8NXuTJpLaW9r z0aMVK9y)X9Tngxf@;tYXXVK6o9AOL}tscS{e!o$uk3o~~jBIo0Op5;&#yTU|jwZht zI40&wWGN$Ef8Ov^fKSO;tsX;*O`prI`XAruCIy&Qi(zp=^iHRkj#|@ zJKe&OAh%ES_Hk<~5B#sZZ1zaqpFa_RhuI_bn@6V5f?@M$DDax_aqyL%vCw+95HR#y zRW$cz+nb&@+uxMmZ03!gk-hxgp0j@tP_{Rl@3)a(e;8Blw@JSkox;DzZ;BXU+hEJI zJ#Bl+_Jr+m+hW@ytTU!u{fz7B!yTDod(NFbaQmx5Ta__{m&~W1T3lC-f85XfjkhTSCZ~K>^o0~>!~uxo!Z@yG zD#+Iue~thwNef2m8p9{2uohHqG3Dpw{!I#%J6LhmmT>Fj6vuFsVuxme=d)W;Ziml= zr7HB_eyz>q>EVraMF&BUy0eE-kUb#Ci8t%sJoBdi%_As?M0q2W&$^6-I3A=?a*T|Y z=8lZLxaH}m>J|d0dU6zN02Y1mebW5&4VVdCe`|CXxA+b2mw3hP7_9tsamzJm3urGv zvjDljoEcd5u=1-Eh2Q7#hmj`02$_HN0Yg5@4EaR$Ak~mbSL8R08va#>S*K|Rr5}DCK zvk3_Cse4&Sm+u5Gl1Lv5qvRp*uo=tJlx+BvHSj!^R{9^gS>sa}+-AH4k6H>$=zeL4 zd

$PjIl2qY2uo9;`iaLCu|pBt zgET^-D$OdU(2VE2sf9F^>5HyRb3{O%JT1w8!JVo}XmCUntyQ8Nnnz|O9AEtv8HC7? zQM*%>GK&He*r6+F@#~7#fA&UUY9%*l0$GOhT(ly_Dk6Lu6j7h1tkNqMgR|avASiGw zvC72U!S8E^q}R4-A}k$jUO9~4?IA*^lxg6%w?VeOX)?gwx>6#XGkLUeqv44_q9vYl z$G%-1fdRg-o!>P%;z+MlC_BH^h+0Ur$h0}m{W|9rMLd-!zT5CmG=%x&FxgMKaE%O+(;d`+x z%GFxxpD(_%=!t-0i)QF{<7`Q#8kPp(LP@#+*aV zCm(~!iWIw1o5->Je-~h(A)Hd~>tZ@Cv{(mm{W@q4c7UY4r?qL-&>ogBK)aCAK2R4_ zM6^5yDkUl&By}^kQ6g6px?UbhI>)sAvFqxx&kfo^NX?QaX{7l&X^x({yp+eE_J7eJ z$i_{$?t>B9w3VjMouqfn*UTvRf?BPC!|5h;3meMH=zxv18-N5`Z>wkDVZKu$zYIfX8D@4#k=U)CFBGZvS&v;va++0zF(o|&!} zb0yXQa!&|Wf9Q<=369ov*Np%nCuG~BB+tPfZ$f-2%rbJ8Hxn;iWUj&`)xi zr;lWn5&TFD$L_^}shjah{`MzyYqaxl^ zzQphPJ9w9>f8uJg$LzRgO>EUAT26J`R&|+{9`)<1F4B_4q2>2^r9!rJ3{Z|#DK`q2 za9XhrqUD{Ja1FX3;PC6C1MOhhFV_OS%BY%FXz)X&vF7jijWIzZcl?OWFenYB7Jw1U zLQCkvf6HfL38TrbBrGk5(nVUz#dt$&(PK`aCG^BYXbB_L0$RfOlut{@S{P%k&$~V2 zF7$**)Pb(sEqXFCmfkL(xrpoLw$e6_totD9@~P6}&eOc6xm0-9>(^6g>8F=ZInVH# zI!QR`mG#66u*;_*33SKmKgcd^zI=*!%Y>5vfBi7(^64_`NhGkJ-__!tJ_I|%gs9#? zJ6nyN32jIPmM)B(P|5E);ePbOJ_Fq&_+wWu5w?=1Y8)|`Q{X+^v$ef>o_vTkQ0e}S z2iAA|?gLu$*1Q8dA+&j~glW9)*GI-6*rOG;Vsy&p5c{fIm$XO6ietR|F5z8G(;vgf ze+b7FXN!_|ylB3L`xrmEzQaDP+ccTmLL@Pt1R*uh?7*@E)5+)L3s`NI2|K9xW#%1$ zO4A9=`5{-!gi2Ont)vQs>@m+1Js7&i9R=Vj#=0#e-Z{_3yR8Ody@c!iG4ULCfJMPQ zxDF}4%5hPgV+{GaS`WFvFS4D?3*plb0d4)xU{~MTaC>M(Z#Z!x8Fuh<&ys=T)gTr39p>n6-BWM~}`+8TvcJ=CYU1rIoc z7q85 zf2;VEG6Jg1TN{OKsFQstf=L-GZXH&*EuoVf9(u*D!^F&zAqiWx;V2S#f7x=aP-&6( zo>vr&SUIF{2XN#2TQBa{gqT}8IYK^_21<){{FZ}}-cykpvwldXVR5F<%%TY$vL^!r zR7rp%Azrc$Cqfgk9x`1vDT!he?l>IcoyX~bL9!4pB>{39v7Th3rRf~f<2JX08s;nF zNkwc+v&d)Wp@kWV;E{xOf63ZGgeu%PF*iw>hsK;AdKKJ(WIZ`ns2XP7O9aS(S`*F9 zq-~hcY9BzLl-Vko4Vv@BybZc^dUP;R6|q$jn~{U0*|>HUPD)l-!Fu@Zy5r!=Br}wr z{8XoDBf=IWpXuoud0cDVq7|xQtb5Ze640`4#r7QCi_wbBF@>$Df46w$I=uxf8F(%w z<~IVyjJ`q=!TCb~1{Likour4~)*R+N8y2wcCT87-n00SW5Sk?6&@f>e@BEBfcavm2 z#H`zGZbpqQ%m8ieG*fL!=4L6gm6*#(<~qr|Rm$8p*4#8K^AIstlFS|CJh?j7Ts|yw z9Wi@ICW@YrSt(`ie;AfoZ#PJ0EV7#FfzW$`w;Gukdbr>grw6i%cxkp1+-|#1hbuzQ zC2)o61oM(3U>;%KQ(>&51QDm?&~E2u1ipWo%lOWO z0ej2a4qB*GXLdp-B~d_q#~@rOECnaElv}Ektnt#UC;9D-f6#Ad*RxM*J_SpTvF=E- zxXm4sb)+Qhm1q8>;zDk|{R=?L>Ck)%a|Kugw+oIHk=s?|*q?AN8vXYLsV@prUld9` z(BRB9I(a2?mDb#(i1mu-kuux)?cZQW?Hcgfme@m0}bU!(LzPtP_&_kM1IUMw@RL0|{I9w57dO_D1gUJ=2 zGvLlp15Da4mU6jto2c0GAU{XM2xW#$q6=~fDtSUZ@ z>jZM!^|lws&1S5hp{2YaS-YXaB^e~1l3>FpkY@!E=y2{@7KhY33h z?m|UE3`wQC(Yz}W?V1|j7_(<+X1)LOMqw+P1=OD@;toZuWRq9kn##5`(Y;jd!DXcT z*Pz^XQ%hoD6KNhMRM|(lV|la$=;9x}tcx~khVAaz5t>AyL)0ew5AfSF_mVbK%UHoP z%v#Ufe-+HG1OXgGE4V9|5Ky$Xsx{`VTC)L1Xps)EV6rv}TNra_$w1pFhe?H?iiNTK z_Wjz2$C+9nIz)n6B+)~}w;F}@h^`ghim|RwvykIbguK2-9RLRpx=c%hC2npOSi0XP ziA_@Bp)q3f(85-YxOGV3HmR_6U}3XkAvHp(f4)d68*OT_VAK1t>DWfW!*o|qJ&4%u z&gd=f`5p$9f9*pIBm&OBTsO|BZC%Wch2|TE8(biaMAa11o`XFRYj5#aCg{2+DY8|B?2~UZX>Y=NQbHS1A#6 ze?z(oIUNSpW3G}i_ZH|h2Zo%0sb~cECt0_F8pFNq;ekmD{!b54Lw@=S<-Houk4z_= zFVE#11NhzZ7MY-FZV?rIFTWk#eN|UZGwV=;pex{4`0aI?M)<}e?O^CJ9h=vNG`;a?*=uqgls=(-R;6ES@}m` z@Ml1~Fle_|b6vZ$m$7JI$(n7(6Ho9ZkmhkVuxOgO_y$3X;@VhT7IPYocm0HZbLW#d zgI_z3+}62kbCE;bDn|a8Vq6QbkBUWz$86O5ZG=hDGz>YqFvDGu+s8pJR~-uXz(uq zNu#~r>WUloX)r~(uD2doc#%5hk|q?@E=Rc>;}~(Nb`{c@+L)xHcI|fHW2(L}$w0Te z^v>>HQR_Si+2oC37!p7d?Ov-Rf8FwZY}U}IauDZ0>_2Iwcmn=$Zu6U@hjhwX7_c&! zC-P`uhVE5O*Q}Y(hVUyKLZMxLr~|jCfYZrk!vB;e$MU<)>uu!GTVb*Ac4>0FB)(7V z!zJ-UVmC^KHRRVL$)ltB?G2hHl042IPKlD{>rLzp9hz7v?t#0u!KXYGf2DM-gJPqr z{3?z!$07R*7g}<^1x|eHwJfLFiM2)3C)_9M6^iNiNv>v0>vzMlDVn(6fU*fj9qY7U z=M>33d1{$%T8T#-p0O~^?fM!(7WuvJ6s4hL20oyx^(RcfPaHSDubza|yHhlTQUb&V z*XvNw_@f^#R>DC(@qZWue+&*g_qInz){zbCsVo>l=~hPVcTlR5`*D6)WMwcU4 zDpE`QF1P0@S}xK^a3h#^E(*g#J2vTN_43=jT2~v28gRc_N;0Mb$pzzIMJ3WF&~}Cv(D>Ka;?!TLaqmQIO=mT3yvoZ?0jCQG zyJz3oT|EE+Pf);c0Q6SlT3wz40B0@IfyqA^XjCCNumYpw-iDI!4pg$c;%jP7NLhaN z6pM#?47pUeB;Oy(vI+Je=rg@vhxjU%kv}cKO zA#<$fU-(Nx!ETokE6;ROYbtSp5Axwvmp+!T9G0#9&k~M-jdx*`FQdXbJ2g{NEWGO})DCsWoMWjpFIIXg9>-DpS`zRQ zfAe3nHG!Oz=Aot2+4`W7R8UW^`vi3(OV{vb3`v&g5ar)bv;8 z9So7sp^{#s=yb4rX=vJu^a-_83vQ|)8ddDGq>R~a!|gBw^qT!rn3Sdqm{ZE+n2f1G zEe(+W`~%3xx>Z$9HRXR-VlH46<~1vhdc} zl@XoABj`Qr+(|k%_4+x96PKuy7~^~LYX2J5`s|mPpXdP}=hFwdAzJrNDoa{GWSvYZ>OnyI{8Y=CE4jV2-T_@2ZlH)Tl;Z}As zD{iCGV2!L?P?tk`<_U|Y-X}&Rv2qo?r#8DsQC)}I9$#gop@upV@5OgWQzI3Zr8Ves zs~@6ix4S~7G9#HXZu)(E$$U^me~HI2ury4e&{_Ud4KAFW8s-{khD*DVYVkR7t&Vq= z;QF62t^H$~McIk<%13l_;3E_o?M|ZYO)Yrnrv{IeRFy`4mkZCf z((iGlP10i}if9|fb<*V%mn2$PT>dNCk&!7fNQbeH^2uE+Wc!jaknDEFVg#W&@jZw4 z6vL5=BHu$ag`_iZ5l+`#e~W}<4&N)0# z?l+09TW-=YuUig{!~LNuOkZUY zkJ*J*^$H)qZ*a*0$FQO+qa2gmFKgV^4m^NghU4}%xk!5bUrP+Mf8``3!S|vTXx6RL zcfTA~mZF)ygfBsd@ye9xR=(s%KzU`z^x1sL=eUSUcVzj7Lgn;DylV)iymmc|h+PL! z$=cyNhA1MG_>$jayFt^l9fi~Fjyrt+z?!wZ3s0BbcAdo{4K$rdpYMB@Jxc>!2gJLo z{|>|Izg^M-Rq#fUf6}8mjh7ts|AJPi(m0O7DBcG)T--x1AjZui){e61(jiGGo4HkU zIH65E)1cveQFwcg^`-8|`EL*D+dmSzfrzFukF>LawtobG)6zo08c?8LkEOcf%&xZg zQqugsfhtM_a`nf6$MC%xvb8?EXhtc$ndHJ0nm6&Lyq3ySf4@7P*EwO+pdUB+Kd1eT3=n%eR_IV55^tXg$tGmEbvzIduJyaaHu+z^h;X&Qxgw&&FG zO{M;iQXG;hf1ZIzc&mwjb3NT4kqoaEpTb)s(vz?1iqC+4Ux_?M4j%STTL0=~Sl~EM zX(m1CZYRTEO`35APh>v-S1la4dl}LKdx93P?v3QQQM64|@hRG(iFgnDCY4RVF4{Gd z=DONR8DcRp=uIFjxKlM`5Edlet7O0T>_F3g((G-Ie;8GiF>V7Z^FX-aM^iIa-(qSG zz3@8UJ-k`cZq+ycJnqtm9Cw{VBWTC9sf8VM#mRgAPK~}&so4bJA8PKxPt$=)YomZkE<+u{@@`W0_?)`)REYRj%CcG&pe{8{(QppL&5Z>6%*T@F`?sfp;`Zz?v zYtNt`+t?_)#mo@xO({7c4i147K}fkw<5VZ ze=V<*^b*8~Mw-t)tdCh}AfFe1t0*HlM-=&@_&bhkSI8C8pu&ceMio}bPDM*4>l@*; z%NA}-)6nBYC?eJpcIZ}whi)bICF%2V0fSq3WCQNssq7Zgpow6Kg45@#GSO{T6=~5= zAu@$x7ker22ny=|y&{x5g>~`15$G~Ae=FVMRy?6BjPAL{-`xh|=4>*;u;EUvho3kI zmk|5}-sr)rqD6R7w&r<`8_n6OCWPFgT{=OzfBn+Y%A{12C)IQ!)pQ`$)RJntoND^s zZ1R{*2h64xv+0D{)L}-*WwS|1{lY)q*=rQXs5~G8&T~34edJOj5{p+RnLMTwf2ISb z7F3bx`!D>x!9Bu8f%<|?Z=e?xwj~OC`PUu<3tT4b1#4d)zLCN~u=UQWO7wZW>o#hj zRq8>VWHCrddUlE@6;>q_ZsSW1)2m%j-piNNVmWiG1mS8J$*d&e4t9*IX&Z8ZovJKr zjF&30AE{~!_I80>(Uxz8QcUSKe|&BxpC$^GN{=OqmEcS?kwFove7M!TN8vdxF>~V{x@(`grC_{$M(k|SaSt_ZaFV2uo>PkDQsFuW{kIGg?r;A!6RAg$?H`0e?UT7^TwFW zEyxvV8if>LntWP(n$kKR<;yj{+5@;;ie@Ja28cJIN*D6OjJ@E-`jyQJ}Mm{$kFSI z%zG7KukQm~HDI;rgd}crXDGy4nUGnzdX+Sl6z-KQI%2IN$H_Md)@`eQwd_K?^d=P) z6u%35OEm8#=ZBfA>;uVB7!3lCV%04F;blkTi}xcY-ZsLH$(I-3e_@5Aq~YQ_Zczm{ zUVJARnDtB7CxFufNAK)RnjWju!*q5Mf^UvkJJgBL#3X2u%n&3_lEOm?)+WB>aSSwT zqhSuD;4&*-TBReI%|vX~F4D)WGLTFU5$nkpQs$uqbGsyV4E@?ZKq_pPGCL9rn}=n# z@~;lY0CrF+Jd|i|e%nb{%DpaWO9w;DTD?-3C3B(cH>?@h2Cax8Ja5Umld^b#aH z!qv{y$ILgVe@DB8C-EwTwLRe|IX=wV(Km1&bQO29`UHRp9Yfpt534;+5e_-M@%{>w z;TI^wt`it>nlzo8k$1dY6mpX(6;`aVbidGACBM-M=`RNRnn&Nm6P7CZt4{-4gK

CqOcU~w^4vc?nFA_~DXG+U!l`+jNddn?f7-|BC0yo$&*O z4#$fqfBJF|-Jivd)>w>ZhjIx*k(607jD}=;hE{BkfeEBux3PZ+EW~57qZK?c)_Ux; zTSAJbCw$Gokm2|R#h;;pvUq!S#QRVkQ@tOt z4An>QE4=#Tdq`a`r5om_S+v@ibX^)-cIMs+=<++TLQ8Sh#X~aV%fI2Jt>SZgsR?D% ze<7#l!PKCdkcGk*uF^e>L?spD>68^sPJzZX5_2?3jD;i zv325m8no@gngy@#S6hJv9!MGe&^(Sj{eXy=^|Gb@}5R*1l5o~dBO zLQ{tW;CTNEqwujRUBV7@rCDzuJM7P3cD{SXW*@-1( zXA-4oYLSz1$LgXYu2aNvW#>z@l1|(Ussxs18VT!~Kj1yO<$JzRJn-xj2iWb>&603P$}A$<>*rIO7U$Ch+>);thoA1r@R@rr&c&f1f1A5j#zW!Y zJxZ4Wx3nI^lOwv>>guL9mkjWThpTwM+S*7V{4N(B*;wHFd;HE#Mw*{MXj%Le%mdu# z^S0~w-4#FJW^1!0cM+ZcQ2+EIsK*UAR^O}E+pyl%iZ{@qUKgy#LrAPI!up(6yw?u( z`e6M4wf+xSFSO!ZLmBzqf4I1`!EoOWYkq$Btu|MSgO@}Dzk9IFb%1vrpgX^aYJ(}R z10RFmT3CL=w~%>qM=C*^fC$CU!4A!7=F24aYXH# z06x`so*k}lyhb-?|9lP4Om&b~^9bIsnSx#KT%*E`La3%q^Qof_f5iA$s-?`5+dv*0 z8IWe-cSl%qKSVFA2WOjm3KcM$1v&q3-L*;mM>ZSJyMcd*xYy`bG3DI?p9|d;h?|xM zys!C0Jwv5^Nt`Xg)dMBRd}m!4zdHuvz9Md^nza*e4YI99n=~N6S%ghW!K+!Uq?0lY zHllSl4B&UuO-Dq^OzAk)L>s4=0)(LU+JK>DIDAXhj+Hax@Z zn#$~~?+ZjY^D~gtb1i)*#^-2M8cCfmp5{P0O>b)vS3HFce-DjF>NT5@^g7bPeqP9h zRq`rtKSzYgmVZc5?Ft$aZb#7b$iRy%R_vp{Ht-mYPqi-sjvAsW&|e*AxsUJ{n)n3n zLb@wP_p$J&Pq9e%plG0Qr}EBIxJ^Ii5cv+zHbNpmkJ@G#^W~-kwnXz5-uW39NV2@d z9UDlqg1wRXNfGxdVwL2^R{iw8^q;JEqkrg3-va>I zhnc+Jun)(=AHFY)yDmef!@P|S^8z}gG}Y)AQ8Er(e;-la{rJX#984oh-ze^2A%I?= z^!-3HXpAtl!ACfRUjhBmFofSO^NiLCtu%P3*)DP-f72AW7v{F`&eL?{TFG}bI=Jv= z7M5`2DE0?UeIwUle~HnCQJYKCl3)kcH&py$q%OPxLv}%~+!wqPCea4sScp$BNNavk zFqQ?SfA#c>Dn})d#5(lfI@ABg9;W0yOv!twl7m;o+;d0joE@FY^VgWV=NF$FjVoFW zabe__7awBlvBRjfmp`YkBJRYR+^-R`93YLlkw0Mhna`P!C-5zcdtlV$d7tCE4d61} zCE+v~J|he-UV4^p`?8&=_;brmq6+@y&tUoa?IJ z`zm;qX~h6sy;QjuX-J#=`d4(HA76iDHcE{M8VrHp$=;zv0Xzw9_S=i54;Um4A^RUq zIBt)cRc5%gbndN+|3Z@gG)+s8x%|(-^w^73?!v7X|5_D~=UaC}C!0s^W~5HQ`qL=W zf6J)xbQ{)VnQ2aU@1$9uSY?6E=^pVPz-E`##cRW{VQ}|?z8+Dj5hIeFg-x9JD{=?^ znhSL^*#D0(Hc}jdHeoaQFBjPWwD>16R{j9%XCFGJWf$VLQxJ!4@zX`RCq6v5QGk8T zN~DzRL)m5lF6qUlz-EEm30=vD{pyjkfBYa2-kh|D@$xS4QXNfyTg6R1nw+&ap#KuQ zHc)e%Uizd}r}v;WCCdG}X@UsvRTSy$fQb*$O%p z4PQkY@mSzhw6*gBucG}pFYqebTjs#4XjkV2UPZe-Dex-Vl%&9`XmgSRucB$#t7xd; z${Q5S?V$?(I9$C9se&yvAbO(`f0s-5+#2YuC;D!+hP`qPTvwst?D~|>sxPtpz8X|6 zvmZ^NN7cmJ|3%_Q)fb6rWys6K7girLdCFonMLkiD!KLL%pu40Q3b-5bY(o(~aS30G zBVc^7oa@_$w@O@>#b2UO;eP|qyX7Z3{Iq)fN5IW+#!ZTEC0nWFwjz%Me;Blg-YMY3 zDWunR+421R`5C!)0TubX15_OR@e=u=+JI*;F!?pUtMEC`{~1!VA$k>yVDb-;4?4RC zIYz%?aCTpG#5=n$IU@bCvpdI8;6LT`YwWe|rxbrxG6?aJ>4bkfc#t>t17C4Cw$dE| z``-*itJzHqz~E|vzULVYe?xe`AHp})efKN@p+U>}9?;OY)b9JY#5V`pipCoWzZR_2 z0#U605XC)!v1AI;Bb{<}6$>T?OGbu#4yI{??oRIUr*Rg!U6`JzFRU+mA|rPR^L%2#-2_dgxeoZXilBYa+Z$8iwv!czeDQac^8S799df6uy3I6irlL2HoO za)f>ae3*cbggX1ysj!S;Wxe)y9*&7Efa$JAzry-G+ zE6|1ppWCqwoq|xAF1cIj-9;MyBWYDfZ@-I=3$Xd`uV4y8Z)=`78x*12$d`Oi4K0ax z@p#LZ9-RGo27axkr~5^c8|m?XChj(Rh4dso)x3jWcd%Ee^09-7SMU^+boRS3a6Zti z!G-u7w8N)pfBS9N?oZH8c7CGX@J0kp8YT`)`1_~7e8XR&h}P5hC+Tp7Uf;(FZ3>h2BP&Ab*YaY~@1Q%iKq4Vg4Le#r_+;tUJ^ z(3IQF(X~T&Z&2>%{dlJUl@fK6+ER8~PO6wnH8ma6tGdV|4g;ZBgz^Cz&(&9A{Hvp@ zOl7Bze{zr1a__;44RsjK%l8C+Z(!Y?;OpvrSKAt0XdG{;4tfr>t4_jA3wp^7C*QLl z1=Al7h5$-Xax!n+~U>@rY9*{t$V#Cf9L{}BJi#;>Y&R@PZSNsr|>+n*o&zX z`P`%sH~wG_42(kGtWkE-Ex#txBmcDnANznfEhLIfK2>|#g$dsz@@t)zV#L%UHnHo; zuMLgPz>iTiI@hTsLPw*|MkK0i60dIbx@i+afzJAPWhd$(cO#D7DKGuC4Txm9Moc9R zf5Y?RPboW5zq$7#MAsjNste{2Jl?0tVZOTqCITqe|(>xF61|_rMRFyf7`mU zJvhv~UP}Qb}s*b);H67Z?ZTr*+(bgBLjMcUe zt_vi)&Z+wfYOs1ma-s8dwrfZOf4v&uSRt=%!^_KU!Kj5X>n5a@1xWevSD$W%G2sUl zLuI=!ZrM@P_2)w()&>+Jh6&-k%3{@3j8#|FSk-||@}LQ%S}azXKLp6a^UO}XSpA6l zFc@p_QY=uPO#Kv^Zf^O9m@n4;f5oa_1!7gQB^S@!ZW^xkci>e>?{E&&(T>6kQSmlAKR~9u3R&3#=`Xv9Q1~5MiO=abK0HdVE z5m{P}I7$BR8;U$M8d0;)KZKE@k$b~+#tM#ht#iYa#-wQaJ^;I0yD145C2_OyV11^Z z%r}rhN%ZHrW~;YC7@c1pe+r}@jojzDuipn+wvPNqffmzAb%}vNKrY$)uVQEiy?4LuU&YXlz8JdwuQ!jOz3=~g3{5^5%wHG6 zI5~i@@5m2$6#O3qQ)(7B#M8xJ{o8nI+wrsU^!nII10)KWtDvcPe` zIRzna*MtPfM-lQyO=y73LeL8}7$DW;-G{Fsgjk1EOZN}x%dTX`&1^*bDUMnrxAv(A zqQE|W|JrSD%hPe+B00J-`37T4){}Gtx#MPpY7Q`?Eq?b80uUOu^t*qss7z)?H_rUO znC+?qjHQU!H%o!ifA_y$njv4^O<5x8u^7eIpx{N-{Y1SvZ#B=qz|W|zA9mgiFMke*Hu8LEm_$Xo0Jl5BgygbeG7cw4&SlxeW&};cz616 zi^ZLMC;Yn|Hx1G5N;i z!=*T4ifU=_z`Wz+4S9!0%{xv~A4_BQlvZ$#>plu*A35)`?Bf;fO|y^p-|d%uguVN7 z*#}g<{BF=mf9>gHeyim#C<4nl?r6MO&e74==wN3c=eW>74@Dr~AXn5}!`BeZGER50 zpYd4A<%ZF>>gjv;o$}KxeJQTR=hWZRK**Spz_SJBH zS92Qu8K8e+U%floF|~6rs-i@Tj97AS*#T8&psK+c4FILgIRqQGf8%T_E~RDFFE~es z(LK<6f3d-bJE_%ze@%&&GGfQlfgV2YH>nR5sRnUDqR;*p3C6k$ zx8^48P=lJO1+PQPuExlrl*tIVv*w&VJoc2p2MT$-oz2Lh3}MGZs?rCU`{U46g( zlQl>;U8U}>iWnMFFdx-`Xq{i)7;5m{e{D@5^8F3Q&>0^_r>jO{x5Avm;n{mt z=d3r%k+8gUKWgl`c6ROCKmQZJzk|BIAMf4U`P2NR+(F-9jjd)Qu=t!!otd9)#@}>s z`8XSLzhZ}tD#d1M0SuU0w`{S|Gsn*ryg4wC0kb#TNCU<1{@Zog0JJ*qptJ<5xCv-bRkIn)q7!7CkD$R?WRcxwCGykv6$&r$4T*t_JH6 zJZ}f>g&aS-_D?@6|DWg*Ammy%(0S<~%YFCZkZt@HkGVS^$KyD6*0sLZA|x~YDNA!3 z$vmn4_Dp7n>jYo=zw{)DzHma0xLRH?e{@;fyV{&BT-R}O1e~bY<~o7Dk<*dTygHL~ zc6EWb7uwi6QnqqQ=t!trJxYa`PLMXq+9sLXT?ZTyDwV)%5aoRBLFf4qz=HUALS2DA zp^JZgCp4nRrv3(7IVgA_y(@>mPY*qtJMiEDI`pz`p{4&%?$un^G3ODk>jaYpf208J z={v78&>(3tW^NnPbmR=_DfJ#X8+jamRVTBp^w^Q_NMSSn^wm*-{|L{g$wesnBae_a z($gij;{Caj#SwFBqS&!o52*gHpntx$!Pz;2 z2%txR7lbDko?H_xWp+sBlVh$7y$I-daaCwV{J#OdOX<_=WzeetdhP0xgp+gaG?4+;L0N^`G>>$Sh_5<_{dOQOZe*r8<;w4?w z*BPKnE}&kIbbSYd_+`S8g8Lk!p#L#Vz~LQ44G%$H3AM90z6VDusnM_5bH^J_!b6&TH=>5LZp*?+9kG=!=$0>Ov2%U+hL8? zX;OR(6)HEHC(umTZ}*kEQxvFpkdBARDY$< z;R~vpFZ~te>YQtbId>W*?t#If`VdY=HWLBdO*=fop;G717^^Bga98`xCzAU;8iok4;=w-_ZmMFN}v|(10&tMXTF_=)*b!lMik2o7Lka zG2V5VFS&#MW?Z}k12};!(y3IK+Y2_~Yrmj=u0ymYd;@;2e}R8J63^t0gCg)Ze5k{d z%<(YQ*8yEJfMn?WWwvs19vni*Ohx-^10B~vyDl6UpE+c1?#FqwpI8r3-7;M^lERbt zQ^#O)qzxfxil8@CdE`|npd!%=Le|uV>IT#Gg3tSwzQWL&U~Ml*bIb(+AueXo-wA9U zYsKFHBn@Tee?vF~NE;0Khzxoo50HlgD)2S3c^lM-Z&xq!n$T#kbU&_)>BJGjU;k?J zZ-mNTs4NdOeM3#{ZuU1}?F4RuY2u{GQ|^CYYC_htOR{rp0OZorXB#aG(u`czl2v)r zj4Aoz%4{P5EygT|an#x48Mke~Mv?Cr?;0&B&Q^R^%7FV9Z*+ zJby`+BQJlY(Uz6BJSUr*oo8QW%qb|yF8~7Ljk62#R_8!zoN?}~nFxvEa@IN~PBS_R z@>VT>!I-x)JFg&TiNp9T5L#w8iYx8ns#W;~4j^UAa!dkDM%d`cHx}e%WgC|)7wwK5 zq;9kof8?()uE<&ybtCHX{Qjr_T0vP3;!WK1 zLdqPYWoFs}ZqCZpS9C;`>mojs~q=`nOF+g}p{z?bP2%_aVXa{0Jj&by; z>@j_8LZ`-2cH_!?KtP>GaZd}$sZXb*Kh5PVf62Akry1>e&#laIV9Pw#VN{^z0e%L7 z`6i8pMGI7__7{NZ6~^4GewsAeawsjkiYcxHmFKU{Dad*jXwkv42WYX;Ny~X&%(2s^ z*xlWu>~|aU?8Yo38!gb|UEJuE;_~HVxS7Do%6mmSqcwHn1kj)ZOasvKR@(EjbD))4 zYlo(wv48Oa>w%#&=B&-lLQQ9n=Th^Y%T-4yU|9JD(~OUa4jd3x!M!5PP2qBu+ol=k zfdaCOY%~B!IYslrI_t`1EA!W^G}?2Y25#(mFXn)J1;#XC?#uuecU^}{>l`nv%9&;y zwJ3^v=%I%=D`PutrkR_WY?%Wlvt)Tz-U?=1f*AmI_37b)tW~*rOYFwgV92PxV2z~!`h}UcGHXT7 zO@F`zIji$j;(;n*_MF+q>>LN181^LvIXNo<&z`?rq*ES7Wt6x!$Vi{j+yti&jd__B zS&k*SAe?bUel~LuSq?DWRStx~Y_;b&0{8{M@Ux=L2HMQZ&IZ~r3(z?w=Znj;={x{r zGzBoWd`d6WK<4H-9Lsa=1#RSIt-QfdD1XjM|9oX`oV-0a2llz|g=J0qfIX7p?GHercEXGmUw1FiE z=tB>M1|au63w+$SoN_jPiS4<5Jy9f(C7XK29K;uJuC55q#A#97!)Y@usdJLkxqk(7 z%)(>V1zc2=(Fl(J{uRbPff4Y)il``*b2)l$P!OH*(*T6%lOKR6F=@gIbW${2um%Bk z&^>}nMF&RP<>lDNbAwQaD1Dab$OqHNTLKOMqXQVvIO8fDbLi&<BxrZ3!36)f+JgF$ND9?`G5KLoN-7WjD}hhvO3QA%bZ{0V@@`><|X+nR#1hY zzPLw)w0XkZr<2XI=gyfYfaDJvxlwjlL#q{*w8s`a#?jB@$L0nL%={p9|vE z`WoRRf!VPVY#pW$Qib`_H(B}+M~Sr0KuyrIMD?MhAUuz;8sghSh@>;`Z46;0bQ=9j zyqvX5a&ofm)N*J{0Ov%@j(-C1fd8g3aAjWsR*43c3pW2R3G}%_yCZAKGMY{;3XzjV z0;3(|Q{zqFn1N}Fc4(>kI-CTc0)}ONY_@f-z)V9er!PpGGwS!W1_u%2rrm|wmofNf0rQ*&-MtcFmZfDZre0a~7n{X45{Td|gBc)&yKYN^m(u zLj*2J3bKRr*(0S-7de<1a5Q3FPdBjSQH2PpQvbH3a@_lm+<*A57T`VbFJlhJZJX1- z?uz=n4*s>jz;Od!RNc&mnSYHlKY<3b22%XF_&YLwMOk(;{DmR-GY4`YI&MsJZ=6#U?M?8P^h2K) z@{~LK-j;4fC7Mk0A0?t2 zikGk)8^J-#s7RQ=FI;A>*%k#2V;pYR<=xd?`@Pm`+Q!?uD_d%SV#CJ*eyk$!Dt?rx zY~5+B@FPJq?*Dntxif&;?!JF^ojLcM=RD_mp7VU2k2~F(f%(R zQwf-*ZonoS%y}tDG6yN|LJtj+e*+|SoUzcNbGidGBn1Z@A@zYc7XBUdybj>?fk=Z6 zo;|DlkND@A508MF(pJ6|YD`U?mydq~72q@*?R(8TZkEw)u%Fa$UD0xl>Egh$)wKYHZ>KEEI8vBxuQFyJOog6p4W9J z@COb%J(I}cs+*&94MR_R&n|ub1;#U}GP#RJ=w^%vaD?*jx%s_rc`m1Vg8_v;&ihZ3 z8<6X&U=+Q{O*<4t&A6{0XlUFV05$+fJB23ICU@S<01o?iYJ@p2e~lnQJ8357v!JZX zDG&px+SZ0@EwlmEYThq7M=CM5!sL(+MS^yhTQawbf*cW(H*?4=ai&Xk49I&!4G|~1 z&WOQ!Ynx;~JI{O1Q{D$>hB$`DoN`1;x$T99QSn7{@6$n1o;s?)Ench}zGv5 zUT8;MlZ19>?Fc{ne=fIUAZSkt3`mKGIuK)x6d+I4=f!Z2p|ey_SVu@42`JJP4w&uz zCm>w;^QX=QJ zmK#vl-B}1<)vq7C8;AP$tiiMN*aSZ#G}sKTJF_>b#w1;c^GPi z7G0GDM8RM|FqoWi%_kE|^ZZ_##n5`8nGt-ld?+LM<9eYs996y}xYc1Wsor}S=?q~T zs{B%*n3zkEf25RTW!&>VIwfmu;oQh(l3GT@-CFCwR7P+OIiZ?s%Yp$_tWZX}qJ`a( zxin{wEHwM6eYU5UT3fO2f5k;}M;ku)y8txI9UZiNbOJ4eZXXK;UKcn4zLHZGTffN# zh#;;kjN8zET@kiYqQvrZ3}HlwiMf9o7J{uTtlIgecBdX6!>t>I=^=ttrMo?kD~x+SCD46aJBROo}w(1VnNH z99JmmxWT)j85xl%ZG_TUld>4+gValo z(P7g3(Ggd7yzqR@VxTmLoWvHW3%mL;X?)=hf5@25R}5Eocthpac~y1{QGdL;;}-M< zu-BoR58aI&xvp5%94HB^0PNF+%AwQo>F+nuug~TK;?Bm`R2&H?iu`s z$?)VpL_ zK2$jZm84pJLLJxG7uO!BW>BPF`3*cIB`vn7Cp=lYyA!sO;x6ltd-3hKXHnc3f0ap{ z5(8fg7p5?HuW&c4_xAK*H@L^gE<Y%4O7@yR^DAwB$ma=4YQ# z#dcL}^W*3fRcTf+jb=QTO--bsC@Am7497solV`+vugHnIm^#P6yme}bL-*vInA2;& zAcGMYGHN+dEwZR!zz#z}f0Ngcx2`7yQ!AxT=gTsjm%>yrLKWdNR274g)HOk>CDd7K zJm_aQf>;$|Zs!j)Legv7mIL!(t5O2^&)h`lkWxeWU9FI9Z*xGsY$zncC6ikpnF&t> z5-stP9PxhnKn(D?ZT#M;1DkuKT*dj7PSiu9MP|%%RvVl*RPlVAe?GOt*%c=K!&w{A zFP#8)P6UNC66+;$h?qMhF$e}Fr>f2y7RsSNpdu_J$4NEmQl11?!SA}is~IVovcesz z54?qCQ7P9`|9thsCC~ZTANwU$IGVQDZfl%)G{<+KeE@VlyXt$q~JnjpzyU_*Yv zhP+(FDW||#5n~rhe-kNI{sbh{1yantL(Ig578@Y4-vEvN0T6Z71$|OE^oJ!3;LfGE z57zhv5vI(8Mv1ZqN!_eV6v@q)&NoJrj&ZH;cHUfZG*mwrv00KNowU#(%?qL~FX5RN zyvOPU#kdXEeK14Y6q-JFke+d0LjU_n2lR$cf+ATjN#+jae@*PQ7n;C4jR z2X-|3EdQETVlwqq^!UW7^Zd0(BY|mv5{sU48eQt%kKGWysK-xc1TJl910?x#XAX9} zI5SAhlvoGIe?1{sp)>vg9IflRBXj{n!i#5P38Ts0I4tdi(p6e2!FWSk(PK`cCG^BYX$d3MB3i=ulub)WS^y)h z*Soza=eqlF)Q+xO7TqZ+%kNVzUd45DYhkNfG5js$`uW1s&I`P*u~7J^${R#$3lCjC z@4U$CY9!%ol@dg%pzitwNCM@EpueRTHeNqZf2xXvvrzj<$n^_F*0YG9n%~1EHJ=tI8HdNI-At2(|HSZ+~@ew`8AGd-Kk66*@qMJSzuBJ-43oeIFlSD$6&QtBRcNBoCaO=)K@y>ZEO16d)>or{O?-|B% z2U!%{hwG61n;aLyImVGM%Y%UUiYQ2`e@Uyd@q1kMi^D9Iz)vJANieab)wlmbm2M>we>M_p zF?uLqR463YcO)T9vPKYLE3xjV7fPu&6n3+1hpjO}sU+-<7IyH?**dH#m8`qe)M?mVorb7XaU-}!es8TMa|H_RSLn4Z8soGfRpjl;{JIeAFdc6&rBJ;Rx?MO(zVJg(xWwfLn?6ESoJ|$Ix!s+y-J; zsETJ*u{Ft}WG_GsGZMiqe+g}pwVeoMxN%}`kW!C~yFC0RxC6<0cDzs)ZQV}<$bed6 z&5firT4=EkAW%wek<6jG%f!4BhIG0OV5q9tqKb`3LEKziy9#F|E39DM{4T?3aAlGi zO3xiK=vs-e1JS3tJ4c_^TX*P%vT*DEB#Q*NtR>i=qkA!Wu`xWie+A_hrQRktpC$v% zg~a@hPnpqINFq3Y2*4ns{iK6*^E(>@s=f*EX?FwD?juaQOJaluNjMTM?Bt#QpxWIa zS&uO7md%YQvBfDMt=VQOEy>&{rM3`rF-hGhnMxs;^tCYQ<0@#f;_ z)Q!aKCaK7JOlql=f4Vz5wbmXgnX$-P$_K&dF;(SA#PH)e_c+~%3%U8OV*r-Xt~&&_0wjXl1;>iOZ5nXIk7$cV?<0QfOZ?cE^u_M$ zaPby3UdddhH#ewattz^u)HZ(CIUJ}>2VT24+`17IhJo+Ch1msw)auL)LsO5S#yoI` zrGZHX$reMBe-uRblam+9#hXD6Nowf`khfYIg`eUGRRr^bp+SQ}mEZo@yLk;Nmwzb~ zcZTY~Xpb%DGU+x^W0f*cpD?znE!flqJje07LwVDE{Y8o%Nqph{f zU4eDQe+b|pTEJa_K|s;kqP3Vy^yW~Up(O@@0%NTgb}-^llL5C=36OF@6pJJHUDf(0 zCYYKaIs}7QB+*U8&Go_-1lJ3j!>wDAEabE_P}$P0O@M<3StcdH5;yZaXu8)Xi49Wj zk#S<<@Z1)iSTZzsrHw>p#IjBA^9k4#u_j&Q7MsLgQWbsj0gaLP6O`b8rn`fM}g=On}gRy)xFM%4WCU z0l5=3Lk9P;Tgt5^xiFy-(o<0fFljWY{D+;*UtO;G`5E@bT4YcS?JT3w+rx|r4hBe(WNr>P-i(3Lp#P4e8%-F3v zgb@WDcA3`Obc33Be>U?k-NMw-Wx%9l6NjHi<;qa_E+3}Fa3JV8&64Cz*dnN`E>_$IM26@_6rz|)G#kIDX(%R^5vMokV}PahW)!%^5h;t4WY?EaWl>Iit*Uhev+x1Er#EKiBjSXG zz3qGZw95%PLNNhgo$GBV=)7T1s=0iDNif$e|u&3P1Ib(5hG(Y?_3gq=WxvE=JfEps`Rc_WYy79h&}PoxBI3 zbsgonm#S<&50ow*BF`P!RXzYK-li2JprWT7m*2`-sBl&y9x(o?fTIl2ffg7Y57!k0 zwxf{cOt9+aB{xh7^Jvg1^=nkYxG@+{>e@dGumJ4CQ&C(vMBF|5f zi}5hI>YHGaGMyw$_1aWAl(XLGti(bX@8SWqCk&4`f+d#^wz=J~F}w<^lNv_*%OUyLz#(?l^)@mgf-ef355>s?>FjM%P6y%bO4u#=#z|ulPdF2Q=i2M*muV&X>bYElboPZRlO< zSQj!tPB0Lc198x?B}#|V(?!RA(EC>3YH*VOqz!z53p|kLr9Py{G7^GmBctWQ<^Htn zz{-cup)}v=@dZK3+nLpENa}irB9d{f1VNtsnaG$uj*a>9*PSRrRV2k>fIXL zz`Itccm{_i@pm+dm%gR5UQeeV|2%^NF|6?}jPXU3S!aiCdV+;_J&)3et5sE#bePtMlcV$qQj};%Bmizn*NuF0$e8C>uq-g;!lj!dz+nbY$W8Gtt^~ ze`KM-GOz`Uf(Zlc!91F~t(p;944a#XY?KWrS zvoNUvA~pGQs1TK2#EiL48C?K0@gG(S+uWp z2HyEHF4Gy&`gfBo>K<%YKc#E2IHHy)0%aw}GuDDTYL_8~_6DL?PWcAfhTF2^ zI=15%1kN5BhSwvHdp1*~d6mdKC?L8Z$9$(dkHX4M+^1NG^xQF5J0Va=e@^h$Jujk5{>-%nWlzQ7K^t=h;_!K%^{BGo@f7jf@^o1!4=Q)ZDQgpYkVfZ7Fx9Hbo_xK z1qU6`c{j#5rpRyTWNSMfhM#K%m@mmy(&PP7VpUNP2=X6BInZ=j!!N%PP?VsXxr{GB zU-0I%nO45wdjNTJ=*+o%!BJfOBsf zCRlpPpsON>y+5Z78aK*Gn8!yzmGZmkWx&We#M)jIRyZ^cc{8`@j>oi$7wdGKCj@WO zv9YwhG4FkS#`cbee_<9b^bwD^TLHIs6jVcu>QgO(0KGw2dh86-tX-O>^Dsv{H~6&e>JEDdvWDbz1@wsa3;~r zU3#wQ7J>ENNKZ2 zOLUHbV>rmiy(22PFg)3T55@dX6tMHqKoVZnJ&Gh7f1X|1*Bpg*JV4J4m4q-Nv`Rt* zm?UW=-BsTV%)fwIN~~?TUB&M_HL}V(k{kv}U~TGItv0gC8|kZc=C&Ig_rhnO7=|dq z7z$+xJx6O(EcE*<-3XPet$Bx>B%)QyZ6U9>8l1Hg`gw}i(Nkc^!_%%%dI}1(l}JJq z5q3Izf8xZ4@aQS1&(YH*RDw2KR9e`fQ>609399s^YQ;9F{;uKy{4^abHGWR-Ja&IK z+j%1l^7b18-?&nNSFgYGegn99mkDpJ2|I9!Q*g#HlsC5V6-p@oU>j88!nTiqFI_}G zwzXc^%+wI|O)WSh4(U^q2hrp@4N@JXn_e=4e{2u3DPf0X-AeCk=htzZk#nA;w|y`M zuKiYByueb+buLJm#I~>@kYtG#Zcq=OqJ~IeNJfkwvLfOm5Q|(?L@c zipccsF>jB5bFW_5Pd&jA^n$|9SYbcE{+FPED}?=^?OOudXgx5t#aY&YK96?|f1?Uo zrX89|mQX1!h@GfOxn(iAJNbg+^qLiv_wxmnSWYdGAY4V0)KVhuW=E>J)}dF}3CD{1 zD5(_3k;>X}v@7I>zF2`$c;O{{ZX}0dg;H`jI(0YyyPCpNv0^E?2@g4s#zOz*=+s*N zw>1T)9K&KoH#XGTX=*$YqM!0Xe;cHVzUl!4O1ZVZUUoylL2&>(6$J{39y}B~IvQ6s z9PGb@BnFWsp{h{k!9C)AD$jATsavV40*L5yG~hw?8_T*v856{5VzW|Y_Gc)cJt*Zn!AGq*Npx!&v!Ppv(`!ALPjY4z}P zyz`fuK6j|jX0W8dwlGI)OP!_f7`l}zt z1F>G|_5^UI?--n&53@5DJlJMu&iEFGwOuoW2F5{?WQHJdmgF9Zf3Y_31q&5<ZL_5o6Eo0Qrfo7)(j+QPpz z1OwP%DfdXMxsCKhi|qiA+9u_;$ELbru6XCS^i%)`9WORU=eDedJ$*=1>As4qJ7nGG*xN_1ig@8eL-iOB(9Z^ir$D7-tQ`^Y~ zivNAYFPV{A!lvYXoR9kT9omgn*`lM^@Rlp0#!By>obCWR8W1X(!$@HV#nLK4lrE%L zHn-E7GAVU`UoG>^&K#I44_z(+iEpCKes{Jv4TL#skfs?Sf93A1!#iG%0nV>(IqSeq z8^EJA=`Ig#CLqbwc4-!!xZM5aIH-1}PsFpt3NySv#(KoD%=v1VPPEbsiR?I4KRYOV zVW@V@ntK+nC0N^HPLk8n*7n|sbEB&m$=YL}PG}$A+J9Q@k*aXSSrz5oggj&-4-cKi zh|{3!*p9U0e?^}@w~7*BSsFpN`mALN_rH+-Vz94}FEs-cqN^lEfD0ip95o}Xw2k)QpY_}t7kkIbZi?u;FHY2~A zaonyTf5%5jNtVo0DBZBrloqjVAlk>sFH(+?@8PXE8zdobJS9Yu zX@2=0ij6sGiJr)j&;asWfWeb?*SjjA;IV2<*JFD40)plq599>CGP?YS5_&pib}9ko zH%f5(U;j#+I@ko5RZu_!U|niC=-` zBmW1n2T94H3zIB*eR#4Vi7h)bmq3d${FJIDIBTLHnek-b@d8!;rTtWe(&>~_^7qOk|IHt}eOh(H1rv6G@qP*VVQ|b_$*+1aS4#~^?i;gLI*~dT+X=Urg|Iwjt zf9F>GlEI#ZHtz+A>K=P1L_5U=X4zw<>kZLUSV#To_GCB zrQTKDvxuTVPE>KTDi)}aEuZS0wJLguXT%-J4t)J>G|NON7BN&$XFQzFxKv5?e_5f4e=k>d~Gi;coh-3HT{bh0n}vv_%=hfLy8IX|DfHqbn3rDeh@J z^ugm);_9Neh(h5JPet*r^TB#r!|!!n0tgFye~aIlF2orFIF~*TcF^%7e|lpB|JkPR zprmWGWd1*D|Iq%z5@_doeC<72dkMDRXu;dy&~EUzRgXz8x*8Kcu_u5=d4qg&N`Ok*fTnBmALAt$*pf)gZ1Na#H*2D4} zzKxtFnV^1>iF_Il9fE#jf5#89EAy65Mhp8$=%YG%3xr-f3!C}07JB+-fQ`?kN=hsl2K?B_fFuk5 z*+5I?HT1hd;A}I0h6-EO%rxS^se?Aw>n-DfB3268J zT|4}wV@aGX#?=ia$3kaK0RLGy#C=uVQTEnuyurt|8g0@5A7uk=QUYF+VkLu=8fqhY zXWan)v-i4CA1=atxvr!1YP_GIz$yM)&{y0FZ0m5LoEvJ39Vq^n1-R2&GM_}A+M7_G z_@aQchpO@bNk*AVf0YyHu>7;nSTcW&kQGfxbTpkc#uPc(%Y6WFpLYy$g)`*67nxpD zo;z!M0})#OW<+(SsrRV&5{*iusq@9naY(1x%_&zDtsBudB5C(y==tsM5BKvzE^JcT ztNJ-2Ot!p3^D0--kZ>PXeToEp$700+`sV-BG(J`S8ep^#e{~Z5)oGUd2!Eo9kMCZh zylHGN3E_vaNcW&T5extuH@ zgWa;E($%m%e|yMx_=EvSFFsA<$p}hq6pbehs<>Yj%OrYW(NFHne_*22tzykfK&Jd;2#T9_|*#cSiR6fgNK&wA|*=le?i}cF4@96FVLB5Az#zz;KD0a zSi+g3&|?nv&Ro0wb%q;eZ9Yv)`~z6u(cph*z$tqNrtFF``g8wfE{S#!$3uLANqXhy zIpbMS+Csmma5MzFS(4?wceeMPeN4#vn2`5TA^Y!k$@51Wob4UzuWm7MFU-F*7FV=7 z;=;(Ue;hl))??v+2B}>+N?!}ygDsgxtZ9Rqdc){RSZ+DWm^_1TJY--^^-+A!09>YA z5J;2ZQ_?1i^~%Y93!66)coXaH**Ac`o0+)@EAtrsoly35#vGFW($^nv@n?Q?TXV-3 z{yRvk2H@(YOkScRt;*3a=srKbipX@7DiL&We?jnM?=vC;?wD5leR(qn3>Jry>Zf8( z+e79Qh2C2@|6bL5CC+<+rX@(+#eab6v6q_U+>)z*E{nqRtt=R1d-`66>I|$ujS9UO z8b!BZ-Im$rWO)zG`ouB|3{Llm2Z7G6sEN`CVn_e(1$|YaR3{FMcjh*5;zQ(q{ACsD ze`av}WiY-JiB;RMoAM`iL~CmDPGO{c32RReI;Ry^qV&@chHmlGMY=mG(7#cDW6g=B znC!#ZW&tkg#RlJIfszhGDaXCqxw7H{#M|>K7%d*4r96!O&WTJtn)1K2(#_l(HYS8E57}+?1bw2!nIxN*FnFe>Jkc20kkAh0Zd3ds8`lT?_UgVA6_P>_;XI zML9Nb1L%uNOn_m^p#w-8ZiOHIo=$Qmoq^CytOGmV30kNZc3YB^I1sgM+Zy)HsGk4K zy&d0i+m0`J*`&zTwEi22h)pCCUvDFk_#zm;t9peyRLKV1+wpZq&`J8@^lSC_f2tV1 z7B=c>-)mv(7WiHZ`+kA%wXn@*-)mtv7x-QayD!f7TG+HW-)mv>;(V`#>DX&wDBvr1 z2-vZY3i$It?G~d}U0VUH*Q=2wbkD8Mb%|byz<1i%>(4-SH!99UhpAOX?Zh|T*#g0I zo&A7`OQ9$B{a@;RN_(l7Huib3fA`ATQzmy&gf6c;#4)6>I1gkOH%kR~BYsnthfiG0 zm*OaxUo2;i--#DOT-U{4AX87klV`_|boy!Ynooe5VisKzJgeDCCG%dS@z<<2uaYt( zP9r_8>yBS7T$qx%44ao8qU_)gi71~|`aDA@<6q~w37-qR|3GXd2tI*fe^XwoxM_iUiFs60~4Q`&Ukl$2jOafu1K6)>3*O7 z{}Ygwv+EWB;i&NYo)>it;8H(;J2wiGz6;o&vBJ%;}U}2i)G5TxT4Ae~Q)K!rC^h z{S@fZ?A~QSPz2P?>cJnTcsmU5PDKnT zTr@xzQ{&Jlg6_YjD-0dkht#OsNX@~t>Za!ezH{rmY2aNqx|sSd0CV#k=w=Ut{&G7d zJ3sSH8QqtS002)he?V7^{|kCd3N!jMcGYwbI=sOOu%|=VDSePZ1bfMc$uR^UEB4|l zqC?wEjq5uwC3s5zffwSy!@6<(L7QKr-CO)udp4cW?rdbPK~#AZl|uR>c^#27-GDwc z_@rSUYJ$+1EXghOrUwoG7TVO_|IXs?vHS0CUe_7}<@&(^gMT_HIJYLVG z2WKD5!mqXTbU#m$5g-2nkz47N#IyKR@gaWQ&t7Nx8xAn}2A+bFj(#@=F8jLGxz5rH zI29k_Qp1wpf5Y*|@kgR8i&O4~VHCsQosOD)m-er&^&y0#JCu~WdjZh12=CTVFKw}C zY1-p|#r3~$`KVBF>K)VH9OmrOIYv9X0>l{XUVz;rQER&l%t3pwMz87dOZafTlRfOj z2TvzDi#-!);*a!YKC}x)I#!DtSzZ2XmACvQPW6=xe_Dxdxgn88$1hkRPMl@IAAOQ# zj;B~XP#I0 zpnNmeVa=3kHtlrZdjr-y;H!cE2W9TSsv#JJnVrC5DT#sKWgZ*JRw8-d`bKBvV(R zb4-DJs1E8gv9TP1E8G=q=lp<|F66hD(NXvJ>ZbBo8^(A{+)+*L$1xMCaB+ZD^Z-*K zU*m66l+v!dwXU>fdkL-E>EleM&gQ)df7FnuiEX;oqvc=J=QzR{tpSdZdg{b6E`n(x zvgC!CC=*R|6cYly$8DXm9mLEsR-rLAAn%%8S3ibT^1e-)RsU*}ZXV53;)D za-WEG4w-oS088L*vRHK!W7SP9e^&kcZ_p(RFR9+tV%2Z3X7OdFCwhE%QhTuA!>r3R zR!yaT3RO3=>2H`X9{B$is~+;js(3K(FjW1!1f=SAyb6gFAjn++PJE?BEGDH1KN+#E zBB|>t?~GVHx~mtUq2kd`D1l`hSYT1e99Xdh76!$6uhoJ2VQ4BU{t=KAe>6FQ3yTpZ z&iid$9u_#J_Ir|RHx1u z=y6&iv?T@x0i|pIzlx!Ve@*#%=f8@f?Y%MdXFKm6Lv#N8(=oKje>y*SG0f9mK*Ylp% z)=JkMzos`flsVdnHC>AOg$#ClHDFqM6+{+=`wk z_UdhyvWD(Egf6BDfJJHB`JagCH*av0%hx>d$nP{U{ZNWqe^-(`i6$RY?@T^isv|tF zk_HdVJI>ybcc4GRyyGnOu{35+YXRqY;uC-Naq1(MeY~l^YxXg+q+j;2_M@N5KA`c+ zM}8-@uY>um1ca|=IY)Z^-Exj4CH_u_JA64uOg%jmfqaA9&~lAQ_5Lj5LI?XvjpbZs z0DT>vzA)dRe>Ai7CBG7%6Vr2&*&_NZFzZ?H4SIpGniqiHI_P~_=L^ZudsC@);ei5) zAq?6;6Wg)$Bq^BC0$z-{iOS!(7p00-GJSL6nWc*}hkc5B%+NqDB7-K_K0~ev4UhG% zYdyZ(3|L~poxWjN4HSeU1z+>|-*?~<8re5G0MGE9f8F>}4dlws0rYpMM(}$Zlju+K zJceWC>}AK)&LJp@0zDF9$y|g@i=nB`83q+Bk4Jnw9>VUP56L*FhTmtBPk?*fCht8+~YOXqo-3oJ#faj{424}5N$pyzI zKV|H`^^M{EpZ+=Cky$cciH)=>EB1OLd)q3o4Xdkn(^1IjZw!C@ ze@XuTNS6S8u5|;R*AKJYm&2KK{XSLsfNo{wX z;S2vtPm<^hC#2cc^lE6QwXL(&*~E38Ce7eP#a7oD{Jom?n8vlKq@%MFyuHxM-jT8u zOG0~0&Dt?qjp+<&m8`9jxy^OZF;K(ee|rt0n6EtSygUj>5TA*u$q9<-tJtv6)B8txE!TO<+01pGVY~nrKs|k3brvclO~%Zv z;~JVTlJ3H)=5K;e<1gH#wicdh{+i@A;?Gc>g!=E{`2x8LC2w#uX(ipAVhi4%f9uR> zj5(Pz!ZAc+$@37dvx|$&t<7J>)Y&~S{!`wI#ilbJ{2|}s+vM9%vRnH|_5?^a*eBK# z^c4m3S=V*(XDHZ{Yo7!D8u422-2_L>EwN(z+8_Y+egWh2m37XJQA7YaLVZqPZ0^}t z!lcx8$$WO)jp0`T951d4EeQV?e}H$Xy>h({auqzLvyxavJKsgRw!57Xc$wE5Ue47v*&ku#zh%*XGWz zVG>WoH0M0x7z5*vYXCC8EHXDXex#Cv zfWWG}4SrdVpzqMMOJb;$isE)Pi4ieZ*T%tES0N?t_Ps|Gb7gIqNj159Yiyu{-OkQY zVqDCXoM8O<=(o3H;zl*Fm7D@i@1ucuZq?CwnbZNr@YUHD50%fjE+G8^zD{%+H4SDj z_&8o0z5%RX!5U&c3lCqxe?(ACJOMLAI>@0;v5g!jb)6Suj_2G5YqSoN>RGH(zEM2^ zXH2!-Q!FQ_(C|w-A11eFT3>w|!G0uE%Ju16lNc3qZtWsKe;Rb@1YY#>QA;kzoL)Nw zTl&hOn(9!SI6LNajv=P=mEdtb!<)%voU;a?!Uqa8ksEzA2+gq-fBz#CR5mBPn~F7? zYXh6RfE;(jMrp$vG6oaWFnm7t+DBrO4a{%5@nn@GNLbMl1dx z5U9#n$AhF{T*vU6s44BJDQ#3!sGj)exXONdywDmA!=5B{-lM(th&s}SBBH<5Mot3{ zkH&n-um3&%haawMfA465hUZ2>G8l?4VTEbig6PBAea45ncy8?kNsMw`=L_zqzuy)m z!30hsOAHzo=Jxzu_{w9{&$Wxzm~-Ig>iD;V@l5VC2m*h6hdMmT90jJn5%7`$B*ow@ zvK5od;1K#)D(YV=$hZdjb>hT$%zbRL8ttf>SdUQIGFjG>f84Y9v%{csq!nvW6+vz& z^5C0LKtZAxgsiC*#SN-k1wQX9`U*o!jI}K%$uS=ogt(YSf3vS~ycK_skJJ^JkKhy_ zZcyZA1>{B^BTx85;HhVJ>z9aUZx7NMQ*SSopHatk;0)m}akYB4LSqj!7W=xsqosDf zze(#Rag$7wf2T~H_UL2NW71w)mY!jQN-imRuFD=5b`wC-5PEK|XAed;Jo0GLR14q7`ebHV@^g|x^dY`(eB7V>_%Ho_A2A5v^61j zg09T&4+>SQD9L_Uii~xb0K;aiTLWZ3=L`@*w$0ynS!P<+>JUyym}j)iPFlpxTfH`I zWmdXze@$ABBMTYl5@s)>CS}`VcS6UhM!Lfwe3L9YD;`e6b5H2a> zS7L@88KNB?9Akgbm}NJn8JWC65)W`=SBooGe~#m31FqE%i}tja05D_v0?XQgLAFRj%MU4iF`zWE2?8#C5rrlG9TCvu5dFK23U_Nhj8&J5$zq60Y_qOju{!&e)kb^f3qXxM>(?2;ZH_TXm_OS` z#RIp2(tkF`t7|f57{@FL;U0hdan8!fPMU4zX2)CR!K5!+nU=K*D_O;Ylw@uWD1t^? zQieSvXD#U7oa}4|>JVr^-#$-e3wsZAwOt9Y_agaev|%QLB7fFhhl1dwL=#ZB1s@GP`jt zs3MBb-(tyualuwrr>)AkOLb1h+AIyZuSu9YZ>}*t!@*SBzAPsrV>Q6pvsa4LXkk{y zi0k}>^eW9=V0yurpIDXVSe6OQ8CPYeGZRm9I5JkPabO+Tn?1wfgUJx2EupDnITr!v^Y!lP6F zRVx^2pVs+VtFl&S7$;4f8WKWh+nA27iqVyvk(R@FL!ASIwq?D{I^sme_dfSp;Y2Pz zGh^8b?BjP0#xd!%gT-Ib3*NWZSM$hAK!3+0D=B3Ym)TzKHxdN`Uec*=%RqPmZFQC3 z5@&>PPbAH@B+iRZ<`&H}3r|}YaUmf_Be?EIR~dU5#)`*Qg@hoVE7A9YfT+dKfGPx^ z`WX26DU(*Ao1qS$b?}jc4i20mx**ywE5kmK8;mkU?$bm^HmF9{GH?Ls-$8jM7=PE` zoWnS;8dqezN|nQry~gOs%m8HKYDYSlFGz};4bJNoJGL*&%+9uFOhEjgG*p|A)CtC4 zWc&gjGt$AiF3VoEiV6hf#XTh?EfD6v5O1D4f8GKCIRB-Q8)Ju+uhw8mdV0~*9Q}-c zdcMEF)DN70mMsem-|ol)hm_&#G=Dc~UW(wy00Cg$qIpj*xTE4WB>v__iG9nrLG@~X z_8KtD71X!T$@Wn(!?-9Dyl}k5YD~}0U_M`qkH$x*KKv5M0F7m0FFb-`7?}3(%8a#u zZB5$CI4N4E5N@IdnVFu`+X;;XtYbCkI+ze*1$*f=mR`UyA|2D$;`b~ey?-DHSf9m6 z?c>|~AW3H4+t`PczGn0<;WE}O%g9K#Q_Z0<0h|*pJ95AS{+rG~m3AztA2Cxf|VDr!nG;KF#rBP7c_VF=I{kvP_`J z8qznE=lD8L^aHL;do^2h^rD#TFZ^GXbMk+#os;{h=j8ubKPUeO3Of1UYv|-VwP*6( zb@Zno|3fYPsqX&=J)QjT6m{~y(A3HQMpaqF;2>h$b-2FzW%U19Kz}`Fz&EBKy|u{@ zC04&YAQZ}GW+1b_d6hK2}SQskuj@v}#YpDt4{G2m##x*e}?(V{WYr-}aUNaVPW zpS<&5CDeDrzm$0#w{u?qwj0{>M)>)v}fH{K$6W-RZH#h?W-Uz9gT{pXa_TQnyoIw^ zSjWv|uJw|t>hA)-tRMJ-K2Pz30_OC48}B!VB+SQEx7jKmlHcyWL6v diff --git a/stage2/fs/ext2.c b/stage2/fs/ext2.c index 766322d1..a087ee33 100644 --- a/stage2/fs/ext2.c +++ b/stage2/fs/ext2.c @@ -7,7 +7,14 @@ #include /* EXT2 Filesystem States */ -#define EXT2_FS_ERRORS 2 +#define EXT2_FS_UNRECOVERABLE_ERRORS 3 + +/* Ext2 incompatible features */ +#define EXT2_IF_COMPRESSION 0x01 +#define EXT2_IF_EXTENTS 0x40 +#define EXT2_IF_64BIT 0x80 +#define EXT2_IF_INLINE_DATA 0x8000 +#define EXT2_IF_ENCRYPT 0x10000 #define EXT2_S_MAGIC 0xEF53 @@ -74,7 +81,6 @@ struct ext2_bgd { /* EXT2 Inode Types */ #define EXT2_INO_DIRECTORY 0x4000 -#define EXT2_INO_FILE 0x8000 /* EXT2 Directory Entry */ struct ext2_dir_entry { @@ -89,22 +95,28 @@ static int inode_read(void *buf, uint64_t loc, uint64_t count, uint64_t drive, struct part *part); // parse an inode given the partition base and inode number -static int ext2_get_inode(struct ext2_inode *ret, uint64_t drive, struct part *part, uint64_t inode, struct ext2_superblock *sb) { +static int ext2_get_inode(struct ext2_inode *ret, uint64_t drive, struct part *part, + uint64_t inode, struct ext2_superblock *sb) { if (inode == 0) return -1; - uint64_t ino_blk_grp = (inode - 1) / sb->s_inodes_per_group; - uint64_t ino_tbl_idx = (inode - 1) % sb->s_inodes_per_group; + const uint64_t ino_blk_grp = (inode - 1) / sb->s_inodes_per_group; + const uint64_t ino_tbl_idx = (inode - 1) % sb->s_inodes_per_group; - uint64_t block_size = ((uint64_t)1024 << sb->s_log_block_size); + const uint64_t block_size = ((uint64_t)1024 << sb->s_log_block_size); struct ext2_bgd target_descriptor; - uint64_t bgd_start_offset = block_size >= 2048 ? block_size : block_size * 2; + const uint64_t bgd_start_offset = block_size >= 2048 ? block_size : block_size * 2; + const uint64_t bgd_offset = bgd_start_offset + (sizeof(struct ext2_bgd) * ino_blk_grp); - read_partition(drive, part, &target_descriptor, bgd_start_offset + (sizeof(struct ext2_bgd) * ino_blk_grp), sizeof(struct ext2_bgd)); + read_partition(drive, part, &target_descriptor, bgd_offset, sizeof(struct ext2_bgd)); - read_partition(drive, part, ret, (target_descriptor.bg_inode_table * block_size) + (sb->s_inode_size * ino_tbl_idx), sizeof(struct ext2_inode)); + const uint64_t ino_size = sb->s_rev_level == 0 ? sizeof(struct ext2_inode) : sb->s_inode_size; + const uint64_t ino_offset = (target_descriptor.bg_inode_table * block_size) + + (ino_size * ino_tbl_idx); + + read_partition(drive, part, ret, ino_offset, sizeof(struct ext2_inode)); return 0; } @@ -118,7 +130,7 @@ static int ext2_parse_dirent(struct ext2_dir_entry *dir, struct ext2_file_handle bool escape = false; - char token[128] = {0}; + char token[256] = {0}; next: for (size_t i = 0; *path != '/' && *path != '\0'; i++, path++) @@ -136,12 +148,13 @@ next: fd->drive, &fd->part); // name read - char *name = balloc(dir->name_len); - inode_read(name, i + sizeof(struct ext2_dir_entry), dir->name_len, - fd->block_size, current_inode, - fd->drive, &fd->part); + char *name = balloc(dir->name_len + 1); - int r = strncmp(token, name, dir->name_len); + memset(name, 0, dir->name_len + 1); + inode_read(name, i + sizeof(struct ext2_dir_entry), dir->name_len, + fd->block_size, current_inode, fd->drive, &fd->part); + + int r = strcmp(token, name); brewind(dir->name_len); @@ -164,17 +177,16 @@ next: } int ext2_open(struct ext2_file_handle *ret, int drive, int partition, const char *path) { - if (get_part(&ret->part, drive, partition)) { + if (get_part(&ret->part, drive, partition)) panic("Invalid partition"); - } ret->drive = drive; struct ext2_superblock sb; read_partition(drive, &ret->part, &sb, 1024, sizeof(struct ext2_superblock)); - if (sb.s_state == EXT2_FS_ERRORS) - panic("ext2 fs has errors\n"); + if (sb.s_state == EXT2_FS_UNRECOVERABLE_ERRORS) + panic("EXT2: unrecoverable errors found\n"); ret->block_size = ((uint64_t)1024 << sb.s_log_block_size); @@ -189,15 +201,14 @@ int ext2_open(struct ext2_file_handle *ret, int drive, int partition, const char ext2_get_inode(&ret->inode, drive, &ret->part, entry.inode, &sb); ret->size = ret->inode.i_size; - if (ret->inode.i_mode & EXT2_INO_DIRECTORY) - panic("Requested file \"%s\" is a directory!", path); + if ((ret->inode.i_mode & 0xf000) == EXT2_INO_DIRECTORY) + panic("ext2: Requested file \"%s\" is a directory!", path); return 0; } int ext2_read(struct ext2_file_handle *file, void *buf, uint64_t loc, uint64_t count) { - return inode_read(buf, loc, count, - file->block_size, &file->inode, + return inode_read(buf, loc, count, file->block_size, &file->inode, file->drive, &file->part); } @@ -258,20 +269,28 @@ static int inode_read(void *buf, uint64_t loc, uint64_t count, } // attempts to initialize the ext2 filesystem +// and checks if all features are supported int ext2_check_signature(int drive, int partition) { struct part part; - if (get_part(&part, drive, partition)) { + if (get_part(&part, drive, partition)) panic("Invalid partition"); - } - uint16_t magic = 0; + struct ext2_superblock sb; + read_partition(drive, &part, &sb, 1024, sizeof(struct ext2_superblock)); - // read only the checksum of the superblock - read_partition(drive, &part, &magic, 1024 + 56, 2); + if (sb.s_magic != EXT2_S_MAGIC) + return 0; - if (magic == EXT2_S_MAGIC) { + // If the revision level is 0, we can't test for features. + if (sb.s_rev_level == 0) return 1; - } - return 0; + if (sb.s_feature_incompat & EXT2_IF_COMPRESSION || + sb.s_feature_incompat & EXT2_IF_EXTENTS || + sb.s_feature_incompat & EXT2_IF_INLINE_DATA || + sb.s_feature_incompat & EXT2_IF_64BIT || + sb.s_feature_incompat & EXT2_IF_ENCRYPT) + panic("EXT2: filesystem has unsupported features"); + + return 1; }