
­­­­­­­­­­­­­­­­­­
<!DOCTYPE html>
<html>
3
ybnz                 @   sB  d dl Z d dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlm	Z	 d dl
mZ d dlZddlmZ e ZddlmZ ddlmZ ddlmZ dd	lmZ dd
lmZmZmZmZmZ ddlmZ ddlmZ ddl m!Z! ddl"m#Z# e$ej%dZ&e$ej%dZ'e$ej%dZ(dd Z)dZ*G dd dZ+G dd dej,Z-dS )    N)defaultdict)SIGINT   )create_logger)blake2b_128)Archiver)Archive)FuseVersionsIndex)	daemonizehardlinkablesignal_handlerformat_file_sizeError)msgpack)Item)LRUCache)RemoteRepositoryst_mtime_nsst_birthtimest_birthtime_nsc               C   s   t jddS )Nr   )workers)llfusemain r   r   /usr/lib64/python3.6/fuse.py	fuse_main#   s    r      c               @   s8   e Zd ZdZdZejdZdd Zdd Z	dddZ
d	S )	ItemCachez
    This is the "meat" of the file system's metadata storage.

    This class generates inode numbers that efficiently index items in archives,
    and retrieves items from these inode numbers.
       i   z=cIIc             C   sJ   || _ t | _d| _d| _tjdd| _tddd d| _	d| _
d| _d S )	Nr   i@B zborg-tmp)prefix
   c             S   s   d S )Nr   )_r   r   r   <lambda>_   s    z$ItemCache.__init__.<locals>.<lambda>)capacitydispose)decrypted_repository	bytearraymetawrite_offsetoffsettempfileZTemporaryFilefdr   chunksindirect_itemsdirect_items)selfr%   r   r   r   __init__A   s    zItemCache.__init__c             C   s(  || j  }|dk rtd| j| tdkr| jj| j|\}}}|| }t| j||d  }| jj|}|st	| j
j|g\}	}|| j|< t||d  }
tj }|j|
 tt	|dS | j| tdkrtj| j|d |d  d	}| jj|tj tt	tj| jd
ddS tdd S )Nr   z3ItemCache.get() called with an invalid inode number   I    )internal_dict   Sr   	   littlei   )Z	read_sizezInvalid entry type in self.meta)r)   
ValueErrorr'   ordindirect_entry_structunpack_frombytesr,   getnextr%   get_many
memoryviewr   Unpackerfeedr   int
from_bytesr+   seekioSEEK_SET)r/   inoder)   r!   Zchunk_id_relative_offsetchunk_offsetZchunk_id_offsetchunk_idchunkcsizedataunpackerZ	fd_offsetr   r   r   r<   g   s(    


zItemCache.getNFc             #   s  t j }dd}d}d | j}| j}| jj}	 fdd}
xt|| jj|D ]\}\}}|d t	|kr|t
| j  | _}||||d < |}|d7 }||7 }t	|}|j| x8y|j|
}W n t jk
r   P Y nX t|d}|r|| s| rd|krd q }t	|}| |k }d |d t	|krX|t
| j  | _}|r| jjdtj}| jj| d	|jd
d |||d < |  jd7  _n.| | }|	||d|| | |  jd7  _|| j }|d7 }||fV  qW qPW || _d S )Nr       c                s    | 7  t | 7 d S )N)len)Zappend_msgpacked_bytes)msgpacked_bytesstream_offsetr   r   write_bytes   s    z1ItemCache.iter_archive_items.<locals>.write_bytesr2   )r3   partr5   r4      r6   r   r1   )r   r@   r(   r'   r9   	pack_intozipr%   r>   rO   r;   GROW_META_BYrA   unpackZ	OutOfDatar   r+   rD   rE   SEEK_ENDwriteto_bytesr.   r-   r)   )r/   Zarchive_item_idsfilterconsider_part_filesrM   Zchunk_beginZlast_chunk_lengthr(   r'   Zpack_indirect_intorR   keyrK   rL   Zcurrent_id_offsetitemZcurrent_itemZcurrent_item_lengthZcurrent_spans_chunksposZitem_offsetrG   r   )rP   rQ   r   iter_archive_items   sZ    $

"
zItemCache.iter_archive_itemsi   i    )NF)__name__
__module____qualname____doc__rW   structStructr9   r0   r<   ra   r   r   r   r   r   .   s   
&r   c                   s   e Zd ZdZdZdZdZdZdZ fddZ	dd Z
d	d
 Zd1ddZd2ddZg fddZdd Zdd Zdd Zd3ddZdd Zg fddZd4ddZd5dd Zd6d!d"Zd#d$ Zd7d%d&Zd8d'd(Zd9d)d*Zd+d, Zd-d. Zd:d/d0Z  ZS );FuseOperationsz(Export archive as a FUSE filesystem
    FNr   c                s   t  j  || _|| _|| _|| _|| _i | _tt	dd d| _
