
­­­­­­­­­­­­­­­­­­
<!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               @   sF   e Zd ZdZdZejdZejdks(t	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=cII	   c             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   r   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)r0   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_bytesr3   )r4   partr   r5      r6   r   r2   )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*   )r0   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   sizeAssertionErrorr1   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    )!superr1   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)r0   r^   Z
repositoryrn   rm   r&   Zdata_cache_capacity)	__class__r   r   r1      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   )rs   z_for versions view, do not specify a single archive, but always give the repository as location.g    eA)rs   mtime)_create_dirrm   locationarchiveversionsr   process_archiver	   versions_indexrn   ZarchivesZlist_consideringnamerB   ZtsZ	timestampru   rv   fsencoder|   )r0   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   rr   rO   rs   r   sys	getsizeofr|   r}   r/   r.   r(   rv   statr,   filenost_sizer   ro   Z	_capacitysumr&   Zlog_instrumentation)r0   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  t | tst xt| D ]\}}||kr8| j| |S |j|d r| j| |jddd }|tkr|j }	|	dkr|dS |	dkrd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   )
isinstancelistri   	enumeratepop
startswithsplitboollowerr7   rB   )
optionsr^   ZpresentZnot_presentZwanted_typeint_baseidxZoptionvaluevr   r   r   
pop_option&  s2    

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   rx   rz   r   timer{   r   r   Zinitr
   r   rl   r   Zmigrate_lockr   r   r   r   close)r0   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   r{   Zas_dictro   r   rs   )r0   rs   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   rl   r^   rn   rm   r]   strip_componentsr   Zbuild_matcherZpatternspathsemptyZbuild_filterr}   ra   Zmetadataro   rv   sepjoinr   r   r   r   S_ISDIRr   _find_inodeKeyErrorprocess_innerprocess_leafr   r   r   )r0   archive_namer    Zt0r   r   Zmatcherr   r\   
item_inoder_   r   is_dirrG   segmentsrs   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)r0   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   )rsplitrv   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   rv   r   r   r   r   r<   r   r   r   r   r   r   warningget_itemr   ro   r-   r   rs   ru   )r0   r   r_   rs   r    r   r   r   Zstripped_componentsr   r   r   r   r-   Zlink_targetr   rG   Zenc_pathr   )r0   r   r     sL    












zFuseOperations.process_leafc             C   s6   | j | }||kr|| }n| j|}|r2|||< |S )N)ru   r   )r0   r   parent_inodedirrG   r   r   r   r     s    


zFuseOperations.process_innerc             C   s   |  j d7  _ | j S )Nr   )rr   )r0   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   )r0   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)rq   r<   ro   r   r}   )r0   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   ru   )r0   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   rx   st_uidr   r   rz   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   )r0   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)r0   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)r0   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)r|   r   r   rv   r   )r0   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	  rs   ru   r<   r   r  errnoENOENTr  )r0   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)r0   rG   flagsr   r_   r   r   r   open[  s    

zFuseOperations.openc             C   s   | j | |S )N)r	  )r0   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decryptrl   appendZupdr   )r0   fhr*   rh   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   )rs   r   ru   ro   r   r  )r0   r  ZoffZentriesir   rG   r   r   r   readdir  s     zFuseOperations.readdirc             C   s   | j |}tj|jS )N)r   rv   r   r   )r0   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   r1   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   rj      s8   
M
,G







+rj   ).r  rE   rv   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   rp   r   Z
Operationsrj   r   r   r   r   <module>   s:    +