o
    *b:  ã                   @   sV   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„ ZG dd„ dƒZ	dS )é    N)ÚProcessPoolExecutorc                 C   sN   t  | ¡}tj |d¡}| |¡ | ¡  tj ||j d¡d  d¡d ¡S )NZcleanerú/éÿÿÿÿú.tarr   )	ÚtarfileÚopenÚosÚpathÚjoinÚ
extractallÚcloseÚnameÚsplit)Úarchive_pathÚtmpdirÚarchiver	   © r   ú?/usr/lib/python3/dist-packages/sos/cleaner/archives/__init__.pyÚextract_archive   s
   

$r   c                   @   s  e Zd ZdZg ZdZdZdZdZdZ	g Z
i Zdd„ Zedd„ ƒZd	d
„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zedd„ ƒZdd„ Zdd„ Zdd „ Zd>d!d"„Zd#d$„ Zd%d&„ Zd'd(„ Zd)d*„ Z d+d,„ Z!d-d.„ Z"d/d0„ Z#d1d2„ Z$d3d4„ Z%d5d6„ Z&d7d8„ Z'd9d:„ Z(d;d<„ Z)d=S )?ÚSoSObfuscationArchivea  A representation of an extracted archive or an sos archive build
    directory which is used by SoSCleaner.

    Each archive that needs to be obfuscated is loaded into an instance of this
    class. All report-level operations should be contained within this class.
    r   ZundeterminedFc                 C   sˆ   || _ | j | _|| _| j  d¡d  d¡d | _| j| _t d¡| _t d¡| _	|  
¡ | _d| _|  ¡  d| _|  d	| j | jf ¡ d S )
Nr   r   r   r   ZsosZsos_uiFÚ zLoaded %s as type %s)r   Úfinal_archive_pathr   r   Úarchive_nameÚui_nameÚloggingZ	getLoggerÚsoslogÚui_logÚ_load_skip_listÚ	skip_listÚis_extractedÚ
_load_selfÚarchive_rootÚlog_infoÚdescription)Úselfr   r   r   r   r   Ú__init__1   s    

ÿÿzSoSObfuscationArchive.__init__c                 C   s   dS )z=Check if the archive is a well-known type we directly supportFr   )ÚclsZarc_pathr   r   r   Úcheck_is_typeB   s   z#SoSObfuscationArchive.check_is_typec                 C   s   | j rt | j¡| _d S d S ©N)Ú
is_tarfiler   r   r   Útarobj©r$   r   r   r   r    G   s   ÿz SoSObfuscationArchive._load_selfc                 C   s   g S )a/  Return a list of ObfuscationArchives that represent additional
        archives found within the target archive. For example, an archive from
        `sos collect` will return a list of ``SoSReportArchive`` objects.

        This should be overridden by individual types of ObfuscationArchive's
        r   r+   r   r   r   Úget_nested_archivesK   s   z)SoSObfuscationArchive.get_nested_archivesc                 C   s0   | j r| jj}| ¡ r|jS tjS tj | j	¡S )z|Set the root path for the archive that should be prepended to any
        filenames given to methods in this class.
        )
r)   r*   ZfirstmemberÚisdirr   r   Úsepr	   Úabspathr   )r$   Ztoplevelr   r   r   Úget_archive_rootT   s   z&SoSObfuscationArchive.get_archive_rootc                 C   s   | j  d | jd |¡¡ dS )z9Helper to easily format ui messages on a per-report basisz	{:<50} {}z :N)r   ÚinfoÚformatr   ©r$   Úmsgr   r   r   Ú
report_msg`   s   z SoSObfuscationArchive.report_msgc                 C   s   d| j |f S )Nz[cleaner:%s] %s)r   r3   r   r   r   Ú_fmt_log_msgd   s   z"SoSObfuscationArchive._fmt_log_msgc                 C   ó   | j  |  |¡¡ d S r(   )r   Údebugr6   r3   r   r   r   Ú	log_debugg   ó   zSoSObfuscationArchive.log_debugc                 C   r7   r(   )r   r1   r6   r3   r   r   r   r"   j   r:   zSoSObfuscationArchive.log_infoc                 C   s   g d¢S )zyProvide a list of files and file regexes to skip obfuscation on

        Returns: list of files and file regexes
        )zproc/kallsymsz
sosreport-zsys/firmwarezsys/fszsys/kernel/debugz
sys/moduler   r+   r   r   r   r   m   s   z%SoSObfuscationArchive._load_skip_listc                 C   s$   zt  | j¡W S  ty   Y dS w )NF)r   r)   r   Ú	Exceptionr+   r   r   r   r)   {   s
   ÿz SoSObfuscationArchive.is_tarfilec                 C   s<   |   |¡}|r|  d| ¡ t |¡ |  jd7  _dS dS )zˆRemove a file from the archive. This is used when cleaner encounters
        a binary file, which we cannot reliably obfuscate.
        z&Removing binary file '%s' from archiveé   N)Úget_file_pathr"   r   ÚremoveÚremoved_file_count)r$   ÚfnameZ
full_fnamer   r   r   Úremove_file‚   s   

ýz!SoSObfuscationArchive.remove_filec                 C   s6   | j s| js|  ¡ | _tj | j|¡S tj | j|¡S )zºBased on the type of archive we're dealing with, do whatever that
        archive requires to a provided **relative** filepath to be able to
        access it within the archive
        )r   r!   r0   r   r	   r
   Úextracted_path)r$   r@   r   r   r   Úformat_file_name   s
   
z&SoSObfuscationArchive.format_file_namec                 C   s’   | j du r+| jr+|  |¡}z| j |¡ ¡  d¡W S  ty*   |  d| ¡ Y dS w t	|  |¡dƒ}| ¡ W  d  ƒ S 1 sBw   Y  dS )zÀReturn the content from the specified fname. Particularly useful for
        tarball-type archives so we can retrieve prep file contents prior to
        extracting the entire archive
        Fzutf-8z.Unable to retrieve %s: no such file in archiver   ÚrN)
r   r)   rC   r*   ZextractfileÚreadÚdecodeÚKeyErrorr9   r   )r$   r@   ÚfilenameZto_readr   r   r   Úget_file_content™   s   
ÿü$ÿz&SoSObfuscationArchive.get_file_contentc                 C   sX  | j r|s
|  d¡ |  ¡ | _d| _n| j| _t ¡ dkr¢|  d¡ t 	| j¡D ]y\}}}z[|D ]}tj
 ||¡}t |¡j}t ||tjB ¡ q0|D ];}tj
 ||¡}	tj
 |	¡r`tj
 |	¡raqKt |	tj¡rot |	tj¡s†|  d|	 | j¡d  ¡ t |	tjtjB ¡ qKW q( ty¡ }
 z|  d|
 ¡ W Y d }
