U
    \b 5                     @   s  d dl mZmZmZmZ d dlmZ d dlmZ	 d dl
mZmZmZmZ d dlZddlmZ ddlmZmZ d	ZeeZejjd
kZzd dlmZ eZW n ek
r   dd ZY nX esd dlm Z m!Z! e Z e!Z!nd dl"m#Z#m$Z$ e#j%j&Z'e$j(e'_)e$j*e$j*e$j+ge'_,z&e#j%j-Z.e$j(e._)e$j*e$j*e$j/ge._,W n e0k
rF   dZ.Y nX dd Z1dd Z2e1Z e2Z!erlesd dlm3Z3 eZeZe3Z3n:d dl"m4Z4m5Z5m6Z6m7Z7m8Z8m#Z#m$Z$ d dl9Z9d dlm:Z: d dl
m;Z; d dlZd dl<Z<dd Zdd ZdZ=dZ>dZ?dZ@d ZAd ZBG d!d" d"e5ZCe4eCZDe#j%jEZFe$jGeDfeF_,e$jHeF_)e#j%jIZJe$jHeDfeJ_,e$jKeJ_)e$Hd#jLZMe#j%jNZOe$j/eO_)e$jGfeO_,d$d% ZPd&d' ZQG d(d) d)e<jRZRd*d+ ZSd,d- ZTd.d/ ZUd0d1 ZVd2d3 ZWd4d5 ZXdZYd6ZZd7Z[d8Z\e4e$j/Z]e$j+Z^G d9d: d:e5Z_e4e_Z`e#j%jaZbe$jGe$j/e$j/e`e$j/e$j/e$jHfeb_,e$jHeb_)e#j%jcZce$jHfec_,e$jKec_)d d;l"mdZdmeZemfZfmgZgmhZhmiZi G d<d= d=e5Zjd>d? Z3e#j%jkZke$jHe$j/e$j+e$j/e$j+e$j/e]e^gek_,e$j(ek_)dBd@dAZldS )C    )absolute_importdivisionprint_functionunicode_literals)	getLogger)chmod)abspathisdirislinklexistsN   )on_win)CondaOSError
ParseError)r
   lchmodr   linkreadlinksymlinkZpypy)r   c                 C   s   t | st| | d S N)r
   os_chmod)pathmode r   7lib/python3.8/site-packages/conda/gateways/disk/link.pyr      s    r   )r   r   )windllwintypesc                 C   s    t || dstd| |f dS )z;Equivalent to os.link, using the win32 CreateHardLink call.Nz*win32 hard link failed
  src: %s
  dst: %s)CreateHardLinkr   srcZdstr   r   r   win_hard_link5   s    r   c                 C   s4   t dkrtdt || t| s0td| |f dS )zBEquivalent to os.symlink, using the win32 CreateSymbolicLink call.Nzwin32 soft link not supportedz*win32 soft link failed
  src: %s
  dst: %s)CreateSymbolicLinkr   r	   r   r   r   r   win_soft_link:   s    r!   )r   )POINTER	Structurebyrefc_uint64castr   r   )getcwd)isfilec                 C   s   t | ot| S )z(Determine if the given path is a symlink)is_reparse_point
is_symlinkr   r   r   r   r
   T   s    r
   c                 C   s(   t | rdS t| rdS t| r$dS dS )NTF)r
   r	   r(   r+   r   r   r   r   X   s    r   i  l     @ l    i      c                
   @   sl   e Zd Zdejfdejfdejfdejfdejd fdejd fdeje fd	ejd
 fgZe	dd Z
dS )WIN32_FIND_DATAZfile_attributesZcreation_timeZlast_access_timeZlast_write_timefile_size_words   reservedfilenameZalternate_filename   c                 C   s   t | jttjS r   )r&   r.   r"   r%   contentsselfr   r   r   	file_sizet   s    zWIN32_FIND_DATA.file_sizeN)__name__
__module____qualname__r   DWORDZFILETIMEWCHARMAX_PATH_fields_propertyr6   r   r   r   r   r-   h   s   r-   c                 C   s   | dkrt  d S Nr   )WindowsError)resultr   r   r   handle_nonzero_success   s    rC   c              	   C   sf   d}d}||B }d}| }d}t  }d}d}	tj||||t|||	}
t|
 |j}tj| |S )zr
        Call FormatMessage with a system error number to retrieve
        the descriptive error message.
           i   Nr   )	r   LPWSTRr   kernel32ZFormatMessageWr$   rC   valueZ	LocalFree)errnoZALLOCATE_BUFFERZFROM_SYSTEMflagssourceZ
