o
    +ke                      @   s   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m	Z	 ddl
mZ e	 ZG dd dZG d	d
 d
eZG dd deZG dd deZejeejeiZG dd deZG dd deZG dd deZdS )    N)compare_digest   )IntegrityError)create_logger)StreamingXXH64c                   @   sT   e Zd Zdd Zdd Zdd ZejfddZd	d
 Z	dddZ
dd Zdd ZdS )FileLikeWrapperc                 C   s   | j   | S N)fd	__enter__self r   >usr/lib/python3.10/site-packages/borg/crypto/file_integrity.pyr
      s   
zFileLikeWrapper.__enter__c                 C   s   | j ||| d S r   )r	   __exit__r   exc_typeexc_valexc_tbr   r   r   r      s   zFileLikeWrapper.__exit__c                 C   
   | j  S r   )r	   tellr   r   r   r   r         
zFileLikeWrapper.tellc                 C   s   | j ||S r   )r	   seek)r   offsetwhencer   r   r   r         zFileLikeWrapper.seekc                 C      | j |S r   )r	   writer   datar   r   r   r         zFileLikeWrapper.writeNc                 C   r   r   )r	   read)r   nr   r   r   r       r   zFileLikeWrapper.readc                 C   s   | j   d S r   )r	   flushr   r   r   r   r"   "   r   zFileLikeWrapper.flushc                 C   r   r   )r	   filenor   r   r   r   r#   %   r   zFileLikeWrapper.filenor   )__name__
__module____qualname__r
   r   r   ioSEEK_SETr   r   r    r"   r#   r   r   r   r   r      s    
r   c                       sj   e Zd ZdZdZdZdd Z fddZ fddZd fd	d
	Z	dd Z
defddZdddZ  ZS )FileHashingWrappera'  
    Wrapper for file-like objects that computes a hash on-the-fly while reading/writing.

    WARNING: Seeks should only be used to query the size of the file, not
    to skip data, because skipped data isn't read and not hashed into the digest.

    Similarly skipping while writing to create sparse files is also not supported.

    Data has to be read/written in a symmetric fashion, otherwise different
    digests will be generated.

    Note: When used as a context manager read/write operations outside the enclosed scope
    are illegal.
    Nc                 C   s   || _ || _|  | _d S r   )r	   writingFACTORYhash)r   
backing_fdr   r   r   r   __init__<   s   zFileHashingWrapper.__init__c                    s$   |d u r|    t ||| d S r   )hash_lengthsuperr   r   	__class__r   r   r   A   s   zFileHashingWrapper.__exit__c                    s   t  |}| j| |S )zI
        Write *data* to backing file and update internal state.
        )r0   r   r,   update)r   r   r!   r1   r   r   r   F      zFileHashingWrapper.writec                    s   t  |}| j| |S )zf
        Read *data* from backing file (*n* has the usual meaning) and update internal state.
        )r0   r    r,   r3   )r   r!   r   r1   r   r   r    N   r4   zFileHashingWrapper.readc                 C   r   )zn
        Return current digest bytes as hex-string.

        Note: this can be called multiple times.
        )r,   	hexdigestr   r   r   r   r5   V   s   
zFileHashingWrapper.hexdigestr   c                 C   s   | j | d S r   )r,   r3   r   r   r   r   r3   ^   s   zFileHashingWrapper.updateFc                 C   s.   |r	|  dtj | jt|    d S )Nr   )r   r'   SEEK_ENDr,   r3   strr   encode)r   seek_to_endr   r   r   r/   a   s   zFileHashingWrapper.hash_lengthr   F)r$   r%   r&   __doc__	ALGORITHMr+   r.   r   r   r    r5   bytesr3   r/   __classcell__r   r   r1   r   r)   )   s    r)   c                   @   s   e Zd ZdZejZdS )SHA512FileHashingWrapperZSHA512N)r$   r%   r&   r<   hashlibsha512r+   r   r   r   r   r?   h   s    
r?   c                   @   s   e Zd ZdZeZdS )XXH64FileHashingWrapperZXXH64N)r$   r%   r&   r<   r   r+   r   r   r   r   rB   m   s    rB   c                   @   s   e Zd ZdZdS )FileIntegrityErrorzFile failed integrity check: {}N)r$   r%   r&   r;   r   r   r   r   rC   x   s    rC   c                   @   s^   e Zd ZdddZdd ZdddZeded	efd
dZdddZ	dd Z
d	efddZdS )IntegrityCheckedFileNc           
      C   s   || _ || _|r