~
q(d }
~
ww |  d| j ¡ d S )	NzExtracting...Tr   z)Verifying permissions of archive contentsz!Adding owner rw permissions to %sr   z#Error while trying to set perms: %szExtracted path is %s)r)   r5   Úextract_selfrB   r   r   r   Úgetuidr9   Úwalkr	   r
   ÚstatÚst_modeÚchmodÚS_IRWXUÚexistsÚislinkÚaccessÚR_OKÚW_OKr   ÚS_IRUSRÚS_IWUSRr;   )r$   ÚquietÚdirnameÚdirsÚfilesÚ_dirZ_dirnameZ
_dir_permsrH   r@   Úerrr   r   r   Úextract«   sD   


ÿÿÿ€õ€ÿzSoSObfuscationArchive.extractc                 C   s.   | j  | j|¡}|| _t | j |¡ || _ dS )zÐRename the top-level directory to new_name, which should be an
        obfuscated string that scrubs the hostname from the top-level dir
        which would be named after the unobfuscated sos report
        N)rB   Úreplacer   r   Úrename)r$   Únew_nameÚ_pathr   r   r   Úrename_top_dirÐ   s   
z$SoSObfuscationArchive.rename_top_dirc                 C   s   | j r| j d¡rdS dS dS )z¸Return the compression type used by the archive, if any. This is
        then used by SoSCleaner to generate a policy-derived compression
        command to repack the archive
        ÚxzÚgzN)r)   r   Úendswithr+   r   r   r   Úget_compressionÚ   s
   z%SoSObfuscationArchive.get_compressionc                 C   s–   d}| j d }i }|r$|d| 7 }|d| 7 }|dkr ddi}ndd	i}|  d
| ¡ tj|fd|i|¤Ž}|j| j tj | j¡d d | 	¡  |S )zIPack the extracted archive as a tarfile to then be re-compressed
        Úwz-obfuscated.tarz:%sz.%srd   Úpreseté   Úcompresslevelé   zBuilding tar file %sÚmoder<   )Zarcname)
rB   r9   r   r   Úaddr   r	   r   r   r   )r$   Úmethodrm   ZtarpathZ
compr_argsÚtarr   r   r   Úbuild_tar_fileå   s    

ÿz$SoSObfuscationArchive.build_tar_filec              
   C   s˜   z|   |¡| _W n ty } z|  d| ¡ ‚ d}~ww |  d| j ¡ z|  ¡  W dS  tyK } z|  d| ¡ |  d¡ W Y d}~dS d}~ww )z•Execute the compression command, and set the appropriate final
        archive path for later reference by SoSCleaner on a per-archive basis
        z*Exception while re-compressing archive: %sNzCompressed to %sz)Failed to remove extraction directory: %sz/Failed to remove temporary extraction directory)rq   r   r;   r9   Úremove_extracted_pathr5   )r$   ro   r]   r   r   r   Úcompressù   s   €þ€þzSoSObfuscationArchive.compressc                 C   s,   dd„ }|   d| j ¡ tj| j|d dS )z¦After the tarball has been re-compressed, remove the extracted path
        so that we don't take up that duplicate space any longer during
        execution
        c                 S   s6   t  |tj¡ t j |¡rt  |¡ d S t |¡ d S r(   )	r   rO   rM   rW   r	   Úisfiler>   ÚshutilÚrmtree)Úactionr   Úexcr   r   r   Úforce_delete_file  s   zFSoSObfuscationArchive.remove_extracted_path.<locals>.force_delete_filezRemoving %s)ÚonerrorN)r9   rB   ru   rv   )r$   ry   r   r   r   rr   	  s   z+SoSObfuscationArchive.remove_extracted_pathc                 C   sJ   t dƒ}| t| j| j¡}| ¡ }|W  d  ƒ S 1 sw   Y  dS )z}Extract an archive into our tmpdir so that we may inspect it or
        iterate through its contents for obfuscation
        r<   N)r   Zsubmitr   r   r   Úresult)r$   Z_poolZ_path_futurer	   r   r   r   rJ     s   