message_idZlanguage_idZresult_bufferZbuffer_sizeZ	argumentsbytesmessager   r   r   format_system_message   s,    rM   c                       sF   e Zd Zd fdd	Zedd Zedd Zdd	 Zd
d Z  Z	S )rA   Nc                    s:   |d krt j }t|}d|d |f}tt| j|  d S r@   )r   rF   ZGetLastErrorrM   superrA   __init__)r5   rG   strerrorargs	__class__r   r   rO      s
    
zWindowsError.__init__c                 C   s   | j S r   )rP   r4   r   r   r   rL      s    zWindowsError.messagec                 C   s   | j S r   )Zwinerrorr4   r   r   r   code   s    zWindowsError.codec                 C   s   | j S r   )rL   r4   r   r   r   __str__   s    zWindowsError.__str__c                 C   s   dj f t S )Nz*{self.__class__.__name__}({self.winerror}))formatvarsr4   r   r   r   __repr__   s    zWindowsError.__repr__)N)
r7   r8   r9   rO   r>   rL   rT   rU   rX   __classcell__r   r   rR   r   rA      s   

rA   c                 C   s   | j d tkS r@   )r0   IO_REPARSE_TAG_SYMLINK)Z	find_datar   r   r   _is_symlink   s    r[   c                 C   s<   |  dr| S t| } | d dks4t dd |  } d|  S )a;  
        Paths have a max length of api.MAX_PATH characters (260). If a target path
        is longer than that, it needs to be made absolute and prepended with
        \\?\ in order to work with API calls.
        See http://msdn.microsoft.com/en-us/library/aa365247%28v=vs.85%29.aspx for
        details.
        z\\?\   :Nr/   )
startswithr   r'   r+   r   r   r   _patch_path   s    
r_   c                 C   s   t  jj}| |S )z
        format the string using variables in the caller's local namespace.
        >>> a = 3
        >>> local_format("{a:5}")
        '    3'
        )inspectZcurrentframef_backf_locals
format_map)stringcontextr   r   r   local_format   s    rf   c              
   C   sT   t | } zttt| W S  tk
rN } zd}tt|W 5 d}~X Y nX dS )zP
        Assuming path is a reparse point, determine if it's a symlink.
        z,Error accessing {path}: {orig_error.message}N)r_   r[   next
find_filesrA   builtinsrf   )r   Z
orig_errorZtmplr   r   r   r*      s    r*   c                 c   sn   t  }t| t|}|tkr"t |V  t  }t|t|}|dkrt }|jtkrXq^q|qtj	
| dS )a  
        A pythonic wrapper around the FindFirstFile/FindNextFile win32 api.
        >>> root_files = tuple(find_files(r'c:\*'))
        >>> len(root_files) > 1
        True
        >>> root_files[0].filename == root_files[1].filename
        False
        >>> # This test might fail on a non-standard installation
        >>> 'Windows' in (fd.filename for fd in root_files)
        True
        r   N)r-   FindFirstFiler$   INVALID_HANDLE_VALUErA   FindNextFilerT   ERROR_NO_MORE_FILESr   rF   Z	FindClose)specfdhandlereserrorr   r   r   rh      s    
rh   c                 C   s   t | }|tkot|t@ S )z
        Determine if the given path is a reparse point.
        Return False if the file does not exist or the file attributes cannot
        be determined.
        )GetFileAttributesINVALID_FILE_ATTRIBUTESboolFILE_ATTRIBUTE_REPARSE_POINT)r   rq   r   r   r   r)   	  s    
