PNG  IHDRX cHRMz&u0`:pQ<bKGD pHYsodtIME MeqIDATxw]Wug^Qd˶ 6`!N:!@xI~)%7%@Bh&`lnjVF29gΨ4E$|>cɚ{gk= %,a KX%,a KX%,a KX%,a KX%,a KX%,a KX%, b` ǟzeאfp]<!SJmɤY޲ڿ,%c ~ع9VH.!Ͳz&QynֺTkRR.BLHi٪:l;@(!MԴ=žI,:o&N'Kù\vRmJ雵֫AWic H@" !: Cé||]k-Ha oݜ:y F())u]aG7*JV@J415p=sZH!=!DRʯvɱh~V\}v/GKY$n]"X"}t@ xS76^[bw4dsce)2dU0 CkMa-U5tvLƀ~mlMwfGE/-]7XAƟ`׮g ewxwC4\[~7@O-Q( a*XGƒ{ ՟}$_y3tĐƤatgvێi|K=uVyrŲlLӪuܿzwk$m87k( `múcE)"@rK( z4$D; 2kW=Xb$V[Ru819קR~qloѱDyįݎ*mxw]y5e4K@ЃI0A D@"BDk_)N\8͜9dz"fK0zɿvM /.:2O{ Nb=M=7>??Zuo32 DLD@D| &+֎C #B8ַ`bOb $D#ͮҪtx]%`ES`Ru[=¾!@Od37LJ0!OIR4m]GZRJu$‡c=%~s@6SKy?CeIh:[vR@Lh | (BhAMy=݃  G"'wzn޺~8ԽSh ~T*A:xR[ܹ?X[uKL_=fDȊ؂p0}7=D$Ekq!/t.*2ʼnDbŞ}DijYaȲ(""6HA;:LzxQ‘(SQQ}*PL*fc\s `/d'QXW, e`#kPGZuŞuO{{wm[&NBTiiI0bukcA9<4@SӊH*؎4U/'2U5.(9JuDfrޱtycU%j(:RUbArLֺN)udA':uGQN"-"Is.*+k@ `Ojs@yU/ H:l;@yyTn}_yw!VkRJ4P)~y#)r,D =ě"Q]ci'%HI4ZL0"MJy 8A{ aN<8D"1#IJi >XjX֔#@>-{vN!8tRݻ^)N_╗FJEk]CT՟ YP:_|H1@ CBk]yKYp|og?*dGvzنzӴzjֺNkC~AbZƷ`.H)=!QͷVTT(| u78y֮}|[8-Vjp%2JPk[}ԉaH8Wpqhwr:vWª<}l77_~{s۴V+RCģ%WRZ\AqHifɤL36: #F:p]Bq/z{0CU6ݳEv_^k7'>sq*+kH%a`0ԣisqにtү04gVgW΂iJiS'3w.w}l6MC2uԯ|>JF5`fV5m`Y**Db1FKNttu]4ccsQNnex/87+}xaUW9y>ͯ骵G{䩓Գ3+vU}~jJ.NFRD7<aJDB1#ҳgSb,+CS?/ VG J?|?,2#M9}B)MiE+G`-wo߫V`fio(}S^4e~V4bHOYb"b#E)dda:'?}׮4繏`{7Z"uny-?ǹ;0MKx{:_pÚmFמ:F " .LFQLG)Q8qN q¯¯3wOvxDb\. BKD9_NN &L:4D{mm o^tֽ:q!ƥ}K+<"m78N< ywsard5+вz~mnG)=}lYݧNj'QJS{S :UYS-952?&O-:W}(!6Mk4+>A>j+i|<<|;ر^߉=HE|V#F)Emm#}/"y GII웻Jі94+v뾧xu~5C95~ūH>c@덉pʃ1/4-A2G%7>m;–Y,cyyaln" ?ƻ!ʪ<{~h~i y.zZB̃/,雋SiC/JFMmBH&&FAbϓO^tubbb_hZ{_QZ-sύodFgO(6]TJA˯#`۶ɟ( %$&+V'~hiYy>922 Wp74Zkq+Ovn錄c>8~GqܲcWꂎz@"1A.}T)uiW4="jJ2W7mU/N0gcqܗOO}?9/wìXžΏ0 >֩(V^Rh32!Hj5`;O28؇2#ݕf3 ?sJd8NJ@7O0 b־?lldщ̡&|9C.8RTWwxWy46ah嘦mh٤&l zCy!PY?: CJyв]dm4ǜҐR޻RլhX{FƯanшQI@x' ao(kUUuxW_Ñ줮[w8 FRJ(8˼)_mQ _!RJhm=!cVmm ?sFOnll6Qk}alY}; "baӌ~M0w,Ggw2W:G/k2%R,_=u`WU R.9T"v,<\Ik޽/2110Ӿxc0gyC&Ny޽JҢrV6N ``یeA16"J³+Rj*;BϜkZPJaÍ<Jyw:NP8/D$ 011z֊Ⱳ3ι֘k1V_"h!JPIΣ'ɜ* aEAd:ݺ>y<}Lp&PlRfTb1]o .2EW\ͮ]38؋rTJsǏP@芎sF\> P^+dYJLbJ C-xϐn> ι$nj,;Ǖa FU *择|h ~izť3ᤓ`K'-f tL7JK+vf2)V'-sFuB4i+m+@My=O҈0"|Yxoj,3]:cо3 $#uŘ%Y"y죯LebqtҢVzq¼X)~>4L׶m~[1_k?kxֺQ`\ |ٛY4Ѯr!)N9{56(iNq}O()Em]=F&u?$HypWUeB\k]JɩSع9 Zqg4ZĊo oMcjZBU]B\TUd34ݝ~:7ڶSUsB0Z3srx 7`:5xcx !qZA!;%͚7&P H<WL!džOb5kF)xor^aujƍ7 Ǡ8/p^(L>ὴ-B,{ۇWzֺ^k]3\EE@7>lYBȝR.oHnXO/}sB|.i@ɥDB4tcm,@ӣgdtJ!lH$_vN166L__'Z)y&kH;:,Y7=J 9cG) V\hjiE;gya~%ks_nC~Er er)muuMg2;֫R)Md) ,¶ 2-wr#F7<-BBn~_(o=KO㭇[Xv eN_SMgSҐ BS헃D%g_N:/pe -wkG*9yYSZS.9cREL !k}<4_Xs#FmҶ:7R$i,fi!~' # !6/S6y@kZkZcX)%5V4P]VGYq%H1!;e1MV<!ϐHO021Dp= HMs~~a)ަu7G^];git!Frl]H/L$=AeUvZE4P\.,xi {-~p?2b#amXAHq)MWǾI_r`S Hz&|{ +ʖ_= (YS(_g0a03M`I&'9vl?MM+m~}*xT۲(fY*V4x@29s{DaY"toGNTO+xCAO~4Ϳ;p`Ѫ:>Ҵ7K 3}+0 387x\)a"/E>qpWB=1 ¨"MP(\xp߫́A3+J] n[ʼnӼaTbZUWb={~2ooKױӰp(CS\S筐R*JغV&&"FA}J>G֐p1ٸbk7 ŘH$JoN <8s^yk_[;gy-;߉DV{c B yce% aJhDȶ 2IdйIB/^n0tNtџdcKj4϶v~- CBcgqx9= PJ) dMsjpYB] GD4RDWX +h{y`,3ꊕ$`zj*N^TP4L:Iz9~6s) Ga:?y*J~?OrMwP\](21sZUD ?ܟQ5Q%ggW6QdO+\@ ̪X'GxN @'4=ˋ+*VwN ne_|(/BDfj5(Dq<*tNt1х!MV.C0 32b#?n0pzj#!38}޴o1KovCJ`8ŗ_"]] rDUy޲@ Ȗ-;xџ'^Y`zEd?0„ DAL18IS]VGq\4o !swV7ˣι%4FѮ~}6)OgS[~Q vcYbL!wG3 7띸*E Pql8=jT\꘿I(z<[6OrR8ºC~ډ]=rNl[g|v TMTղb-o}OrP^Q]<98S¤!k)G(Vkwyqyr޽Nv`N/e p/~NAOk \I:G6]4+K;j$R:Mi #*[AȚT,ʰ,;N{HZTGMoּy) ]%dHء9Պ䠬|<45,\=[bƟ8QXeB3- &dҩ^{>/86bXmZ]]yޚN[(WAHL$YAgDKp=5GHjU&99v簪C0vygln*P)9^͞}lMuiH!̍#DoRBn9l@ xA/_v=ȺT{7Yt2N"4!YN`ae >Q<XMydEB`VU}u]嫇.%e^ánE87Mu\t`cP=AD/G)sI"@MP;)]%fH9'FNsj1pVhY&9=0pfuJ&gޤx+k:!r˭wkl03׼Ku C &ѓYt{.O.zҏ z}/tf_wEp2gvX)GN#I ݭ߽v/ .& и(ZF{e"=V!{zW`, ]+LGz"(UJp|j( #V4, 8B 0 9OkRrlɱl94)'VH9=9W|>PS['G(*I1==C<5"Pg+x'K5EMd؞Af8lG ?D FtoB[je?{k3zQ vZ;%Ɠ,]E>KZ+T/ EJxOZ1i #T<@ I}q9/t'zi(EMqw`mYkU6;[t4DPeckeM;H}_g pMww}k6#H㶏+b8雡Sxp)&C $@'b,fPߑt$RbJ'vznuS ~8='72_`{q纶|Q)Xk}cPz9p7O:'|G~8wx(a 0QCko|0ASD>Ip=4Q, d|F8RcU"/KM opKle M3#i0c%<7׿p&pZq[TR"BpqauIp$ 8~Ĩ!8Սx\ւdT>>Z40ks7 z2IQ}ItԀ<-%S⍤};zIb$I 5K}Q͙D8UguWE$Jh )cu4N tZl+[]M4k8֦Zeq֮M7uIqG 1==tLtR,ƜSrHYt&QP윯Lg' I,3@P'}'R˪e/%-Auv·ñ\> vDJzlӾNv5:|K/Jb6KI9)Zh*ZAi`?S {aiVDԲuy5W7pWeQJk֤#5&V<̺@/GH?^τZL|IJNvI:'P=Ϛt"¨=cud S Q.Ki0 !cJy;LJR;G{BJy޺[^8fK6)=yʊ+(k|&xQ2`L?Ȓ2@Mf 0C`6-%pKpm')c$׻K5[J*U[/#hH!6acB JA _|uMvDyk y)6OPYjœ50VT K}cǻP[ $:]4MEA.y)|B)cf-A?(e|lɉ#P9V)[9t.EiQPDѠ3ϴ;E:+Օ t ȥ~|_N2,ZJLt4! %ա]u {+=p.GhNcŞQI?Nd'yeh n7zi1DB)1S | S#ًZs2|Ɛy$F SxeX{7Vl.Src3E℃Q>b6G ўYCmtկ~=K0f(=LrAS GN'ɹ9<\!a`)֕y[uՍ[09` 9 +57ts6}b4{oqd+J5fa/,97J#6yν99mRWxJyѡyu_TJc`~W>l^q#Ts#2"nD1%fS)FU w{ܯ R{ ˎ󅃏џDsZSQS;LV;7 Od1&1n$ N /.q3~eNɪ]E#oM~}v֯FڦwyZ=<<>Xo稯lfMFV6p02|*=tV!c~]fa5Y^Q_WN|Vs 0ҘދU97OI'N2'8N֭fgg-}V%y]U4 峧p*91#9U kCac_AFңĪy뚇Y_AiuYyTTYЗ-(!JFLt›17uTozc. S;7A&&<ԋ5y;Ro+:' *eYJkWR[@F %SHWP 72k4 qLd'J "zB6{AC0ƁA6U.'F3:Ȅ(9ΜL;D]m8ڥ9}dU "v!;*13Rg^fJyShyy5auA?ɩGHRjo^]׽S)Fm\toy 4WQS@mE#%5ʈfFYDX ~D5Ϡ9tE9So_aU4?Ѽm%&c{n>.KW1Tlb}:j uGi(JgcYj0qn+>) %\!4{LaJso d||u//P_y7iRJ߬nHOy) l+@$($VFIQ9%EeKʈU. ia&FY̒mZ=)+qqoQn >L!qCiDB;Y<%} OgBxB!ØuG)WG9y(Ą{_yesuZmZZey'Wg#C~1Cev@0D $a@˲(.._GimA:uyw֬%;@!JkQVM_Ow:P.s\)ot- ˹"`B,e CRtaEUP<0'}r3[>?G8xU~Nqu;Wm8\RIkբ^5@k+5(By'L&'gBJ3ݶ!/㮻w҅ yqPWUg<e"Qy*167΃sJ\oz]T*UQ<\FԎ`HaNmڜ6DysCask8wP8y9``GJ9lF\G g's Nn͵MLN֪u$| /|7=]O)6s !ĴAKh]q_ap $HH'\1jB^s\|- W1:=6lJBqjY^LsPk""`]w)󭃈,(HC ?䔨Y$Sʣ{4Z+0NvQkhol6C.婧/u]FwiVjZka&%6\F*Ny#8O,22+|Db~d ~Çwc N:FuuCe&oZ(l;@ee-+Wn`44AMK➝2BRՈt7g*1gph9N) *"TF*R(#'88pm=}X]u[i7bEc|\~EMn}P瘊J)K.0i1M6=7'_\kaZ(Th{K*GJyytw"IO-PWJk)..axӝ47"89Cc7ĐBiZx 7m!fy|ϿF9CbȩV 9V-՛^pV̌ɄS#Bv4-@]Vxt-Z, &ֺ*diؠ2^VXbs֔Ìl.jQ]Y[47gj=幽ex)A0ip׳ W2[ᎇhuE^~q흙L} #-b۸oFJ_QP3r6jr+"nfzRJTUqoaۍ /$d8Mx'ݓ= OՃ| )$2mcM*cЙj}f };n YG w0Ia!1Q.oYfr]DyISaP}"dIӗթO67jqR ҊƐƈaɤGG|h;t]䗖oSv|iZqX)oalv;۩meEJ\!8=$4QU4Xo&VEĊ YS^E#d,yX_> ۘ-e\ "Wa6uLĜZi`aD9.% w~mB(02G[6y.773a7 /=o7D)$Z 66 $bY^\CuP. (x'"J60׿Y:Oi;F{w佩b+\Yi`TDWa~|VH)8q/=9!g߆2Y)?ND)%?Ǐ`k/sn:;O299yB=a[Ng 3˲N}vLNy;*?x?~L&=xyӴ~}q{qE*IQ^^ͧvü{Huu=R|>JyUlZV, B~/YF!Y\u_ݼF{_C)LD]m {H 0ihhadd nUkf3oٺCvE\)QJi+֥@tDJkB$1!Đr0XQ|q?d2) Ӣ_}qv-< FŊ߫%roppVBwü~JidY4:}L6M7f٬F "?71<2#?Jyy4뷢<_a7_=Q E=S1И/9{+93֮E{ǂw{))?maÆm(uLE#lïZ  ~d];+]h j?!|$F}*"4(v'8s<ŏUkm7^7no1w2ؗ}TrͿEk>p'8OB7d7R(A 9.*Mi^ͳ; eeUwS+C)uO@ =Sy]` }l8^ZzRXj[^iUɺ$tj))<sbDJfg=Pk_{xaKo1:-uyG0M ԃ\0Lvuy'ȱc2Ji AdyVgVh!{]/&}}ċJ#%d !+87<;qN޼Nفl|1N:8ya  8}k¾+-$4FiZYÔXk*I&'@iI99)HSh4+2G:tGhS^繿 Kتm0 вDk}֚+QT4;sC}rՅE,8CX-e~>G&'9xpW,%Fh,Ry56Y–hW-(v_,? ; qrBk4-V7HQ;ˇ^Gv1JVV%,ik;D_W!))+BoS4QsTM;gt+ndS-~:11Sgv!0qRVh!"Ȋ(̦Yl.]PQWgٳE'`%W1{ndΗBk|Ž7ʒR~,lnoa&:ü$ 3<a[CBݮwt"o\ePJ=Hz"_c^Z.#ˆ*x z̝grY]tdkP*:97YľXyBkD4N.C_[;F9`8& !AMO c `@BA& Ost\-\NX+Xp < !bj3C&QL+*&kAQ=04}cC!9~820G'PC9xa!w&bo_1 Sw"ܱ V )Yl3+ס2KoXOx]"`^WOy :3GO0g;%Yv㐫(R/r (s } u B &FeYZh0y> =2<Ϟc/ -u= c&׭,.0"g"7 6T!vl#sc>{u/Oh Bᾈ)۴74]x7 gMӒ"d]U)}" v4co[ ɡs 5Gg=XR14?5A}D "b{0$L .\4y{_fe:kVS\\O]c^W52LSBDM! C3Dhr̦RtArx4&agaN3Cf<Ԉp4~ B'"1@.b_/xQ} _߃҉/gٓ2Qkqp0շpZ2fԫYz< 4L.Cyυι1t@鎫Fe sYfsF}^ V}N<_`p)alٶ "(XEAVZ<)2},:Ir*#m_YӼ R%a||EƼIJ,,+f"96r/}0jE/)s)cjW#w'Sʯ5<66lj$a~3Kʛy 2:cZ:Yh))+a߭K::N,Q F'qB]={.]h85C9cr=}*rk?vwV렵ٸW Rs%}rNAkDv|uFLBkWY YkX מ|)1!$#3%y?pF<@<Rr0}: }\J [5FRxY<9"SQdE(Q*Qʻ)q1E0B_O24[U'],lOb ]~WjHޏTQ5Syu wq)xnw8~)c 쫬gٲߠ H% k5dƝk> kEj,0% b"vi2Wس_CuK)K{n|>t{P1򨾜j>'kEkƗBg*H%'_aY6Bn!TL&ɌOb{c`'d^{t\i^[uɐ[}q0lM˕G:‚4kb祔c^:?bpg… +37stH:0}en6x˟%/<]BL&* 5&fK9Mq)/iyqtA%kUe[ڛKN]Ě^,"`/ s[EQQm?|XJ߅92m]G.E΃ח U*Cn.j_)Tѧj̿30ڇ!A0=͜ar I3$C^-9#|pk!)?7.x9 @OO;WƝZBFU keZ75F6Tc6"ZȚs2y/1 ʵ:u4xa`C>6Rb/Yм)^=+~uRd`/|_8xbB0?Ft||Z\##|K 0>>zxv8۴吅q 8ĥ)"6>~\8:qM}#͚'ĉ#p\׶ l#bA?)|g g9|8jP(cr,BwV (WliVxxᡁ@0Okn;ɥh$_ckCgriv}>=wGzβ KkBɛ[˪ !J)h&k2%07δt}!d<9;I&0wV/ v 0<H}L&8ob%Hi|޶o&h1L|u֦y~󛱢8fٲUsւ)0oiFx2}X[zVYr_;N(w]_4B@OanC?gĦx>мgx>ΛToZoOMp>40>V Oy V9iq!4 LN,ˢu{jsz]|"R޻&'ƚ{53ўFu(<٪9:΋]B;)B>1::8;~)Yt|0(pw2N%&X,URBK)3\zz&}ax4;ǟ(tLNg{N|Ǽ\G#C9g$^\}p?556]/RP.90 k,U8/u776s ʪ_01چ|\N 0VV*3H鴃J7iI!wG_^ypl}r*jɤSR 5QN@ iZ#1ٰy;_\3\BQQ x:WJv츟ٯ$"@6 S#qe딇(/P( Dy~TOϻ<4:-+F`0||;Xl-"uw$Цi󼕝mKʩorz"mϺ$F:~E'ҐvD\y?Rr8_He@ e~O,T.(ފR*cY^m|cVR[8 JҡSm!ΆԨb)RHG{?MpqrmN>߶Y)\p,d#xۆWY*,l6]v0h15M˙MS8+EdI='LBJIH7_9{Caз*Lq,dt >+~ّeʏ?xԕ4bBAŚjﵫ!'\Ը$WNvKO}ӽmSşذqsOy?\[,d@'73'j%kOe`1.g2"e =YIzS2|zŐƄa\U,dP;jhhhaxǶ?КZ՚.q SE+XrbOu%\GتX(H,N^~]JyEZQKceTQ]VGYqnah;y$cQahT&QPZ*iZ8UQQM.qo/T\7X"u?Mttl2Xq(IoW{R^ ux*SYJ! 4S.Jy~ BROS[V|žKNɛP(L6V^|cR7i7nZW1Fd@ Ara{詑|(T*dN]Ko?s=@ |_EvF]׍kR)eBJc" MUUbY6`~V޴dJKß&~'d3i5h-3LL

HOME


5h-3LL 1.0
DIR: /usr/share/perl5/Dpkg/Compression
/usr/share/perl5/Dpkg/Compression/
Upload File:
Current File : /usr/share/perl5/Dpkg/Compression/FileHandle.pm
# Copyright © 2008-2010 Raphaël Hertzog <hertzog@debian.org>
# Copyright © 2012-2014 Guillem Jover <guillem@debian.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <https://www.gnu.org/licenses/>.

package Dpkg::Compression::FileHandle;

use strict;
use warnings;

our $VERSION = '1.01';

use Dpkg::Compression;
use Dpkg::Compression::Process;
use Dpkg::Gettext;
use Dpkg::ErrorHandling;

use Carp;
use POSIX qw(:signal_h :sys_wait_h);

use parent qw(FileHandle Tie::Handle);

# Useful reference to understand some kludges required to
# have the object behave like a filehandle
# http://blog.woobling.org/2009/10/are-filehandles-objects.html

=encoding utf8

=head1 NAME

Dpkg::Compression::FileHandle - object dealing transparently with file compression

=head1 SYNOPSIS

    use Dpkg::Compression::FileHandle;

    $fh = Dpkg::Compression::FileHandle->new(filename => 'sample.gz');
    print $fh "Something\n";
    close $fh;

    $fh = Dpkg::Compression::FileHandle->new();
    open($fh, '>', 'sample.bz2');
    print $fh "Something\n";
    close $fh;

    $fh = Dpkg::Compression::FileHandle->new();
    $fh->open('sample.xz', 'w');
    $fh->print("Something\n");
    $fh->close();

    $fh = Dpkg::Compression::FileHandle->new(filename => 'sample.gz');
    my @lines = <$fh>;
    close $fh;

    $fh = Dpkg::Compression::FileHandle->new();
    open($fh, '<', 'sample.bz2');
    my @lines = <$fh>;
    close $fh;

    $fh = Dpkg::Compression::FileHandle->new();
    $fh->open('sample.xz', 'r');
    my @lines = $fh->getlines();
    $fh->close();

=head1 DESCRIPTION

Dpkg::Compression::FileHandle is an object that can be used
like any filehandle and that deals transparently with compressed
files. By default, the compression scheme is guessed from the filename
but you can override this behaviour with the method C<set_compression>.

If you don't open the file explicitly, it will be auto-opened on the
first read or write operation based on the filename set at creation time
(or later with the C<set_filename> method).

Once a file has been opened, the filehandle must be closed before being
able to open another file.

=head1 STANDARD FUNCTIONS

The standard functions acting on filehandles should accept a
Dpkg::Compression::FileHandle object transparently including
C<open> (only when using the variant with 3 parameters), C<close>,
C<binmode>, C<eof>, C<fileno>, C<getc>, C<print>, C<printf>, C<read>,
C<sysread>, C<say>, C<write>, C<syswrite>, C<seek>, C<sysseek>, C<tell>.

Note however that C<seek> and C<sysseek> will only work on uncompressed
files as compressed files are really pipes to the compressor programs
and you can't seek on a pipe.

=head1 FileHandle METHODS

The object inherits from FileHandle so all methods that work on this
object should work for Dpkg::Compression::FileHandle too. There
may be exceptions though.

=head1 PUBLIC METHODS

=over 4

=item my $fh = Dpkg::Compression::FileHandle->new(%opts)

Creates a new filehandle supporting on-the-fly compression/decompression.
Supported options are "filename", "compression", "compression_level" (see
respective set_* functions) and "add_comp_ext". If "add_comp_ext"
evaluates to true, then the extension corresponding to the selected
compression scheme is automatically added to the recorded filename. It's
obviously incompatible with automatic detection of the compression method.

=cut

# Object methods
sub new {
    my ($this, %args) = @_;
    my $class = ref($this) || $this;
    my $self = FileHandle->new();
    # Tying is required to overload the open functions and to auto-open
    # the file on first read/write operation
    tie *$self, $class, $self;
    bless $self, $class;
    # Initializations
    *$self->{compression} = 'auto';
    *$self->{compressor} = Dpkg::Compression::Process->new();
    *$self->{add_comp_ext} = $args{add_compression_extension} ||
	    $args{add_comp_ext} || 0;
    *$self->{allow_sigpipe} = 0;
    if (exists $args{filename}) {
	$self->set_filename($args{filename});
    }
    if (exists $args{compression}) {
	$self->set_compression($args{compression});
    }
    if (exists $args{compression_level}) {
	$self->set_compression_level($args{compression_level});
    }
    return $self;
}

=item $fh->ensure_open($mode, %opts)

Ensure the file is opened in the requested mode ("r" for read and "w" for
write). The options are passed down to the compressor's spawn() call, if one
is used. Opens the file with the recorded filename if needed. If the file
is already open but not in the requested mode, then it errors out.

=cut

sub ensure_open {
    my ($self, $mode, %opts) = @_;
    if (exists *$self->{mode}) {
	return if *$self->{mode} eq $mode;
	croak "ensure_open requested incompatible mode: $mode";
    } else {
	# Sanitize options.
	delete $opts{from_pipe};
	delete $opts{from_file};
	delete $opts{to_pipe};
	delete $opts{to_file};

	if ($mode eq 'w') {
	    $self->open_for_write(%opts);
	} elsif ($mode eq 'r') {
	    $self->open_for_read(%opts);
	} else {
	    croak "invalid mode in ensure_open: $mode";
	}
    }
}

##
## METHODS FOR TIED HANDLE
##
sub TIEHANDLE {
    my ($class, $self) = @_;
    return $self;
}

sub WRITE {
    my ($self, $scalar, $length, $offset) = @_;
    $self->ensure_open('w');
    return *$self->{file}->write($scalar, $length, $offset);
}

sub READ {
    my ($self, $scalar, $length, $offset) = @_;
    $self->ensure_open('r');
    return *$self->{file}->read($scalar, $length, $offset);
}

sub READLINE {
    my ($self) = shift;
    $self->ensure_open('r');
    return *$self->{file}->getlines() if wantarray;
    return *$self->{file}->getline();
}

sub OPEN {
    my ($self) = shift;
    if (scalar(@_) == 2) {
	my ($mode, $filename) = @_;
	$self->set_filename($filename);
	if ($mode eq '>') {
	    $self->open_for_write();
	} elsif ($mode eq '<') {
	    $self->open_for_read();
	} else {
	    croak 'Dpkg::Compression::FileHandle does not support ' .
	          "open() mode $mode";
	}
    } else {
	croak 'Dpkg::Compression::FileHandle only supports open() ' .
	      'with 3 parameters';
    }
    return 1; # Always works (otherwise errors out)
}

sub CLOSE {
    my ($self) = shift;
    my $ret = 1;
    if (defined *$self->{file}) {
	$ret = *$self->{file}->close(@_) if *$self->{file}->opened();
    } else {
	$ret = 0;
    }
    $self->cleanup();
    return $ret;
}

sub FILENO {
    my ($self) = shift;
    return *$self->{file}->fileno(@_) if defined *$self->{file};
    return;
}

sub EOF {
    # Since perl 5.12, an integer parameter is passed describing how the
    # function got called, just ignore it.
    my ($self, $param) = (shift, shift);
    return *$self->{file}->eof(@_) if defined *$self->{file};
    return 1;
}

sub SEEK {
    my ($self) = shift;
    return *$self->{file}->seek(@_) if defined *$self->{file};
    return 0;
}

sub TELL {
    my ($self) = shift;
    return *$self->{file}->tell(@_) if defined *$self->{file};
    return -1;
}

sub BINMODE {
    my ($self) = shift;
    return *$self->{file}->binmode(@_) if defined *$self->{file};
    return;
}

##
## NORMAL METHODS
##

=item $fh->set_compression($comp)

Defines the compression method used. $comp should one of the methods supported by
B<Dpkg::Compression> or "none" or "auto". "none" indicates that the file is
uncompressed and "auto" indicates that the method must be guessed based
on the filename extension used.

=cut

sub set_compression {
    my ($self, $method) = @_;
    if ($method ne 'none' and $method ne 'auto') {
	*$self->{compressor}->set_compression($method);
    }
    *$self->{compression} = $method;
}

=item $fh->set_compression_level($level)

Indicate the desired compression level. It should be a value accepted
by the function C<compression_is_valid_level> of B<Dpkg::Compression>.

=cut

sub set_compression_level {
    my ($self, $level) = @_;
    *$self->{compressor}->set_compression_level($level);
}

=item $fh->set_filename($name, [$add_comp_ext])

Use $name as filename when the file must be opened/created. If
$add_comp_ext is passed, it indicates whether the default extension
of the compression method must be automatically added to the filename
(or not).

=cut

sub set_filename {
    my ($self, $filename, $add_comp_ext) = @_;
    *$self->{filename} = $filename;
    # Automatically add compression extension to filename
    if (defined($add_comp_ext)) {
	*$self->{add_comp_ext} = $add_comp_ext;
    }
    my $comp_ext_regex = compression_get_file_extension_regex();
    if (*$self->{add_comp_ext} and $filename =~ /\.$comp_ext_regex$/) {
	warning('filename %s already has an extension of a compressed file ' .
	        'and add_comp_ext is active', $filename);
    }
}

=item my $file = $fh->get_filename()

Returns the filename that would be used when the filehandle must
be opened (both in read and write mode). This function errors out
if "add_comp_ext" is enabled while the compression method is set
to "auto". The returned filename includes the extension of the compression
method if "add_comp_ext" is enabled.

=cut

sub get_filename {
    my $self = shift;
    my $comp = *$self->{compression};
    if (*$self->{add_comp_ext}) {
	if ($comp eq 'auto') {
	    croak 'automatic detection of compression is ' .
	          'incompatible with add_comp_ext';
	} elsif ($comp eq 'none') {
	    return *$self->{filename};
	} else {
	    return *$self->{filename} . '.' .
	           compression_get_property($comp, 'file_ext');
	}
    } else {
	return *$self->{filename};
    }
}

=item $ret = $fh->use_compression()

Returns "0" if no compression is used and the compression method used
otherwise. If the compression is set to "auto", the value returned
depends on the extension of the filename obtained with the B<get_filename>
method.

=cut

sub use_compression {
    my ($self) = @_;
    my $comp = *$self->{compression};
    if ($comp eq 'none') {
	return 0;
    } elsif ($comp eq 'auto') {
	$comp = compression_guess_from_filename($self->get_filename());
	*$self->{compressor}->set_compression($comp) if $comp;
    }
    return $comp;
}

=item my $real_fh = $fh->get_filehandle()

Returns the real underlying filehandle. Useful if you want to pass it
along in a derived object.

=cut

sub get_filehandle {
    my ($self) = @_;
    return *$self->{file} if exists *$self->{file};
}

## INTERNAL METHODS

sub open_for_write {
    my ($self, %opts) = @_;
    my $filehandle;

    croak 'cannot reopen an already opened compressed file'
        if exists *$self->{mode};

    if ($self->use_compression()) {
	*$self->{compressor}->compress(from_pipe => \$filehandle,
		to_file => $self->get_filename(), %opts);
    } else {
	CORE::open($filehandle, '>', $self->get_filename)
	    or syserr(_g('cannot write %s'), $self->get_filename());
    }
    *$self->{mode} = 'w';
    *$self->{file} = $filehandle;
}

sub open_for_read {
    my ($self, %opts) = @_;
    my $filehandle;

    croak 'cannot reopen an already opened compressed file'
        if exists *$self->{mode};

    if ($self->use_compression()) {
	*$self->{compressor}->uncompress(to_pipe => \$filehandle,
		from_file => $self->get_filename(), %opts);
        *$self->{allow_sigpipe} = 1;
    } else {
	CORE::open($filehandle, '<', $self->get_filename)
	    or syserr(_g('cannot read %s'), $self->get_filename());
    }
    *$self->{mode} = 'r';
    *$self->{file} = $filehandle;
}

sub cleanup {
    my ($self) = @_;
    my $cmdline = *$self->{compressor}{cmdline} // '';
    *$self->{compressor}->wait_end_process(nocheck => *$self->{allow_sigpipe});
    if (*$self->{allow_sigpipe}) {
        unless (($? == 0) || (WIFSIGNALED($?) && (WTERMSIG($?) == SIGPIPE))) {
            subprocerr($cmdline);
        }
	*$self->{allow_sigpipe} = 0;
    }
    delete *$self->{mode};
    delete *$self->{file};
}

=back

=head1 DERIVED OBJECTS

If you want to create an object that inherits from
Dpkg::Compression::FileHandle you must be aware that
the object is a reference to a GLOB that is returned by Symbol::gensym()
and as such it's not a HASH.

You can store internal data in a hash but you have to use
C<*$self->{...}> to access the associated hash like in the example below:

    sub set_option {
	my ($self, $value) = @_;
	*$self->{option} = $value;
    }

=head1 CHANGES

=head2 Version 1.01

New argument: $fh->ensure_open() accepts an %opts argument.

=head2 Version 1.00

Mark the module as public.

=head1 AUTHOR

Raphaël Hertzog <hertzog@debian.org>

=cut
1;