B
    '\F                 @   s  d dl mZmZmZmZ d dlmZ d dlmZ	m
Z
 d dlmZmZmZmZ ddlmZmZ ddlmZmZ dZeeZerd	d
 Zn2y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%_*y&e!j#j+Z,e"j&e,_'e"j(e"j(e"j-ge,_*W n e.k
rH   dZ,Y nX dd Z/dd Z0e/Ze0Zernesd dlm1Z1 eZeZe1Z1nFd dl m2Z2m3Z3m4Z4m5Z5m6Z6m!Z!m"Z" d dl7Z7d dlm8Z8 d dlm9Z9 d dl:Z:ddl;m<Z< e<j=j>Z>dd Zdd ZdZ?dZ@dZAd ZBd ZCd!ZDG d"d# d#e3ZEe2eEZFe!j#jGZHe"jIeFfeH_*e"jJeH_'e!j#jKZLe"jJeFfeL_*e"jMeL_'e"Jd$jNZOe!j#jPZQe"j-eQ_'e"jIfeQ_*d%d& ZRd'd( ZSG d)d* d*e>jTZTd+d, ZUd-d. ZVd/d0 ZWd1d2 ZXd3d4 ZYd5d6 ZZdZ[d7Z\d8Z]d9Z^e2e"j-Z_e"j)Z`G d:d; d;e3Zae2eaZbe!j#jcZde"jIe"j-e"j-ebe"j-e"j-e"jJfed_*e"jJed_'e!j#jeZee"jJfee_*e"jMee_'d d<l mfZfmgZgmhZhmiZimjZjmkZk G d=d> d>e3Zld?d@ Z1e!j#jmZme"jJe"j-e"j)e"j-e"j)e"j-e_e`gem_*e"j&em_'dEdAdBZnG dCdD dDeoZpep ZqdS )F    )absolute_importdivisionprint_functionunicode_literals)	getLogger)chmodlstat)abspathisdirislinklexists   )PY2on_win)CondaOSError
ParseError)r   lchmodr   linkreadlink
stat_nlinksymlinkc          
   C   sD   yt | |dd W n, tttfk
r>   t| s:t | | Y nX d S )NF)follow_symlinks)os_chmod	TypeErrorNotImplementedErrorSystemErrorr   )pathmode r   7lib/python3.7/site-packages/conda/gateways/disk/link.pyr      s
    r   )r   c             C   s   t | st| | d S )N)r   r   )r   r   r   r   r   r   #   s    )r   r   )windllwintypesNc             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   )srcdstr   r   r   win_hard_link=   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   r   win_soft_linkB   s    r'   )r   )POINTER	Structurebyrefc_uint64castr    r!   )getcwd)isfile)sixc             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   ]   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   a   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 )N)r,   r4   r(   r+   contents)selfr   r   r   	file_size}   s    zWIN32_FIND_DATA.file_sizeN)__name__
__module____qualname__r!   DWORDFILETIMEWCHARMAX_PATH_fields_propertyr;   r   r   r   r   r3   q   s   r3   c             C   s   | dkrt  d S )Nr   )WindowsError)resultr   r   r   handle_nonzero_success   s    rH   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*   rH   valueZ	LocalFree)errnoZALLOCATE_BUFFERZFROM_SYSTEMflagssourceZ
message_idZlanguage_idZresult_bufferbuffer_sizeZ	argumentsbytesmessager   r   r   format_system_message   s*    rS   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 )rF   Nc                sN   |d krt j }t|}tjdkr2d|d |f}n||f}tt| j|  d S )N)r   r   r   )	r    rK   ZGetLastErrorrS   sysversion_infosuperrF   __init__)r:   rL   strerrorargs)	__class__r   r   rW      s    

zWindowsError.__init__c             C   s   | j S )N)rX   )r:   r   r   r   rR      s    zWindowsError.messagec             C   s   | j S )N)Zwinerror)r:   r   r   r   code   s    zWindowsError.codec             C   s   | j S )N)rR   )r:   r   r   r   __str__   s    zWindowsError.__str__c             C   s   dj f t S )Nz*{self.__class__.__name__}({self.winerror}))formatvars)r:   r   r   r   __repr__   s    zWindowsError.__repr__)N)
r<   r=   r>   rW   rD   rR   r[   r\   r_   __classcell__r   r   )rZ   r   rF      s
   
rF   c             C   s   | j d tkS )Nr   )r6   IO_REPARSE_TAG_SYMLINK)Z	find_datar   r   r   _is_symlink   s    rb   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\\?\   :Nr5   )
startswithr	   r-   )r   r   r   r   _patch_path   s    
rf   c             C   s,   t  jj}tjdk r"| jf |S | |S )z
        format the string using variables in the caller's local namespace.
        >>> a = 3
        >>> local_format("{a:5}")
        '    3'
        )r   r5   )inspectZcurrentframef_backf_localsrT   rU   r]   
format_map)stringcontextr   r   r   local_format   s    
rm   c          
   C   sR   t | } yttt| S  tk
