o 0ka,X@sddlmZddlmZddlmZddlmZddlZddlZddlZddlm Z ddlm Z ddlm Z dd lm Z dd lm Z dd lmZdd lmZdd lmZddlmZddlTddlT GdddeZddZd7ddZd7ddZddZddZddZdd ZGd!d"d"eZGd#d$d$eZGd%d&d&eZ d'd(Z!Gd)d*d*eZ"d+d,Z#d-d.Z$d/d0Z%d7d1d2Z&d3d4Z'Gd5d6d6eZ(dS)8)map)next)object)rangeN)errors)diffdir)config)librsync)log) selection)tarfile)tempdir)util)*c@s eZdZdS)PatchDirExceptionN)__name__ __module__ __qualname__rr4/usr/lib/python3/dist-packages/duplicity/patchdir.pyr.srcCs(tdd|}t|||rJdS)z6Patch given base_path and file object containing delta arbitraryrN)r TarFilepatch_diff_tarfileclose) base_pathdifftar_fileobj diff_tarfilerrrPatch2s rrcCst|}t|||dS)z8Patch given base_path and iterator of delta file objectsN)TarFile_FromFileobjsr)r fileobj_iterrestrict_indexrrrrPatch_from_iter9sr"c Cs|r t|}nt}t|}|rt||}t||}t t |g}|D]C\}}|rMt t dt|t jjt|||j||q(t t dt|t jjt|||j||q(||dS)zPatch given Path object using delta tarfile (as in tarfile.TarFile) If restrict_index is set, ignore any deltas in diff_tarfile that don't start with restrict_index. z Patching %sN)existsr Selectset_iter empty_iterdifftar2path_iterfilter_path_iterr collate2itersIterTreeReducer PathPatcherr Info_rfsdecodeget_relative_pathInfoCodepatch_file_patchingescapeindexFinishsetdata) rrr! path_iterdiff_path_itercollatedITR basis_path diff_ropathrrrr?s,       rccsdSNrrrrrr&`sr&ccsVt|tr|s J|t|}|D]}|jd||kr(|j|d|_|VqdS)zRewrite path elements of path_iter so they start with index Discard any that doesn't start with index, and remove the index prefix from the rest. N) isinstancetuplelenr3)r6r3lpathrrrr(esr(ccst|}d}zt|g}Wn tyYdSw |ds dS|r*|js*|qt|d\}}}t|}||d||_|dkrId|_ n | ri|r_t ||||}| ||Vq| | |d|Vzt||d<Wn ty~YdSwq)z2Turn file-like difftarobj into iterator of ROPathsNrdeleted)iterr StopIterationat_endrget_index_from_tarinfoROPathinit_from_tarinfodifftypetypeisregMultivol_Filelike setfileobj extractfile)rtar_itermultivol_fileobj tarinfo_listr3rJmultivolropathrrrr'tsH    r'cCsDdD]d}t|}tjjdkrt|tr|}||rf|t |d}|drI|dkr1d}nd}d}t d d |\}}|dkrHt d |n|dd }|t |d}| d rb|dd }d}nqt d ||dksu|dkrxd}n%tjjdkrtt|d}nt|d}d|vrt dt||||fS)z;Return (index, difftype, multivol) pair from tarinfo object)z snapshot/zdiff/zdeleted/multivol_diff/zmultivol_snapshot/NrSrUdiffsnapshotrBz+(?s)^multivol_(diff|snapshot)/?(.*)/[0-9]+$z\2zUnrecognized diff entry %s/r.r/s..z/Tar entry %s contains '..'. Security violation)rget_tarinfo_namesys version_infomajorr=unicodeencode startswithr?resubnrendswithr>fsencodesplitr.)tarinfoprefixtinamenamerJrSnum_subsr3rrrrGsP        rGc@s2eZdZdZddZd ddZddZd d Zd S) rMzEmulate a file like object from multivols Maintains a buffer about the size of a volume. When it is read() to the end, pull in more volumes as desired. cCs*|||_|_||_||_d|_d|_dS)z9Initializer. tf is TarFile obj, tarinfo is first tarinforN)tfrPrRr3bufferrF)selfrqrPrRr3rrr__init__s  zMultivol_Filelike.__init__rYcCs~|dkr|r |st|j}nt|j|kr&|snt|j|kstt|j|}|jd|}|j|d|_|S)zRead length bytes from filerN) addtobufferr?rrmin)rslengthreal_lenresultrrrreads zMultivol_Filelike.readcCs|jrdSt|jd\}}}|r||jkrd|_dS|j|jd}|j|7_|z t |j |jd<WdSt yNd|jd<d|_YdSw)zAdd next chunk to bufferNrrB) rFrGrRr3rqrOrrrzrrrPrE)rsr3rJrSfprrrrus" zMultivol_Filelike.addtobuffercCs$|js d|_|s nqd|_dS)z"If not at end, read remaining datarBrpN)rFrrrursrrrrs zMultivol_Filelike.closeN)rY)rrr__doc__rtrzrurrrrrrMs   rMc@8eZdZdZddZddZddZdd Zd d Zd S) r+z2Used by DirPatch, process the given basis and diffcCs||_d|_dSz#Set base_path, Path of root of treeN)rdir_diff_ropathrsrrrrrt s zPathPatcher.__init__cCs|r|s|dksJt|||||dS|s-|j|}|r(J|n |s9||||_ ||_ dS)z0Start processing when diff_ropath is a directoryrN) isdirruindex fast_processr new_indexr#mkdirdeletedir_basis_pathrrsr3r:r;rrr start_processs     zPathPatcher.start_processcC|jr |j|jdSdS)z,Copy directory permissions when leaving treeN)r copy_attribsrr|rrr end_process#zPathPatcher.end_processcCs|o| S)z3No need to recurse if diff_ropath isn't a directory)rrrrrcan_fast_process(szPathPatcher.can_fast_processcCs|sdS|s|jdkr dS||j|dS|jdkr-|r'|dS|dS|r:|rN|jdkrN|rC|n|||dS|jdksXJ|j||dS)z#For use when neither is a directoryNrCrXrW) rJcopyrrrdeltreerrLpatch_with_attribsrrrrr,s"     zPathPatcher.fast_processN rrrr}rtrrrrrrrrr+ s r+c@r~) rz@Like a tarfile.TarFile iterator, but read from multiple fileobjscCs||_d\|_|_d|_dS)zMake new tarinfo iterator fileobj_iter should be an iterator of file objects opened for reading. They will be closed at end of reading. )NNN)r r rP current_fp)rsr rrrrtHs  zTarFile_FromFileobjs.__init__cCs|Sr<rr|rrr__iter__SszTarFile_FromFileobjs.__iter__cCsV|jr |jr J t|j}t|tjrq ||_ td|j|_ t |j |_ dS)z9Set tarfile from next file object, or raise StopIterationTrN) rrrr r=rBadVolumeExceptionr make_tarfiler rDrP)rsxrrr set_tarfileVs  z TarFile_FromFileobjs.set_tarfilecCsh|jsz|Wn tyYdSwzt|jWSty3|jr(J|t|jYSwr<)r rrErrPrr|rrr__next__gs    zTarFile_FromFileobjs.__next__cCs |j|S)z)Return data associated with given tarinfo)r rO)rsrkrrrrOts z TarFile_FromFileobjs.extractfileN) rrrr}rtrrrrOrrrrrFs  rcsjtdkrtddSdg}|dd}fddddfd d }|||S) aCollate iterators by index Input is a list of n iterators each of which must iterate elements with an index attribute. The elements must come out in increasing order, and the index should be a tuple itself. The output is an iterator which yields tuples where all elements in the tuple have the same index, and the tuple has n elements in it. If any iterator lacks an element with that index, the tuple will have None in that spot. rVrrBNc s^tD](}||s,||dur,z t|||<Wqty+d||<d||<YqwqdS)zSet the overflow and rorps listNrB)rrrE)overflowelemsi) iter_listiter_numrrsetrorpss   zcollate_iters..setrorpscSstdddd|DDS)z;Return the first index in elems, assuming elems isn't emptycSsg|]}|jqSr)r3).0elemrrr sz8collate_iters..getleastindex..cSsg|]}|r|qSrrrrrrrr)rv)rrrr getleastindexsz$collate_iters..getleastindexc3sx ||d|vr dS|}g}t|D]}||r0||j|kr0|||d||<q|dqt|Vqr<)rr3appendr>)rrrr3yieldvalr)rrrr yield_tupless     z#collate_iters..yield_tuples)r?rr))rrrrr)rrrrr collate_itersys    rc@sheZdZdZddZddZddZdd Zd d Zd d Z ddZ ddZ ddZ ddZ ddZdS) IndexedTuplez?Like a tuple, but has .index (used previously by collate_iters)cCs||_t||_dSr<)r3r>data)rsr3sequencerrrrtszIndexedTuple.__init__cCs t|jSr<)r?rr|rrr__len__s zIndexedTuple.__len__cCs |j|S)z4This only works for numerical keys (easier this way))r)rskeyrrr __getitem__s zIndexedTuple.__getitem__cC||dkSNrY__cmp__rsotherrrr__lt__zIndexedTuple.__lt__cC||dkSNrBrrrrr__le__rzIndexedTuple.__le__cCs || Sr<)__eq__rrrr__ne__s zIndexedTuple.__ne__cCrrrrrrr__gt__rzIndexedTuple.__gt__cCrrrrrrr__ge__rzIndexedTuple.__ge__cCs2t|tsJ|j|jkrdS|j|jkrdSdS)NrYrrB)r=rr3rrrrrs   zIndexedTuple.__cmp__cCs:t|tr|j|jko|j|jkSt|tr|j|kSdSr<)r=rr3rr>rrrrrs   zIndexedTuple.__eq__cCsddtt|j|jfS)Nz(%s).%sz, )joinrstrrr3r|rrr__str__szIndexedTuple.__str__N)rrrr}rtrrrrrrrrrrrrrrrs rcCsXg}t|d}|dkr*||}|dur"|d||jdkr" |S|d8}|dks |S)a$Given an sequence of ROPath deltas, remove blank and unnecessary The sequence is assumed to be in patch order (later patches apply to earlier ones). A patch is unnecessary if a later one doesn't require it (for instance, any patches before a "delete" are unnecessary). rBrNrW)r?insertrJ)patch_sequence result_listrdeltarrr normalize_pss   rcCs|d}|jdksJd||s%t|dks!Jdt||S|d}|ddD]>}|jdks.csg|]}t|qSr)r(rr!rrr=s)r) tarfile_listr! diff_itersrrrtarfiles2rop_iter3srcCs>tt|g}d}|D] }d}||j|q |||S)zxWrite out ropaths in rop_iter starting at base_path Returns 1 if something was actually written, 0 otherwise. rrB)r*ROPath_IterWriterr3r4r5)rrop_iterr9 return_valrTrrr Write_ROPathsAs rc@r~) rzUsed in Write_ROPaths above We need to use an ITR because we have to update the permissions/times of directories after we write the files in them. cCs||_d|_d|_dSr)rr dir_new_pathrrrrrtXs zROPath_IterWriter.__init__cCs|s%|jdksJ|j|j|}|r%|r ||||j||_|jr=tj s=|dkssL               !+,@;351&