d| _i | _tt| _tj | _tj | _d | _i | _t|| _ttjjdtj pd}tjd| t|dd d| _tt	d	d d| _ d S )
Nc             S   s   d S )Nr   )r!   r   r   r   r"      s    z)FuseOperations.__init__.<locals>.<lambda>)r#   r$   r   ZBORG_MOUNT_DATA_CACHE_ENTRIESr   z$mount data cache capacity: %d chunksc             S   s   d S )Nr   )r!   r   r   r   r"      s    c             S   s   d S )Nr   )r!   r   r   r   r"      s    )!superr0   repository_uncachedr%   argsmanifestr^   itemsr   FILES_inode_cache_inode_countparentr   dictcontentsosgetuiddefault_uidgetgiddefault_giddefault_dirpending_archivesr   cacherB   environr<   	cpu_countloggerdebug
data_cache	_last_pos)r/   r^   Z
repositoryrl   rk   r%   Zdata_cache_capacity)	__class__r   r   r0      s(    




zFuseOperations.__init__c             C   s   | j dd | jjjr6| jr$td| j| jjj ntt | _xj| j	j
j| jD ]V}| jrh| j|j qP| j dt|jj d d}|| jd tj|j< |j| j|< qPW d S )Nr   )rq   z_for versions view, do not specify a single archive, but always give the repository as location.g    eA)rq   mtime)_create_dirrk   locationarchiveversionsr   process_archiver	   versions_indexrl   ZarchivesZlist_consideringnamerB   ZtsZ	timestamprs   rt   fsencoderz   )r/   r   Zarchive_inoder   r   r   _create_filesystem  s    
z!FuseOperations._create_filesystemc          	   C   s   t jd| jt| jttj| jt| jtj| j   t jdt| j t jd| j	j
| j	j | j	j
| j	jttj| j	jttj| j	jj j t jdt| jj | jjttdd | jj D  | jj  d S )Nz$fuse: %d synth inodes, %d edges (%s)zfuse: %d pending archivesz]fuse: ItemCache %d entries (%d direct, %d indirect), meta-array size %s, direct items size %sz#fuse: data cache: %d/%d entries, %sc             s   s   | ]\}}t |V  qd S )N)rO   ).0r^   rJ   r   r   r   	<genexpr>   s    z2FuseOperations.sig_info_handler.<locals>.<genexpr>)r~   r   rp   rO   rq   r   sys	getsizeofrz   r{   r.   r-   r'   rt   statr+   filenost_sizer   rm   Z	_capacitysumr%   Zlog_instrumentation)r/   Zsig_nostackr   r   r   sig_info_handler  s    (zFuseOperations.sig_info_handlerc             C   s  ddd}dddg}|r(|j |jd ||dd	d
t}|rL||dd	d
t ||dd	d
t| _||dd	d
t| _||dddt| _||dddt| _||dddtdd| _| jdk	r| jn| j	}| jdk	r| jn| j
}d| j @ }	t|	ttj d ||d| _| j  tj| || |sBt \}
}t| jtsB| jj|
| d
}zRtd| j$ td| j t }W dQ R X W dQ R X |dkp|tko|}W dtj| X dS )z6Mount filesystem on *mountpoint* with *mount_options*.r   c       
      S   s    xt | D ]\}}||kr*| j| |S |j|d r| j| |jddd }|tkr|j }	|	dkrndS |	dkrzdS td| |tkryt||dS  tk
r   td| d Y nX y||S  tk
 r   td| d Y qX qW |S d S )N=r   yyestrue1Tnnofalse0Fzunsupported value in option: %s)base)r   r   r   r   )r   r   r   r   )	enumeratepop
startswithsplitboollowerr7   rB   )
optionsr^   ZpresentZnot_presentZwanted_typeint_baseidxZoptionvaluevr   r   r   
pop_option&  s0    

z(FuseOperations.mount.<locals>.pop_optionzfsname=borgfsZroZdefault_permissions,ignore_permissionsTFallow_damaged_filesr   uidNgidumaskrT   )r   iA  g    eA)moder   r   r   SIGUSR1ZSIGINFO)r   )extendr   r   r   r   rB   
uid_forced
gid_forcedr   rv   rx   r   timery   r   r   Zinitr
   
isinstancerj   r   Zmigrate_lockr   r   r   r   close)r/   Z
mountpointZmount_optionsZ
foregroundr   r   r   Zdir_uidZdir_gidZdir_modeZold_idZnew_idZumountsignalr   r   r   mount#  s:    
!

