o w[eJ @sdZdZdZdZddlmZddlZddlZddl Z ddl Z ddl Z ddl Z ddl Z ddlZddlZddlZzddlZWn eyGdZYnwzddlZWn eyYdZYnweefZzeef7ZWn eynYnwgdZdZd Zed Zd Zd Zd Zd Z dZ!dZ"dZ#dZ$dZ%dZ&dZ'dZ(dZ)dZ*dZ+dZ,dZ-dZ.dZ/dZ0dZ1dZ2dZ3e3Z4e"e#e$e%e(e)e*e&e'e+e,e-f Z5e"e#e*e-fZ6e+e,e-fZ7dZ8hd Z9e:e:e:e;e;e;d!Zne?Z>d$d%Z@d&d'ZAd(d)ZBd*e4fd+d,ZCd-d.ZDdedfd/d0ZEd1d2ZFGd3d4d4eGZHGd5d6d6eHZIGd7d8d8eHZJGd9d:d:eHZKGd;d<dd>eHZMGd?d@d@eMZNGdAdBdBeMZOGdCdDdDeMZPGdEdFdFeMZQGdGdHdHeMZRGdIdJdJZSGdKdLdLZTGdMdNdNeUZVGdOdPdPeUZWGdQdRdRe jXZYGdSdTdTeHZZGdUdVdVeZZ[GdWdXdXeZZ\GdYdZdZeZZ]Gd[d\d\eZZ^Gd]d^d^eZZ_drd`daZ`dbdcZadddeZbdfdgZceaebecdhZdeUZeGdidjdjeUZfGdkdldleUZgdmdnZhegjZdodpZiejdqkreidSdS)sz,Read from and write to tar format archives. z0.9.0u"Lars Gustäbel (lars@gustaebel.de)u4Gustavo Niemeyer, Niels Gustäbel, Richard Townsend.)openN)TarFileTarInfo is_tarfileTarError ReadErrorCompressionError StreamError ExtractError HeaderErrorENCODING USTAR_FORMAT GNU_FORMAT PAX_FORMATDEFAULT_FORMATrisustar sustar00d01234567LKSxgX)pathlinkpathsizemtimeuidgidunamegname>r%r,r+r&)atimectimer(r)r*r'ntutf-8cCs8|durtd|||}|d||t|tS)z8Convert a string to a null-terminated bytes object. Nzmetadata cannot contain None) ValueErrorencodelenNUL)slengthencodingerrorsr9/usr/lib/python3.10/tarfile.pystns r;cCs*|d}|dkr|d|}|||S)z8Convert a null-terminated bytes object to a string. rN)finddecode)r5r7r8pr9r9r:ntss   r@cCs|ddvr2d}tt|dD]}|dK}|||d7}q|ddkr0dt|d| }|Szt|dd}t|p?d d}W|StyOtd w) z/Convert a number field to a python number. r)r#rBasciistrict0invalid header)ranger3r@intstripr1InvalidHeaderError)r5nir9r9r:ntis    rOrCcCs|}t|}d|krd|dkr%nntd|d|fdt}|S|tkrmd|d |krprint)r5r7r9r9r: _safe_printsrtc@eZdZdZdS)rzBase exception.N__name__ __module__ __qualname____doc__r9r9r9r:rrc@ru)r z%General exception for extract errors.Nrvr9r9r9r:r r{r c@ru)rz&Exception for unreadable tar archives.Nrvr9r9r9r:rr{rc@ru)rz.Exception for unavailable compression methods.Nrvr9r9r9r:rr{rc@ru)r z=Exception for unsupported operations on stream-like TarFiles.Nrvr9r9r9r:r r{r c@ru)r z!Base exception for header errors.Nrvr9r9r9r:r r{r c@ru)EmptyHeaderErrorzException for empty headers.Nrvr9r9r9r:r|!r{r|c@ru)TruncatedHeaderErrorz Exception for truncated headers.Nrvr9r9r9r:r}$r{r}c@ru)EOFHeaderErrorz"Exception for end of file headers.Nrvr9r9r9r:r~'r{r~c@ru)rLzException for invalid headers.Nrvr9r9r9r:rL*r{rLc@ru)SubsequentHeaderErrorz3Exception for missing and invalid extended headers.Nrvr9r9r9r:r-r{rc@0eZdZdZddZddZddZdd Zd S) _LowLevelFilezLow-level file object. Supports reading and writing. It is used instead of a regular file object for streaming access. cCsFtjtjtjBtjBd|}ttdr|tjO}t||d|_dS)NrwO_BINARYi) osO_RDONLYO_WRONLYO_CREATO_TRUNChasattrrrfd)selfnamemoder9r9r:__init__:s  z_LowLevelFile.__init__cCst|jdSN)rcloserrr9r9r:rCsz_LowLevelFile.closecCst|j|Sr)rrdrrr'r9r9r:rdFz_LowLevelFile.readcCst|j|dSr)rrerrr5r9r9r:reIsz_LowLevelFile.writeN)rwrxryrzrrrdrer9r9r9r:r4s   rc@sreZdZdZddZddZddZdd Zd d Zd d Z ddZ ddZ dddZ ddZ ddZddZdS)_StreamaClass that serves as an adapter between TarFile and a stream-like object. The stream-like object only needs to have a read() or write() method and is accessed blockwise. Use of gzip or bzip2 compression is possible. A stream-like object could be for example: sys.stdin, sys.stdout, a socket, a tape device etc. _Stream is intended to be used only internally. c Csd|_|durt||}d|_|dkrt|}|}|pd|_||_||_||_||_d|_ d|_ d|_ z|dkrlzddl }Wn t yLtd dw||_ |d|_|d kre||j|_WdS|WdS|d krzddl}Wn t ytd dw|d krd|_||_t|_WdS||_WdS|d krzddl}Wn t ytddw|d krd|_||_|j|_WdS||_WdS|dkrtd|WdS|js|jd|_ )z$Construct a _Stream object. TNF*rgzzzlib module is not availablerbz2bz2 module is not availablexzlzma module is not availabletarunknown compression type %r) _extfileobjr _StreamProxy getcomptyperrcomptypefileobjrir\posclosedzlib ImportErrorrcrc32crc _init_read_gzerrorrh_init_write_gzrdbufBZ2DecompressorcmpOSError BZ2CompressorlzmaLZMADecompressor LZMAErrorLZMACompressorr) rrrrrrirrrr9r9r:rWst                 z_Stream.__init__cCs$t|dr|js|dSdSdS)Nr)rrrrr9r9r:__del__s z_Stream.__del__cCs|jd|jj|jj |jjd|_tdtt }| d|d|j dr3|j dd|_ t j|j |_ | |j d d tdS) z6Initialize for writing with gzip compression. rs  rc@sjeZdZdZdddZddZddZd d Zd d Zd dZ e j fddZ dddZ ddZddZdS) _FileInFilezA thin wrapper around an existing file object that provides a part of its data as an individual file object. NcCs||_||_||_d|_t|dd|_d|_|durd|fg}d|_g|_d}|j}|D]&\}}||kr>|j d||df|j d||||f||7}||}q,||jkre|j d||jdfdSdS)NrrFT) roffsetr'positionrprr map_indexmapr)rrrr' blockinfolastposrealposr9r9r:rbs*    z_FileInFile.__init__cCsdSrr9rr9r9r:r{z_FileInFile.flushcCdSNTr9rr9r9r:readable~rz_FileInFile.readablecCrNFr9rr9r9r:writablerz_FileInFile.writablecCs |jSr)rseekablerr9r9r:r z_FileInFile.seekablecCr)z*Return the current file position. )rrr9r9r:rrz_FileInFile.tellcCs|tjkrtt|d|j|_|jS|tjkr4|dkr't|j|d|_|jSt|j||j|_|jS|tjkrItt|j||jd|_|jStd)z(Seek to a position in the file. rzInvalid argument) ioSEEK_SETminmaxr'rSEEK_CURSEEK_ENDr1)rrwhencer9r9r:rs   z_FileInFile.seekc Cs|dur |j|j}n t||j|j}d}|dkr |j|j\}}}}||jkr0|kr3nnn|jd7_|jt|jkrEd|_qt|||j}|rp|j||j||j|}t||krkt d||7}n|t |7}||8}|j|7_|dks|S)z!Read data from the file. NrrTr#r`) r'rrrrr3rrrdrr4) rr'r\datastartstoprr6rlr9r9r:rds2    z_FileInFile.readcCs&|t|}||dt|<t|Sr)rdr3)rrlr\r9r9r:readintosz_FileInFile.readintocCs d|_dSr)rrr9r9r:rrz_FileInFile.closer)rwrxryrzrrrrrrrrrrdrrr9r9r9r:r\s   rceZdZfddZZS) ExFileObjectcs&t|j|j|j|j}t|dSr)rr offset_datar'sparsesuperr)rtarfiletarinfor __class__r9r:rs zExFileObject.__init__rwrxryr __classcell__r9r9rr:rsrc@s eZdZdS) FilterErrorN)rwrxryr9r9r9r:r sr cr)AbsolutePathErrorcs ||_td|jddS)Nzmember z has an absolute pathrrrrrrrr9r:rszAbsolutePathError.__init__r r9r9rr:r r cr)OutsideDestinationErrorc.||_||_t|jd|dddS)Nz would be extracted to , which is outside the destinationr_pathrrrrrr%rr9r:r  z OutsideDestinationError.__init__r r9r9rr:rrrcr)SpecialFileErrorc||_t|jddS)Nz is a special filerrrr9r:rzSpecialFileError.__init__r r9r9rr:rrrcr)AbsoluteLinkErrorcr)Nz! is a symlink to an absolute pathrrrr9r:rrzAbsoluteLinkError.__init__r r9r9rr:rrrcr)LinkOutsideDestinationErrorcr)Nz would link to rrrrrr9r:rrz$LinkOutsideDestinationError.__init__r r9r9rr:rrrTcCsi}|j}tj|}|dtjfr |jdtj}|d<tj|r*t|tjtj ||}tj ||g|krDt |||j }|dur~|d@}|ru| sY|rf|d@sa|dM}|dO}n|sn|rqd}nt|||j kr~||d<|r|jdurd|d<|jdurd|d <|jdurd|d <|jdurd|d <|s|rtj|jrt|tjtj ||j}tj ||g|krt|||S) N/ri@irr)r*r+r,)rrr%realpathrseplstripisabsr r commonpathrrisregislnkisdirissymrr)r*r+r,linknamerr)member dest_pathfor_data new_attrsr target_pathrr9r9r:_get_filtered_attrssN          r0cCs|Srr9)r+r,r9r9r:fully_trusted_filter)rr1cCs,t||d}|r|jdi|ddiS|S)NFdeepr9r0rr+r,r.r9r9r: tar_filter, r5cCs,t||d}|r|jdi|ddiS|S)NTr2Fr9r3r4r9r9r: data_filter2r6r7) fully_trustedrrc @s,eZdZdZed|idddddddd d d d d ddddddddddddddddddd d!d"d#d$d%d&d%d'd%Zd}d)d*Zed+d,Zej d-d,Zed.d/Z e j d0d/Z d1d2Z e e e e e e e e d3e d4 d5d6Z d7d8Zeed9fd:d;Zdd?Zd@dAZedBdCZdDdEZedFdGZedHdIZedJdKZedLdMZedNdOZedPdQZdRdSZdTdUZ dVdWZ!dXdYZ"dZd[Z#d\d]Z$d^d_Z%d`daZ&dbdcZ'dddeZ(dfdgZ)dhdiZ*djdkZ+dldmZ,dndoZ-dpdqZ.drdsZ/dtduZ0dvdwZ1dxdyZ2dzd{Z3d%S)~raInformational class which holds the details about an archive member given by a tar header block. TarInfo objects are returned by TarFile.getmember(), TarFile.getmembers() and TarFile.gettarinfo() and are usually created internally. rzName of the archive member.rzPermission bits.r)z6User ID of the user who originally stored this member.r*z7Group ID of the user who originally stored this member.r'zSize in bytes.r(zTime of last modification.chksumzHeader checksum.typezFile type. type is usually one of these constants: REGTYPE, AREGTYPE, LNKTYPE, SYMTYPE, DIRTYPE, FIFOTYPE, CONTTYPE, CHRTYPE, BLKTYPE, GNUTYPE_SPARSE.r*zcName of the target file name, which is only present in TarInfo objects of type LNKTYPE and SYMTYPE.r+z User name.r,z Group name.devmajorzDevice major number.devminorzDevice minor number.rzThe tar header starts here.rzThe file's data starts here. pax_headerszMA dictionary containing key-value pairs of an associated pax extended header.rzSparse member information.rN_sparse_structs _link_targetrcCsj||_d|_d|_d|_d|_d|_d|_t|_d|_ d|_ d|_ d|_ d|_ d|_d|_d|_i|_dS)zXConstruct a TarInfo object. name is the optional name of the member. irrN)rrr)r*r'r(r9REGTYPEr:r*r+r,r;r<rrrr=rrr9r9r:rhs" zTarInfo.__init__cCr)z(In pax headers, "name" is called "path".rrr9r9r:r%rz TarInfo.pathcC ||_dSrrBrAr9r9r:r% cCr)z0In pax headers, "linkname" is called "linkpath".r*rr9r9r:r&rzTarInfo.linkpathcCrCrrE)rr*r9r9r:r&rDcCsd|jj|jt|fS)Nz<%s %r at %#x>)r rwridrr9r9r:__repr__szTarInfo.__repr__T) rr(rr*r)r*r+r,r2_KEEPc Cs| rt|} nt|} || ur|| _|| ur|| _|| ur"|| _|| ur)|| _|| ur0|| _|| ur7|| _|| ur>|| _|| urE|| _ | S)zGReturn a deep copy of self with the given attributes replaced. ) copydeepcopyrr(rr*r)r*r+r,) rrr(rr*r)r*r+r,r2rHresultr9r9r:rs(  zTarInfo.replacecCs|jdurd}n|jd@}|j||j|j|j|j|j|j|j|j |j |j |j d }|dt kr>|dds>|dd7<|S)z9Return the TarInfo's attributes as a dictionary. N) rrr)r*r'r(r9r:r*r+r,r;r<r:rr)rrr)r*r'r(r9r:r*r+r,r;r<DIRTYPEr)rrinfor9r9r:get_infos(  zTarInfo.get_infosurrogateescapecCsv|}|D]\}}|durtd|q|tkr"||||S|tkr-||||S|tkr7|||Std)zr(rstrip GNU_TYPES)rqr\r7r8r9objrXrstructsrNrnumbytes isextendedorigsizer9r9r:frombufs\          zTarInfo.frombufcCs8|jt}|||j|j}|jt|_||S)zOReturn the next TarInfo object from TarFile object tarfile. ) rrdrrr7r8rr _proc_member)rqrr\rr9r9r: fromtarfiles  zTarInfo.fromtarfilecCsP|jttfvr ||S|jtkr||S|jtttfvr#| |S| |S)zYChoose the right processing method depending on the type and call it. ) r:rar` _proc_gnulongr _proc_sparserjrpSOLARIS_XHDTYPE _proc_pax _proc_builtin)rrr9r9r:rs     zTarInfo._proc_membercCsh|j|_|j}|s|jtvr|||j7}||_| |j |j |j | r2|jd|_|S)zfProcess a builtin type or an unknown type which will be treated as a regular file. r)rrrr&r:SUPPORTED_TYPES_blockr'r_apply_pax_infor=r7r8r(rr)rrrr9r9r:r"s zTarInfo._proc_builtinc Cs|j||j}z||}Wnty$}ztt|dd}~ww|j|_|j t kr8t ||j |j |_n|j tkrFt ||j |j |_|rQ|jd|_|S)zSProcess the blocks that hold a GNU longname or longlink member. Nr)rrdrr'rr rrhrr:rar@r7r8rr`r*r( removesuffix)rrr\nextrr9r9r:r8s  zTarInfo._proc_gnulongc Cs|j\}}}|`|rS|jt}d}tdD]4}zt|||d}t||d|d} Wn ty:Ynw|rF| rF||| f|d7}qt|d}|s ||_ |j |_ |j | |j |_||_ |S)z8Process a GNU sparse header plus extra headers. rrcri)r>rrdrrIrOr1rrrrrrr'r) rrrrrr\rrNrrr9r9r:rSs,       zTarInfo._proc_sparsec Cs,|j||j}|jtkr|j}n|j}t d|}|dur,| d d|d<| d}|dkr9|j }nd}td}d} |||}|sLnN|\} } t| } | dkr^td ||d d|d| d} || dd|j} | tvr|| ||j |j} n || dd|j} | || <|| 7}qCz||} Wnty} ztt| dd} ~ wwd |vr|| |n!d |vr|| ||n| ddkr| ddkr|| |||jtt fvr| !||j |j|j"| _"d|vr| j#}| $s | jt%vr|| | j7}||_"| S)zVProcess an extended or global header as described in POSIX.1-2008. s\d+ hdrcharset=([^\n]+)\nNr#r0 hdrcharsetBINARYs(\d+) ([^=]+)=rTrHr$GNU.sparse.mapGNU.sparse.sizezGNU.sparse.major1zGNU.sparse.minorrGr')&rrdrr'r:rpr=rIresearchgroupr>rvr7compilematchgroupsrJrLror_decode_pax_fieldr8PAX_NAME_FIELDSrr rrh_proc_gnusparse_01_proc_gnusparse_00_proc_gnusparse_10rjrrrrr&r)rrr\r=rrr7regexrr6rrUrrrr9r9r:rosp       $    zTarInfo._proc_paxcCshg}td|D] }|t|dqg}td|D] }|t|dqtt|||_dS)z?Process a GNU tar extended sparse header, version 0.0. s\d+ GNU.sparse.offset=(\d+)\nr#s\d+ GNU.sparse.numbytes=(\d+)\nN)rfinditerrrJrlistzipr)rrr=r\offsetsrrr9r9r:rszTarInfo._proc_gnusparse_00cCs@dd|ddD}tt|ddd|ddd|_dS)z?Process a GNU tar extended sparse header, version 0.1. cSsg|]}t|qSr9)rJ).0xr9r9r: sz.TarInfo._proc_gnusparse_01..r,Nr$r#)rsrrr)rrr=rr9r9r:rs(zTarInfo._proc_gnusparse_01cCsd}g}|jt}|dd\}}t|}t||dkrAd|vr*||jt7}|dd\}}|t|t||dks|j|_t t |ddd|ddd|_ dS)z?Process a GNU tar extended sparse header, version 1.0. Nrr#r$) rrdrrsrJr3rrrrrr)rrr=rfieldsrr\numberr9r9r:rs  (zTarInfo._proc_gnusparse_10c Cs|D]T\}}|dkrt|d|q|dkr t|dt|q|dkr-t|dt|q|tvrX|tvrIzt||}Wn tyHd}Ynw|dkrR|d}t|||q||_dS) zoReplace fields with supplemental information from a previous pax extended or global header. zGNU.sparse.namer%rr'zGNU.sparse.realsizerrN) rQsetattrrJ PAX_FIELDSPAX_NUMBER_FIELDSr1rrIr=)rr=r7r8rrUr9r9r:rs&   zTarInfo._apply_pax_infocCs.z||dWSty|||YSw)z1Decode a single field from a pax record. rF)r>UnicodeDecodeError)rrUr7fallback_encodingfallback_errorsr9r9r:rs  zTarInfo._decode_pax_fieldcCs"t|t\}}|r |d7}|tS)z_Round up a byte count by BLOCKSIZE and return it, e.g. _block(834) => 1024. r#)rcr)rrrjrkr9r9r:rszTarInfo._blockcCs |jtvSz4Return True if the Tarinfo object is a regular file.)r: REGULAR_TYPESrr9r9r:r& rDz TarInfo.isregcCs|Sr)r&rr9r9r:isfile$szTarInfo.isfilecC |jtkS)z!Return True if it is a directory.)r:rMrr9r9r:r((rDz TarInfo.isdircCr)z%Return True if it is a symbolic link.)r:SYMTYPErr9r9r:r),rDz TarInfo.issymcCr)z!Return True if it is a hard link.)r:LNKTYPErr9r9r:r'0rDz TarInfo.islnkcCr)z(Return True if it is a character device.)r:rwrr9r9r:ischr4rDz TarInfo.ischrcCr)z$Return True if it is a block device.)r:rxrr9r9r:isblk8rDz TarInfo.isblkcCr)zReturn True if it is a FIFO.)r:FIFOTYPErr9r9r:isfifo<rDzTarInfo.isfifocCs |jduSr)rrr9r9r:issparse@rzTarInfo.issparsecCs|jtttfvS)zCReturn True if it is one of character device, block device or FIFO.)r:rwrxrrr9r9r:isdevCsz TarInfo.isdevr9)r)4rwrxryrzdict __slots__rpropertyr%setterr&rGrHrrOrr rVrRrSrT classmethodrrr\ staticmethodr]r}r_rirrrrrrrrrrrrrr&rr(r)r'rrrrrr9r9r9r:rEs         :  )   2 >  h   rc@seZdZdZdZdZdZdZeZ e Z dZ e ZeZdZ    dfdd Zedddefd d Zedgd d ZedhddZedhddZediddZdddddZddZddZddZd d!Zdjd"d#Zdkdd%d&d'Z dldd(d)d*Z!dmd+d,Z"d-d.Z#dnddd0d1d2Z$doddd0d4d5Z%d6d7Z&d8d9Z'd:d;Z(dd?Z* $ dpd@dAZ+dBdCZ,dDdEZ-dFdGZ.dHdIZ/dJdKZ0dLdMZ1dNdOZ2dPdQZ3dRdSZ4dTdUZ5dqdVdWZ6dXdYZ7dmdZd[Z8d\d]Z9d^d_Z:d`daZ;dbdcZ.not_compressed)keyNrz - method z:  z'file could not be opened successfully: :r#rr|rzmode must be 'r' or 'w'Frzundiscernible mode)r1sortedrrprrrrrrrsrrrr)rqrrrrikwargsr error_msgsrfunc saved_posrerror_msgs_summaryfilemodestreamrr9rr:rsZ%      z TarFile.opencKs$|dvrtd||||fi|S)zCOpen uncompressed tar archive name for reading or writing. rr)r1)rqrrrrr9r9r:r1szTarFile.taropenrc Ks|dvrtdzddlm}Wn tytddwz |||d||}WntyB}z|dur=|dkr=td |d}~wwz |j|||fi|}Wn!tyj}z||dkretd |d}~w|d |_ |S) zkOpen gzip compressed tar archive name for reading or writing. Appending is not allowed. rrrmode must be 'r', 'w' or 'x'r)GzipFilezgzip module is not availableNrlrrF) r1gziprrrrrrrr) rqrrr compresslevelrrrrr9r9r:gzopen9s8    zTarFile.gzopenc Ks|dvrtdzddlm}Wn tytddw||p!|||d}z |j|||fi|}Wn#ttfyO}z||dkrJt d |d}~w|d |_ |S) zlOpen bzip2 compressed tar archive name for reading or writing. Appending is not allowed. rrr)BZ2FilerN)rrznot a bzip2 fileF) r1rrrrrrEOFErrorrrr) rqrrrrrrrrr9r9r:bz2openZs*   zTarFile.bz2openc Ks|dvrtdz ddlm}m}Wn tytddw||p#|||d}z |j|||fi|}Wn#|tfyQ} z||dkrLt d | d} ~ w|d |_ |S) zkOpen lzma compressed tar archive name for reading or writing. Appending is not allowed. rrr)LZMAFilerrN)presetrznot an lzma fileF) r1rrrrrrrrrr) rqrrrr rrrrrr9r9r:xzopenvs*   zTarFile.xzopenrrrr )rrrrcCs|jrdSd|_z;|jdvr7|jttd|jtd7_t|jt\}}|dkr7|jtt|W|j sB|j dSdS|j sM|j ww)zlClose the TarFile. In write-mode, two finishing zero blocks are appended to the archive. NTrr$r) rrrrer4rrrc RECORDSIZErr)rrjrkr9r9r:rs   z TarFile.closecCs(||d}|durtd||S)aReturn a TarInfo object for member `name'. If `name' can not be found in the archive, KeyError is raised. If a member occurs more than once in the archive, its last occurrence is assumed to be the most up-to-date version. rNzfilename %r not found) _getmemberrKeyError)rrrr9r9r: getmembers zTarFile.getmembercCs||js ||jS)zReturn the members of the archive as a list of TarInfo objects. The list has the same order as the members in the archive. )_checkr_loadrrr9r9r: getmembersszTarFile.getmemberscCsdd|DS)zReturn the members of the archive as a list of their names. It has the same order as the list returned by getmembers(). cSsg|]}|jqSr9rB)rrr9r9r:rsz$TarFile.getnames..)rrr9r9r:getnamesszTarFile.getnamesc CsJ|d|dur |j}|dur|}tj|\}}|tjd}|d}|}||_ |dur@|j s:t |}n t |}nt |}d}|j}t |r|j|jf} |j ss|jdkrs| |jvrs||j| krst} |j| }n;t} | dr~||j| <n/t |rt} n't |rt} nt |rt} t|}nt |rt} n t |rt!} ndS||_||_"|j#|_$|j%|_&| tkr|j'|_(nd|_(|j)|_*| |_+||_,t-rz t-.|j$d|_/Wn t0yYnwt1rz t12|j&d|_3Wn t0yYnw| tt!fvr#t4tdr#t4tdr#t5|j6|_7t8|j6|_9|S) aCreate a TarInfo object from the result of os.stat or equivalent on an existing file. The file is either named by `name', or specified as a file object `fileobj' with a file descriptor. If given, `arcname' specifies an alternative name for the file in the archive, otherwise, the name is taken from the 'name' attribute of 'fileobj', or the 'name' argument. The name should be a text string. awxNrrr#rmajorminor):rrrr% splitdriverr"r#rrrlstatstatfstatfilenost_modeS_ISREGst_inost_devst_nlinkrrr@S_ISDIRrMS_ISFIFOrS_ISLNKrreadlinkS_ISCHRrwS_ISBLKrxrst_uidr)st_gidr*st_sizer'st_mtimer(r:r*pwdgetpwuidr+r grpgetgrgidr,rrst_rdevr;rr<) rrarcnamerdrvrstatresr*stmdinoder:r9r9r: gettarinfos                zTarFile.gettarinfoT)rcCs"||dur |}|D]}|rf|jdurtdntt|jtd|jp)|j|jp.|jf| s:| rGtdd|j |j fntd|j |jdurXtdntdt|jdd t|j|rod nd |r|rtd |j|rtd |jtq dS)aPrint a table of contents to sys.stdout. If `verbose' is False, only the names of the members are printed. If it is True, an `ls -l'-like output is produced. `members' is optional and must be a subset of the list returned by getmembers(). Nz ??????????z%s/%sz%10sz%d,%dz%10dz????-??-?? ??:??:??z%d-%02d-%02d %02d:%02d:%02drrrz-> zlink to )rrrtrrr+r)r,r*rrr;r<r'r(r localtimerr(r)r*r'rs)rverboserrr9r9r:r0s:     z TarFile.listfiltercCsP|d|dur |}|jdur#tj||jkr#|dd|dS|d||||}|dur=|dd|dS|durS||}|durS|dd|dS|rut|d}| ||WddS1snwYdS| r| ||rt t |D]}|j tj||tj||||d qdSdS| |dS) a!Add the file `name' to the archive. `name' may be any type of file (directory, fifo, symbolic link, etc.). If given, `arcname' specifies an alternative name for the file in the archive. Directories are added recursively by default. This can be avoided by setting `recursive' to False. `filter' is a function that expects a TarInfo object argument and returns the changed TarInfo object, if it returns None the TarInfo object will be excluded from the archive. rNr$ztarfile: Skipped %rr#ztarfile: Unsupported type %rtarfile: Excluded %rrr7)rrrr%r_dbgr4r&raddfiler(rlistdiraddr)rrr/ recursiver8rfr9r9r:r=Vs<    " z TarFile.addcCs|dt|}||j|j|j}|j||jt |7_|j }|durWt ||j|j |dt |j t\}}|dkrN|jtt||d7}|j|t7_|j|dS)aAdd the TarInfo object `tarinfo' to the archive. If `fileobj' is given, it should be a binary file, and tarinfo.size bytes are read from it and added to the archive. You can create TarInfo objects directly, or by using gettarinfo(). rN)rirr#)rrIrVrTr7r8rrerr3rrbr'rcrr4rr)rrrr\rirjrkr9r9r:r;s   zTarFile.addfilecCsh|dur|j}|dur tSt|trtd|St|r|Szt|WSty3td|ddw)NzrString names are not supported for TarFile.extraction_filter. Use a function such as tarfile.data_filter directly.zfilter z not found) extraction_filterr1rerh TypeErrorcallable_NAMED_FILTERSr r1)rr8r9r9r:_get_filter_functions    zTarFile._get_filter_function.) numeric_ownerr8c Csg}||}|dur |}|D]#}||||}|durq|r&|||j||| |dq|jdddd|D]7}tj||j } z|j || |d| || | || Wq>t yu} z || WYd} ~ q>d} ~ wwdS)aExtract all members from the archive to the current working directory and set owner, modification time and permissions on directories afterwards. `path' specifies a different directory to extract to. `members' is optional and must be a subset of the list returned by getmembers(). If `numeric_owner` is True, only the numbers for user/group names are used and not the names. The `filter` function will be called on each member just before extraction. It can return a changed TarInfo or None to skip the member. String names of common filters are accepted. N set_attrsrFcSrrrB)rr9r9r:sz$TarFile.extractall..T)rreverse)rF)rD_get_extract_tarinfor(r _extract_onesortrr%rrchownutimechmodr _handle_nonfatal_error) rr%rrFr8 directoriesfilter_functionr+rdirpathrr9r9r: extractalls2   zTarFile.extractallrcCs8||}||||}|dur|||||dSdS)aExtract a member from the archive to the current working directory, using its full name. Its file information is extracted as accurately as possible. `member' may be a filename or a TarInfo object. You can specify a different directory using `path'. File attributes (owner, mtime, mode) are set unless `set_attrs' is False. If `numeric_owner` is True, only the numbers for user/group names are used and not the names. The `filter` function will be called before extraction. It can return a changed TarInfo or None to skip the member. String names of common filters are accepted. N)rDrKrL)rr+r%rHrFr8rSrr9r9r:extracts zTarFile.extractc Cst|tr ||}n|}|}z|||}Wn/ttfy/}z ||WYd}~nd}~wtyE}z ||WYd}~nd}~ww|durU|dd|j dS| rgt |}t j ||j|_|S)z@Get filtered TarInfo (or None) from member, which might be a strNr$r9)rerhrrr _handle_fatal_errorr rQr:rr'rIrr%rr*r?)rr+rSr%r unfilteredrr9r9r:rKs(   zTarFile._get_extract_tarinfoc Cs|dz|j|tj||j||dWdSty/}z ||WYd}~dSd}~wtyF}z | |WYd}~dSd}~ww)z%Extract from filtered tarinfo to diskrrGN) r_extract_memberrr%rrrrWr rQ)rrr%rHrFrr9r9r:rL s  zTarFile._extract_onecCs |jdkr|dd|dS)z=Handle non-fatal error (ExtractError) according to errorlevelr# tarfile: %sN)rr:rrr9r9r:rQ s zTarFile._handle_nonfatal_errorcCsp|jdkrt|tr)|jdur|dd|jdS|dd|j|jfdS|ddt|j|fdS)z1Handle "fatal" error according to self.errorlevelrNr#rZztarfile: %s %rztarfile: %s %s)rrerfilenamer:strerrorr:rwr[r9r9r:rW s   zTarFile._handle_fatal_errorcCsz|dt|tr||}n|}|s|jtvr!|||S|s)| r;t|j t r3t d| ||SdS)a\Extract a member from the archive as a file object. `member' may be a filename or a TarInfo object. If `member' is a regular file or a link, an io.BufferedReader object is returned. For all other existing members, None is returned. If `member' does not appear in the archive, KeyError is raised. rz'cannot extract (sym)link as file objectN)rrerhrr&r:r fileobjectr'r)rrr extractfile_find_link_target)rr+rr9r9r:r_+ s     zTarFile.extractfilecCsV|d}|dtj}tj|}|rtj|st||s'| r4| dd|j |j fn| d|j | rF|||nF|rQ|||n;|r\|||n0|sd|rk|||n!|ss| rz|||n|jtvr|||n||||r||||| s||||||dSdSdS)z\Extract the TarInfo object tarinfo to a physical file called targetpath. rr#z%s -> %sN)rrrr"r%dirnamermakedirsr'r)r:rr*r&makefiler(makedirrmakefiforrmakedevmakelinkr:r makeunknownrNrPrO)rr targetpathrHrF upperdirsr9r9r:rYK s8      zTarFile._extract_membercCsBz|jdurt|WdSt|dWdSty YdSw)z,Make a directory called targetpath. Ni)rrmkdirFileExistsErrorrrrir9r9r:rd| s  zTarFile.makedircCs|j}||j|j}t|d?}|jdur7|jD]\}}||t|||t|q||j| nt|||jt|WddSWddS1sSwYdS)z'Make a file called targetpath. rN) rrrrrrrbrr'truncate)rrrisourceritargetrr'r9r9r:rc s      "zTarFile.makefilecCs"||||dd|jdS)zYMake a file from a TarInfo object with an unknown type at targetpath. r#z9tarfile: Unknown file type %r, extracted as regular file.N)rcr:r:rmr9r9r:rh s  zTarFile.makeunknowncCs ttdr t|dStd)z'Make a fifo called targetpath. mkfifozfifo not supported by systemN)rrrqr rmr9r9r:re s zTarFile.makefifocCsjttdr ttdstd|j}|durd}|r!|tjO}n|tjO}t||t |j |j dS)z     z TarFile.chownc CsF|jdurdSz t||jWdSty"}ztd|d}~ww)zASet file permissions of targetpath according to tarinfo. Nzcould not change mode)rrrPrr )rrrirr9r9r:rP s  z TarFile.chmodc CsZ|j}|dur dSttdsdSz t|||fWdSty,}ztd|d}~ww)zBSet modification time of targetpath according to tarinfo. NrOz"could not change modification time)r(rrrOrr )rrrir(rr9r9r:rO s  z TarFile.utimec Cs:|d|jdur|j}d|_|S|j|jkr-|j|jd|jds-tdd} z|j |}Wnt ye}z!|j r[| dd|j|f|jt 7_WYd}~q/WYd}~nd}~wty}z-|j r| dd|j|f|jt 7_WYd}~q/|jdkrtt|dWYd}~nqd}~wty|jdkrtd dYn[ty}z|jdkrtt|dWYd}~nBd}~wty}ztt|dd}~wty }zzddl}t||jrtd |d|ty|wd}~ww |dur|j||Sd|_|S) zReturn the next member of the archive as a TarInfo object, when TarFile is opened for reading. Return None if there is no more available. raNr#r`Tr$z0x%X: %srz empty filez zlib error: )rrrrrrrdrrrr~rr:rrLrhr|r}r Exceptionrrerrrrr)rmrrrr9r9r:r st                z TarFile.nextc Cs|}d}|dur#z||}Wn tyd}Ynw|d|}|r+tj|}t|D]"}|r<|j|jkr;d}q/|rFtj|j}n|j}||krQ|Sq/|rXt|dS)z}Find an archive member by name from bottom to top. If tarinfo is given, it is used as the starting point. FNT) rindexr1rr%normpathreversedrr) rrr normalizerskippingrr+ member_namer9r9r:r M s2     zTarFile._getmembercCs |}|dur nqd|_dS)zWRead through the entire archive file and look for readable members. TN)rrrr9r9r:ru s  z TarFile._loadcCs>|jr td|jj|dur|j|vrtd|jdSdS)znCheck if TarFile is still open, and if the operation's mode corresponds to TarFile's mode. z %s is closedNzbad operation for mode %r)rrr rwr)rrr9r9r:r s zTarFile._checkcCs`|rdtdtj|j|jf}d}n|j}|}|j||dd}|dur.t d||S)zZFind the target member of a symlink or hardlink member in the archive. rNT)rrzlinkname %r not found) r)rr8rr%rarr*r r )rrr*limitr+r9r9r:r` s  zTarFile._find_link_targetccs|jr |jEdHdSd}|jdur|}|d7}|V |t|jkr,|j|}n|js;|}|s:d|_dSndS|d7}|Vq)z$Provide an iterator object. Nrr#T)rrrrr3)rrrr9r9r:__iter__ s,   zTarFile.__iter__cCs ||jkrt|tjddSdS)z.Write debugging output to sys.stderr. fileN)rrsrqstderr)rlevelmsgr9r9r:r: s z TarFile._dbgcCs ||Sr)rrr9r9r: __enter__ szTarFile.__enter__cCs.|dur |dS|js|jd|_dSr)rrrr)rr:rU tracebackr9r9r:__exit__ s    zTarFile.__exit__) NrNNNNNNrPNNNN)rN)rNr)rNN)NNNTrr)rEN)rT)TFr)>rwrxryrzrrrrrrTr r7r8rrrr^r@rrr rrrrr rrrrrr4rr=r;rDrUrVrKrLrQrWr_rYrdrcrhrerfrgrNrPrOrr rrr`rr:rrr9r9r9r:rHs o]       c& 3 -     1!  ?(   rcCsBzt|dr t|d}nt|}|WdSty YdSw)zReturn True if name points to a tar archive that we are able to handle, else return False. 'name' should be a string, file, or file-like object. rd)rTF)rrrr)rrr9r9r:r s   rc Cshddl}d}|j|d}|jdddddd |jd d td d |jdd}|jddddd|jdddddd|jdddddd|jdd dd!d|}|jr]|jdur]|d"d#|j dur|j }t |rt |d$}| t | tjd%Wdn1swY|jrt d&|dSdS|d"d'|dS|jdur|j}t |rt |d(}|j|jd)WddS1swYdS|d"d'|dS|jdurRt|jd"kr|jd}tj}nt|jd*kr|j\}}n|d"|t |rGt |d(}|j||jd+Wdn 1s%wY|jrE|d,kr9d-|} nd.||} t | dSdS|d"d'|dS|jdur|jd} tj| \} } d/d/d0d0d1d1d1d1d2} | | vr|d3| | nd4}|j}t | |}|D]}||qWdn 1swY|jrt d5| dSdSdS)6Nrz3A simple command-line interface for tarfile module.) descriptionz-vz --verbose store_trueFzVerbose output)actiondefaulthelpz--filterz zFilter for extraction)metavarchoicesrT)requiredz-lz--list zShow listing of a tarfile)rrz-ez --extract+)rz zExtract tarfile into target dir)nargsrrz-cz--create)zzzCreate tarfile from sourcesz-tz--testzTest if a tarfile is validr#z&--filter is only valid for extraction rrz{!r} is a tar archive.z{!r} is not a tar archive. r)r6r$)r%r8rEz{!r} file is extracted.z+{!r} file is extracted into {!r} directory.rrr)rz.tgzz.xzz.txzz.bz2z.tbzz.tbz2z.tb2zw:rz{!r} file created.)argparseArgumentParser add_argumentrCadd_mutually_exclusive_group parse_argsr8rVexittestrrrrsrqrr6rTrrr3rcurdir format_helprUcreatepopr%splitextr=)rrparserrargsrfrtfrrtar_name_ext compressionstar_mode tar_files file_namer9r9r:main s           "          r__main__r)krzversion __author__ __credits__builtinsrrrqrrrarrrZrIrwarningsr*rr,AttributeErrorNotImplementedErrorryr NameError__all__r4rr r^rYr[rZrtr@rrrrwrxrMrCONTTYPErar`rrjrprr rrrrrrrrrfrJrrr getfilesystemencodingr;r@rOrVr_rbrtrrr rrr r r|r}r~rLrrrobjectrrBufferedReaderrr r rrrrr0r1r5r7rCrHrrrrrwr9r9r9r:s"         sh  8   _