r)   i    i   i 	 c                   @   s(   e Zd ZdejfdejfdejffZdS )SECURITY_ATTRIBUTESZlengthZp_security_descriptorZinherit_handleN)r7   r8   r9   r   r:   LPVOIDBOOLEANr=   r   r   r   r   rw     s   rw   )Arraycreate_string_bufferc_bytec_ulongc_ushortsizeofc                   @   sZ   e Zd Zdefdefdefdefdefdefdefdefd	ed
 fg	Zdd Zdd ZdS )REPARSE_DATA_BUFFERtagZdata_lengthr0   substitute_name_offsetsubstitute_name_lengthprint_name_offsetprint_name_lengthrI   path_bufferr\   c                 C   s:   t tj}tj| j|  }t| j| j}t|t|j	j
S r   )r   r   r;   r   r$   r   r   r&   r"   r3   rG   r5   Z
wchar_sizeZarr_typdatar   r   r   get_print_nameD  s    
z"REPARSE_DATA_BUFFER.get_print_namec                 C   s:   t tj}tj| j|  }t| j| j}t|t|j	j
S r   )r   r   r;   r   r$   r   r   r&   r"   r3   rG   r   r   r   r   get_substitute_nameJ  s    
z'REPARSE_DATA_BUFFER.get_substitute_nameN)	r7   r8   r9   r}   r~   r|   r=   r   r   r   r   r   r   r   7  s   
r   c                 C   s|   t | dddtttB d}|tkr&t t|tdd}t|}t	|t
t}|j}|jtkshtd|j tt| | S )z{
        readlink(link) -> target
        Return a string representing the path to which the symbolic link points.
        r   Ni (  z+Expected IO_REPARSE_TAG_SYMLINK, but got %d)
CreateFileOPEN_EXISTINGFILE_FLAG_OPEN_REPARSE_POINTFILE_FLAG_BACKUP_SEMANTICSrk   rA   reparse_DeviceIoControlFSCTL_GET_REPARSE_POINTr{   r&   r"   r   r3   r   rZ   r   rC   CloseHandler   )r   rp   rq   rK   Zp_rdbZrdbr   r   r   r   P  s    
r   c           	   	   C   s   |d k	rt dt|tr"t|}|d k	r2t|nd}t|}t|tsLtt }t	| |||||||}t
| t
| |d |j S )Nz$overlapped handles not yet supportedr   )NotImplementedError
isinstanceintr{   lenrz   AssertionErrorr   r:   DeviceIoControlrC   rG   )	ZdeviceZio_control_codeZ	in_bufferZ
out_bufferZ
overlappedZin_buffer_sizeZout_buffer_sizeZreturned_bytesrq   r   r   r   r   t  s*    
  	r   )N)mZ
__future__r   r   r   r   Zloggingr   osr   r   os.pathr   r	   r
   Z	os_islinkr   Z
os_lexistssysZcommon.compatr   
exceptionsr   r   __all__r7   logimplementationnameZPYPYr   Z	os_lchmodImportErrorr   r   Zctypesr   r   rF   ZCreateHardLinkWr   ZBOOLZrestypeZLPCWSTRrx   ZargtypesZCreateSymbolicLinkWr    r:   AttributeErrorr   r!   r   r"   r#   r$   r%   r&   r`   r'   r(   ri   r<   rZ   rt   rv   ZNULLrm   r-   ZLPWIN32_FIND_DATAZFindFirstFileWrj   rE   ZHANDLEZFindNextFileWrl   ry   rG   rk   ZGetFileAttributesWrs   rC   rM   rA   r[   r_   rf   r*   rh   r)   r   r   r   r   ZLPDWORDZLPOVERLAPPEDrw   ZLPSECURITY_ATTRIBUTESZCreateFileWr   r   rz   r{   r|   r}   r~   r   r   r   r   r   r   r   r   <module>   s   

$	
#

	
 