zFuseOperations.mountc             C   sN   | j  }|dk	r4tf | jj | j|< || j| _n| j| j|< || j|< |S )zCreate directory
        N)allocate_inoder   ry   Zas_dictrm   r   rq   )r/   rq   r   Zinor   r   r   r   p  s    
zFuseOperations._create_dirc                s  i | _ tj }t| j| j| j|| jjd}| jj	}t
j| jj| jj}|j  pR|r\i nd  fdd}t
j|||}x| jj|jj|| jjdD ]\}	}
|rtjj|
jjtj|d |
_tj|
j}tj|
j}|ry| j||}W n tk
r   Y nX |
| j|< q||jd }d}x"|dd	 D ]}| j||}q6W | j |d
 |
||||	 | qW tj | }t!j"d||j# dS )z9Build FUSE inode hierarchy from archive metadata
        )r]   Nc                sD   r@| r@t | jr@| jddr@d| kr@| jdd f | jd< d S )NZhardlink_masterTsourcer,   path)r   r   r<   )r_   Zmatched)hardlink_masterspartial_extractr   r   peek_and_store_hardlink_masters  s    zGFuseOperations.process_archive.<locals>.peek_and_store_hardlink_masters)r\   r]      /r   z8fuse: process_archive completed in %.1f s for archive %sr   )$file_versionsr   Zperf_counterr   rj   r^   rl   rk   r]   strip_componentsr   Zbuild_matcherZpatternspathsemptyZbuild_filterr{   ra   Zmetadatarm   rt   sepjoinr   r   r   r   S_ISDIRr   _find_inodeKeyErrorprocess_innerprocess_leafr~   r   r   )r/   archive_namer   Zt0r   r   Zmatcherr   r\   