ÿ$üz"SoSObfuscationArchive.extract_selfc                 C   s€   g | _ t | j¡D ]3\}}}|D ]}tj ||¡}tj |¡r+tj |¡r+| j  |¡ q|D ]}| j  tj ||¡¡ q.q	| j S )z-Return a list of all files within the archive)	Z	file_listr   rL   rB   r	   r
   rR   r-   Úappend)r$   rY   rZ   r[   r\   Z_dirpathrH   r   r   r   Úget_file_list"  s   €ÿz#SoSObfuscationArchive.get_file_listc                 C   s*   g }t  | j¡D ]
\}}}| |¡ q|S )z3Return a list of all directories within the archive)r   rL   rB   r|   )r$   Zdir_listrY   rZ   r[   r   r   r   Úget_directory_list/  s   z(SoSObfuscationArchive.get_directory_listc                 C   s   | j  |¡ |  j|7  _dS )z’Called when a file has finished being parsed and used to track
        total substitutions made and number of files that had changes made
        N)Úfile_sub_listr|   Útotal_sub_count)r$   r@   Úcountr   r   r   Úupdate_sub_count6  s   z&SoSObfuscationArchive.update_sub_countc                 C   s*   t j | j| d¡¡}t j |¡r|S dS )zReturn the filepath of a specific file within the archive so that
        it may be selectively inspected if it exists
        r   r   )r   r	   r
   rB   ÚlstriprQ   )r$   r@   rb   r   r   r   r=   =  s   z#SoSObfuscationArchive.get_file_pathc                 C   sT   t j |  |¡¡st j |  |¡¡sdS | jD ]}| |¡s$t ||¡r' dS qdS )a%  Checks the provided filename against a list of filepaths to not
        perform obfuscation on, as defined in self.skip_list

        Positional arguments:

            :param filename str:        Filename relative to the extracted
                                        archive root
        TF)	r   r	   rt   r=   rR   r   Ú
startswithÚreÚmatch)r$   rH   Z_skipr   r   r   Úshould_skip_fileD  s   
ÿ
ÿz&SoSObfuscationArchive.should_skip_filec                 C   sD   g d¢}|D ]}t  ||¡r dS qtj |  |¡¡r |  |¡S dS )aa  Determine if the file should be removed or not, due to an inability
        to reliably obfuscate that file based on the filename.

        :param fname:       Filename relative to the extracted archive root
        :type fname:        ``str``

        :returns:   ``True`` if the file cannot be reliably obfuscated
        :rtype:     ``bool``
        )	z.*\.gzz.*\.xzz	.*\.bzip2z.*\.tar\..*z.*\.txz$z.*\.tgz$z.*\.binz.*\.journalz.*\~$TF)r…   r†   r   r	   rt   r=   Úfile_is_binary)r$   r@   Zobvious_removesZ_arc_regr   r   r   Úshould_remove_fileW  s   
ÿ
z(SoSObfuscationArchive.should_remove_filec              	   C   sd   t |  |¡dƒ }z| d¡ W W d  ƒ dS  ty'   Y W d  ƒ dS w 1 s+w   Y  dS )a  Determine if the file is a binary file or not.


        :param fname:          Filename relative to the extracted archive root
        :type fname:           ``str``

        :returns:   ``True`` if file is binary, else ``False``
        :rtype:     ``bool``
        Útrr<   NFT)r   r=   rE   ÚUnicodeDecodeError)r$   r@   Ztfiler   r   r   rˆ   x  s   

ûùúz$SoSObfuscationArchive.file_is_binaryN)F)*Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r€   r?   Ú	type_namer#   Z	is_nestedZ
skip_filesZ
prep_filesr%   Úclassmethodr'   r    r,   r0   r5   r6   r9   r"   r   Úpropertyr)   rA   rC   rI   r^   rc   rg   rq   rs   rr   rJ   r}   r~   r‚   r=   r‡   r‰   rˆ   r   r   r   r   r       sP    
	

%
!r   )
r   r   ru   rM   r   r…   Zconcurrent.futuresr   r   r   r   r   r   r   Ú<module>   s   
