
    yf?                     X   S SK r S SKrS SKrS SKrS SKrS SKrS SKrS SKrSSKJ	r	  SSK
Jr  SSKJr  SSK7  SSKJr  \" 5       r\R"                  \R$                  -  \R&                  -  S	4S
 jrS rS rS-S jrS rS rS rS r\R8                  " S5      rS rS rS r S r!SS.S jr"S r#S r$S r%S r&\&" SSS5      r'\'\&" S 5      -  r(\'r)\'\&" S!S 5      -  r*\*\&" S"5      -  r+\&" S#SS 5      r,SSSS$S%.S& jr-SSSS$S'.S( jr.S) r/S SKr0S SKr1S SK r2S S*K3J4r4J5r5J6r6J7r7J8r8  S.S+ jr9S/S, jr:g)0    N   )Error)prepare_subprocess_env   )is_win32)*)create_loggerTc                      [         R                  " XSS9  g! [         a!  nU(       a  [        [	        U5      5      ee SnAff = f)a  
Ensures that the dir exists with the right permissions.
1) Make sure the directory exists in a race-free operation
2) If mode is not None and the directory has been created, give the right
permissions to the leaf directory. The current umask value is masked out first.
3) If pretty_deadly is True, catch exceptions, reraise them with a pretty
message.
Returns if the directory has been created and has the right permissions,
An exception otherwise. If a deadly exception happened it is reraised.
T)modeexist_okN)osmakedirsOSErrorr   str)pathr   pretty_deadlyes       1/usr/lib/python3/dist-packages/borg/helpers/fs.py
ensure_dirr      s9    
Dd3 A-	s    
A>Ac                     [         R                  R                  S5      =(       d    [         R                  R                  S5      n U (       d@  [         R                  R	                  S[         R                  R                  SS5      -  5      n U $ )zsGet home directory / base directory for borg:

- BORG_BASE_DIR, if set
- HOME, if set
- ~$USER, if USER is set
- ~
BORG_BASE_DIRHOMEz~%sUSER )r   environgetr   
expanduser)base_dirs    r   get_base_dirr   )   sZ     zz~~o.H"**..2HH
 77%%ebjjnnVR.H&HIO    c                      [         R                  R                  S5      n U c(  [         R                  R	                  [        5       S5      n [        U 5        U $ ),Determine where to repository keys and cacheBORG_KEYS_DIRkeysr   r   r   r   joinget_config_dirr   )keys_dirs    r   get_keys_dirr)   ;   s>    zz~~o.H77<< 0&9xOr    c                     [         R                  R                  S5      nUc(  [         R                  R	                  [        5       S5      nU (       a  [         R                  R	                  X5      n[        U5        U$ )z4Determine where to store local security information.BORG_SECURITY_DIRsecurityr%   )repository_idsecurity_dirs     r   get_security_dirr/   E   sU    ::>>"56Lww||N$4jAww||L@|r    c                     [         R                  R                  [        5       S5      n [         R                  R                  S5      (       d   [         R                  R                  SU 5      n [         R                  R                  S[         R                  R                  U S5      5      n[        U5        [         R                  R                  U[        5      n[         R                  R                  U5      (       dU  [        [        R                  " S5      R                  S5      -   nSS	KJn  U" US
S9 nUR                  U5        SSS5        U$ U$ ! , (       d  f       U$ = f)r"   z.cacher   XDG_CACHE_HOMEBORG_CACHE_DIRborgz
        # This file is a cache directory tag created by Borg.
        # For information about cache directory tags, see:
        #       http://www.bford.info/cachedir/spec.html
        asciir   )SaveFileT)binaryN)r   r   r&   r   r   r   r   CACHE_TAG_NAMEexistsCACHE_TAG_CONTENTStextwrapdedentencodeplatformr5   write)
cache_home	cache_dircache_tag_fncache_tag_contentsr5   fds         r   get_cache_dirrD   Q   s     lnh7J::>>/**ZZ^^$4jA


/j&1QRIy77<<	>:L77>>,''/(// C 3 VG_	
 	(l40BHH'( 19 10s   7E
E$c                  p   [         R                  R                  [        5       S5      n [         R                  R                  S5      (       d   [         R                  R                  SU 5      n [         R                  R                  S[         R                  R                  U S5      5      n[        U5        U$ )z%Determine where to store whole configz.configr   XDG_CONFIG_HOMEBORG_CONFIG_DIRr3   )r   r   r&   r   r   r   r   )config_home
config_dirs     r   r'   r'   i   st     '',,|~y9K::>>/**jjnn%6D 1277<<V3TUJzr    c                 l   [         R                  R                  U [        5      n [         R                  R	                  U5      (       aI  [        US5       nUR                  [        [        5      5      nU[        :X  a
   SSS5        g SSS5        g g! , (       d  f       g= f! [         a     gf = f)zDetermines whether the specified path is a cache directory (and
therefore should potentially be excluded from the backup) according to
the CACHEDIR.TAG protocol
(http://www.bford.info/cachedir/spec.html).
rbNTF)
r   r   r&   r7   r8   openreadlenr9   r   )r   tag_pathtag_filetag_datas       r   dir_is_cachedirrR   w   s     ww||D.1H77>>(##h%#==-?)@A11 &%1 &  $  &%   s5   0B& *B B& 
B& 
B#B& #B& &
B32B3c                 &   / nU(       a%  [        U 5      (       a  UR                  [        5        Ub_  U HY  n[        R                  R                  X5      n[        R                  R                  U5      (       d  MH  UR                  U5        M[     U$ )a  Determines whether the specified path is excluded by being a cache
directory or containing user-specified tag files/directories. Returns a
list of the names of the tag files/directories (either CACHEDIR.TAG or the
matching user-specified files/directories).
)rR   appendr7   r   r   r&   r8   )r   exclude_cachesexclude_if_present	tag_namestagrO   s         r   dir_is_taggedrY      so     I/$//(%%Cww||D.Hww~~h''  % & r    z^((\.\.)?/+)+c                 @    [         R                  SU 5      =(       d    S$ )z3Make path safe by making it relative and local
    r   .)_safe_resub)r   s    r   make_path_safer^      s     <<D!(S(r    c                     U R                  S5      nUS:  a3  [        R                  R                  U S U 5      [        R                  -   $ g )Nz/./r   )findr   r   normpathsep)r   poss     r   get_strip_prefixrd      sB     ))E
C
QwwwTc
+bff44 r    c                     [         R                  " U 5      =(       dP    [         R                  " U 5      =(       d3    [         R                  " U 5      =(       d    [         R                  " U 5      $ )z7return True if we support hardlinked items of this type)statS_ISREGS_ISBLKS_ISCHRS_ISFIFO)r   s    r   hardlinkablerk      s<    <<`d!3`t||D7I`T]][_M``r    c                      SU R                  5       4$ ! [         a9  n[        R                  SU R                  U5        SU R
                  4s S nA$ S nAff = f)Nr   z&scandir_inorder: Unable to stat %s: %sr   )inoder   loggerdebugr   name)direntr   s     r   scandir_keyfuncrr      sN    	 6<<>""  =v{{AN
 6;; s    
A.AAA)rC   c                 T    Ub  UOU n[        [        R                  " U5      [        S9$ )N)key)sortedr   scandirrr   )r   rC   args      r   scandir_inorderrx      s"    "DC"**S/77r    c                   [        U S5       n[        R                  " UR                  5       5      nUR                  S:  a  U(       dc  UR                  [        R                  " UR                  5      5        UR                  5         [        R                  " UR                  5       5        SSS5        [        R                  " U 5        g! , (       d  f       N%= f)aq  Attempt to securely erase a file by writing random data over it before deleting it.

If avoid_collateral_damage is True, we only secure erase if the total link count is 1,
otherwise we just do a normal "delete" (unlink) without first overwriting it with random.
This avoids other hardlinks pointing to same inode as <path> getting damaged, but might be less secure.
A typical scenario where this is useful are quick "hardlink copies" of bigger directories.

If avoid_collateral_damage is False, we always secure erase.
If there are hardlinks pointing to the same inode as <path>, they will contain random garbage afterwards.
r+br   N)rL   r   rf   filenost_nlinkr>   urandomst_sizeflushfsyncunlink)r   avoid_collateral_damagerC   sts       r   secure_eraser      s     
dE	bWWRYY[!a$;HHRZZ

+,HHJHHRYY[! 
 IIdO 
	s   BC
Cc                     [         R                  " U 5        g! [         a  nUR                  [        R                  :w  a  e [         R
                  " U 5      nUR                  S:  a  e  [        U S5       nUR                  5         SSS5        O! , (       d  f       O= f[         R                  " U 5         SnAg! [         a    Uef = fSnAff = f)a  
Safely unlink (delete) *path*.

If we run out of space while deleting the file, we try truncating it first.
BUT we truncate only if path is the only hardlink referring to this content.

Use this when deleting potentially large files when recovering
from a VFS error such as ENOSPC. It can help a full file system
recover. Refer to the "File system interaction" section
in repository.py for further explanations.
r   rz   N)	r   r   r   errnoENOSPCrf   r|   rL   truncate)r   
unlink_errr   rC   s       r   safe_unlinkr      s    
		$ u||+WWT];;?		dE"b #"" IIdOO  		sE    
CAC*B<6B	B<
B	B<!C<C		CCc                     SU;  d   eU S:X  a:  SU;   a  [         R                  O[         R                  nSU;   a  UR                  $ U$ [	        X5      $ )N+-rb)sysstdinstdoutbufferrL   )r   r   streams      r   	dash_openr     sJ    d??s{!Tkszz #tv}}77Dr    c                  J    SnU  H  nU[        [        SU-   S5      -  nM     U$ )Nr   O_)getattrr   )flagsresultflags      r   r   r     s-    F'"dTk1-- Mr    BINARYNOCTTYRDONLYNOFOLLOWNONBLOCKNOATIME	DIRECTORYF)r   	parent_fdrp   noatimec                    U(       a  Ub  UnOUSp%[         (       a%  [        R                  R                  U5      (       a  gU nU(       a&  U[	        S5      -  n [        R
                  " XWUS9nU$ [        R
                  " XVUS9nU$ ! [         a    Xv:X  a  e [        R
                  " XVUS9n U$ [         aP  n	SSKJ	n
  SU
;   a>  U	R                  [        R                  :X  a   Xv:w  a  [        R
                  " XVUS9n Sn	A	U$ e Sn	A	ff = f)a  
Use os.open to open a fs item.

If parent_fd and name are given, they are preferred and openat will be used,
path is not used in this case.

:param path: full (but not necessarily absolute) path
:param parent_fd: open directory file descriptor
:param name: name relative to parent_fd
:param flags: open flags for os.open() (int)
:param noatime: True if access time shall be preserved
:return: file descriptor
Nr   )dir_fdr   )workaroundsretry_erofs)r   r   r   isdirr   rL   PermissionErrorr   r   r   r   EROFS)r   r   r   rp   r   fname_flags_normal_flags_noatimerC   excr   s              r   os_openr     s     	%yxBGGMM%((M&I6	yAB  I WWU)<I  	A.i@B I  	%+		U[[0H^MlWWU)D
 I 	s%   B %D/	D8ADDD)r   r   rp   follow_symlinksc                 L    U(       a  Ub  UnOU Sp[         R                  " XAUS9$ )a0  
Use os.stat to open a fs item.

If parent_fd and name are given, they are preferred and statat will be used,
path is not used in this case.

:param path: full (but not necessarily absolute) path
:param parent_fd: open directory file descriptor
:param name: name relative to parent_fd
:return: stat info
N)r   r   )r   rf   )r   r   rp   r   r   s        r   os_statr   I  s)     	%y775OLLr    c                     SSK Jn  [        SS9n [        R                  " SSU /US9nU" U5        g ! [
         a    [        R                  " SU /US9n N,f = f)	Nr   )set_ecT)system
fusermountz-u)envumount)r   r   r   
subprocesscallFileNotFoundError)
mountpointr   r   rcs       r   r   r   ]  sZ    
 
-C>__lD*=3G 2J  >__h
3=>s   2 !AA)_sanitize_params_get_candidate_namesTMP_MAX_text_openflags_bin_openflagsc                    [         R                  R                  U 5      n [        5       nU[        L a  [        [         R                  U5      n[        [        5       He  n[        U5      n[         R                  R                  XU-   U-   5      n	[        R                  " SU	5         [         R                  " XU5      n
X4s  $    [        [(        R*                  S5      e! [         a     M  [         ag    [         R                   S:X  aQ  [         R                  R#                  U 5      (       a-  [         R$                  " U [         R&                  5      (       a   M  e f = f)z>Code common to mkstemp, TemporaryFile, and NamedTemporaryFile.ztempfile.mkstempntz#No usable temporary file name found)_osr   abspathr   bytesmapfsencoderanger   nextr&   _sysauditrL   FileExistsErrorr   rp   r   accessW_OK_errnoEEXIST)dirpresufr   output_typer   namesseqrp   filerC   s              r   _mkstemp_innerr   q  s    ((

3
C "EeCLL%(W~E{xx}}S*s"23

%t,
	$t,B x " &--)N
OO  	 	 xx4CHHNN3$7$7CJJsCHH<U<U	s   'C
E,A+EEc                 b    [        XU5      u  pp%U(       a  [        nO[        n[        X!XXT5      $ )a9  User-callable function to create and return a unique temporary
file.  The return value is a pair (fd, name) where fd is the
file descriptor returned by os.open, and name is the filename.
If 'suffix' is not None, the file name will end with that suffix,
otherwise there will be no suffix.
If 'prefix' is not None, the file name will begin with that prefix,
otherwise a default prefix is used.
If 'dir' is not None, the file will be created in that directory,
otherwise a default directory is used.
If 'text' is specified and true, the file is opened in text
mode.  Else (the default) the file is opened in binary mode.
If any of 'suffix', 'prefix' and 'dir' are not None, they must be the
same type.  If they are bytes, the returned name will be bytes; str
otherwise.
The file is readable and writable only by the creating user ID.
If the operating system uses permission bits to indicate whether a
file is executable, the file is executable by no one. The file
descriptor is not inherited by children of this process.
Caller is responsible for deleting the file when done with it.
)r   r   r   r   )suffixprefixr   textr   r   r   s          r   mkstemp_moder     s1    , (8'L$FC#vkHHr    )N)  )NNNFr   );r   r   os.pathrerf   r   r   r:   errorsr   processr   platformflagsr   	constantsrn   r	   S_IRWXUS_IRWXGS_IRWXOr   r   r)   r/   rD   r'   rR   rY   compiler\   r^   rd   rk   rr   rx   r   r   r   r   
flags_baseflags_specialflags_special_followflags_normalflags_noatime	flags_dirr   r   r   r   r   r   tempfiler   r   r   r   r   r   r    r    r   <module>r      sS    	  	   
   + $  "	 ,,5DTX ($	0&$ ::&')a

  !% 8
(!H  (H-
R
^+! Bz:66r)},{Hj1	  4dE +\ DtU M(    e eP8Ir    