item_inoder_   r   is_dirrG   segmentsrq   segmentZdurationr   )r   r   r   r   |  s>     
zFuseOperations.process_archivec	                s  |j }	|` |pi } fdd}
ddd}d|ko8t|jr,tjj|jjtj|d  }|j|jd |f\}}|rtj	|} j
r j| }|||dd}y j||}W n" tk
r   tjd	|	| d S X  j|}|jd
dd |_| j|< n2|d k	r0||_|}| j|< |r0d |	f||j< n|} j
r~| r~ j||}tj	|	}|
||}|d k	r~|||}| j|< | j|< |r| j| |< d S )Nc                sf   d| krbt |} jj|d\}}dd | jD }t dj|}||kr^|d7 }||f j|< |S d S )Nr,   r   c             S   s   g | ]\}}}|qS r   r   )r   rI   r!   r   r   r   
<listcomp>  s    zEFuseOperations.process_leaf.<locals>.file_version.<locals>.<listcomp>rN   r   )r   N)r   r   r<   r,   r   )r_   r   Zfile_idZcurrent_versionZprevious_idZ	chunk_idsZcontents_id)r/   r   r   file_version  s    z1FuseOperations.process_leaf.<locals>.file_versionFc             S   sJ   |r | j dd}| d|d  7 } tjj| \} }tjd| }| | | S )Nr   r   z.%05dr   )rsplitrt   r   splitextr   )r   versionadd_dirZ
path_fnameZextZversion_encr   r   r   make_versioned_name  s    z8FuseOperations.process_leaf.<locals>.make_versioned_namer   T)r   z#Skipping broken hard link: %s -> %snlinkr   )F)r   r   r   rt   r   r   r   r   r<   r   r   r   r   r   r~   warningget_itemr   rm   r,   r   rq   rs   )r/   r   r_   rq   r   r   r   r   Zstripped_componentsr   r   r   r   r,   Zlink_targetr   rG   Zenc_pathr   )r/   r   r     sL    












zFuseOperations.process_leafc             C   s6   | j | }||kr|| }n| j|}|r2|||< |S )N)rs   r   )r/   r   parent_inodedirrG   r   r   r   r     s    


zFuseOperations.process_innerc             C   s   |  j d7  _ | j S )Nr   )rp   )r/   r   r   r   r     s    zFuseOperations.allocate_inodec             C   sL   t j }d|_d|_d|_d|_d|_d|_d|_d|_	t
|drHd|_|S )Ni   r   	f_namemax   )r   ZStatvfsDataf_bsizef_frsizef_blocksf_bfreef_bavailf_filesf_ffreef_favailhasattrr   )r/   ctxZstat_r   r   r   statfs  s    
zFuseOperations.statfsc             C   sR   | j j|}|d k	r|S y
| j| S  tk
rL   | jj|}|| j |< |S X d S )N)ro   r<   rm   r   r{   )r/   rG   r_   r   r   r   r     s    

zFuseOperations.get_itemc             C   s2   ||j d }d}x|D ]}| j| | }qW |S )Nr   r   )r   rs   )r/   r   r   r   rG   r   r   r   r   r     s
    
zFuseOperations._find_inodec             C   s\  | j |}tj }||_d|_d|_d|_|j| j @ |_	|j
dd|_| jd k	rX| jn|jdkrh|jn| j|_| jd k	r| jn|jdkr|jn| j|_|j
dd|_|j |_d|_|j|j d |j |_|j}tr||_|j
d||_|j
d||_trX|j
d	||_nF|d
 |_ |j
d|d
 |_!|j
d|d
 |_"t#rX|j
d	|d
 |_$|S )Nr   i,  r   r   Zrdevi   ZatimeZctimeZ	birthtimeg    eA)%r   r   EntryAttributesst_inoZ
generationZentry_timeoutZattr_timeoutr   r   st_moder<   st_nlinkr   r   rv   st_uidr   r   rx   st_gidst_rdevZget_sizer   
st_blksize	st_blocksr   have_fuse_xtime_nsr   st_atime_nsst_ctime_nshave_fuse_birthtime_nsr   st_mtimest_atimest_ctimehave_fuse_birthtimer   )r/   rG   r   r_   entryZmtime_nsr   r   r   getattr  s6    
((

zFuseOperations.getattrc             C   s   | j |}|jdi j S )Nxattrs)r   r<   keys)r/   rG   r   r_   r   r   r   	listxattr>  s    
zFuseOperations.listxattrc             C   sF   | j |}y|jdi | pdS  tk
r@   tjtjd Y nX d S )Nr  rN   )r   r<   r   r   	FUSEErrorZENOATTR)r/   rG   r   r   r_   r   r   r   getxattrB  s
    
zFuseOperations.getxattrc             C   s*   | j j|d }|r&| j|tj|g d S )N)rz   r   r   rt   r   )r/   rG   r   r   r   r   _load_pending_archiveI  s    z$FuseOperations._load_pending_archivec             C   sV   | j | |dkr|}n4|dkr,| j| }n | j| j|}|sLtjtj| j|S )N   .s   ..)	r  rq   rs   r<   r   r  errnoENOENTr   )r/   r   r   r   rG   r   r   r   lookupO  s    
zFuseOperations.lookupc             C   s2   | j s.| j|}d|kr.tjd tjtj|S )NZchunks_healthyzzFile has damaged (all-zero) chunks. Try running borg check --repair. Mount with allow_damaged_files to read damaged files.)r   r   r~   r   r   r  r  ZEIO)r/   rG   flagsr   r_   r   r   r   open[  s    

zFuseOperations.openc             C   s   | j | |S )N)r  )r/   rG   r   r   r   r   opendirg  s    
zFuseOperations.opendirc             C   sT  g }| j |}| jj|d\}}||kr0d\}}||8 }|j}xt|t|D ]}	||	 \}
}}||k r||8 }||7 }|d7 }qPt||| }|
| jkr| j|
 }|| t|kr| j|
= n0| jj	|
| j
j|
}|| t|k r|| j|
< |j||||   d}||8 }|sP|| jkr6| jj|||f n||f| j|< P qPW dj|S )Nr   r   rN   )r   r   )r   r   )r   r   r<   r,   rangerO   minr   r^   Zdecryptrj   appendZupdr   )r/   fhr)   sizepartsr_   Zchunk_norH   r,   r   idsrK   r   rL   r   r   r   readk  s>    




zFuseOperations.readc             c   sh   d|fd| j | fg}|j| j| j  x8t||d  |D ]"\}\}}|| j||d fV  q>W d S )Nr  s   ..r   )rq   r   rs   rm   r   r   )r/   r  ZoffZentriesir   rG   r   r   r   readdir  s     zFuseOperations.readdirc             C   s   | j |}tj|jS )N)r   rt   r   r   )r/   rG   r   r_   r   r   r   readlink  s    
zFuseOperations.readlink)F)N)N)N)N)N)N)N)N)N) rb   rc   rd   re   r   r   r   r   r   r0   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r
  r  r  r  r  r  __classcell__r   r   )r   r   rh      s8   
M
,G







+rh   ).r  rE   rt   r   rf   r   r*   r   collectionsr   r   r   r   r~   r   Zcrypto.low_levelr   Zarchiverr   r   r   Z	hashindexr	   Zhelpersr
   r   r   r   r   r   r_   r   Zlrucacher   Zremoter   r   r   r   r   r   r   rn   r   Z
Operationsrh   r   r   r   r   <module>   s:    +