rL } zd}tt|W d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)rf   rb   next
find_filesrF   builtinsrm   )r   Z
orig_errorZtmplr   r   r   r1      s    r1   c             c   sr   t  }t| t|}xL|tkr$t |V  t  }t|t|}|dkrt }|jtkrZP q|qW 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)r3   FindFirstFiler*   INVALID_HANDLE_VALUErF   FindNextFiler[   ERROR_NO_MORE_FILESr    rK   Z	FindClose)specfdhandlereserrorr   r   r   ro      s    
ro   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   rx   r   r   r   r0     s    r0   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_ATTRIBUTESlengthZp_security_descriptorZinherit_handleN)r<   r=   r>   r!   r?   LPVOIDBOOLEANrC   r   r   r   r   r~   +  s   r~   )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_lengthr6   substitute_name_offsetsubstitute_name_lengthprint_name_offsetprint_name_lengthrN   path_bufferrc   c             C   s:   t tj}tj| j|  }t| j| j}t|t|j	j
S )N)r   r!   rA   r   r*   r   r   r,   r(   r9   rL   )r:   
wchar_sizearr_typdatar   r   r   get_print_nameR  s    
z"REPARSE_DATA_BUFFER.get_print_namec             C   s:   t tj}tj| j|  }t| j| j}t|t|j	j
S )N)r   r!   rA   r   r*   r   r   r,   r(   r9   rL   )r:   r   r   r   r   r   r   get_substitute_nameX  s    
z'REPARSE_DATA_BUFFER.get_substitute_nameN)	r<   r=   r>   r   r   r   rC   r   r   r   r   r   r   r   E  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_SEMANTICSrr   rF   reparse_DeviceIoControlFSCTL_GET_REPARSE_POINTr   r,   r(   r   r9   r   ra   r   rH   CloseHandler   )r   rw   rx   rQ   Zp_rdbZrdbr   r   r   r   ^  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   )r   
isinstanceintr   lenr   AssertionErrorr!   r?   DeviceIoControlrH   rL   )	ZdeviceZio_control_codeZ	in_bufferZ
out_bufferZ
overlappedZin_buffer_sizeZout_buffer_sizeZreturned_bytesrx   r   r   r   r     s$    
r   c               @   sH   e Zd ZdZdd Zedd Zedd Zedd	 Zed
d Z	dS )CrossPlatformStLinkNc             C   s
   |  |S )N)st_nlink)r:   r   r   r   r   __call__  s    zCrossPlatformStLink.__call__c             C   s   | j d kr|   |  |S )N)	_st_nlink_initialize)clsr   r   r   r   r     s    
zCrossPlatformStLink.st_nlinkc             C   s
   t |jS )N)r   r   )r   r   r   r   r   _standard_st_nlink  s    z&CrossPlatformStLink._standard_st_nlinkc       
   	   C   s   |  |}|dkr|S d}d}d}| |||d |dd }|d krRddlm} | |  }| ||}	| | |	dkrddlm} | |jS d S )Nr   l        rc   r   )WinError)r   r   ctypesr   BY_HANDLE_FILE_INFORMATIONGetFileInformationByHandler   nNumberOfLinks)
r   r   r   ZGENERIC_READZFILE_SHARE_READr   Zhfiler   inforvr   r   r   _windows_st_nlink  s$    


z%CrossPlatformStLink._windows_st_nlinkc                s   t s| j| _nddlm}m}m}m} ddlm	 m
}m} tjj| _|  |  |g| j_|| j_tjj| _|g| j_|| j_G  fddd|G  fddd|}|| _tjj| _|||g| j_|| j_| j| _d S )Nr   )r(   r)   c_void_p	c_wchar_p)r?   HANDLEBOOLc                   s   e Zd Zd fd fgZdS )z1CrossPlatformStLink._initialize.<locals>.FILETIMEZdwLowDateTimeZdwHighDateTimeN)r<   r=   r>   rC   r   )r?   r   r   r@     s   r@   c                   sL   e Zd Zd fdfdfdfd fd fd fd fd	 fd
 fg
ZdS )zCCrossPlatformStLink._initialize.<locals>.BY_HANDLE_FILE_INFORMATIONZdwFileAttributesZftCreationTimeZftLastAccessTimeZftLastWriteTimeZdwVolumeSerialNumberZnFileSizeHighZnFileSizeLowr   ZnFileIndexHighZnFileIndexLowN)r<   r=   r>   rC   r   )r?   r@   r   r   r     s   r   )r   r   r   r   r(   r)   r   r   Zctypes.wintypesr?   r   r   r    rK   CreateFileWr   argtypesrestyper   r   r   r   )r   r(   r)   r   r   r   r   r   r   )r?   r@   r   r     s$    




zCrossPlatformStLink._initialize)
r<   r=   r>   r   r   classmethodr   r   r   r   r   r   r   r   r     s   r   )N)rZ
__future__r   r   r   r   Zloggingr   osr   r   r   os.pathr	   r
   r   Z	os_islinkr   Z
os_lexistsZcommon.compatr   r   
exceptionsr   r   __all__r<   logr   Z	os_lchmodImportErrorr   r   r   r    r!   rK   ZCreateHardLinkWr"   r   r   ZLPCWSTRr   r   ZCreateSymbolicLinkWr&   r?   AttributeErrorr%   r'   r   r(   r)   r*   r+   r,   rg   r-   r.   rT   Z_vendor.auxlib._vendorr/   Zmovesrp   rB   ra   r{   r}   ZNULLrt   r3   ZLPWIN32_FIND_DATAZFindFirstFileWrq   rJ   r   ZFindNextFileWrs   r   rL   rr   ZGetFileAttributesWrz   rH   rS   rF   rb   rf   rm   r1   ro   r0   r   r   r   r   ZLPDWORDZLPOVERLAPPEDr~   ZLPSECURITY_ATTRIBUTESr   r   r   r   r   r   r   r   r   r   r   r   objectr   r   r   r   r   r   <module>   s   
	

$	
#


 
U