dnd}|pt||| _|d u | _i | _t}|s1| ||}|r1|\}	| _t|	 }|| j|d | _	| _
| | d S )Nwbrb)r-   r   )pathr*   openfile_fdfile_openeddigestsrB   load_integrity_dataSUPPORTED_ALGORITHMSr	   hasherhash_filename)
r   rG   r   filenameoverride_fdintegrity_datamodeZhash_clsZalgorithm_and_digests	algorithmr   r   r   r.   }   s   

zIntegrityCheckedFile.__init__c                 C   s   |d ur
|  ||S d S r   )parse_integrity_datar   rG   rR   r   r   r   rL      s   z(IntegrityCheckedFile.load_integrity_datac                 C   s>   t j|p| j}| jdt|   | j|  d S )N%10d)osrG   basenamerN   r3   lenr8   )r   rP   r   r   r   rO      s   z"IntegrityCheckedFile.hash_filenamerG   r   c              
   C   s~   z$t |}|d }|tvrtd|| W d S |d }|d  ||fW S  tttfy> } ztd|| t|d }~ww )NrT   z3Cannot verify integrity of %s: Unknown algorithm %rrK   finalz)Could not parse integrity data for %s: %s)	jsonloadsrM   loggerwarning
ValueError	TypeErrorKeyErrorrC   )clsrG   r   rR   rT   rK   er   r   r   rU      s   

z)IntegrityCheckedFile.parse_integrity_dataFc                 C   s   | j s| jsd S | jdt|   | j|  | jj|d | j }| j r2|| j|< d S | jrDt| j	|d|sFt
| jd S d S )NrW   )r9    )r*   rK   rN   r3   rZ   r8   r/   r5   r   getrC   rG   )r   Zpartnameis_finaldigestr   r   r   	hash_part   s   

zIntegrityCheckedFile.hash_partc                 C   s   |d u}z|s| j ddd | j||| W | jr| j  n
| jr)| j  w w |r.d S | jrA| t	| jj
| jd d S | jrMtd| j d S d S )Nr[   T)rg   )rT   rK   zVerified integrity of %s)ri   rN   r   rJ   rI   closer*   store_integrity_datar\   dumpsr<   rK   r^   debugrG   )r   r   r   r   	exceptionr   r   r   r      s*   
zIntegrityCheckedFile.__exit__c                 C   s
   || _ d S r   )rR   r   r   r   r   rk      r   z)IntegrityCheckedFile.store_integrity_data)NNNr   r:   )r$   r%   r&   r.   rL   rO   classmethodr7   rU   ri   r   rk   r   r   r   r   rD   |   s    


rD   c                       sL   e Zd Zd fdd	Zdd Zedd Zedd	 Zd
e	fddZ
  ZS )DetachedIntegrityCheckedFileNc                    sH   t  |||| |ptj|}tj|}| tj||| _d S r   )	r0   r.   rX   rG   rY   dirnameintegrity_file_pathjoinoutput_integrity_file)r   rG   r   rP   rQ   
output_dirr1   r   r   r.      s   z%DetachedIntegrityCheckedFile.__init__c                 C   s   |rJ d|  | jS )NzCCannot pass explicit integrity_data to DetachedIntegrityCheckedFile)read_integrity_filerG   rV   r   r   r   rL      s   z0DetachedIntegrityCheckedFile.load_integrity_datac                 C   s   | d S )Nz
.integrityr   )rG   r   r   r   rr      s   z0DetachedIntegrityCheckedFile.integrity_file_pathc              
   C   s   z#t | |}| || W  d    W S 1 sw   Y  W d S  ty3   td| Y d S  tyI } ztd|| t	|d }~ww )NzNo integrity file found for %sz(Could not read integrity file for %s: %s)
rH   rr   rU   r    FileNotFoundErrorr^   infoOSErrorr_   rC   )rc   rG   r	   rd   r   r   r   rv      s   (z0DetachedIntegrityCheckedFile.read_integrity_filer   c                 C   s<   t | jd}|| W d    d S 1 sw   Y  d S )Nw)rH   rt   r   )r   r   r	   r   r   r   rk      s   "z1DetachedIntegrityCheckedFile.store_integrity_data)NN)r$   r%   r&   r.   rL   staticmethodrr   ro   rv   r7   rk   r>   r   r   r1   r   rp      s    


rp   )r@   r'   r\   rX   Zhmacr   helpersr   r^   r   Zalgorithms.checksumsr   r   r)   r?   rB   r<   rM   rC   rD   rp   r   r   r   r   <module>   s&    ?Z